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 "rtl.h"
00026 #include "regs.h"
00027 #include "hard-reg-set.h"
00028 #include "real.h"
00029 #include "insn-config.h"
00030 #include "conditions.h"
00031 #include "insn-attr.h"
00032 #include "flags.h"
00033 #include "recog.h"
00034 #include "obstack.h"
00035 #include "tree.h"
00036 #include "expr.h"
00037 #include "optabs.h"
00038 #include "except.h"
00039 #include "function.h"
00040 #include "output.h"
00041 #include "basic-block.h"
00042 #include "integrate.h"
00043 #include "toplev.h"
00044 #include "ggc.h"
00045 #include "hashtab.h"
00046 #include "tm_p.h"
00047 #include "target.h"
00048 #include "target-def.h"
00049 #include "langhooks.h"
00050 #include "reload.h"
00051
00052 #ifndef TARGET_NO_PROTOTYPE
00053 #define TARGET_NO_PROTOTYPE 0
00054 #endif
00055
00056 #define min(A,B) ((A) < (B) ? (A) : (B))
00057 #define max(A,B) ((A) > (B) ? (A) : (B))
00058
00059
00060
00061 enum processor_type rs6000_cpu;
00062 struct rs6000_cpu_select rs6000_select[3] =
00063 {
00064
00065 { (const char *)0, "--with-cpu=", 1, 1 },
00066 { (const char *)0, "-mcpu=", 1, 1 },
00067 { (const char *)0, "-mtune=", 1, 0 },
00068 };
00069
00070
00071 const char *rs6000_long_double_size_string;
00072 int rs6000_long_double_type_size;
00073
00074
00075 int rs6000_altivec_abi;
00076
00077
00078 static int common_mode_defined;
00079
00080
00081 static int rs6000_flag_pic;
00082
00083
00084
00085 rtx rs6000_compare_op0, rs6000_compare_op1;
00086 int rs6000_compare_fp_p;
00087
00088
00089
00090 int rs6000_pic_labelno;
00091
00092 #ifdef USING_ELFOS_H
00093
00094 const char *rs6000_abi_name = RS6000_ABI_NAME;
00095
00096
00097 enum rs6000_sdata_type rs6000_sdata = SDATA_DATA;
00098
00099
00100 const char *rs6000_sdata_name = (char *)0;
00101
00102
00103 int fixuplabelno = 0;
00104 #endif
00105
00106
00107 enum rs6000_abi rs6000_current_abi;
00108
00109
00110 const char *rs6000_abi_string;
00111
00112
00113 const char *rs6000_debug_name;
00114 int rs6000_debug_stack;
00115 int rs6000_debug_arg;
00116
00117
00118 int toc_initialized;
00119 char toc_label_name[10];
00120
00121
00122 static int rs6000_sr_alias_set;
00123
00124 static void rs6000_add_gc_roots PARAMS ((void));
00125 static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
00126 static void validate_condition_mode
00127 PARAMS ((enum rtx_code, enum machine_mode));
00128 static rtx rs6000_generate_compare PARAMS ((enum rtx_code));
00129 static void rs6000_maybe_dead PARAMS ((rtx));
00130 static void rs6000_emit_stack_tie PARAMS ((void));
00131 static void rs6000_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT, rtx, rtx));
00132 static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
00133 static unsigned rs6000_hash_constant PARAMS ((rtx));
00134 static unsigned toc_hash_function PARAMS ((const void *));
00135 static int toc_hash_eq PARAMS ((const void *, const void *));
00136 static int toc_hash_mark_entry PARAMS ((void **, void *));
00137 static void toc_hash_mark_table PARAMS ((void *));
00138 static int constant_pool_expr_1 PARAMS ((rtx, int *, int *));
00139 static void rs6000_free_machine_status PARAMS ((struct function *));
00140 static void rs6000_init_machine_status PARAMS ((struct function *));
00141 static bool rs6000_assemble_integer PARAMS ((rtx, unsigned int, int));
00142 static int rs6000_ra_ever_killed PARAMS ((void));
00143 static tree rs6000_handle_longcall_attribute PARAMS ((tree *, tree, tree, int, bool *));
00144 const struct attribute_spec rs6000_attribute_table[];
00145 static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00146 static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00147 static rtx rs6000_emit_set_long_const PARAMS ((rtx,
00148 HOST_WIDE_INT, HOST_WIDE_INT));
00149 #if TARGET_ELF
00150 static unsigned int rs6000_elf_section_type_flags PARAMS ((tree, const char *,
00151 int));
00152 static void rs6000_elf_asm_out_constructor PARAMS ((rtx, int));
00153 static void rs6000_elf_asm_out_destructor PARAMS ((rtx, int));
00154 #endif
00155 #ifdef OBJECT_FORMAT_COFF
00156 static void xcoff_asm_named_section PARAMS ((const char *, unsigned int));
00157 #endif
00158 static bool rs6000_binds_local_p PARAMS ((tree));
00159 static int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00160 static int rs6000_adjust_priority PARAMS ((rtx, int));
00161 static int rs6000_issue_rate PARAMS ((void));
00162
00163 static void rs6000_init_builtins PARAMS ((void));
00164 static void altivec_init_builtins PARAMS ((void));
00165 static rtx rs6000_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
00166 static rtx altivec_expand_builtin PARAMS ((tree, rtx));
00167 static rtx altivec_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx));
00168 static rtx altivec_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
00169 static rtx altivec_expand_abs_builtin PARAMS ((enum insn_code, tree, rtx));
00170 static rtx altivec_expand_predicate_builtin PARAMS ((enum insn_code, const char *, tree, rtx));
00171 static rtx altivec_expand_ternop_builtin PARAMS ((enum insn_code, tree, rtx));
00172 static rtx altivec_expand_stv_builtin PARAMS ((enum insn_code, tree));
00173 static void rs6000_parse_abi_options PARAMS ((void));
00174 static int first_altivec_reg_to_save PARAMS ((void));
00175 static unsigned int compute_vrsave_mask PARAMS ((void));
00176 static void is_altivec_return_reg PARAMS ((rtx, void *));
00177 int vrsave_operation PARAMS ((rtx, enum machine_mode));
00178 static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
00179 static void altivec_frame_fixup PARAMS ((rtx, rtx, HOST_WIDE_INT));
00180 static int easy_vector_constant PARAMS ((rtx));
00181
00182
00183 char rs6000_reg_names[][8] =
00184 {
00185 "0", "1", "2", "3", "4", "5", "6", "7",
00186 "8", "9", "10", "11", "12", "13", "14", "15",
00187 "16", "17", "18", "19", "20", "21", "22", "23",
00188 "24", "25", "26", "27", "28", "29", "30", "31",
00189 "0", "1", "2", "3", "4", "5", "6", "7",
00190 "8", "9", "10", "11", "12", "13", "14", "15",
00191 "16", "17", "18", "19", "20", "21", "22", "23",
00192 "24", "25", "26", "27", "28", "29", "30", "31",
00193 "mq", "lr", "ctr","ap",
00194 "0", "1", "2", "3", "4", "5", "6", "7",
00195 "xer",
00196
00197 "0", "1", "2", "3", "4", "5", "6", "7",
00198 "8", "9", "10", "11", "12", "13", "14", "15",
00199 "16", "17", "18", "19", "20", "21", "22", "23",
00200 "24", "25", "26", "27", "28", "29", "30", "31",
00201 "vrsave"
00202 };
00203
00204 #ifdef TARGET_REGNAMES
00205 static const char alt_reg_names[][8] =
00206 {
00207 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
00208 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
00209 "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
00210 "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31",
00211 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
00212 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
00213 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
00214 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
00215 "mq", "lr", "ctr", "ap",
00216 "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
00217 "xer",
00218
00219 "%v0", "%v1", "%v2", "%v3", "%v4", "%v5", "%v6", "%v7",
00220 "%v8", "%v9", "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
00221 "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
00222 "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
00223 "vrsave"
00224 };
00225 #endif
00226
00227 #ifndef MASK_STRICT_ALIGN
00228 #define MASK_STRICT_ALIGN 0
00229 #endif
00230
00231
00232 #undef TARGET_ATTRIBUTE_TABLE
00233 #define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table
00234
00235 #undef TARGET_ASM_ALIGNED_DI_OP
00236 #define TARGET_ASM_ALIGNED_DI_OP DOUBLE_INT_ASM_OP
00237
00238
00239
00240 #ifndef OBJECT_FORMAT_ELF
00241 #ifdef OBJECT_FORMAT_COFF
00242
00243
00244 #undef TARGET_ASM_UNALIGNED_HI_OP
00245 #define TARGET_ASM_UNALIGNED_HI_OP "\t.vbyte\t2,"
00246 #undef TARGET_ASM_UNALIGNED_SI_OP
00247 #define TARGET_ASM_UNALIGNED_SI_OP "\t.vbyte\t4,"
00248 #undef TARGET_ASM_UNALIGNED_DI_OP
00249 #define TARGET_ASM_UNALIGNED_DI_OP "\t.vbyte\t8,"
00250 #else
00251
00252 #undef TARGET_ASM_UNALIGNED_HI_OP
00253 #define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
00254 #undef TARGET_ASM_UNALIGNED_SI_OP
00255 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
00256 #endif
00257 #endif
00258
00259
00260
00261 #undef TARGET_ASM_INTEGER
00262 #define TARGET_ASM_INTEGER rs6000_assemble_integer
00263
00264 #undef TARGET_ASM_FUNCTION_PROLOGUE
00265 #define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
00266 #undef TARGET_ASM_FUNCTION_EPILOGUE
00267 #define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
00268
00269 #if TARGET_ELF
00270 #undef TARGET_SECTION_TYPE_FLAGS
00271 #define TARGET_SECTION_TYPE_FLAGS rs6000_elf_section_type_flags
00272 #endif
00273
00274 #undef TARGET_SCHED_ISSUE_RATE
00275 #define TARGET_SCHED_ISSUE_RATE rs6000_issue_rate
00276 #undef TARGET_SCHED_ADJUST_COST
00277 #define TARGET_SCHED_ADJUST_COST rs6000_adjust_cost
00278 #undef TARGET_SCHED_ADJUST_PRIORITY
00279 #define TARGET_SCHED_ADJUST_PRIORITY rs6000_adjust_priority
00280
00281 #undef TARGET_INIT_BUILTINS
00282 #define TARGET_INIT_BUILTINS rs6000_init_builtins
00283
00284 #undef TARGET_EXPAND_BUILTIN
00285 #define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
00286
00287
00288 #define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
00289
00290 struct gcc_target targetm = TARGET_INITIALIZER;
00291
00292
00293
00294
00295 void
00296 rs6000_override_options (default_cpu)
00297 const char *default_cpu;
00298 {
00299 size_t i, j;
00300 struct rs6000_cpu_select *ptr;
00301
00302
00303
00304
00305 #define POWER_MASKS (MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING)
00306 #define POWERPC_MASKS (MASK_POWERPC | MASK_PPC_GPOPT \
00307 | MASK_PPC_GFXOPT | MASK_POWERPC64)
00308 #define POWERPC_OPT_MASKS (MASK_PPC_GPOPT | MASK_PPC_GFXOPT)
00309
00310 static struct ptt
00311 {
00312 const char *const name;
00313 const enum processor_type processor;
00314 const int target_enable;
00315 const int target_disable;
00316 } const processor_target_table[]
00317 = {{"common", PROCESSOR_COMMON, MASK_NEW_MNEMONICS,
00318 POWER_MASKS | POWERPC_MASKS},
00319 {"power", PROCESSOR_POWER,
00320 MASK_POWER | MASK_MULTIPLE | MASK_STRING,
00321 MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
00322 {"power2", PROCESSOR_POWER,
00323 MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
00324 POWERPC_MASKS | MASK_NEW_MNEMONICS},
00325 {"power3", PROCESSOR_PPC630,
00326 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00327 POWER_MASKS | MASK_PPC_GPOPT},
00328 {"powerpc", PROCESSOR_POWERPC,
00329 MASK_POWERPC | MASK_NEW_MNEMONICS,
00330 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00331 {"powerpc64", PROCESSOR_POWERPC64,
00332 MASK_POWERPC | MASK_POWERPC64 | MASK_NEW_MNEMONICS,
00333 POWER_MASKS | POWERPC_OPT_MASKS},
00334 {"rios", PROCESSOR_RIOS1,
00335 MASK_POWER | MASK_MULTIPLE | MASK_STRING,
00336 MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
00337 {"rios1", PROCESSOR_RIOS1,
00338 MASK_POWER | MASK_MULTIPLE | MASK_STRING,
00339 MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
00340 {"rsc", PROCESSOR_PPC601,
00341 MASK_POWER | MASK_MULTIPLE | MASK_STRING,
00342 MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
00343 {"rsc1", PROCESSOR_PPC601,
00344 MASK_POWER | MASK_MULTIPLE | MASK_STRING,
00345 MASK_POWER2 | POWERPC_MASKS | MASK_NEW_MNEMONICS},
00346 {"rios2", PROCESSOR_RIOS2,
00347 MASK_POWER | MASK_MULTIPLE | MASK_STRING | MASK_POWER2,
00348 POWERPC_MASKS | MASK_NEW_MNEMONICS},
00349 {"rs64a", PROCESSOR_RS64A,
00350 MASK_POWERPC | MASK_NEW_MNEMONICS,
00351 POWER_MASKS | POWERPC_OPT_MASKS},
00352 {"401", PROCESSOR_PPC403,
00353 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
00354 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00355 {"403", PROCESSOR_PPC403,
00356 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS | MASK_STRICT_ALIGN,
00357 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00358 {"405", PROCESSOR_PPC405,
00359 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
00360 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00361 {"505", PROCESSOR_MPCCORE,
00362 MASK_POWERPC | MASK_NEW_MNEMONICS,
00363 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00364 {"601", PROCESSOR_PPC601,
00365 MASK_POWER | MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_MULTIPLE | MASK_STRING,
00366 MASK_POWER2 | POWERPC_OPT_MASKS | MASK_POWERPC64},
00367 {"602", PROCESSOR_PPC603,
00368 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00369 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00370 {"603", PROCESSOR_PPC603,
00371 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00372 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00373 {"603e", PROCESSOR_PPC603,
00374 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00375 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00376 {"ec603e", PROCESSOR_PPC603,
00377 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
00378 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00379 {"604", PROCESSOR_PPC604,
00380 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00381 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00382 {"604e", PROCESSOR_PPC604e,
00383 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00384 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00385 {"620", PROCESSOR_PPC620,
00386 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00387 POWER_MASKS | MASK_PPC_GPOPT},
00388 {"630", PROCESSOR_PPC630,
00389 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00390 POWER_MASKS | MASK_PPC_GPOPT},
00391 {"740", PROCESSOR_PPC750,
00392 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00393 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00394 {"750", PROCESSOR_PPC750,
00395 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00396 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00397 {"7400", PROCESSOR_PPC7400,
00398 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00399 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00400 {"7450", PROCESSOR_PPC7450,
00401 MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
00402 POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
00403 {"801", PROCESSOR_MPCCORE,
00404 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
00405 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00406 {"821", PROCESSOR_MPCCORE,
00407 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
00408 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00409 {"823", PROCESSOR_MPCCORE,
00410 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
00411 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
00412 {"860", PROCESSOR_MPCCORE,
00413 MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
00414 POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64}};
00415
00416 size_t ptt_size = sizeof (processor_target_table) / sizeof (struct ptt);
00417
00418
00419 int multiple = TARGET_MULTIPLE;
00420
00421 int string = TARGET_STRING;
00422
00423
00424 rs6000_select[0].string = default_cpu;
00425 rs6000_cpu = TARGET_POWERPC64 ? PROCESSOR_DEFAULT64 : PROCESSOR_DEFAULT;
00426
00427 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
00428 {
00429 ptr = &rs6000_select[i];
00430 if (ptr->string != (char *)0 && ptr->string[0] != '\0')
00431 {
00432 for (j = 0; j < ptt_size; j++)
00433 if (! strcmp (ptr->string, processor_target_table[j].name))
00434 {
00435 if (ptr->set_tune_p)
00436 rs6000_cpu = processor_target_table[j].processor;
00437
00438 if (ptr->set_arch_p)
00439 {
00440 target_flags |= processor_target_table[j].target_enable;
00441 target_flags &= ~processor_target_table[j].target_disable;
00442 }
00443 break;
00444 }
00445
00446 if (j == ptt_size)
00447 error ("bad value (%s) for %s switch", ptr->string, ptr->name);
00448 }
00449 }
00450
00451
00452
00453 if (BYTES_BIG_ENDIAN && optimize_size)
00454 target_flags |= MASK_MULTIPLE;
00455
00456
00457
00458 if (TARGET_MULTIPLE_SET)
00459 target_flags = (target_flags & ~MASK_MULTIPLE) | multiple;
00460
00461
00462
00463 if (TARGET_STRING_SET)
00464 target_flags = (target_flags & ~MASK_STRING) | string;
00465
00466
00467
00468
00469
00470
00471
00472 if (! BYTES_BIG_ENDIAN && rs6000_cpu != PROCESSOR_PPC750)
00473 {
00474 if (TARGET_MULTIPLE)
00475 {
00476 target_flags &= ~MASK_MULTIPLE;
00477 if (TARGET_MULTIPLE_SET)
00478 warning ("-mmultiple is not supported on little endian systems");
00479 }
00480
00481 if (TARGET_STRING)
00482 {
00483 target_flags &= ~MASK_STRING;
00484 if (TARGET_STRING_SET)
00485 warning ("-mstring is not supported on little endian systems");
00486 }
00487 }
00488
00489 if (flag_pic != 0 && DEFAULT_ABI == ABI_AIX)
00490 {
00491 rs6000_flag_pic = flag_pic;
00492 flag_pic = 0;
00493 }
00494
00495 #ifdef XCOFF_DEBUGGING_INFO
00496 if (flag_function_sections && (write_symbols != NO_DEBUG)
00497 && DEFAULT_ABI == ABI_AIX)
00498 {
00499 warning ("-ffunction-sections disabled on AIX when debugging");
00500 flag_function_sections = 0;
00501 }
00502
00503 if (flag_data_sections && (DEFAULT_ABI == ABI_AIX))
00504 {
00505 warning ("-fdata-sections not supported on AIX");
00506 flag_data_sections = 0;
00507 }
00508 #endif
00509
00510
00511 if (rs6000_debug_name)
00512 {
00513 if (! strcmp (rs6000_debug_name, "all"))
00514 rs6000_debug_stack = rs6000_debug_arg = 1;
00515 else if (! strcmp (rs6000_debug_name, "stack"))
00516 rs6000_debug_stack = 1;
00517 else if (! strcmp (rs6000_debug_name, "arg"))
00518 rs6000_debug_arg = 1;
00519 else
00520 error ("unknown -mdebug-%s switch", rs6000_debug_name);
00521 }
00522
00523
00524 rs6000_long_double_type_size = 64;
00525 if (rs6000_long_double_size_string)
00526 {
00527 char *tail;
00528 int size = strtol (rs6000_long_double_size_string, &tail, 10);
00529 if (*tail != '\0' || (size != 64 && size != 128))
00530 error ("Unknown switch -mlong-double-%s",
00531 rs6000_long_double_size_string);
00532 else
00533 rs6000_long_double_type_size = size;
00534 }
00535
00536
00537 rs6000_parse_abi_options ();
00538
00539 #ifdef TARGET_REGNAMES
00540
00541
00542 if (TARGET_REGNAMES)
00543 memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
00544 #endif
00545
00546 #ifdef SUBTARGET_OVERRIDE_OPTIONS
00547 SUBTARGET_OVERRIDE_OPTIONS;
00548 #endif
00549 #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
00550 SUBSUBTARGET_OVERRIDE_OPTIONS;
00551 #endif
00552
00553
00554
00555
00556 if (!(target_flags & MASK_AIX_STRUCT_RET_SET))
00557 {
00558 if (DEFAULT_ABI == ABI_V4 && !DRAFT_V4_STRUCT_RET)
00559 target_flags = (target_flags & ~MASK_AIX_STRUCT_RET);
00560 else
00561 target_flags |= MASK_AIX_STRUCT_RET;
00562 }
00563
00564
00565 rs6000_add_gc_roots ();
00566
00567
00568 rs6000_sr_alias_set = new_alias_set ();
00569
00570 if (TARGET_TOC)
00571 ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
00572
00573
00574
00575 if (!TARGET_64BIT)
00576 {
00577 targetm.asm_out.aligned_op.di = NULL;
00578 targetm.asm_out.unaligned_op.di = NULL;
00579 }
00580
00581
00582 init_machine_status = rs6000_init_machine_status;
00583 free_machine_status = rs6000_free_machine_status;
00584 }
00585
00586
00587 static void
00588 rs6000_parse_abi_options ()
00589 {
00590 if (rs6000_abi_string == 0)
00591 return;
00592 else if (! strcmp (rs6000_abi_string, "altivec"))
00593 rs6000_altivec_abi = 1;
00594 else if (! strcmp (rs6000_abi_string, "no-altivec"))
00595 rs6000_altivec_abi = 0;
00596 else
00597 error ("unknown ABI specified: '%s'", rs6000_abi_string);
00598 }
00599
00600 void
00601 optimization_options (level, size)
00602 int level ATTRIBUTE_UNUSED;
00603 int size ATTRIBUTE_UNUSED;
00604 {
00605 }
00606
00607
00608
00609 void
00610 rs6000_file_start (file, default_cpu)
00611 FILE *file;
00612 const char *default_cpu;
00613 {
00614 size_t i;
00615 char buffer[80];
00616 const char *start = buffer;
00617 struct rs6000_cpu_select *ptr;
00618
00619 if (flag_verbose_asm)
00620 {
00621 sprintf (buffer, "\n%s rs6000/powerpc options:", ASM_COMMENT_START);
00622 rs6000_select[0].string = default_cpu;
00623
00624 for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
00625 {
00626 ptr = &rs6000_select[i];
00627 if (ptr->string != (char *)0 && ptr->string[0] != '\0')
00628 {
00629 fprintf (file, "%s %s%s", start, ptr->name, ptr->string);
00630 start = "";
00631 }
00632 }
00633
00634 #ifdef USING_ELFOS_H
00635 switch (rs6000_sdata)
00636 {
00637 case SDATA_NONE: fprintf (file, "%s -msdata=none", start); start = ""; break;
00638 case SDATA_DATA: fprintf (file, "%s -msdata=data", start); start = ""; break;
00639 case SDATA_SYSV: fprintf (file, "%s -msdata=sysv", start); start = ""; break;
00640 case SDATA_EABI: fprintf (file, "%s -msdata=eabi", start); start = ""; break;
00641 }
00642
00643 if (rs6000_sdata && g_switch_value)
00644 {
00645 fprintf (file, "%s -G %d", start, g_switch_value);
00646 start = "";
00647 }
00648 #endif
00649
00650 if (*start == '\0')
00651 putc ('\n', file);
00652 }
00653 }
00654
00655
00656
00657
00658 struct rtx_def *
00659 rs6000_float_const (string, mode)
00660 const char *string;
00661 enum machine_mode mode;
00662 {
00663 REAL_VALUE_TYPE value;
00664 value = REAL_VALUE_ATOF (string, mode);
00665 return immed_real_const_1 (value, mode);
00666 }
00667
00668
00669
00670 int
00671 direct_return ()
00672 {
00673 if (reload_completed)
00674 {
00675 rs6000_stack_t *info = rs6000_stack_info ();
00676
00677 if (info->first_gp_reg_save == 32
00678 && info->first_fp_reg_save == 64
00679 && info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1
00680 && ! info->lr_save_p
00681 && ! info->cr_save_p
00682 && info->vrsave_mask == 0
00683 && ! info->push_p)
00684 return 1;
00685 }
00686
00687 return 0;
00688 }
00689
00690
00691
00692 int
00693 any_operand (op, mode)
00694 rtx op ATTRIBUTE_UNUSED;
00695 enum machine_mode mode ATTRIBUTE_UNUSED;
00696 {
00697 return 1;
00698 }
00699
00700
00701 int
00702 count_register_operand (op, mode)
00703 rtx op;
00704 enum machine_mode mode ATTRIBUTE_UNUSED;
00705 {
00706 if (GET_CODE (op) != REG)
00707 return 0;
00708
00709 if (REGNO (op) == COUNT_REGISTER_REGNUM)
00710 return 1;
00711
00712 if (REGNO (op) > FIRST_PSEUDO_REGISTER)
00713 return 1;
00714
00715 return 0;
00716 }
00717
00718
00719 int
00720 altivec_register_operand (op, mode)
00721 rtx op;
00722 enum machine_mode mode ATTRIBUTE_UNUSED;
00723 {
00724
00725 return (register_operand (op, mode)
00726 && (GET_CODE (op) != REG
00727 || REGNO (op) > FIRST_PSEUDO_REGISTER
00728 || ALTIVEC_REGNO_P (REGNO (op))));
00729 }
00730
00731 int
00732 xer_operand (op, mode)
00733 rtx op;
00734 enum machine_mode mode ATTRIBUTE_UNUSED;
00735 {
00736 if (GET_CODE (op) != REG)
00737 return 0;
00738
00739 if (XER_REGNO_P (REGNO (op)))
00740 return 1;
00741
00742 return 0;
00743 }
00744
00745
00746
00747
00748 int
00749 s8bit_cint_operand (op, mode)
00750 rtx op;
00751 enum machine_mode mode ATTRIBUTE_UNUSED;
00752 {
00753 return ( GET_CODE (op) == CONST_INT
00754 && (INTVAL (op) >= -128 && INTVAL (op) <= 127));
00755 }
00756
00757
00758
00759 int
00760 short_cint_operand (op, mode)
00761 rtx op;
00762 enum machine_mode mode ATTRIBUTE_UNUSED;
00763 {
00764 return (GET_CODE (op) == CONST_INT
00765 && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
00766 }
00767
00768
00769
00770 int
00771 u_short_cint_operand (op, mode)
00772 rtx op;
00773 enum machine_mode mode ATTRIBUTE_UNUSED;
00774 {
00775 return (GET_CODE (op) == CONST_INT
00776 && CONST_OK_FOR_LETTER_P (INTVAL (op) & GET_MODE_MASK (mode), 'K'));
00777 }
00778
00779
00780
00781 int
00782 non_short_cint_operand (op, mode)
00783 rtx op;
00784 enum machine_mode mode ATTRIBUTE_UNUSED;
00785 {
00786 return (GET_CODE (op) == CONST_INT
00787 && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);
00788 }
00789
00790
00791
00792
00793 int
00794 exact_log2_cint_operand (op, mode)
00795 rtx op;
00796 enum machine_mode mode ATTRIBUTE_UNUSED;
00797 {
00798 return (GET_CODE (op) == CONST_INT
00799 && INTVAL (op) > 0
00800 && exact_log2 (INTVAL (op)) >= 0);
00801 }
00802
00803
00804
00805
00806 int
00807 gpc_reg_operand (op, mode)
00808 rtx op;
00809 enum machine_mode mode;
00810 {
00811 return (register_operand (op, mode)
00812 && (GET_CODE (op) != REG
00813 || (REGNO (op) >= ARG_POINTER_REGNUM
00814 && !XER_REGNO_P (REGNO (op)))
00815 || REGNO (op) < MQ_REGNO));
00816 }
00817
00818
00819
00820
00821 int
00822 cc_reg_operand (op, mode)
00823 rtx op;
00824 enum machine_mode mode;
00825 {
00826 return (register_operand (op, mode)
00827 && (GET_CODE (op) != REG
00828 || REGNO (op) >= FIRST_PSEUDO_REGISTER
00829 || CR_REGNO_P (REGNO (op))));
00830 }
00831
00832
00833
00834
00835 int
00836 cc_reg_not_cr0_operand (op, mode)
00837 rtx op;
00838 enum machine_mode mode;
00839 {
00840 return (register_operand (op, mode)
00841 && (GET_CODE (op) != REG
00842 || REGNO (op) >= FIRST_PSEUDO_REGISTER
00843 || CR_REGNO_NOT_CR0_P (REGNO (op))));
00844 }
00845
00846
00847
00848
00849
00850 int
00851 reg_or_short_operand (op, mode)
00852 rtx op;
00853 enum machine_mode mode;
00854 {
00855 return short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
00856 }
00857
00858
00859
00860
00861 int
00862 reg_or_neg_short_operand (op, mode)
00863 rtx op;
00864 enum machine_mode mode;
00865 {
00866 if (GET_CODE (op) == CONST_INT)
00867 return CONST_OK_FOR_LETTER_P (INTVAL (op), 'P');
00868
00869 return gpc_reg_operand (op, mode);
00870 }
00871
00872
00873
00874
00875
00876 int
00877 reg_or_aligned_short_operand (op, mode)
00878 rtx op;
00879 enum machine_mode mode;
00880 {
00881 if (gpc_reg_operand (op, mode))
00882 return 1;
00883 else if (short_cint_operand (op, mode) && !(INTVAL (op) & 3))
00884 return 1;
00885
00886 return 0;
00887 }
00888
00889
00890
00891
00892
00893 int
00894 reg_or_u_short_operand (op, mode)
00895 rtx op;
00896 enum machine_mode mode;
00897 {
00898 return u_short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
00899 }
00900
00901
00902
00903
00904 int
00905 reg_or_cint_operand (op, mode)
00906 rtx op;
00907 enum machine_mode mode;
00908 {
00909 return (GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode));
00910 }
00911
00912
00913
00914
00915 int
00916 reg_or_arith_cint_operand (op, mode)
00917 rtx op;
00918 enum machine_mode mode;
00919 {
00920 return (gpc_reg_operand (op, mode)
00921 || (GET_CODE (op) == CONST_INT
00922 #if HOST_BITS_PER_WIDE_INT != 32
00923 && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000)
00924 < (unsigned HOST_WIDE_INT) 0x100000000ll)
00925 #endif
00926 ));
00927 }
00928
00929
00930
00931
00932 int
00933 reg_or_add_cint64_operand (op, mode)
00934 rtx op;
00935 enum machine_mode mode;
00936 {
00937 return (gpc_reg_operand (op, mode)
00938 || (GET_CODE (op) == CONST_INT
00939 && INTVAL (op) < 0x7fff8000
00940 #if HOST_BITS_PER_WIDE_INT != 32
00941 && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
00942 < 0x100000000ll)
00943 #endif
00944 ));
00945 }
00946
00947
00948
00949
00950 int
00951 reg_or_sub_cint64_operand (op, mode)
00952 rtx op;
00953 enum machine_mode mode;
00954 {
00955 return (gpc_reg_operand (op, mode)
00956 || (GET_CODE (op) == CONST_INT
00957 && (- INTVAL (op)) < 0x7fff8000
00958 #if HOST_BITS_PER_WIDE_INT != 32
00959 && ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
00960 < 0x100000000ll)
00961 #endif
00962 ));
00963 }
00964
00965
00966
00967
00968 int
00969 reg_or_logical_cint_operand (op, mode)
00970 rtx op;
00971 enum machine_mode mode;
00972 {
00973 if (GET_CODE (op) == CONST_INT)
00974 {
00975 if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
00976 {
00977 if (GET_MODE_BITSIZE (mode) <= 32)
00978 abort ();
00979
00980 if (INTVAL (op) < 0)
00981 return 0;
00982 }
00983
00984 return ((INTVAL (op) & GET_MODE_MASK (mode)
00985 & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0);
00986 }
00987 else if (GET_CODE (op) == CONST_DOUBLE)
00988 {
00989 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
00990 || mode != DImode)
00991 abort ();
00992
00993 return CONST_DOUBLE_HIGH (op) == 0;
00994 }
00995 else
00996 return gpc_reg_operand (op, mode);
00997 }
00998
00999
01000
01001 int
01002 got_operand (op, mode)
01003 rtx op;
01004 enum machine_mode mode ATTRIBUTE_UNUSED;
01005 {
01006 return (GET_CODE (op) == SYMBOL_REF
01007 || GET_CODE (op) == CONST
01008 || GET_CODE (op) == LABEL_REF);
01009 }
01010
01011
01012
01013
01014 int
01015 got_no_const_operand (op, mode)
01016 rtx op;
01017 enum machine_mode mode ATTRIBUTE_UNUSED;
01018 {
01019 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF);
01020 }
01021
01022
01023
01024
01025 static int
01026 num_insns_constant_wide (value)
01027 HOST_WIDE_INT value;
01028 {
01029
01030 if (CONST_OK_FOR_LETTER_P (value, 'I'))
01031 return 1;
01032
01033
01034 else if (CONST_OK_FOR_LETTER_P (value, 'L'))
01035 return 1;
01036
01037 #if HOST_BITS_PER_WIDE_INT == 64
01038 else if (TARGET_POWERPC64)
01039 {
01040 HOST_WIDE_INT low = value & 0xffffffff;
01041 HOST_WIDE_INT high = value >> 32;
01042
01043 low = (low ^ 0x80000000) - 0x80000000;
01044
01045 if (high == 0 && (low & 0x80000000) == 0)
01046 return 2;
01047
01048 else if (high == -1 && (low & 0x80000000) != 0)
01049 return 2;
01050
01051 else if (! low)
01052 return num_insns_constant_wide (high) + 1;
01053
01054 else
01055 return (num_insns_constant_wide (high)
01056 + num_insns_constant_wide (low) + 1);
01057 }
01058 #endif
01059
01060 else
01061 return 2;
01062 }
01063
01064 int
01065 num_insns_constant (op, mode)
01066 rtx op;
01067 enum machine_mode mode;
01068 {
01069 if (GET_CODE (op) == CONST_INT)
01070 {
01071 #if HOST_BITS_PER_WIDE_INT == 64
01072 if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1
01073 && mask64_operand (op, mode))
01074 return 2;
01075 else
01076 #endif
01077 return num_insns_constant_wide (INTVAL (op));
01078 }
01079
01080 else if (GET_CODE (op) == CONST_DOUBLE && mode == SFmode)
01081 {
01082 long l;
01083 REAL_VALUE_TYPE rv;
01084
01085 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
01086 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
01087 return num_insns_constant_wide ((HOST_WIDE_INT) l);
01088 }
01089
01090 else if (GET_CODE (op) == CONST_DOUBLE)
01091 {
01092 HOST_WIDE_INT low;
01093 HOST_WIDE_INT high;
01094 long l[2];
01095 REAL_VALUE_TYPE rv;
01096 int endian = (WORDS_BIG_ENDIAN == 0);
01097
01098 if (mode == VOIDmode || mode == DImode)
01099 {
01100 high = CONST_DOUBLE_HIGH (op);
01101 low = CONST_DOUBLE_LOW (op);
01102 }
01103 else
01104 {
01105 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
01106 REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
01107 high = l[endian];
01108 low = l[1 - endian];
01109 }
01110
01111 if (TARGET_32BIT)
01112 return (num_insns_constant_wide (low)
01113 + num_insns_constant_wide (high));
01114
01115 else
01116 {
01117 if (high == 0 && low >= 0)
01118 return num_insns_constant_wide (low);
01119
01120 else if (high == -1 && low < 0)
01121 return num_insns_constant_wide (low);
01122
01123 else if (mask64_operand (op, mode))
01124 return 2;
01125
01126 else if (low == 0)
01127 return num_insns_constant_wide (high) + 1;
01128
01129 else
01130 return (num_insns_constant_wide (high)
01131 + num_insns_constant_wide (low) + 1);
01132 }
01133 }
01134
01135 else
01136 abort ();
01137 }
01138
01139
01140
01141
01142
01143 int
01144 easy_fp_constant (op, mode)
01145 rtx op;
01146 enum machine_mode mode;
01147 {
01148 if (GET_CODE (op) != CONST_DOUBLE
01149 || GET_MODE (op) != mode
01150 || (GET_MODE_CLASS (mode) != MODE_FLOAT && mode != DImode))
01151 return 0;
01152
01153
01154 if (TARGET_SOFT_FLOAT && mode != DImode)
01155 return 1;
01156
01157
01158 if (flag_pic && DEFAULT_ABI == ABI_V4)
01159 return 0;
01160
01161 #ifdef TARGET_RELOCATABLE
01162
01163
01164 if (TARGET_RELOCATABLE)
01165 return 0;
01166 #endif
01167
01168 if (mode == DFmode)
01169 {
01170 long k[2];
01171 REAL_VALUE_TYPE rv;
01172
01173 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
01174 REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
01175
01176 return (num_insns_constant_wide ((HOST_WIDE_INT)k[0]) == 1
01177 && num_insns_constant_wide ((HOST_WIDE_INT)k[1]) == 1);
01178 }
01179
01180 else if (mode == SFmode)
01181 {
01182 long l;
01183 REAL_VALUE_TYPE rv;
01184
01185 REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
01186 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
01187
01188 return num_insns_constant_wide (l) == 1;
01189 }
01190
01191 else if (mode == DImode)
01192 return ((TARGET_POWERPC64
01193 && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
01194 || (num_insns_constant (op, DImode) <= 2));
01195
01196 else if (mode == SImode)
01197 return 1;
01198 else
01199 abort ();
01200 }
01201
01202
01203
01204
01205 static int
01206 easy_vector_constant (op)
01207 rtx op;
01208 {
01209 rtx elt;
01210 int units, i;
01211
01212 if (GET_CODE (op) != CONST_VECTOR)
01213 return 0;
01214
01215 units = CONST_VECTOR_NUNITS (op);
01216
01217
01218 for (i = 0; i < units; ++i)
01219 {
01220 elt = CONST_VECTOR_ELT (op, i);
01221
01222
01223
01224
01225
01226 switch (GET_CODE (elt))
01227 {
01228 case CONST_INT:
01229 if (INTVAL (elt) != 0)
01230 return 0;
01231 break;
01232 case CONST_DOUBLE:
01233 if (CONST_DOUBLE_LOW (elt) != 0 || CONST_DOUBLE_HIGH (elt) != 0)
01234 return 0;
01235 break;
01236 default:
01237 return 0;
01238 }
01239 }
01240
01241
01242
01243 return 1;
01244 }
01245
01246
01247
01248 int
01249 zero_constant (op, mode)
01250 rtx op;
01251 enum machine_mode mode;
01252 {
01253 return op == CONST0_RTX (mode);
01254 }
01255
01256
01257 int
01258 zero_fp_constant (op, mode)
01259 rtx op;
01260 enum machine_mode mode;
01261 {
01262 return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
01263 }
01264
01265
01266
01267
01268
01269
01270 int
01271 volatile_mem_operand (op, mode)
01272 rtx op;
01273 enum machine_mode mode;
01274 {
01275 if (GET_CODE (op) != MEM)
01276 return 0;
01277
01278 if (!MEM_VOLATILE_P (op))
01279 return 0;
01280
01281 if (mode != GET_MODE (op))
01282 return 0;
01283
01284 if (reload_completed)
01285 return memory_operand (op, mode);
01286
01287 if (reload_in_progress)
01288 return strict_memory_address_p (mode, XEXP (op, 0));
01289
01290 return memory_address_p (mode, XEXP (op, 0));
01291 }
01292
01293
01294
01295 int
01296 offsettable_mem_operand (op, mode)
01297 rtx op;
01298 enum machine_mode mode;
01299 {
01300 return ((GET_CODE (op) == MEM)
01301 && offsettable_address_p (reload_completed || reload_in_progress,
01302 mode, XEXP (op, 0)));
01303 }
01304
01305
01306
01307
01308 int
01309 mem_or_easy_const_operand (op, mode)
01310 rtx op;
01311 enum machine_mode mode;
01312 {
01313 return memory_operand (op, mode) || easy_fp_constant (op, mode);
01314 }
01315
01316
01317
01318
01319 int
01320 add_operand (op, mode)
01321 rtx op;
01322 enum machine_mode mode;
01323 {
01324 if (GET_CODE (op) == CONST_INT)
01325 return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
01326 || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
01327
01328 return gpc_reg_operand (op, mode);
01329 }
01330
01331
01332
01333 int
01334 non_add_cint_operand (op, mode)
01335 rtx op;
01336 enum machine_mode mode ATTRIBUTE_UNUSED;
01337 {
01338 return (GET_CODE (op) == CONST_INT
01339 && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
01340 && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
01341 }
01342
01343
01344
01345
01346 int
01347 logical_operand (op, mode)
01348 rtx op;
01349 enum machine_mode mode;
01350 {
01351 HOST_WIDE_INT opl, oph;
01352
01353 if (gpc_reg_operand (op, mode))
01354 return 1;
01355
01356 if (GET_CODE (op) == CONST_INT)
01357 {
01358 opl = INTVAL (op) & GET_MODE_MASK (mode);
01359
01360 #if HOST_BITS_PER_WIDE_INT <= 32
01361 if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT && opl < 0)
01362 return 0;
01363 #endif
01364 }
01365 else if (GET_CODE (op) == CONST_DOUBLE)
01366 {
01367 if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
01368 abort ();
01369
01370 opl = CONST_DOUBLE_LOW (op);
01371 oph = CONST_DOUBLE_HIGH (op);
01372 if (oph != 0)
01373 return 0;
01374 }
01375 else
01376 return 0;
01377
01378 return ((opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0
01379 || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff0000) == 0);
01380 }
01381
01382
01383
01384
01385 int
01386 non_logical_cint_operand (op, mode)
01387 rtx op;
01388 enum machine_mode mode;
01389 {
01390 return ((GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
01391 && ! logical_operand (op, mode)
01392 && reg_or_logical_cint_operand (op, mode));
01393 }
01394
01395
01396
01397
01398
01399
01400 int
01401 mask_operand (op, mode)
01402 rtx op;
01403 enum machine_mode mode ATTRIBUTE_UNUSED;
01404 {
01405 HOST_WIDE_INT c, lsb;
01406
01407 if (GET_CODE (op) != CONST_INT)
01408 return 0;
01409
01410 c = INTVAL (op);
01411
01412
01413
01414 if (TARGET_POWERPC64 && (c & 0x80000001) == 0x80000001)
01415 return 0;
01416
01417
01418
01419 if (c & 1)
01420 c = ~c;
01421
01422
01423 if (c == 0)
01424 return 0;
01425
01426
01427 lsb = c & -c;
01428
01429
01430 c = ~c;
01431
01432
01433 c &= -lsb;
01434
01435
01436 lsb = c & -c;
01437
01438
01439 return c == -lsb;
01440 }
01441
01442
01443
01444
01445
01446
01447 int
01448 mask64_operand (op, mode)
01449 rtx op;
01450 enum machine_mode mode;
01451 {
01452 if (GET_CODE (op) == CONST_INT)
01453 {
01454 HOST_WIDE_INT c, lsb;
01455
01456
01457
01458 c = INTVAL (op);
01459 if (c & 1)
01460 c = ~c;
01461
01462
01463 if (c == 0)
01464 return 0;
01465
01466
01467 lsb = c & -c;
01468 return c == -lsb;
01469 }
01470 else if (GET_CODE (op) == CONST_DOUBLE
01471 && (mode == VOIDmode || mode == DImode))
01472 {
01473 HOST_WIDE_INT low, high, lsb;
01474
01475 if (HOST_BITS_PER_WIDE_INT < 64)
01476 high = CONST_DOUBLE_HIGH (op);
01477
01478 low = CONST_DOUBLE_LOW (op);
01479 if (low & 1)
01480 {
01481 if (HOST_BITS_PER_WIDE_INT < 64)
01482 high = ~high;
01483 low = ~low;
01484 }
01485
01486 if (low == 0)
01487 {
01488 if (HOST_BITS_PER_WIDE_INT >= 64 || high == 0)
01489 return 0;
01490
01491 lsb = high & -high;
01492 return high == -lsb;
01493 }
01494
01495 lsb = low & -low;
01496 return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0);
01497 }
01498 else
01499 return 0;
01500 }
01501
01502
01503
01504
01505 int
01506 and64_operand (op, mode)
01507 rtx op;
01508 enum machine_mode mode;
01509 {
01510 if (fixed_regs[CR0_REGNO])
01511 return (gpc_reg_operand (op, mode) || mask64_operand (op, mode));
01512
01513 return (logical_operand (op, mode) || mask64_operand (op, mode));
01514 }
01515
01516
01517
01518
01519 int
01520 and_operand (op, mode)
01521 rtx op;
01522 enum machine_mode mode;
01523 {
01524 if (fixed_regs[CR0_REGNO])
01525 return (gpc_reg_operand (op, mode) || mask_operand (op, mode));
01526
01527 return (logical_operand (op, mode) || mask_operand (op, mode));
01528 }
01529
01530
01531
01532 int
01533 reg_or_mem_operand (op, mode)
01534 rtx op;
01535 enum machine_mode mode;
01536 {
01537 return (gpc_reg_operand (op, mode)
01538 || memory_operand (op, mode)
01539 || volatile_mem_operand (op, mode));
01540 }
01541
01542
01543
01544
01545
01546 int
01547 lwa_operand (op, mode)
01548 rtx op;
01549 enum machine_mode mode;
01550 {
01551 rtx inner = op;
01552
01553 if (reload_completed && GET_CODE (inner) == SUBREG)
01554 inner = SUBREG_REG (inner);
01555
01556 return gpc_reg_operand (inner, mode)
01557 || (memory_operand (inner, mode)
01558 && GET_CODE (XEXP (inner, 0)) != PRE_INC
01559 && GET_CODE (XEXP (inner, 0)) != PRE_DEC
01560 && (GET_CODE (XEXP (inner, 0)) != PLUS
01561 || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT
01562 || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
01563 }
01564
01565
01566
01567
01568
01569 int
01570 call_operand (op, mode)
01571 rtx op;
01572 enum machine_mode mode;
01573 {
01574 if (mode != VOIDmode && GET_MODE (op) != mode)
01575 return 0;
01576
01577 return (GET_CODE (op) == SYMBOL_REF
01578 || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER));
01579 }
01580
01581
01582
01583
01584 int
01585 current_file_function_operand (op, mode)
01586 rtx op;
01587 enum machine_mode mode ATTRIBUTE_UNUSED;
01588 {
01589 return (GET_CODE (op) == SYMBOL_REF
01590 && (SYMBOL_REF_FLAG (op)
01591 || (op == XEXP (DECL_RTL (current_function_decl), 0)
01592 && ! DECL_WEAK (current_function_decl))));
01593 }
01594
01595
01596
01597 int
01598 input_operand (op, mode)
01599 rtx op;
01600 enum machine_mode mode;
01601 {
01602
01603 if (memory_operand (op, mode))
01604 return 1;
01605
01606
01607 if (GET_CODE (op) == CONSTANT_P_RTX)
01608 return 1;
01609
01610
01611 if (GET_MODE_CLASS (mode) == MODE_FLOAT
01612 && CONSTANT_P (op)
01613 && easy_fp_constant (op, mode))
01614 return 1;
01615
01616
01617 if (GET_MODE_CLASS (mode) == MODE_INT
01618 && (GET_CODE (op) == CONST_INT
01619 || GET_CODE (op) == CONST_DOUBLE))
01620 return 1;
01621
01622
01623
01624 if (GET_MODE_CLASS (mode) == MODE_FLOAT
01625 || GET_MODE_SIZE (mode) > UNITS_PER_WORD)
01626 return register_operand (op, mode);
01627
01628
01629
01630
01631 if (register_operand (op, mode))
01632 return 1;
01633
01634
01635 if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op))
01636 return 1;
01637
01638
01639 if (TOC_RELATIVE_EXPR_P (op))
01640 return 1;
01641
01642
01643
01644 if (DEFAULT_ABI == ABI_V4
01645 && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)
01646 && small_data_operand (op, Pmode))
01647 return 1;
01648
01649 return 0;
01650 }
01651
01652
01653
01654 int
01655 small_data_operand (op, mode)
01656 rtx op ATTRIBUTE_UNUSED;
01657 enum machine_mode mode ATTRIBUTE_UNUSED;
01658 {
01659 #if TARGET_ELF
01660 rtx sym_ref;
01661
01662 if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)
01663 return 0;
01664
01665 if (DEFAULT_ABI != ABI_V4)
01666 return 0;
01667
01668 if (GET_CODE (op) == SYMBOL_REF)
01669 sym_ref = op;
01670
01671 else if (GET_CODE (op) != CONST
01672 || GET_CODE (XEXP (op, 0)) != PLUS
01673 || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF
01674 || GET_CODE (XEXP (XEXP (op, 0), 1)) != CONST_INT)
01675 return 0;
01676
01677 else
01678 {
01679 rtx sum = XEXP (op, 0);
01680 HOST_WIDE_INT summand;
01681
01682
01683
01684 summand = INTVAL (XEXP (sum, 1));
01685 if (summand < 0 || summand > g_switch_value)
01686 return 0;
01687
01688 sym_ref = XEXP (sum, 0);
01689 }
01690
01691 if (*XSTR (sym_ref, 0) != '@')
01692 return 0;
01693
01694 return 1;
01695
01696 #else
01697 return 0;
01698 #endif
01699 }
01700
01701 static int
01702 constant_pool_expr_1 (op, have_sym, have_toc)
01703 rtx op;
01704 int *have_sym;
01705 int *have_toc;
01706 {
01707 switch (GET_CODE(op))
01708 {
01709 case SYMBOL_REF:
01710 if (CONSTANT_POOL_ADDRESS_P (op))
01711 {
01712 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode))
01713 {
01714 *have_sym = 1;
01715 return 1;
01716 }
01717 else
01718 return 0;
01719 }
01720 else if (! strcmp (XSTR (op, 0), toc_label_name))
01721 {
01722 *have_toc = 1;
01723 return 1;
01724 }
01725 else
01726 return 0;
01727 case PLUS:
01728 case MINUS:
01729 return (constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc)
01730 && constant_pool_expr_1 (XEXP (op, 1), have_sym, have_toc));
01731 case CONST:
01732 return constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc);
01733 case CONST_INT:
01734 return 1;
01735 default:
01736 return 0;
01737 }
01738 }
01739
01740 int
01741 constant_pool_expr_p (op)
01742 rtx op;
01743 {
01744 int have_sym = 0;
01745 int have_toc = 0;
01746 return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym;
01747 }
01748
01749 int
01750 toc_relative_expr_p (op)
01751 rtx op;
01752 {
01753 int have_sym = 0;
01754 int have_toc = 0;
01755 return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc;
01756 }
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780 rtx
01781 rs6000_legitimize_address (x, oldx, mode)
01782 rtx x;
01783 rtx oldx ATTRIBUTE_UNUSED;
01784 enum machine_mode mode;
01785 {
01786 if (GET_CODE (x) == PLUS
01787 && GET_CODE (XEXP (x, 0)) == REG
01788 && GET_CODE (XEXP (x, 1)) == CONST_INT
01789 && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000)
01790 {
01791 HOST_WIDE_INT high_int, low_int;
01792 rtx sum;
01793 high_int = INTVAL (XEXP (x, 1)) & (~ (HOST_WIDE_INT) 0xffff);
01794 low_int = INTVAL (XEXP (x, 1)) & 0xffff;
01795 if (low_int & 0x8000)
01796 high_int += 0x10000, low_int |= ((HOST_WIDE_INT) -1) << 16;
01797 sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
01798 GEN_INT (high_int)), 0);
01799 return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
01800 }
01801 else if (GET_CODE (x) == PLUS
01802 && GET_CODE (XEXP (x, 0)) == REG
01803 && GET_CODE (XEXP (x, 1)) != CONST_INT
01804 && GET_MODE_NUNITS (mode) == 1
01805 && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || mode != DFmode)
01806 && (TARGET_POWERPC64 || mode != DImode)
01807 && mode != TImode)
01808 {
01809 return gen_rtx_PLUS (Pmode, XEXP (x, 0),
01810 force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
01811 }
01812 else if (ALTIVEC_VECTOR_MODE (mode))
01813 {
01814 rtx reg;
01815
01816
01817 if (GET_CODE (x) == PLUS)
01818 return gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
01819 force_reg (Pmode, XEXP (x, 1)));
01820
01821 reg = force_reg (Pmode, x);
01822 return reg;
01823 }
01824 else if (TARGET_ELF && TARGET_32BIT && TARGET_NO_TOC && ! flag_pic
01825 && GET_CODE (x) != CONST_INT
01826 && GET_CODE (x) != CONST_DOUBLE
01827 && CONSTANT_P (x)
01828 && GET_MODE_NUNITS (mode) == 1
01829 && (GET_MODE_BITSIZE (mode) <= 32
01830 || (TARGET_HARD_FLOAT && mode == DFmode)))
01831 {
01832 rtx reg = gen_reg_rtx (Pmode);
01833 emit_insn (gen_elf_high (reg, (x)));
01834 return gen_rtx_LO_SUM (Pmode, reg, (x));
01835 }
01836 else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
01837 && ! flag_pic
01838 && GET_CODE (x) != CONST_INT
01839 && GET_CODE (x) != CONST_DOUBLE
01840 && CONSTANT_P (x)
01841 && (TARGET_HARD_FLOAT || mode != DFmode)
01842 && mode != DImode
01843 && mode != TImode)
01844 {
01845 rtx reg = gen_reg_rtx (Pmode);
01846 emit_insn (gen_macho_high (reg, (x)));
01847 return gen_rtx_LO_SUM (Pmode, reg, (x));
01848 }
01849 else if (TARGET_TOC
01850 && CONSTANT_POOL_EXPR_P (x)
01851 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
01852 {
01853 return create_TOC_reference (x);
01854 }
01855 else
01856 return NULL_RTX;
01857 }
01858
01859
01860
01861
01862 #ifndef REG_MODE_OK_FOR_BASE_P
01863 #define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
01864 #endif
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879 rtx
01880 rs6000_legitimize_reload_address (x, mode, opnum, type, ind_levels, win)
01881 rtx x;
01882 enum machine_mode mode;
01883 int opnum;
01884 int type;
01885 int ind_levels ATTRIBUTE_UNUSED;
01886 int *win;
01887 {
01888
01889 if (GET_CODE (x) == PLUS
01890 && GET_CODE (XEXP (x, 0)) == PLUS
01891 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
01892 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01893 && GET_CODE (XEXP (x, 1)) == CONST_INT)
01894 {
01895 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01896 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01897 opnum, (enum reload_type)type);
01898 *win = 1;
01899 return x;
01900 }
01901
01902 #if TARGET_MACHO
01903 if (DEFAULT_ABI == ABI_DARWIN && flag_pic
01904 && GET_CODE (x) == LO_SUM
01905 && GET_CODE (XEXP (x, 0)) == PLUS
01906 && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx
01907 && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
01908 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == CONST
01909 && XEXP (XEXP (XEXP (x, 0), 1), 0) == XEXP (x, 1)
01910 && GET_CODE (XEXP (XEXP (x, 1), 0)) == MINUS
01911 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == SYMBOL_REF
01912 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == SYMBOL_REF)
01913 {
01914
01915
01916 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01917 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
01918 opnum, (enum reload_type)type);
01919 *win = 1;
01920 return x;
01921 }
01922 #endif
01923 if (GET_CODE (x) == PLUS
01924 && GET_CODE (XEXP (x, 0)) == REG
01925 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
01926 && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
01927 && GET_CODE (XEXP (x, 1)) == CONST_INT
01928 && !ALTIVEC_VECTOR_MODE (mode))
01929 {
01930 HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
01931 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
01932 HOST_WIDE_INT high
01933 = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
01934
01935
01936 if (high + low != val)
01937 {
01938 *win = 0;
01939 return x;
01940 }
01941
01942
01943
01944
01945 x = gen_rtx_PLUS (GET_MODE (x),
01946 gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
01947 GEN_INT (high)),
01948 GEN_INT (low));
01949
01950 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01951 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01952 opnum, (enum reload_type)type);
01953 *win = 1;
01954 return x;
01955 }
01956 #if TARGET_MACHO
01957 if (GET_CODE (x) == SYMBOL_REF
01958 && DEFAULT_ABI == ABI_DARWIN
01959 && !ALTIVEC_VECTOR_MODE (mode)
01960 && flag_pic)
01961 {
01962
01963 rtx offset = gen_rtx (CONST, Pmode,
01964 gen_rtx (MINUS, Pmode, x,
01965 gen_rtx (SYMBOL_REF, Pmode,
01966 machopic_function_base_name ())));
01967 x = gen_rtx (LO_SUM, GET_MODE (x),
01968 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
01969 gen_rtx (HIGH, Pmode, offset)), offset);
01970 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01971 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
01972 opnum, (enum reload_type)type);
01973 *win = 1;
01974 return x;
01975 }
01976 #endif
01977 if (TARGET_TOC
01978 && CONSTANT_POOL_EXPR_P (x)
01979 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
01980 {
01981 (x) = create_TOC_reference (x);
01982 *win = 1;
01983 return x;
01984 }
01985 *win = 0;
01986 return x;
01987 }
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006 int
02007 rs6000_legitimate_address (mode, x, reg_ok_strict)
02008 enum machine_mode mode;
02009 rtx x;
02010 int reg_ok_strict;
02011 {
02012 if (LEGITIMATE_INDIRECT_ADDRESS_P (x, reg_ok_strict))
02013 return 1;
02014 if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
02015 && !ALTIVEC_VECTOR_MODE (mode)
02016 && TARGET_UPDATE
02017 && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (x, 0), reg_ok_strict))
02018 return 1;
02019 if (LEGITIMATE_SMALL_DATA_P (mode, x))
02020 return 1;
02021 if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (x))
02022 return 1;
02023
02024 if (! reg_ok_strict
02025 && GET_CODE (x) == PLUS
02026 && GET_CODE (XEXP (x, 0)) == REG
02027 && XEXP (x, 0) == virtual_stack_vars_rtx
02028 && GET_CODE (XEXP (x, 1)) == CONST_INT)
02029 return 1;
02030 if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, reg_ok_strict))
02031 return 1;
02032 if (mode != TImode
02033 && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || mode != DFmode)
02034 && (TARGET_POWERPC64 || mode != DImode)
02035 && LEGITIMATE_INDEXED_ADDRESS_P (x, reg_ok_strict))
02036 return 1;
02037 if (LEGITIMATE_LO_SUM_ADDRESS_P (mode, x, reg_ok_strict))
02038 return 1;
02039 return 0;
02040 }
02041
02042
02043
02044
02045
02046
02047
02048 rtx
02049 rs6000_emit_set_const (dest, mode, source, n)
02050 rtx dest, source;
02051 enum machine_mode mode;
02052 int n ATTRIBUTE_UNUSED;
02053 {
02054 HOST_WIDE_INT c0, c1;
02055
02056 if (mode == QImode || mode == HImode || mode == SImode)
02057 {
02058 if (dest == NULL)
02059 dest = gen_reg_rtx (mode);
02060 emit_insn (gen_rtx_SET (VOIDmode, dest, source));
02061 return dest;
02062 }
02063
02064 if (GET_CODE (source) == CONST_INT)
02065 {
02066 c0 = INTVAL (source);
02067 c1 = -(c0 < 0);
02068 }
02069 else if (GET_CODE (source) == CONST_DOUBLE)
02070 {
02071 #if HOST_BITS_PER_WIDE_INT >= 64
02072 c0 = CONST_DOUBLE_LOW (source);
02073 c1 = -(c0 < 0);
02074 #else
02075 c0 = CONST_DOUBLE_LOW (source);
02076 c1 = CONST_DOUBLE_HIGH (source);
02077 #endif
02078 }
02079 else
02080 abort ();
02081
02082 return rs6000_emit_set_long_const (dest, c0, c1);
02083 }
02084
02085
02086
02087
02088
02089 static rtx
02090 rs6000_emit_set_long_const (dest, c1, c2)
02091 rtx dest;
02092 HOST_WIDE_INT c1, c2;
02093 {
02094 if (!TARGET_POWERPC64)
02095 {
02096 rtx operand1, operand2;
02097
02098 operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0,
02099 DImode);
02100 operand2 = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,
02101 DImode);
02102 emit_move_insn (operand1, GEN_INT (c1));
02103 emit_move_insn (operand2, GEN_INT (c2));
02104 }
02105 else
02106 {
02107 HOST_WIDE_INT ud1, ud2, ud3, ud4;
02108
02109 ud1 = c1 & 0xffff;
02110 ud2 = (c1 & 0xffff0000) >> 16;
02111 #if HOST_BITS_PER_WIDE_INT >= 64
02112 c2 = c1 >> 32;
02113 #endif
02114 ud3 = c2 & 0xffff;
02115 ud4 = (c2 & 0xffff0000) >> 16;
02116
02117 if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
02118 || (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))
02119 {
02120 if (ud1 & 0x8000)
02121 emit_move_insn (dest, GEN_INT (((ud1 ^ 0x8000) - 0x8000)));
02122 else
02123 emit_move_insn (dest, GEN_INT (ud1));
02124 }
02125
02126 else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
02127 || (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))
02128 {
02129 if (ud2 & 0x8000)
02130 emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
02131 - 0x80000000));
02132 else
02133 emit_move_insn (dest, GEN_INT (ud2 << 16));
02134 if (ud1 != 0)
02135 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
02136 }
02137 else if ((ud4 == 0xffff && (ud3 & 0x8000))
02138 || (ud4 == 0 && ! (ud3 & 0x8000)))
02139 {
02140 if (ud3 & 0x8000)
02141 emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000)
02142 - 0x80000000));
02143 else
02144 emit_move_insn (dest, GEN_INT (ud3 << 16));
02145
02146 if (ud2 != 0)
02147 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud2)));
02148 emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (16)));
02149 if (ud1 != 0)
02150 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
02151 }
02152 else
02153 {
02154 if (ud4 & 0x8000)
02155 emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000)
02156 - 0x80000000));
02157 else
02158 emit_move_insn (dest, GEN_INT (ud4 << 16));
02159
02160 if (ud3 != 0)
02161 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud3)));
02162
02163 emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (32)));
02164 if (ud2 != 0)
02165 emit_move_insn (dest, gen_rtx_IOR (DImode, dest,
02166 GEN_INT (ud2 << 16)));
02167 if (ud1 != 0)
02168 emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
02169 }
02170 }
02171 return dest;
02172 }
02173
02174
02175 void
02176 rs6000_emit_move (dest, source, mode)
02177 rtx dest;
02178 rtx source;
02179 enum machine_mode mode;
02180 {
02181 rtx operands[2];
02182 operands[0] = dest;
02183 operands[1] = source;
02184
02185
02186 if (GET_CODE (operands[1]) == CONST_DOUBLE
02187 && ! FLOAT_MODE_P (mode)
02188 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
02189 {
02190
02191
02192
02193 operands[1] =
02194 GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (operands[1]), mode));
02195 }
02196 if (GET_CODE (operands[1]) == CONST_DOUBLE
02197 && ! FLOAT_MODE_P (mode)
02198 && ((CONST_DOUBLE_HIGH (operands[1]) == 0
02199 && CONST_DOUBLE_LOW (operands[1]) >= 0)
02200 || (CONST_DOUBLE_HIGH (operands[1]) == -1
02201 && CONST_DOUBLE_LOW (operands[1]) < 0)))
02202 abort ();
02203
02204
02205
02206 if (GET_CODE (operands[0]) == MEM
02207 && GET_CODE (operands[1]) == MEM
02208 && mode == DImode
02209 && (SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[0]))
02210 || SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[1])))
02211 && ! (SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[0]) > 32
02212 ? 32 : MEM_ALIGN (operands[0])))
02213 || SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[1]) > 32
02214 ? 32
02215 : MEM_ALIGN (operands[1]))))
02216 && ! MEM_VOLATILE_P (operands [0])
02217 && ! MEM_VOLATILE_P (operands [1]))
02218 {
02219 emit_move_insn (adjust_address (operands[0], SImode, 0),
02220 adjust_address (operands[1], SImode, 0));
02221 emit_move_insn (adjust_address (operands[0], SImode, 4),
02222 adjust_address (operands[1], SImode, 4));
02223 return;
02224 }
02225
02226 if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
02227 operands[1] = force_reg (mode, operands[1]);
02228
02229 if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT
02230 && GET_CODE (operands[0]) == MEM)
02231 {
02232 int regnum;
02233
02234 if (reload_in_progress || reload_completed)
02235 regnum = true_regnum (operands[1]);
02236 else if (GET_CODE (operands[1]) == REG)
02237 regnum = REGNO (operands[1]);
02238 else
02239 regnum = -1;
02240
02241
02242
02243
02244 if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER)
02245 {
02246 rtx newreg;
02247 newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (mode));
02248 emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));
02249 operands[1] = newreg;
02250 }
02251 }
02252
02253
02254
02255 if (!VECTOR_MODE_P (mode)
02256 && (! general_operand (operands[1], mode)
02257 || ! nonimmediate_operand (operands[0], mode)
02258 || GET_CODE (operands[1]) == CONSTANT_P_RTX))
02259 {
02260 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
02261 return;
02262 }
02263
02264
02265
02266
02267 switch (mode)
02268 {
02269 case HImode:
02270 case QImode:
02271 if (CONSTANT_P (operands[1])
02272 && GET_CODE (operands[1]) != CONST_INT)
02273 operands[1] = force_const_mem (mode, operands[1]);
02274 break;
02275
02276 case TFmode:
02277 case DFmode:
02278 case SFmode:
02279 if (CONSTANT_P (operands[1])
02280 && ! easy_fp_constant (operands[1], mode))
02281 operands[1] = force_const_mem (mode, operands[1]);
02282 break;
02283
02284 case V16QImode:
02285 case V8HImode:
02286 case V4SFmode:
02287 case V4SImode:
02288 if (CONSTANT_P (operands[1])
02289 && !easy_vector_constant (operands[1]))
02290 operands[1] = force_const_mem (mode, operands[1]);
02291 break;
02292
02293 case SImode:
02294 case DImode:
02295
02296 if (TARGET_ELF
02297 && mode == Pmode
02298 && DEFAULT_ABI == ABI_V4
02299 && (GET_CODE (operands[1]) == SYMBOL_REF
02300 || GET_CODE (operands[1]) == CONST)
02301 && small_data_operand (operands[1], mode))
02302 {
02303 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
02304 return;
02305 }
02306
02307 if (DEFAULT_ABI == ABI_V4
02308 && mode == Pmode && mode == SImode
02309 && flag_pic == 1 && got_operand (operands[1], mode))
02310 {
02311 emit_insn (gen_movsi_got (operands[0], operands[1]));
02312 return;
02313 }
02314
02315 if ((TARGET_ELF || DEFAULT_ABI == ABI_DARWIN)
02316 && TARGET_NO_TOC && ! flag_pic
02317 && mode == Pmode
02318 && CONSTANT_P (operands[1])
02319 && GET_CODE (operands[1]) != HIGH
02320 && GET_CODE (operands[1]) != CONST_INT)
02321 {
02322 rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (mode));
02323
02324
02325
02326 if (DEFAULT_ABI == ABI_AIX
02327 && GET_CODE (operands[1]) == SYMBOL_REF
02328 && XSTR (operands[1], 0)[0] == '.')
02329 {
02330 const char *name = XSTR (operands[1], 0);
02331 rtx new_ref;
02332 while (*name == '.')
02333 name++;
02334 new_ref = gen_rtx_SYMBOL_REF (Pmode, name);
02335 CONSTANT_POOL_ADDRESS_P (new_ref)
02336 = CONSTANT_POOL_ADDRESS_P (operands[1]);
02337 SYMBOL_REF_FLAG (new_ref) = SYMBOL_REF_FLAG (operands[1]);
02338 SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
02339 operands[1] = new_ref;
02340 }
02341
02342 if (DEFAULT_ABI == ABI_DARWIN)
02343 {
02344 emit_insn (gen_macho_high (target, operands[1]));
02345 emit_insn (gen_macho_low (operands[0], target, operands[1]));
02346 return;
02347 }
02348
02349 emit_insn (gen_elf_high (target, operands[1]));
02350 emit_insn (gen_elf_low (operands[0], target, operands[1]));
02351 return;
02352 }
02353
02354
02355
02356
02357 if (TARGET_TOC
02358 && GET_CODE (operands[1]) == SYMBOL_REF
02359 && CONSTANT_POOL_EXPR_P (operands[1])
02360 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
02361 get_pool_mode (operands[1])))
02362 {
02363 operands[1] = create_TOC_reference (operands[1]);
02364 }
02365 else if (mode == Pmode
02366 && CONSTANT_P (operands[1])
02367 && ((GET_CODE (operands[1]) != CONST_INT
02368 && ! easy_fp_constant (operands[1], mode))
02369 || (GET_CODE (operands[1]) == CONST_INT
02370 && num_insns_constant (operands[1], mode) > 2)
02371 || (GET_CODE (operands[0]) == REG
02372 && FP_REGNO_P (REGNO (operands[0]))))
02373 && GET_CODE (operands[1]) != HIGH
02374 && ! LEGITIMATE_CONSTANT_POOL_ADDRESS_P (operands[1])
02375 && ! TOC_RELATIVE_EXPR_P (operands[1]))
02376 {
02377
02378
02379
02380
02381
02382
02383 if (GET_CODE (operands[1]) != LABEL_REF)
02384 emit_insn (gen_rtx_USE (VOIDmode, operands[1]));
02385
02386 #if TARGET_MACHO
02387
02388 if (DEFAULT_ABI == ABI_DARWIN && flag_pic)
02389 {
02390 operands[1] =
02391 rs6000_machopic_legitimize_pic_address (operands[1], mode,
02392 operands[0]);
02393 if (operands[0] != operands[1])
02394 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
02395 return;
02396 }
02397 #endif
02398
02399
02400
02401
02402
02403 if (GET_CODE (operands[1]) == CONST
02404 && TARGET_NO_SUM_IN_TOC && ! reload_in_progress
02405 && GET_CODE (XEXP (operands[1], 0)) == PLUS
02406 && add_operand (XEXP (XEXP (operands[1], 0), 1), mode)
02407 && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
02408 || GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
02409 && ! side_effects_p (operands[0]))
02410 {
02411 rtx sym =
02412 force_const_mem (mode, XEXP (XEXP (operands[1], 0), 0));
02413 rtx other = XEXP (XEXP (operands[1], 0), 1);
02414
02415 sym = force_reg (mode, sym);
02416 if (mode == SImode)
02417 emit_insn (gen_addsi3 (operands[0], sym, other));
02418 else
02419 emit_insn (gen_adddi3 (operands[0], sym, other));
02420 return;
02421 }
02422
02423 operands[1] = force_const_mem (mode, operands[1]);
02424
02425 if (TARGET_TOC
02426 && CONSTANT_POOL_EXPR_P (XEXP (operands[1], 0))
02427 && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (
02428 get_pool_constant (XEXP (operands[1], 0)),
02429 get_pool_mode (XEXP (operands[1], 0))))
02430 {
02431 operands[1]
02432 = gen_rtx_MEM (mode,
02433 create_TOC_reference (XEXP (operands[1], 0)));
02434 set_mem_alias_set (operands[1], get_TOC_alias_set ());
02435 RTX_UNCHANGING_P (operands[1]) = 1;
02436 }
02437 }
02438 break;
02439
02440 case TImode:
02441 if (GET_CODE (operands[0]) == MEM
02442 && GET_CODE (XEXP (operands[0], 0)) != REG
02443 && ! reload_in_progress)
02444 operands[0]
02445 = replace_equiv_address (operands[0],
02446 copy_addr_to_reg (XEXP (operands[0], 0)));
02447
02448 if (GET_CODE (operands[1]) == MEM
02449 && GET_CODE (XEXP (operands[1], 0)) != REG
02450 && ! reload_in_progress)
02451 operands[1]
02452 = replace_equiv_address (operands[1],
02453 copy_addr_to_reg (XEXP (operands[1], 0)));
02454 break;
02455
02456 default:
02457 abort ();
02458 }
02459
02460
02461
02462
02463 if (GET_CODE (operands[1]) == MEM
02464 && ! memory_address_p (mode, XEXP (operands[1], 0))
02465 && ! reload_in_progress)
02466 operands[1] = adjust_address (operands[1], mode, 0);
02467
02468 emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
02469 return;
02470 }
02471
02472
02473
02474
02475
02476
02477
02478
02479 void
02480 init_cumulative_args (cum, fntype, libname, incoming)
02481 CUMULATIVE_ARGS *cum;
02482 tree fntype;
02483 rtx libname ATTRIBUTE_UNUSED;
02484 int incoming;
02485 {
02486 static CUMULATIVE_ARGS zero_cumulative;
02487
02488 *cum = zero_cumulative;
02489 cum->words = 0;
02490 cum->fregno = FP_ARG_MIN_REG;
02491 cum->vregno = ALTIVEC_ARG_MIN_REG;
02492 cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
02493 cum->call_cookie = CALL_NORMAL;
02494 cum->sysv_gregno = GP_ARG_MIN_REG;
02495
02496 if (incoming)
02497 cum->nargs_prototype = 1000;
02498
02499 else if (cum->prototype)
02500 cum->nargs_prototype = (list_length (TYPE_ARG_TYPES (fntype)) - 1
02501 + (TYPE_MODE (TREE_TYPE (fntype)) == BLKmode
02502 || RETURN_IN_MEMORY (TREE_TYPE (fntype))));
02503
02504 else
02505 cum->nargs_prototype = 0;
02506
02507 cum->orig_nargs = cum->nargs_prototype;
02508
02509
02510 if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
02511 cum->call_cookie = CALL_LONG;
02512
02513 if (TARGET_DEBUG_ARG)
02514 {
02515 fprintf (stderr, "\ninit_cumulative_args:");
02516 if (fntype)
02517 {
02518 tree ret_type = TREE_TYPE (fntype);
02519 fprintf (stderr, " ret code = %s,",
02520 tree_code_name[ (int)TREE_CODE (ret_type) ]);
02521 }
02522
02523 if (cum->call_cookie & CALL_LONG)
02524 fprintf (stderr, " longcall,");
02525
02526 fprintf (stderr, " proto = %d, nargs = %d\n",
02527 cum->prototype, cum->nargs_prototype);
02528 }
02529 }
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540 enum direction
02541 function_arg_padding (mode, type)
02542 enum machine_mode mode;
02543 tree type;
02544 {
02545 if (type != 0 && AGGREGATE_TYPE_P (type))
02546 return upward;
02547
02548
02549 return (! BYTES_BIG_ENDIAN
02550 ? upward
02551 : ((mode == BLKmode
02552 ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
02553 && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
02554 : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
02555 ? downward : upward));
02556 }
02557
02558
02559
02560
02561
02562
02563
02564 int
02565 function_arg_boundary (mode, type)
02566 enum machine_mode mode;
02567 tree type ATTRIBUTE_UNUSED;
02568 {
02569 if (DEFAULT_ABI == ABI_V4 && (mode == DImode || mode == DFmode))
02570 return 64;
02571 else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
02572 return 128;
02573 else
02574 return PARM_BOUNDARY;
02575 }
02576
02577
02578
02579
02580
02581 void
02582 function_arg_advance (cum, mode, type, named)
02583 CUMULATIVE_ARGS *cum;
02584 enum machine_mode mode;
02585 tree type;
02586 int named;
02587 {
02588 cum->nargs_prototype--;
02589
02590 if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
02591 {
02592 if (cum->vregno <= ALTIVEC_ARG_MAX_REG && cum->nargs_prototype >= 0)
02593 cum->vregno++;
02594 else
02595 cum->words += RS6000_ARG_SIZE (mode, type);
02596 }
02597 else if (DEFAULT_ABI == ABI_V4)
02598 {
02599 if (TARGET_HARD_FLOAT
02600 && (mode == SFmode || mode == DFmode))
02601 {
02602 if (cum->fregno <= FP_ARG_V4_MAX_REG)
02603 cum->fregno++;
02604 else
02605 {
02606 if (mode == DFmode)
02607 cum->words += cum->words & 1;
02608 cum->words += RS6000_ARG_SIZE (mode, type);
02609 }
02610 }
02611 else
02612 {
02613 int n_words;
02614 int gregno = cum->sysv_gregno;
02615
02616
02617 if ((type && AGGREGATE_TYPE_P (type))
02618 || mode == TFmode)
02619 n_words = 1;
02620 else
02621 n_words = RS6000_ARG_SIZE (mode, type);
02622
02623
02624 if (n_words == 2 && (gregno & 1) == 0)
02625 gregno += 1;
02626
02627
02628 if (gregno + n_words - 1 > GP_ARG_MAX_REG)
02629 {
02630
02631 if (n_words == 2)
02632 cum->words += cum->words & 1;
02633 cum->words += n_words;
02634 }
02635
02636
02637
02638
02639 cum->sysv_gregno = gregno + n_words;
02640 }
02641
02642 if (TARGET_DEBUG_ARG)
02643 {
02644 fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ",
02645 cum->words, cum->fregno);
02646 fprintf (stderr, "gregno = %2d, nargs = %4d, proto = %d, ",
02647 cum->sysv_gregno, cum->nargs_prototype, cum->prototype);
02648 fprintf (stderr, "mode = %4s, named = %d\n",
02649 GET_MODE_NAME (mode), named);
02650 }
02651 }
02652 else
02653 {
02654 int align = (TARGET_32BIT && (cum->words & 1) != 0
02655 && function_arg_boundary (mode, type) == 64) ? 1 : 0;
02656
02657 cum->words += align + RS6000_ARG_SIZE (mode, type);
02658
02659 if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_HARD_FLOAT)
02660 cum->fregno++;
02661
02662 if (TARGET_DEBUG_ARG)
02663 {
02664 fprintf (stderr, "function_adv: words = %2d, fregno = %2d, ",
02665 cum->words, cum->fregno);
02666 fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s, ",
02667 cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode));
02668 fprintf (stderr, "named = %d, align = %d\n", named, align);
02669 }
02670 }
02671 }
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696 struct rtx_def *
02697 function_arg (cum, mode, type, named)
02698 CUMULATIVE_ARGS *cum;
02699 enum machine_mode mode;
02700 tree type;
02701 int named;
02702 {
02703 enum rs6000_abi abi = DEFAULT_ABI;
02704
02705
02706
02707
02708
02709 if (mode == VOIDmode)
02710 {
02711 if (abi == ABI_V4
02712 && TARGET_HARD_FLOAT
02713 && cum->nargs_prototype < 0
02714 && type && (cum->prototype || TARGET_NO_PROTOTYPE))
02715 {
02716 return GEN_INT (cum->call_cookie
02717 | ((cum->fregno == FP_ARG_MIN_REG)
02718 ? CALL_V4_SET_FP_ARGS
02719 : CALL_V4_CLEAR_FP_ARGS));
02720 }
02721
02722 return GEN_INT (cum->call_cookie);
02723 }
02724
02725 if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
02726 {
02727 if (named && cum->vregno <= ALTIVEC_ARG_MAX_REG)
02728 return gen_rtx_REG (mode, cum->vregno);
02729 else
02730 return NULL;
02731 }
02732 else if (abi == ABI_V4)
02733 {
02734 if (TARGET_HARD_FLOAT
02735 && (mode == SFmode || mode == DFmode))
02736 {
02737 if (cum->fregno <= FP_ARG_V4_MAX_REG)
02738 return gen_rtx_REG (mode, cum->fregno);
02739 else
02740 return NULL;
02741 }
02742 else
02743 {
02744 int n_words;
02745 int gregno = cum->sysv_gregno;
02746
02747
02748 if ((type && AGGREGATE_TYPE_P (type))
02749 || mode == TFmode)
02750 n_words = 1;
02751 else
02752 n_words = RS6000_ARG_SIZE (mode, type);
02753
02754
02755 if (n_words == 2 && (gregno & 1) == 0)
02756 gregno += 1;
02757
02758
02759 if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
02760 return gen_rtx_REG (mode, gregno);
02761 else
02762 return NULL;
02763 }
02764 }
02765 else
02766 {
02767 int align = (TARGET_32BIT && (cum->words & 1) != 0
02768 && function_arg_boundary (mode, type) == 64) ? 1 : 0;
02769 int align_words = cum->words + align;
02770
02771 if (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
02772 return NULL_RTX;
02773
02774 if (USE_FP_FOR_ARG_P (*cum, mode, type))
02775 {
02776 if (! type
02777 || ((cum->nargs_prototype > 0)
02778
02779
02780
02781 && (DEFAULT_ABI != ABI_AIX
02782 || ! TARGET_XL_CALL
02783 || (align_words < GP_ARG_NUM_REG))))
02784 return gen_rtx_REG (mode, cum->fregno);
02785
02786 return gen_rtx_PARALLEL (mode,
02787 gen_rtvec (2,
02788 gen_rtx_EXPR_LIST (VOIDmode,
02789 ((align_words >= GP_ARG_NUM_REG)
02790 ? NULL_RTX
02791 : (align_words
02792 + RS6000_ARG_SIZE (mode, type)
02793 > GP_ARG_NUM_REG
02794
02795
02796
02797 ? gen_rtx_REG (SImode,
02798 GP_ARG_MIN_REG + align_words)
02799 : gen_rtx_REG (mode,
02800 GP_ARG_MIN_REG + align_words))),
02801 const0_rtx),
02802 gen_rtx_EXPR_LIST (VOIDmode,
02803 gen_rtx_REG (mode, cum->fregno),
02804 const0_rtx)));
02805 }
02806 else if (align_words < GP_ARG_NUM_REG)
02807 return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
02808 else
02809 return NULL_RTX;
02810 }
02811 }
02812
02813
02814
02815
02816
02817 int
02818 function_arg_partial_nregs (cum, mode, type, named)
02819 CUMULATIVE_ARGS *cum;
02820 enum machine_mode mode;
02821 tree type;
02822 int named ATTRIBUTE_UNUSED;
02823 {
02824 if (DEFAULT_ABI == ABI_V4)
02825 return 0;
02826
02827 if (USE_FP_FOR_ARG_P (*cum, mode, type)
02828 || USE_ALTIVEC_FOR_ARG_P (*cum, mode, type))
02829 {
02830 if (cum->nargs_prototype >= 0)
02831 return 0;
02832 }
02833
02834 if (cum->words < GP_ARG_NUM_REG
02835 && GP_ARG_NUM_REG < (cum->words + RS6000_ARG_SIZE (mode, type)))
02836 {
02837 int ret = GP_ARG_NUM_REG - cum->words;
02838 if (ret && TARGET_DEBUG_ARG)
02839 fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
02840
02841 return ret;
02842 }
02843
02844 return 0;
02845 }
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855 int
02856 function_arg_pass_by_reference (cum, mode, type, named)
02857 CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
02858 enum machine_mode mode ATTRIBUTE_UNUSED;
02859 tree type;
02860 int named ATTRIBUTE_UNUSED;
02861 {
02862 if (DEFAULT_ABI == ABI_V4
02863 && ((type && AGGREGATE_TYPE_P (type))
02864 || mode == TFmode))
02865 {
02866 if (TARGET_DEBUG_ARG)
02867 fprintf (stderr, "function_arg_pass_by_reference: aggregate\n");
02868
02869 return 1;
02870 }
02871
02872 return 0;
02873 }
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889 void
02890 setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
02891 CUMULATIVE_ARGS *cum;
02892 enum machine_mode mode;
02893 tree type;
02894 int *pretend_size;
02895 int no_rtl;
02896
02897 {
02898 CUMULATIVE_ARGS next_cum;
02899 int reg_size = TARGET_32BIT ? 4 : 8;
02900 rtx save_area = NULL_RTX, mem;
02901 int first_reg_offset, set;
02902 tree fntype;
02903 int stdarg_p;
02904
02905 fntype = TREE_TYPE (current_function_decl);
02906 stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
02907 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
02908 != void_type_node));
02909
02910
02911
02912 next_cum = *cum;
02913 if (stdarg_p)
02914 function_arg_advance (&next_cum, mode, type, 1);
02915
02916 if (DEFAULT_ABI == ABI_V4)
02917 {
02918
02919
02920
02921 cfun->machine->sysv_varargs_p = 1;
02922 if (! no_rtl)
02923 save_area = plus_constant (virtual_stack_vars_rtx,
02924 - RS6000_VARARGS_SIZE);
02925
02926 first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG;
02927 }
02928 else
02929 {
02930 first_reg_offset = next_cum.words;
02931 save_area = virtual_incoming_args_rtx;
02932 cfun->machine->sysv_varargs_p = 0;
02933
02934 if (MUST_PASS_IN_STACK (mode, type))
02935 first_reg_offset += RS6000_ARG_SIZE (TYPE_MODE (type), type);
02936 }
02937
02938 set = get_varargs_alias_set ();
02939 if (! no_rtl && first_reg_offset < GP_ARG_NUM_REG)
02940 {
02941 mem = gen_rtx_MEM (BLKmode,
02942 plus_constant (save_area,
02943 first_reg_offset * reg_size)),
02944 set_mem_alias_set (mem, set);
02945 set_mem_align (mem, BITS_PER_WORD);
02946
02947 move_block_from_reg
02948 (GP_ARG_MIN_REG + first_reg_offset, mem,
02949 GP_ARG_NUM_REG - first_reg_offset,
02950 (GP_ARG_NUM_REG - first_reg_offset) * UNITS_PER_WORD);
02951
02952
02953 *pretend_size = (GP_ARG_NUM_REG - first_reg_offset) * UNITS_PER_WORD;
02954 }
02955
02956
02957 if (DEFAULT_ABI == ABI_V4
02958 && TARGET_HARD_FLOAT && ! no_rtl
02959 && next_cum.fregno <= FP_ARG_V4_MAX_REG)
02960 {
02961 int fregno = next_cum.fregno;
02962 rtx cr1 = gen_rtx_REG (CCmode, CR1_REGNO);
02963 rtx lab = gen_label_rtx ();
02964 int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG) * 8);
02965
02966 emit_jump_insn (gen_rtx_SET (VOIDmode,
02967 pc_rtx,
02968 gen_rtx_IF_THEN_ELSE (VOIDmode,
02969 gen_rtx_NE (VOIDmode, cr1,
02970 const0_rtx),
02971 gen_rtx_LABEL_REF (VOIDmode, lab),
02972 pc_rtx)));
02973
02974 while (fregno <= FP_ARG_V4_MAX_REG)
02975 {
02976 mem = gen_rtx_MEM (DFmode, plus_constant (save_area, off));
02977 set_mem_alias_set (mem, set);
02978 emit_move_insn (mem, gen_rtx_REG (DFmode, fregno));
02979 fregno++;
02980 off += 8;
02981 }
02982
02983 emit_label (lab);
02984 }
02985 }
02986
02987
02988
02989 tree
02990 rs6000_build_va_list ()
02991 {
02992 tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
02993
02994
02995
02996 if (DEFAULT_ABI != ABI_V4)
02997 return build_pointer_type (char_type_node);
02998
02999 record = make_lang_type (RECORD_TYPE);
03000 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
03001
03002 f_gpr = build_decl (FIELD_DECL, get_identifier ("gpr"),
03003 unsigned_char_type_node);
03004 f_fpr = build_decl (FIELD_DECL, get_identifier ("fpr"),
03005 unsigned_char_type_node);
03006 f_ovf = build_decl (FIELD_DECL, get_identifier ("overflow_arg_area"),
03007 ptr_type_node);
03008 f_sav = build_decl (FIELD_DECL, get_identifier ("reg_save_area"),
03009 ptr_type_node);
03010
03011 DECL_FIELD_CONTEXT (f_gpr) = record;
03012 DECL_FIELD_CONTEXT (f_fpr) = record;
03013 DECL_FIELD_CONTEXT (f_ovf) = record;
03014 DECL_FIELD_CONTEXT (f_sav) = record;
03015
03016 TREE_CHAIN (record) = type_decl;
03017 TYPE_NAME (record) = type_decl;
03018 TYPE_FIELDS (record) = f_gpr;
03019 TREE_CHAIN (f_gpr) = f_fpr;
03020 TREE_CHAIN (f_fpr) = f_ovf;
03021 TREE_CHAIN (f_ovf) = f_sav;
03022
03023 layout_type (record);
03024
03025
03026 return build_array_type (record, build_index_type (size_zero_node));
03027 }
03028
03029
03030
03031 void
03032 rs6000_va_start (stdarg_p, valist, nextarg)
03033 int stdarg_p;
03034 tree valist;
03035 rtx nextarg;
03036 {
03037 HOST_WIDE_INT words, n_gpr, n_fpr;
03038 tree f_gpr, f_fpr, f_ovf, f_sav;
03039 tree gpr, fpr, ovf, sav, t;
03040
03041
03042 if (DEFAULT_ABI != ABI_V4)
03043 {
03044 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
03045 return;
03046 }
03047
03048 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
03049 f_fpr = TREE_CHAIN (f_gpr);
03050 f_ovf = TREE_CHAIN (f_fpr);
03051 f_sav = TREE_CHAIN (f_ovf);
03052
03053 valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
03054 gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
03055 fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
03056 ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
03057 sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
03058
03059
03060 words = current_function_args_info.words;
03061 n_gpr = current_function_args_info.sysv_gregno - GP_ARG_MIN_REG;
03062 n_fpr = current_function_args_info.fregno - FP_ARG_MIN_REG;
03063
03064 if (TARGET_DEBUG_ARG)
03065 {
03066 fputs ("va_start: words = ", stderr);
03067 fprintf (stderr, HOST_WIDE_INT_PRINT_DEC, words);
03068 fputs (", n_gpr = ", stderr);
03069 fprintf (stderr, HOST_WIDE_INT_PRINT_DEC, n_gpr);
03070 fputs (", n_fpr = ", stderr);
03071 fprintf (stderr, HOST_WIDE_INT_PRINT_DEC, n_fpr);
03072 putc ('\n', stderr);
03073 }
03074
03075 t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, build_int_2 (n_gpr, 0));
03076 TREE_SIDE_EFFECTS (t) = 1;
03077 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03078
03079 t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr, build_int_2 (n_fpr, 0));
03080 TREE_SIDE_EFFECTS (t) = 1;
03081 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03082
03083
03084 t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
03085 if (words != 0)
03086 t = build (PLUS_EXPR, TREE_TYPE (ovf), t,
03087 build_int_2 (words * UNITS_PER_WORD, 0));
03088 t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
03089 TREE_SIDE_EFFECTS (t) = 1;
03090 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03091
03092
03093 t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx);
03094 t = build (PLUS_EXPR, TREE_TYPE (sav), t,
03095 build_int_2 (-RS6000_VARARGS_SIZE, -1));
03096 t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
03097 TREE_SIDE_EFFECTS (t) = 1;
03098 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03099 }
03100
03101
03102
03103 rtx
03104 rs6000_va_arg (valist, type)
03105 tree valist, type;
03106 {
03107 tree f_gpr, f_fpr, f_ovf, f_sav;
03108 tree gpr, fpr, ovf, sav, reg, t, u;
03109 int indirect_p, size, rsize, n_reg, sav_ofs, sav_scale;
03110 rtx lab_false, lab_over, addr_rtx, r;
03111
03112
03113
03114
03115
03116
03117 if (DEFAULT_ABI != ABI_V4)
03118 return std_expand_builtin_va_arg (valist, type);
03119
03120 f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
03121 f_fpr = TREE_CHAIN (f_gpr);
03122 f_ovf = TREE_CHAIN (f_fpr);
03123 f_sav = TREE_CHAIN (f_ovf);
03124
03125 valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
03126 gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
03127 fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
03128 ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
03129 sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
03130
03131 size = int_size_in_bytes (type);
03132 rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03133
03134 if (AGGREGATE_TYPE_P (type) || TYPE_MODE (type) == TFmode)
03135 {
03136
03137 indirect_p = 1;
03138 reg = gpr;
03139 n_reg = 1;
03140 sav_ofs = 0;
03141 sav_scale = 4;
03142 size = UNITS_PER_WORD;
03143 rsize = 1;
03144 }
03145 else if (FLOAT_TYPE_P (type) && ! TARGET_SOFT_FLOAT)
03146 {
03147
03148 indirect_p = 0;
03149 reg = fpr;
03150 n_reg = 1;
03151 sav_ofs = 8*4;
03152 sav_scale = 8;
03153 }
03154 else
03155 {
03156
03157 indirect_p = 0;
03158 reg = gpr;
03159 n_reg = rsize;
03160 sav_ofs = 0;
03161 sav_scale = 4;
03162 }
03163
03164
03165
03166 lab_false = gen_label_rtx ();
03167 lab_over = gen_label_rtx ();
03168 addr_rtx = gen_reg_rtx (Pmode);
03169
03170
03171 if (TREE_CODE (type) != VECTOR_TYPE)
03172 {
03173 TREE_THIS_VOLATILE (reg) = 1;
03174 emit_cmp_and_jump_insns
03175 (expand_expr (reg, NULL_RTX, QImode, EXPAND_NORMAL),
03176 GEN_INT (8 - n_reg + 1), GE, const1_rtx, QImode, 1,
03177 lab_false);
03178
03179
03180 if (n_reg > 1)
03181 {
03182 u = build (BIT_AND_EXPR, TREE_TYPE (reg), reg,
03183 build_int_2 (n_reg - 1, 0));
03184 u = build (PLUS_EXPR, TREE_TYPE (reg), reg, u);
03185 u = build (MODIFY_EXPR, TREE_TYPE (reg), reg, u);
03186 TREE_SIDE_EFFECTS (u) = 1;
03187 expand_expr (u, const0_rtx, VOIDmode, EXPAND_NORMAL);
03188 }
03189
03190 if (sav_ofs)
03191 t = build (PLUS_EXPR, ptr_type_node, sav, build_int_2 (sav_ofs, 0));
03192 else
03193 t = sav;
03194
03195 u = build (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg,
03196 build_int_2 (n_reg, 0));
03197 TREE_SIDE_EFFECTS (u) = 1;
03198
03199 u = build1 (CONVERT_EXPR, integer_type_node, u);
03200 TREE_SIDE_EFFECTS (u) = 1;
03201
03202 u = build (MULT_EXPR, integer_type_node, u, build_int_2 (sav_scale, 0));
03203 TREE_SIDE_EFFECTS (u) = 1;
03204
03205 t = build (PLUS_EXPR, ptr_type_node, t, u);
03206 TREE_SIDE_EFFECTS (t) = 1;
03207
03208 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
03209 if (r != addr_rtx)
03210 emit_move_insn (addr_rtx, r);
03211
03212 emit_jump_insn (gen_jump (lab_over));
03213 emit_barrier ();
03214 }
03215
03216 emit_label (lab_false);
03217
03218
03219
03220
03221
03222
03223
03224
03225 if (n_reg > 1 && TREE_CODE (type) != VECTOR_TYPE)
03226 {
03227 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, build_int_2 (8, 0));
03228 TREE_SIDE_EFFECTS (t) = 1;
03229 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03230 }
03231
03232
03233 if (rsize <= 1)
03234 t = ovf;
03235 else
03236 {
03237 int align;
03238
03239
03240 if (TREE_CODE (type) == VECTOR_TYPE)
03241 align = 15;
03242 else
03243 align = 7;
03244
03245 t = build (PLUS_EXPR, TREE_TYPE (ovf), ovf, build_int_2 (align, 0));
03246 t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align-1, -1));
03247 }
03248 t = save_expr (t);
03249
03250 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
03251 if (r != addr_rtx)
03252 emit_move_insn (addr_rtx, r);
03253
03254 t = build (PLUS_EXPR, TREE_TYPE (t), t, build_int_2 (size, 0));
03255 t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
03256 TREE_SIDE_EFFECTS (t) = 1;
03257 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03258
03259 emit_label (lab_over);
03260
03261 if (indirect_p)
03262 {
03263 r = gen_rtx_MEM (Pmode, addr_rtx);
03264 set_mem_alias_set (r, get_varargs_alias_set ());
03265 emit_move_insn (addr_rtx, r);
03266 }
03267
03268 return addr_rtx;
03269 }
03270
03271
03272
03273 #define def_builtin(MASK, NAME, TYPE, CODE) \
03274 do { \
03275 if ((MASK) & target_flags) \
03276 builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL); \
03277 } while (0)
03278
03279 struct builtin_description
03280 {
03281 const unsigned int mask;
03282 const enum insn_code icode;
03283 const char *const name;
03284 const enum rs6000_builtins code;
03285 };
03286
03287
03288
03289 static const struct builtin_description bdesc_3arg[] =
03290 {
03291 { MASK_ALTIVEC, CODE_FOR_altivec_vmaddfp, "__builtin_altivec_vmaddfp", ALTIVEC_BUILTIN_VMADDFP },
03292 { MASK_ALTIVEC, CODE_FOR_altivec_vmhaddshs, "__builtin_altivec_vmhaddshs", ALTIVEC_BUILTIN_VMHADDSHS },
03293 { MASK_ALTIVEC, CODE_FOR_altivec_vmhraddshs, "__builtin_altivec_vmhraddshs", ALTIVEC_BUILTIN_VMHRADDSHS },
03294 { MASK_ALTIVEC, CODE_FOR_altivec_vmladduhm, "__builtin_altivec_vmladduhm", ALTIVEC_BUILTIN_VMLADDUHM},
03295 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumubm, "__builtin_altivec_vmsumubm", ALTIVEC_BUILTIN_VMSUMUBM },
03296 { MASK_ALTIVEC, CODE_FOR_altivec_vmsummbm, "__builtin_altivec_vmsummbm", ALTIVEC_BUILTIN_VMSUMMBM },
03297 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhm, "__builtin_altivec_vmsumuhm", ALTIVEC_BUILTIN_VMSUMUHM },
03298 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshm, "__builtin_altivec_vmsumshm", ALTIVEC_BUILTIN_VMSUMSHM },
03299 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhs, "__builtin_altivec_vmsumuhs", ALTIVEC_BUILTIN_VMSUMUHS },
03300 { MASK_ALTIVEC, CODE_FOR_altivec_vmsumshs, "__builtin_altivec_vmsumshs", ALTIVEC_BUILTIN_VMSUMSHS },
03301 { MASK_ALTIVEC, CODE_FOR_altivec_vnmsubfp, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
03302 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
03303 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
03304 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
03305 { MASK_ALTIVEC, CODE_FOR_altivec_vperm_16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
03306 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
03307 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
03308 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
03309 { MASK_ALTIVEC, CODE_FOR_altivec_vsel_16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
03310 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
03311 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
03312 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
03313 { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_4sf, "__builtin_altivec_vsldoi_4sf", ALTIVEC_BUILTIN_VSLDOI_4SF },
03314 };
03315
03316
03317
03318 static const struct builtin_description bdesc_dst[] =
03319 {
03320 { MASK_ALTIVEC, CODE_FOR_altivec_dst, "__builtin_altivec_dst", ALTIVEC_BUILTIN_DST },
03321 { MASK_ALTIVEC, CODE_FOR_altivec_dstt, "__builtin_altivec_dstt", ALTIVEC_BUILTIN_DSTT },
03322 { MASK_ALTIVEC, CODE_FOR_altivec_dstst, "__builtin_altivec_dstst", ALTIVEC_BUILTIN_DSTST },
03323 { MASK_ALTIVEC, CODE_FOR_altivec_dststt, "__builtin_altivec_dststt", ALTIVEC_BUILTIN_DSTSTT }
03324 };
03325
03326
03327
03328 static const struct builtin_description bdesc_2arg[] =
03329 {
03330 { MASK_ALTIVEC, CODE_FOR_addv16qi3, "__builtin_altivec_vaddubm", ALTIVEC_BUILTIN_VADDUBM },
03331 { MASK_ALTIVEC, CODE_FOR_addv8hi3, "__builtin_altivec_vadduhm", ALTIVEC_BUILTIN_VADDUHM },
03332 { MASK_ALTIVEC, CODE_FOR_addv4si3, "__builtin_altivec_vadduwm", ALTIVEC_BUILTIN_VADDUWM },
03333 { MASK_ALTIVEC, CODE_FOR_addv4sf3, "__builtin_altivec_vaddfp", ALTIVEC_BUILTIN_VADDFP },
03334 { MASK_ALTIVEC, CODE_FOR_altivec_vaddcuw, "__builtin_altivec_vaddcuw", ALTIVEC_BUILTIN_VADDCUW },
03335 { MASK_ALTIVEC, CODE_FOR_altivec_vaddubs, "__builtin_altivec_vaddubs", ALTIVEC_BUILTIN_VADDUBS },
03336 { MASK_ALTIVEC, CODE_FOR_altivec_vaddsbs, "__builtin_altivec_vaddsbs", ALTIVEC_BUILTIN_VADDSBS },
03337 { MASK_ALTIVEC, CODE_FOR_altivec_vadduhs, "__builtin_altivec_vadduhs", ALTIVEC_BUILTIN_VADDUHS },
03338 { MASK_ALTIVEC, CODE_FOR_altivec_vaddshs, "__builtin_altivec_vaddshs", ALTIVEC_BUILTIN_VADDSHS },
03339 { MASK_ALTIVEC, CODE_FOR_altivec_vadduws, "__builtin_altivec_vadduws", ALTIVEC_BUILTIN_VADDUWS },
03340 { MASK_ALTIVEC, CODE_FOR_altivec_vaddsws, "__builtin_altivec_vaddsws", ALTIVEC_BUILTIN_VADDSWS },
03341 { MASK_ALTIVEC, CODE_FOR_andv4si3, "__builtin_altivec_vand", ALTIVEC_BUILTIN_VAND },
03342 { MASK_ALTIVEC, CODE_FOR_altivec_vandc, "__builtin_altivec_vandc", ALTIVEC_BUILTIN_VANDC },
03343 { MASK_ALTIVEC, CODE_FOR_altivec_vavgub, "__builtin_altivec_vavgub", ALTIVEC_BUILTIN_VAVGUB },
03344 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsb, "__builtin_altivec_vavgsb", ALTIVEC_BUILTIN_VAVGSB },
03345 { MASK_ALTIVEC, CODE_FOR_altivec_vavguh, "__builtin_altivec_vavguh", ALTIVEC_BUILTIN_VAVGUH },
03346 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsh, "__builtin_altivec_vavgsh", ALTIVEC_BUILTIN_VAVGSH },
03347 { MASK_ALTIVEC, CODE_FOR_altivec_vavguw, "__builtin_altivec_vavguw", ALTIVEC_BUILTIN_VAVGUW },
03348 { MASK_ALTIVEC, CODE_FOR_altivec_vavgsw, "__builtin_altivec_vavgsw", ALTIVEC_BUILTIN_VAVGSW },
03349 { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
03350 { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
03351 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
03352 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
03353 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
03354 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
03355 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
03356 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
03357 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
03358 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
03359 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
03360 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
03361 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
03362 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
03363 { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
03364 { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
03365 { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
03366 { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
03367 { MASK_ALTIVEC, CODE_FOR_smaxv16qi3, "__builtin_altivec_vmaxsb", ALTIVEC_BUILTIN_VMAXSB },
03368 { MASK_ALTIVEC, CODE_FOR_uminv8hi3, "__builtin_altivec_vmaxuh", ALTIVEC_BUILTIN_VMAXUH },
03369 { MASK_ALTIVEC, CODE_FOR_sminv8hi3, "__builtin_altivec_vmaxsh", ALTIVEC_BUILTIN_VMAXSH },
03370 { MASK_ALTIVEC, CODE_FOR_uminv4si3, "__builtin_altivec_vmaxuw", ALTIVEC_BUILTIN_VMAXUW },
03371 { MASK_ALTIVEC, CODE_FOR_sminv4si3, "__builtin_altivec_vmaxsw", ALTIVEC_BUILTIN_VMAXSW },
03372 { MASK_ALTIVEC, CODE_FOR_sminv4sf3, "__builtin_altivec_vmaxfp", ALTIVEC_BUILTIN_VMAXFP },
03373 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghb, "__builtin_altivec_vmrghb", ALTIVEC_BUILTIN_VMRGHB },
03374 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghh, "__builtin_altivec_vmrghh", ALTIVEC_BUILTIN_VMRGHH },
03375 { MASK_ALTIVEC, CODE_FOR_altivec_vmrghw, "__builtin_altivec_vmrghw", ALTIVEC_BUILTIN_VMRGHW },
03376 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglb, "__builtin_altivec_vmrglb", ALTIVEC_BUILTIN_VMRGLB },
03377 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglh, "__builtin_altivec_vmrglh", ALTIVEC_BUILTIN_VMRGLH },
03378 { MASK_ALTIVEC, CODE_FOR_altivec_vmrglw, "__builtin_altivec_vmrglw", ALTIVEC_BUILTIN_VMRGLW },
03379 { MASK_ALTIVEC, CODE_FOR_uminv16qi3, "__builtin_altivec_vminub", ALTIVEC_BUILTIN_VMINUB },
03380 { MASK_ALTIVEC, CODE_FOR_sminv16qi3, "__builtin_altivec_vminsb", ALTIVEC_BUILTIN_VMINSB },
03381 { MASK_ALTIVEC, CODE_FOR_uminv8hi3, "__builtin_altivec_vminuh", ALTIVEC_BUILTIN_VMINUH },
03382 { MASK_ALTIVEC, CODE_FOR_sminv8hi3, "__builtin_altivec_vminsh", ALTIVEC_BUILTIN_VMINSH },
03383 { MASK_ALTIVEC, CODE_FOR_uminv4si3, "__builtin_altivec_vminuw", ALTIVEC_BUILTIN_VMINUW },
03384 { MASK_ALTIVEC, CODE_FOR_sminv4si3, "__builtin_altivec_vminsw", ALTIVEC_BUILTIN_VMINSW },
03385 { MASK_ALTIVEC, CODE_FOR_sminv4sf3, "__builtin_altivec_vminfp", ALTIVEC_BUILTIN_VMINFP },
03386 { MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub", ALTIVEC_BUILTIN_VMULEUB },
03387 { MASK_ALTIVEC, CODE_FOR_altivec_vmulesb, "__builtin_altivec_vmulesb", ALTIVEC_BUILTIN_VMULESB },
03388 { MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh", ALTIVEC_BUILTIN_VMULEUH },
03389 { MASK_ALTIVEC, CODE_FOR_altivec_vmulesh, "__builtin_altivec_vmulesh", ALTIVEC_BUILTIN_VMULESH },
03390 { MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub", ALTIVEC_BUILTIN_VMULOUB },
03391 { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
03392 { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
03393 { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
03394 { MASK_ALTIVEC, CODE_FOR_altivec_vnor, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
03395 { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
03396 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
03397 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
03398 { MASK_ALTIVEC, CODE_FOR_altivec_vpkpx, "__builtin_altivec_vpkpx", ALTIVEC_BUILTIN_VPKPX },
03399 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhss, "__builtin_altivec_vpkuhss", ALTIVEC_BUILTIN_VPKUHSS },
03400 { MASK_ALTIVEC, CODE_FOR_altivec_vpkshss, "__builtin_altivec_vpkshss", ALTIVEC_BUILTIN_VPKSHSS },
03401 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwss, "__builtin_altivec_vpkuwss", ALTIVEC_BUILTIN_VPKUWSS },
03402 { MASK_ALTIVEC, CODE_FOR_altivec_vpkswss, "__builtin_altivec_vpkswss", ALTIVEC_BUILTIN_VPKSWSS },
03403 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhus, "__builtin_altivec_vpkuhus", ALTIVEC_BUILTIN_VPKUHUS },
03404 { MASK_ALTIVEC, CODE_FOR_altivec_vpkshus, "__builtin_altivec_vpkshus", ALTIVEC_BUILTIN_VPKSHUS },
03405 { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwus, "__builtin_altivec_vpkuwus", ALTIVEC_BUILTIN_VPKUWUS },
03406 { MASK_ALTIVEC, CODE_FOR_altivec_vpkswus, "__builtin_altivec_vpkswus", ALTIVEC_BUILTIN_VPKSWUS },
03407 { MASK_ALTIVEC, CODE_FOR_altivec_vrlb, "__builtin_altivec_vrlb", ALTIVEC_BUILTIN_VRLB },
03408 { MASK_ALTIVEC, CODE_FOR_altivec_vrlh, "__builtin_altivec_vrlh", ALTIVEC_BUILTIN_VRLH },
03409 { MASK_ALTIVEC, CODE_FOR_altivec_vrlw, "__builtin_altivec_vrlw", ALTIVEC_BUILTIN_VRLW },
03410 { MASK_ALTIVEC, CODE_FOR_altivec_vslb, "__builtin_altivec_vslb", ALTIVEC_BUILTIN_VSLB },
03411 { MASK_ALTIVEC, CODE_FOR_altivec_vslh, "__builtin_altivec_vslh", ALTIVEC_BUILTIN_VSLH },
03412 { MASK_ALTIVEC, CODE_FOR_altivec_vslw, "__builtin_altivec_vslw", ALTIVEC_BUILTIN_VSLW },
03413 { MASK_ALTIVEC, CODE_FOR_altivec_vsl, "__builtin_altivec_vsl", ALTIVEC_BUILTIN_VSL },
03414 { MASK_ALTIVEC, CODE_FOR_altivec_vslo, "__builtin_altivec_vslo", ALTIVEC_BUILTIN_VSLO },
03415 { MASK_ALTIVEC, CODE_FOR_altivec_vspltb, "__builtin_altivec_vspltb", ALTIVEC_BUILTIN_VSPLTB },
03416 { MASK_ALTIVEC, CODE_FOR_altivec_vsplth, "__builtin_altivec_vsplth", ALTIVEC_BUILTIN_VSPLTH },
03417 { MASK_ALTIVEC, CODE_FOR_altivec_vspltw, "__builtin_altivec_vspltw", ALTIVEC_BUILTIN_VSPLTW },
03418 { MASK_ALTIVEC, CODE_FOR_altivec_vsrb, "__builtin_altivec_vsrb", ALTIVEC_BUILTIN_VSRB },
03419 { MASK_ALTIVEC, CODE_FOR_altivec_vsrh, "__builtin_altivec_vsrh", ALTIVEC_BUILTIN_VSRH },
03420 { MASK_ALTIVEC, CODE_FOR_altivec_vsrw, "__builtin_altivec_vsrw", ALTIVEC_BUILTIN_VSRW },
03421 { MASK_ALTIVEC, CODE_FOR_altivec_vsrab, "__builtin_altivec_vsrab", ALTIVEC_BUILTIN_VSRAB },
03422 { MASK_ALTIVEC, CODE_FOR_altivec_vsrah, "__builtin_altivec_vsrah", ALTIVEC_BUILTIN_VSRAH },
03423 { MASK_ALTIVEC, CODE_FOR_altivec_vsraw, "__builtin_altivec_vsraw", ALTIVEC_BUILTIN_VSRAW },
03424 { MASK_ALTIVEC, CODE_FOR_altivec_vsr, "__builtin_altivec_vsr", ALTIVEC_BUILTIN_VSR },
03425 { MASK_ALTIVEC, CODE_FOR_altivec_vsro, "__builtin_altivec_vsro", ALTIVEC_BUILTIN_VSRO },
03426 { MASK_ALTIVEC, CODE_FOR_subv16qi3, "__builtin_altivec_vsububm", ALTIVEC_BUILTIN_VSUBUBM },
03427 { MASK_ALTIVEC, CODE_FOR_subv8hi3, "__builtin_altivec_vsubuhm", ALTIVEC_BUILTIN_VSUBUHM },
03428 { MASK_ALTIVEC, CODE_FOR_subv4si3, "__builtin_altivec_vsubuwm", ALTIVEC_BUILTIN_VSUBUWM },
03429 { MASK_ALTIVEC, CODE_FOR_subv4sf3, "__builtin_altivec_vsubfp", ALTIVEC_BUILTIN_VSUBFP },
03430 { MASK_ALTIVEC, CODE_FOR_altivec_vsubcuw, "__builtin_altivec_vsubcuw", ALTIVEC_BUILTIN_VSUBCUW },
03431 { MASK_ALTIVEC, CODE_FOR_altivec_vsububs, "__builtin_altivec_vsububs", ALTIVEC_BUILTIN_VSUBUBS },
03432 { MASK_ALTIVEC, CODE_FOR_altivec_vsubsbs, "__builtin_altivec_vsubsbs", ALTIVEC_BUILTIN_VSUBSBS },
03433 { MASK_ALTIVEC, CODE_FOR_altivec_vsubuhs, "__builtin_altivec_vsubuhs", ALTIVEC_BUILTIN_VSUBUHS },
03434 { MASK_ALTIVEC, CODE_FOR_altivec_vsubshs, "__builtin_altivec_vsubshs", ALTIVEC_BUILTIN_VSUBSHS },
03435 { MASK_ALTIVEC, CODE_FOR_altivec_vsubuws, "__builtin_altivec_vsubuws", ALTIVEC_BUILTIN_VSUBUWS },
03436 { MASK_ALTIVEC, CODE_FOR_altivec_vsubsws, "__builtin_altivec_vsubsws", ALTIVEC_BUILTIN_VSUBSWS },
03437 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4ubs, "__builtin_altivec_vsum4ubs", ALTIVEC_BUILTIN_VSUM4UBS },
03438 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4sbs, "__builtin_altivec_vsum4sbs", ALTIVEC_BUILTIN_VSUM4SBS },
03439 { MASK_ALTIVEC, CODE_FOR_altivec_vsum4shs, "__builtin_altivec_vsum4shs", ALTIVEC_BUILTIN_VSUM4SHS },
03440 { MASK_ALTIVEC, CODE_FOR_altivec_vsum2sws, "__builtin_altivec_vsum2sws", ALTIVEC_BUILTIN_VSUM2SWS },
03441 { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
03442 { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
03443 };
03444
03445
03446
03447 struct builtin_description_predicates
03448 {
03449 const unsigned int mask;
03450 const enum insn_code icode;
03451 const char *opcode;
03452 const char *const name;
03453 const enum rs6000_builtins code;
03454 };
03455
03456 static const struct builtin_description_predicates bdesc_altivec_preds[] =
03457 {
03458 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpbfp.", "__builtin_altivec_vcmpbfp_p", ALTIVEC_BUILTIN_VCMPBFP_P },
03459 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpeqfp.", "__builtin_altivec_vcmpeqfp_p", ALTIVEC_BUILTIN_VCMPEQFP_P },
03460 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgefp.", "__builtin_altivec_vcmpgefp_p", ALTIVEC_BUILTIN_VCMPGEFP_P },
03461 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4sf, "*vcmpgtfp.", "__builtin_altivec_vcmpgtfp_p", ALTIVEC_BUILTIN_VCMPGTFP_P },
03462 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpequw.", "__builtin_altivec_vcmpequw_p", ALTIVEC_BUILTIN_VCMPEQUW_P },
03463 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtsw.", "__builtin_altivec_vcmpgtsw_p", ALTIVEC_BUILTIN_VCMPGTSW_P },
03464 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v4si, "*vcmpgtuw.", "__builtin_altivec_vcmpgtuw_p", ALTIVEC_BUILTIN_VCMPGTUW_P },
03465 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtuh.", "__builtin_altivec_vcmpgtuh_p", ALTIVEC_BUILTIN_VCMPGTUH_P },
03466 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpgtsh.", "__builtin_altivec_vcmpgtsh_p", ALTIVEC_BUILTIN_VCMPGTSH_P },
03467 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpequh.", "__builtin_altivec_vcmpequh_p", ALTIVEC_BUILTIN_VCMPEQUH_P },
03468 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpequb.", "__builtin_altivec_vcmpequb_p", ALTIVEC_BUILTIN_VCMPEQUB_P },
03469 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtsb.", "__builtin_altivec_vcmpgtsb_p", ALTIVEC_BUILTIN_VCMPGTSB_P },
03470 { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtub.", "__builtin_altivec_vcmpgtub_p", ALTIVEC_BUILTIN_VCMPGTUB_P }
03471 };
03472
03473
03474
03475 static const struct builtin_description bdesc_abs[] =
03476 {
03477 { MASK_ALTIVEC, CODE_FOR_absv4si2, "__builtin_altivec_abs_v4si", ALTIVEC_BUILTIN_ABS_V4SI },
03478 { MASK_ALTIVEC, CODE_FOR_absv8hi2, "__builtin_altivec_abs_v8hi", ALTIVEC_BUILTIN_ABS_V8HI },
03479 { MASK_ALTIVEC, CODE_FOR_absv4sf2, "__builtin_altivec_abs_v4sf", ALTIVEC_BUILTIN_ABS_V4SF },
03480 { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI },
03481 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI },
03482 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI },
03483 { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }
03484 };
03485
03486
03487
03488
03489 static const struct builtin_description bdesc_1arg[] =
03490 {
03491 { MASK_ALTIVEC, CODE_FOR_altivec_vexptefp, "__builtin_altivec_vexptefp", ALTIVEC_BUILTIN_VEXPTEFP },
03492 { MASK_ALTIVEC, CODE_FOR_altivec_vlogefp, "__builtin_altivec_vlogefp", ALTIVEC_BUILTIN_VLOGEFP },
03493 { MASK_ALTIVEC, CODE_FOR_altivec_vrefp, "__builtin_altivec_vrefp", ALTIVEC_BUILTIN_VREFP },
03494 { MASK_ALTIVEC, CODE_FOR_altivec_vrfim, "__builtin_altivec_vrfim", ALTIVEC_BUILTIN_VRFIM },
03495 { MASK_ALTIVEC, CODE_FOR_altivec_vrfin, "__builtin_altivec_vrfin", ALTIVEC_BUILTIN_VRFIN },
03496 { MASK_ALTIVEC, CODE_FOR_altivec_vrfip, "__builtin_altivec_vrfip", ALTIVEC_BUILTIN_VRFIP },
03497 { MASK_ALTIVEC, CODE_FOR_ftruncv4sf2, "__builtin_altivec_vrfiz", ALTIVEC_BUILTIN_VRFIZ },
03498 { MASK_ALTIVEC, CODE_FOR_altivec_vrsqrtefp, "__builtin_altivec_vrsqrtefp", ALTIVEC_BUILTIN_VRSQRTEFP },
03499 { MASK_ALTIVEC, CODE_FOR_altivec_vspltisb, "__builtin_altivec_vspltisb", ALTIVEC_BUILTIN_VSPLTISB },
03500 { MASK_ALTIVEC, CODE_FOR_altivec_vspltish, "__builtin_altivec_vspltish", ALTIVEC_BUILTIN_VSPLTISH },
03501 { MASK_ALTIVEC, CODE_FOR_altivec_vspltisw, "__builtin_altivec_vspltisw", ALTIVEC_BUILTIN_VSPLTISW },
03502 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsb, "__builtin_altivec_vupkhsb", ALTIVEC_BUILTIN_VUPKHSB },
03503 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhpx, "__builtin_altivec_vupkhpx", ALTIVEC_BUILTIN_VUPKHPX },
03504 { MASK_ALTIVEC, CODE_FOR_altivec_vupkhsh, "__builtin_altivec_vupkhsh", ALTIVEC_BUILTIN_VUPKHSH },
03505 { MASK_ALTIVEC, CODE_FOR_altivec_vupklsb, "__builtin_altivec_vupklsb", ALTIVEC_BUILTIN_VUPKLSB },
03506 { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
03507 { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
03508 };
03509
03510 static rtx
03511 altivec_expand_unop_builtin (icode, arglist, target)
03512 enum insn_code icode;
03513 tree arglist;
03514 rtx target;
03515 {
03516 rtx pat;
03517 tree arg0 = TREE_VALUE (arglist);
03518 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03519 enum machine_mode tmode = insn_data[icode].operand[0].mode;
03520 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
03521
03522
03523 if (arg0 == error_mark_node)
03524 return NULL_RTX;
03525
03526 if (target == 0
03527 || GET_MODE (target) != tmode
03528 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03529 target = gen_reg_rtx (tmode);
03530
03531 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03532 op0 = copy_to_mode_reg (mode0, op0);
03533
03534 pat = GEN_FCN (icode) (target, op0);
03535 if (! pat)
03536 return 0;
03537 emit_insn (pat);
03538
03539 return target;
03540 }
03541
03542 static rtx
03543 altivec_expand_abs_builtin (icode, arglist, target)
03544 enum insn_code icode;
03545 tree arglist;
03546 rtx target;
03547 {
03548 rtx pat, scratch1, scratch2;
03549 tree arg0 = TREE_VALUE (arglist);
03550 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03551 enum machine_mode tmode = insn_data[icode].operand[0].mode;
03552 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
03553
03554
03555 if (arg0 == error_mark_node)
03556 return NULL_RTX;
03557
03558 if (target == 0
03559 || GET_MODE (target) != tmode
03560 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03561 target = gen_reg_rtx (tmode);
03562
03563 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03564 op0 = copy_to_mode_reg (mode0, op0);
03565
03566 scratch1 = gen_reg_rtx (mode0);
03567 scratch2 = gen_reg_rtx (mode0);
03568
03569 pat = GEN_FCN (icode) (target, op0, scratch1, scratch2);
03570 if (! pat)
03571 return 0;
03572 emit_insn (pat);
03573
03574 return target;
03575 }
03576
03577 static rtx
03578 altivec_expand_binop_builtin (icode, arglist, target)
03579 enum insn_code icode;
03580 tree arglist;
03581 rtx target;
03582 {
03583 rtx pat;
03584 tree arg0 = TREE_VALUE (arglist);
03585 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
03586 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03587 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03588 enum machine_mode tmode = insn_data[icode].operand[0].mode;
03589 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
03590 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
03591
03592
03593 if (arg0 == error_mark_node || arg1 == error_mark_node)
03594 return NULL_RTX;
03595
03596 if (target == 0
03597 || GET_MODE (target) != tmode
03598 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03599 target = gen_reg_rtx (tmode);
03600
03601 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03602 op0 = copy_to_mode_reg (mode0, op0);
03603 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
03604 op1 = copy_to_mode_reg (mode1, op1);
03605
03606 pat = GEN_FCN (icode) (target, op0, op1);
03607 if (! pat)
03608 return 0;
03609 emit_insn (pat);
03610
03611 return target;
03612 }
03613
03614 static rtx
03615 altivec_expand_predicate_builtin (icode, opcode, arglist, target)
03616 enum insn_code icode;
03617 const char *opcode;
03618 tree arglist;
03619 rtx target;
03620 {
03621 rtx pat, scratch;
03622 tree cr6_form = TREE_VALUE (arglist);
03623 tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
03624 tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
03625 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03626 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03627 enum machine_mode tmode = SImode;
03628 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
03629 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
03630 int cr6_form_int;
03631
03632 if (TREE_CODE (cr6_form) != INTEGER_CST)
03633 {
03634 error ("argument 1 of __builtin_altivec_predicate must be a constant");
03635 return NULL_RTX;
03636 }
03637 else
03638 cr6_form_int = TREE_INT_CST_LOW (cr6_form);
03639
03640 if (mode0 != mode1)
03641 abort ();
03642
03643
03644 if (arg0 == error_mark_node || arg1 == error_mark_node)
03645 return NULL_RTX;
03646
03647 if (target == 0
03648 || GET_MODE (target) != tmode
03649 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03650 target = gen_reg_rtx (tmode);
03651
03652 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03653 op0 = copy_to_mode_reg (mode0, op0);
03654 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
03655 op1 = copy_to_mode_reg (mode1, op1);
03656
03657 scratch = gen_reg_rtx (mode0);
03658
03659 pat = GEN_FCN (icode) (scratch, op0, op1,
03660 gen_rtx (SYMBOL_REF, Pmode, opcode));
03661 if (! pat)
03662 return 0;
03663 emit_insn (pat);
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673 switch (cr6_form_int)
03674 {
03675 case 0:
03676 emit_insn (gen_cr6_test_for_zero (target));
03677 break;
03678 case 1:
03679 emit_insn (gen_cr6_test_for_zero_reverse (target));
03680 break;
03681 case 2:
03682 emit_insn (gen_cr6_test_for_lt (target));
03683 break;
03684 case 3:
03685 emit_insn (gen_cr6_test_for_lt_reverse (target));
03686 break;
03687 default:
03688 error ("argument 1 of __builtin_altivec_predicate is out of range");
03689 break;
03690 }
03691
03692 return target;
03693 }
03694
03695 static rtx
03696 altivec_expand_stv_builtin (icode, arglist)
03697 enum insn_code icode;
03698 tree arglist;
03699 {
03700 tree arg0 = TREE_VALUE (arglist);
03701 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
03702 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
03703 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03704 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03705 rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
03706 rtx pat;
03707 enum machine_mode mode0 = insn_data[icode].operand[0].mode;
03708 enum machine_mode mode1 = insn_data[icode].operand[1].mode;
03709 enum machine_mode mode2 = insn_data[icode].operand[2].mode;
03710
03711
03712 if (arg0 == error_mark_node
03713 || arg1 == error_mark_node
03714 || arg2 == error_mark_node)
03715 return NULL_RTX;
03716
03717 if (! (*insn_data[icode].operand[2].predicate) (op0, mode2))
03718 op0 = copy_to_mode_reg (mode2, op0);
03719 if (! (*insn_data[icode].operand[0].predicate) (op1, mode0))
03720 op1 = copy_to_mode_reg (mode0, op1);
03721 if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
03722 op2 = copy_to_mode_reg (mode1, op2);
03723
03724 pat = GEN_FCN (icode) (op1, op2, op0);
03725 if (pat)
03726 emit_insn (pat);
03727 return NULL_RTX;
03728 }
03729
03730 static rtx
03731 altivec_expand_ternop_builtin (icode, arglist, target)
03732 enum insn_code icode;
03733 tree arglist;
03734 rtx target;
03735 {
03736 rtx pat;
03737 tree arg0 = TREE_VALUE (arglist);
03738 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
03739 tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
03740 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03741 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03742 rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
03743 enum machine_mode tmode = insn_data[icode].operand[0].mode;
03744 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
03745 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
03746 enum machine_mode mode2 = insn_data[icode].operand[3].mode;
03747
03748
03749 if (arg0 == error_mark_node
03750 || arg1 == error_mark_node
03751 || arg2 == error_mark_node)
03752 return NULL_RTX;
03753
03754 if (target == 0
03755 || GET_MODE (target) != tmode
03756 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03757 target = gen_reg_rtx (tmode);
03758
03759 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03760 op0 = copy_to_mode_reg (mode0, op0);
03761 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
03762 op1 = copy_to_mode_reg (mode1, op1);
03763 if (! (*insn_data[icode].operand[3].predicate) (op2, mode2))
03764 op2 = copy_to_mode_reg (mode2, op2);
03765
03766 pat = GEN_FCN (icode) (target, op0, op1, op2);
03767 if (! pat)
03768 return 0;
03769 emit_insn (pat);
03770
03771 return target;
03772 }
03773 static rtx
03774 altivec_expand_builtin (exp, target)
03775 tree exp;
03776 rtx target;
03777 {
03778 struct builtin_description *d;
03779 struct builtin_description_predicates *dp;
03780 size_t i;
03781 enum insn_code icode;
03782 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
03783 tree arglist = TREE_OPERAND (exp, 1);
03784 tree arg0, arg1, arg2;
03785 rtx op0, op1, op2, pat;
03786 enum machine_mode tmode, mode0, mode1, mode2;
03787 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
03788
03789 switch (fcode)
03790 {
03791 case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
03792 icode = CODE_FOR_altivec_lvx_16qi;
03793 arg0 = TREE_VALUE (arglist);
03794 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03795 tmode = insn_data[icode].operand[0].mode;
03796 mode0 = insn_data[icode].operand[1].mode;
03797
03798 if (target == 0
03799 || GET_MODE (target) != tmode
03800 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03801 target = gen_reg_rtx (tmode);
03802
03803 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03804 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03805
03806 pat = GEN_FCN (icode) (target, op0);
03807 if (! pat)
03808 return 0;
03809 emit_insn (pat);
03810 return target;
03811
03812 case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
03813 icode = CODE_FOR_altivec_lvx_8hi;
03814 arg0 = TREE_VALUE (arglist);
03815 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03816 tmode = insn_data[icode].operand[0].mode;
03817 mode0 = insn_data[icode].operand[1].mode;
03818
03819 if (target == 0
03820 || GET_MODE (target) != tmode
03821 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03822 target = gen_reg_rtx (tmode);
03823
03824 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03825 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03826
03827 pat = GEN_FCN (icode) (target, op0);
03828 if (! pat)
03829 return 0;
03830 emit_insn (pat);
03831 return target;
03832
03833 case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
03834 icode = CODE_FOR_altivec_lvx_4si;
03835 arg0 = TREE_VALUE (arglist);
03836 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03837 tmode = insn_data[icode].operand[0].mode;
03838 mode0 = insn_data[icode].operand[1].mode;
03839
03840 if (target == 0
03841 || GET_MODE (target) != tmode
03842 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03843 target = gen_reg_rtx (tmode);
03844
03845 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03846 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03847
03848 pat = GEN_FCN (icode) (target, op0);
03849 if (! pat)
03850 return 0;
03851 emit_insn (pat);
03852 return target;
03853
03854 case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
03855 icode = CODE_FOR_altivec_lvx_4sf;
03856 arg0 = TREE_VALUE (arglist);
03857 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03858 tmode = insn_data[icode].operand[0].mode;
03859 mode0 = insn_data[icode].operand[1].mode;
03860
03861 if (target == 0
03862 || GET_MODE (target) != tmode
03863 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03864 target = gen_reg_rtx (tmode);
03865
03866 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
03867 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03868
03869 pat = GEN_FCN (icode) (target, op0);
03870 if (! pat)
03871 return 0;
03872 emit_insn (pat);
03873 return target;
03874
03875 case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
03876 icode = CODE_FOR_altivec_stvx_16qi;
03877 arg0 = TREE_VALUE (arglist);
03878 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
03879 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03880 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03881 mode0 = insn_data[icode].operand[0].mode;
03882 mode1 = insn_data[icode].operand[1].mode;
03883
03884 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
03885 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03886 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
03887 op1 = copy_to_mode_reg (mode1, op1);
03888
03889 pat = GEN_FCN (icode) (op0, op1);
03890 if (pat)
03891 emit_insn (pat);
03892 return NULL_RTX;
03893
03894 case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
03895 icode = CODE_FOR_altivec_stvx_8hi;
03896 arg0 = TREE_VALUE (arglist);
03897 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
03898 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03899 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03900 mode0 = insn_data[icode].operand[0].mode;
03901 mode1 = insn_data[icode].operand[1].mode;
03902
03903 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
03904 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03905 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
03906 op1 = copy_to_mode_reg (mode1, op1);
03907
03908 pat = GEN_FCN (icode) (op0, op1);
03909 if (pat)
03910 emit_insn (pat);
03911 return NULL_RTX;
03912
03913 case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
03914 icode = CODE_FOR_altivec_stvx_4si;
03915 arg0 = TREE_VALUE (arglist);
03916 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
03917 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03918 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03919 mode0 = insn_data[icode].operand[0].mode;
03920 mode1 = insn_data[icode].operand[1].mode;
03921
03922 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
03923 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03924 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
03925 op1 = copy_to_mode_reg (mode1, op1);
03926
03927 pat = GEN_FCN (icode) (op0, op1);
03928 if (pat)
03929 emit_insn (pat);
03930 return NULL_RTX;
03931
03932 case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
03933 icode = CODE_FOR_altivec_stvx_4sf;
03934 arg0 = TREE_VALUE (arglist);
03935 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
03936 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03937 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
03938 mode0 = insn_data[icode].operand[0].mode;
03939 mode1 = insn_data[icode].operand[1].mode;
03940
03941 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
03942 op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
03943 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
03944 op1 = copy_to_mode_reg (mode1, op1);
03945
03946 pat = GEN_FCN (icode) (op0, op1);
03947 if (pat)
03948 emit_insn (pat);
03949 return NULL_RTX;
03950
03951 case ALTIVEC_BUILTIN_STVX:
03952 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx, arglist);
03953 case ALTIVEC_BUILTIN_STVEBX:
03954 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, arglist);
03955 case ALTIVEC_BUILTIN_STVEHX:
03956 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, arglist);
03957 case ALTIVEC_BUILTIN_STVEWX:
03958 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, arglist);
03959 case ALTIVEC_BUILTIN_STVXL:
03960 return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, arglist);
03961
03962 case ALTIVEC_BUILTIN_MFVSCR:
03963 icode = CODE_FOR_altivec_mfvscr;
03964 tmode = insn_data[icode].operand[0].mode;
03965
03966 if (target == 0
03967 || GET_MODE (target) != tmode
03968 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
03969 target = gen_reg_rtx (tmode);
03970
03971 pat = GEN_FCN (icode) (target);
03972 if (! pat)
03973 return 0;
03974 emit_insn (pat);
03975 return target;
03976
03977 case ALTIVEC_BUILTIN_MTVSCR:
03978 icode = CODE_FOR_altivec_mtvscr;
03979 arg0 = TREE_VALUE (arglist);
03980 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
03981 mode0 = insn_data[icode].operand[0].mode;
03982
03983
03984 if (arg0 == error_mark_node)
03985 return NULL_RTX;
03986
03987 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
03988 op0 = copy_to_mode_reg (mode0, op0);
03989
03990 pat = GEN_FCN (icode) (op0);
03991 if (pat)
03992 emit_insn (pat);
03993 return NULL_RTX;
03994
03995 case ALTIVEC_BUILTIN_DSSALL:
03996 emit_insn (gen_altivec_dssall ());
03997 return NULL_RTX;
03998
03999 case ALTIVEC_BUILTIN_DSS:
04000 icode = CODE_FOR_altivec_dss;
04001 arg0 = TREE_VALUE (arglist);
04002 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
04003 mode0 = insn_data[icode].operand[0].mode;
04004
04005
04006 if (arg0 == error_mark_node)
04007 return NULL_RTX;
04008
04009 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
04010 op0 = copy_to_mode_reg (mode0, op0);
04011
04012 emit_insn (gen_altivec_dss (op0));
04013 return NULL_RTX;
04014 }
04015
04016
04017 d = (struct builtin_description *) bdesc_dst;
04018 for (i = 0; i < sizeof (bdesc_dst) / sizeof *d; i++, d++)
04019 if (d->code == fcode)
04020 {
04021 arg0 = TREE_VALUE (arglist);
04022 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
04023 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
04024 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
04025 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
04026 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
04027 mode0 = insn_data[d->icode].operand[0].mode;
04028 mode1 = insn_data[d->icode].operand[1].mode;
04029 mode2 = insn_data[d->icode].operand[2].mode;
04030
04031
04032 if (arg0 == error_mark_node
04033 || arg1 == error_mark_node
04034 || arg2 == error_mark_node)
04035 return NULL_RTX;
04036
04037 if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
04038 op0 = copy_to_mode_reg (mode0, op0);
04039 if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
04040 op1 = copy_to_mode_reg (mode1, op1);
04041
04042 if (GET_CODE (op2) != CONST_INT || INTVAL (op2) > 3)
04043 {
04044 error ("argument 3 of `%s' must be a 2-bit literal", d->name);
04045 return NULL_RTX;
04046 }
04047
04048 pat = GEN_FCN (d->icode) (op0, op1, op2);
04049 if (pat != 0)
04050 emit_insn (pat);
04051
04052 return NULL_RTX;
04053 }
04054
04055
04056 d = (struct builtin_description *) bdesc_abs;
04057 for (i = 0; i < sizeof (bdesc_abs) / sizeof *d; i++, d++)
04058 if (d->code == fcode)
04059 return altivec_expand_abs_builtin (d->icode, arglist, target);
04060
04061
04062 d = (struct builtin_description *) bdesc_1arg;
04063 for (i = 0; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++)
04064 if (d->code == fcode)
04065 return altivec_expand_unop_builtin (d->icode, arglist, target);
04066
04067
04068 d = (struct builtin_description *) bdesc_2arg;
04069 for (i = 0; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
04070 if (d->code == fcode)
04071 return altivec_expand_binop_builtin (d->icode, arglist, target);
04072
04073
04074 dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
04075 for (i = 0; i < sizeof (bdesc_altivec_preds) / sizeof *dp; i++, dp++)
04076 if (dp->code == fcode)
04077 return altivec_expand_predicate_builtin (dp->icode, dp->opcode, arglist, target);
04078
04079
04080 switch (fcode)
04081 {
04082 case ALTIVEC_BUILTIN_LVSL:
04083 return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsl,
04084 arglist, target);
04085 case ALTIVEC_BUILTIN_LVSR:
04086 return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsr,
04087 arglist, target);
04088 case ALTIVEC_BUILTIN_LVEBX:
04089 return altivec_expand_binop_builtin (CODE_FOR_altivec_lvebx,
04090 arglist, target);
04091 case ALTIVEC_BUILTIN_LVEHX:
04092 return altivec_expand_binop_builtin (CODE_FOR_altivec_lvehx,
04093 arglist, target);
04094 case ALTIVEC_BUILTIN_LVEWX:
04095 return altivec_expand_binop_builtin (CODE_FOR_altivec_lvewx,
04096 arglist, target);
04097 case ALTIVEC_BUILTIN_LVXL:
04098 return altivec_expand_binop_builtin (CODE_FOR_altivec_lvxl,
04099 arglist, target);
04100 case ALTIVEC_BUILTIN_LVX:
04101 return altivec_expand_binop_builtin (CODE_FOR_altivec_lvx,
04102 arglist, target);
04103 default:
04104 break;
04105
04106 }
04107
04108
04109 d = (struct builtin_description *) bdesc_3arg;
04110 for (i = 0; i < sizeof (bdesc_3arg) / sizeof *d; i++, d++)
04111 if (d->code == fcode)
04112 return altivec_expand_ternop_builtin (d->icode, arglist, target);
04113
04114 abort ();
04115 return NULL_RTX;
04116 }
04117
04118
04119
04120
04121
04122
04123
04124 static rtx
04125 rs6000_expand_builtin (exp, target, subtarget, mode, ignore)
04126 tree exp;
04127 rtx target;
04128 rtx subtarget ATTRIBUTE_UNUSED;
04129 enum machine_mode mode ATTRIBUTE_UNUSED;
04130 int ignore ATTRIBUTE_UNUSED;
04131 {
04132 if (TARGET_ALTIVEC)
04133 return altivec_expand_builtin (exp, target);
04134
04135 abort ();
04136 }
04137
04138 static void
04139 rs6000_init_builtins ()
04140 {
04141 if (TARGET_ALTIVEC)
04142 altivec_init_builtins ();
04143 }
04144
04145 static void
04146 altivec_init_builtins (void)
04147 {
04148 struct builtin_description *d;
04149 struct builtin_description_predicates *dp;
04150 size_t i;
04151
04152 tree endlink = void_list_node;
04153
04154 tree pint_type_node = build_pointer_type (integer_type_node);
04155 tree pvoid_type_node = build_pointer_type (void_type_node);
04156 tree pshort_type_node = build_pointer_type (short_integer_type_node);
04157 tree pchar_type_node = build_pointer_type (char_type_node);
04158 tree pfloat_type_node = build_pointer_type (float_type_node);
04159
04160 tree v4sf_ftype_v4sf_v4sf_v16qi
04161 = build_function_type (V4SF_type_node,
04162 tree_cons (NULL_TREE, V4SF_type_node,
04163 tree_cons (NULL_TREE, V4SF_type_node,
04164 tree_cons (NULL_TREE,
04165 V16QI_type_node,
04166 endlink))));
04167 tree v4si_ftype_v4si_v4si_v16qi
04168 = build_function_type (V4SI_type_node,
04169 tree_cons (NULL_TREE, V4SI_type_node,
04170 tree_cons (NULL_TREE, V4SI_type_node,
04171 tree_cons (NULL_TREE,
04172 V16QI_type_node,
04173 endlink))));
04174 tree v8hi_ftype_v8hi_v8hi_v16qi
04175 = build_function_type (V8HI_type_node,
04176 tree_cons (NULL_TREE, V8HI_type_node,
04177 tree_cons (NULL_TREE, V8HI_type_node,
04178 tree_cons (NULL_TREE,
04179 V16QI_type_node,
04180 endlink))));
04181 tree v16qi_ftype_v16qi_v16qi_v16qi
04182 = build_function_type (V16QI_type_node,
04183 tree_cons (NULL_TREE, V16QI_type_node,
04184 tree_cons (NULL_TREE, V16QI_type_node,
04185 tree_cons (NULL_TREE,
04186 V16QI_type_node,
04187 endlink))));
04188
04189
04190 tree v4si_ftype_char
04191 = build_function_type (V4SI_type_node,
04192 tree_cons (NULL_TREE, char_type_node, endlink));
04193
04194
04195 tree v8hi_ftype_char
04196 = build_function_type (V8HI_type_node,
04197 tree_cons (NULL_TREE, char_type_node, endlink));
04198
04199
04200 tree v16qi_ftype_char
04201 = build_function_type (V16QI_type_node,
04202 tree_cons (NULL_TREE, char_type_node, endlink));
04203
04204 tree v4sf_ftype_v4sf
04205 = build_function_type (V4SF_type_node,
04206 tree_cons (NULL_TREE, V4SF_type_node, endlink));
04207
04208
04209 tree v4si_ftype_pint
04210 = build_function_type (V4SI_type_node,
04211 tree_cons (NULL_TREE, pint_type_node, endlink));
04212
04213 tree v8hi_ftype_pshort
04214 = build_function_type (V8HI_type_node,
04215 tree_cons (NULL_TREE, pshort_type_node, endlink));
04216
04217 tree v16qi_ftype_pchar
04218 = build_function_type (V16QI_type_node,
04219 tree_cons (NULL_TREE, pchar_type_node, endlink));
04220
04221 tree v4sf_ftype_pfloat
04222 = build_function_type (V4SF_type_node,
04223 tree_cons (NULL_TREE, pfloat_type_node, endlink));
04224
04225
04226 tree v8hi_ftype_v16qi
04227 = build_function_type (V8HI_type_node,
04228 tree_cons (NULL_TREE, V16QI_type_node, endlink));
04229
04230
04231 tree void_ftype_pvoid_int_char
04232 = build_function_type (void_type_node,
04233 tree_cons (NULL_TREE, pvoid_type_node,
04234 tree_cons (NULL_TREE, integer_type_node,
04235 tree_cons (NULL_TREE,
04236 char_type_node,
04237 endlink))));
04238
04239
04240 tree void_ftype_pint_v4si
04241 = build_function_type (void_type_node,
04242 tree_cons (NULL_TREE, pint_type_node,
04243 tree_cons (NULL_TREE, V4SI_type_node,
04244 endlink)));
04245
04246 tree void_ftype_pshort_v8hi
04247 = build_function_type (void_type_node,
04248 tree_cons (NULL_TREE, pshort_type_node,
04249 tree_cons (NULL_TREE, V8HI_type_node,
04250 endlink)));
04251
04252 tree void_ftype_pchar_v16qi
04253 = build_function_type (void_type_node,
04254 tree_cons (NULL_TREE, pchar_type_node,
04255 tree_cons (NULL_TREE, V16QI_type_node,
04256 endlink)));
04257
04258 tree void_ftype_pfloat_v4sf
04259 = build_function_type (void_type_node,
04260 tree_cons (NULL_TREE, pfloat_type_node,
04261 tree_cons (NULL_TREE, V4SF_type_node,
04262 endlink)));
04263
04264
04265 tree void_ftype_v4si
04266 = build_function_type (void_type_node,
04267 tree_cons (NULL_TREE, V4SI_type_node,
04268 endlink));
04269
04270
04271 tree void_ftype_v4si_int_pvoid
04272 = build_function_type (void_type_node,
04273 tree_cons (NULL_TREE, V4SI_type_node,
04274 tree_cons (NULL_TREE, integer_type_node,
04275 tree_cons (NULL_TREE,
04276 pvoid_type_node,
04277 endlink))));
04278
04279
04280 tree void_ftype_v16qi_int_pvoid
04281 = build_function_type (void_type_node,
04282 tree_cons (NULL_TREE, V16QI_type_node,
04283 tree_cons (NULL_TREE, integer_type_node,
04284 tree_cons (NULL_TREE,
04285 pvoid_type_node,
04286 endlink))));
04287
04288
04289 tree void_ftype_v8hi_int_pvoid
04290 = build_function_type (void_type_node,
04291 tree_cons (NULL_TREE, V8HI_type_node,
04292 tree_cons (NULL_TREE, integer_type_node,
04293 tree_cons (NULL_TREE,
04294 pvoid_type_node,
04295 endlink))));
04296
04297
04298 tree void_ftype_qi
04299 = build_function_type (void_type_node,
04300 tree_cons (NULL_TREE, char_type_node,
04301 endlink));
04302
04303
04304 tree void_ftype_void
04305 = build_function_type (void_type_node, void_list_node);
04306
04307
04308 tree v8hi_ftype_void
04309 = build_function_type (V8HI_type_node, void_list_node);
04310
04311 tree v4si_ftype_v4si_v4si
04312 = build_function_type (V4SI_type_node,
04313 tree_cons (NULL_TREE, V4SI_type_node,
04314 tree_cons (NULL_TREE, V4SI_type_node,
04315 endlink)));
04316
04317
04318
04319 tree v4sf_ftype_v4si_char
04320 = build_function_type (V4SF_type_node,
04321 tree_cons (NULL_TREE, V4SI_type_node,
04322 tree_cons (NULL_TREE, char_type_node,
04323 endlink)));
04324 tree v4si_ftype_v4sf_char
04325 = build_function_type (V4SI_type_node,
04326 tree_cons (NULL_TREE, V4SF_type_node,
04327 tree_cons (NULL_TREE, char_type_node,
04328 endlink)));
04329 tree v4si_ftype_v4si_char
04330 = build_function_type (V4SI_type_node,
04331 tree_cons (NULL_TREE, V4SI_type_node,
04332 tree_cons (NULL_TREE, char_type_node,
04333 endlink)));
04334 tree v8hi_ftype_v8hi_char
04335 = build_function_type (V8HI_type_node,
04336 tree_cons (NULL_TREE, V8HI_type_node,
04337 tree_cons (NULL_TREE, char_type_node,
04338 endlink)));
04339 tree v16qi_ftype_v16qi_char
04340 = build_function_type (V16QI_type_node,
04341 tree_cons (NULL_TREE, V16QI_type_node,
04342 tree_cons (NULL_TREE, char_type_node,
04343 endlink)));
04344
04345
04346
04347 tree v16qi_ftype_v16qi_v16qi_char
04348 = build_function_type (V16QI_type_node,
04349 tree_cons (NULL_TREE, V16QI_type_node,
04350 tree_cons (NULL_TREE, V16QI_type_node,
04351 tree_cons (NULL_TREE,
04352 char_type_node,
04353 endlink))));
04354
04355 tree v8hi_ftype_v8hi_v8hi_char
04356 = build_function_type (V8HI_type_node,
04357 tree_cons (NULL_TREE, V8HI_type_node,
04358 tree_cons (NULL_TREE, V8HI_type_node,
04359 tree_cons (NULL_TREE,
04360 char_type_node,
04361 endlink))));
04362
04363 tree v4si_ftype_v4si_v4si_char
04364 = build_function_type (V4SI_type_node,
04365 tree_cons (NULL_TREE, V4SI_type_node,
04366 tree_cons (NULL_TREE, V4SI_type_node,
04367 tree_cons (NULL_TREE,
04368 char_type_node,
04369 endlink))));
04370
04371 tree v4sf_ftype_v4sf_v4sf_char
04372 = build_function_type (V4SF_type_node,
04373 tree_cons (NULL_TREE, V4SF_type_node,
04374 tree_cons (NULL_TREE, V4SF_type_node,
04375 tree_cons (NULL_TREE,
04376 char_type_node,
04377 endlink))));
04378
04379
04380
04381 tree v4sf_ftype_v4sf_v4sf
04382 = build_function_type (V4SF_type_node,
04383 tree_cons (NULL_TREE, V4SF_type_node,
04384 tree_cons (NULL_TREE, V4SF_type_node,
04385 endlink)));
04386 tree v4sf_ftype_v4sf_v4sf_v4si
04387 = build_function_type (V4SF_type_node,
04388 tree_cons (NULL_TREE, V4SF_type_node,
04389 tree_cons (NULL_TREE, V4SF_type_node,
04390 tree_cons (NULL_TREE,
04391 V4SI_type_node,
04392 endlink))));
04393 tree v4sf_ftype_v4sf_v4sf_v4sf
04394 = build_function_type (V4SF_type_node,
04395 tree_cons (NULL_TREE, V4SF_type_node,
04396 tree_cons (NULL_TREE, V4SF_type_node,
04397 tree_cons (NULL_TREE,
04398 V4SF_type_node,
04399 endlink))));
04400 tree v4si_ftype_v4si_v4si_v4si
04401 = build_function_type (V4SI_type_node,
04402 tree_cons (NULL_TREE, V4SI_type_node,
04403 tree_cons (NULL_TREE, V4SI_type_node,
04404 tree_cons (NULL_TREE,
04405 V4SI_type_node,
04406 endlink))));
04407
04408 tree v8hi_ftype_v8hi_v8hi
04409 = build_function_type (V8HI_type_node,
04410 tree_cons (NULL_TREE, V8HI_type_node,
04411 tree_cons (NULL_TREE, V8HI_type_node,
04412 endlink)));
04413 tree v8hi_ftype_v8hi_v8hi_v8hi
04414 = build_function_type (V8HI_type_node,
04415 tree_cons (NULL_TREE, V8HI_type_node,
04416 tree_cons (NULL_TREE, V8HI_type_node,
04417 tree_cons (NULL_TREE,
04418 V8HI_type_node,
04419 endlink))));
04420 tree v4si_ftype_v8hi_v8hi_v4si
04421 = build_function_type (V4SI_type_node,
04422 tree_cons (NULL_TREE, V8HI_type_node,
04423 tree_cons (NULL_TREE, V8HI_type_node,
04424 tree_cons (NULL_TREE,
04425 V4SI_type_node,
04426 endlink))));
04427 tree v4si_ftype_v16qi_v16qi_v4si
04428 = build_function_type (V4SI_type_node,
04429 tree_cons (NULL_TREE, V16QI_type_node,
04430 tree_cons (NULL_TREE, V16QI_type_node,
04431 tree_cons (NULL_TREE,
04432 V4SI_type_node,
04433 endlink))));
04434
04435 tree v16qi_ftype_v16qi_v16qi
04436 = build_function_type (V16QI_type_node,
04437 tree_cons (NULL_TREE, V16QI_type_node,
04438 tree_cons (NULL_TREE, V16QI_type_node,
04439 endlink)));
04440
04441 tree v4si_ftype_v4sf_v4sf
04442 = build_function_type (V4SI_type_node,
04443 tree_cons (NULL_TREE, V4SF_type_node,
04444 tree_cons (NULL_TREE, V4SF_type_node,
04445 endlink)));
04446
04447 tree v4si_ftype_v4si
04448 = build_function_type (V4SI_type_node,
04449 tree_cons (NULL_TREE, V4SI_type_node, endlink));
04450
04451 tree v8hi_ftype_v8hi
04452 = build_function_type (V8HI_type_node,
04453 tree_cons (NULL_TREE, V8HI_type_node, endlink));
04454
04455 tree v16qi_ftype_v16qi
04456 = build_function_type (V16QI_type_node,
04457 tree_cons (NULL_TREE, V16QI_type_node, endlink));
04458
04459 tree v8hi_ftype_v16qi_v16qi
04460 = build_function_type (V8HI_type_node,
04461 tree_cons (NULL_TREE, V16QI_type_node,
04462 tree_cons (NULL_TREE, V16QI_type_node,
04463 endlink)));
04464
04465 tree v4si_ftype_v8hi_v8hi
04466 = build_function_type (V4SI_type_node,
04467 tree_cons (NULL_TREE, V8HI_type_node,
04468 tree_cons (NULL_TREE, V8HI_type_node,
04469 endlink)));
04470
04471 tree v8hi_ftype_v4si_v4si
04472 = build_function_type (V8HI_type_node,
04473 tree_cons (NULL_TREE, V4SI_type_node,
04474 tree_cons (NULL_TREE, V4SI_type_node,
04475 endlink)));
04476
04477 tree v16qi_ftype_v8hi_v8hi
04478 = build_function_type (V16QI_type_node,
04479 tree_cons (NULL_TREE, V8HI_type_node,
04480 tree_cons (NULL_TREE, V8HI_type_node,
04481 endlink)));
04482
04483 tree v4si_ftype_v16qi_v4si
04484 = build_function_type (V4SI_type_node,
04485 tree_cons (NULL_TREE, V16QI_type_node,
04486 tree_cons (NULL_TREE, V4SI_type_node,
04487 endlink)));
04488
04489 tree v4si_ftype_v16qi_v16qi
04490 = build_function_type (V4SI_type_node,
04491 tree_cons (NULL_TREE, V16QI_type_node,
04492 tree_cons (NULL_TREE, V16QI_type_node,
04493 endlink)));
04494
04495 tree v4si_ftype_v8hi_v4si
04496 = build_function_type (V4SI_type_node,
04497 tree_cons (NULL_TREE, V8HI_type_node,
04498 tree_cons (NULL_TREE, V4SI_type_node,
04499 endlink)));
04500
04501 tree v4si_ftype_v8hi
04502 = build_function_type (V4SI_type_node,
04503 tree_cons (NULL_TREE, V8HI_type_node, endlink));
04504
04505 tree int_ftype_v4si_v4si
04506 = build_function_type (integer_type_node,
04507 tree_cons (NULL_TREE, V4SI_type_node,
04508 tree_cons (NULL_TREE, V4SI_type_node,
04509 endlink)));
04510
04511 tree int_ftype_v4sf_v4sf
04512 = build_function_type (integer_type_node,
04513 tree_cons (NULL_TREE, V4SF_type_node,
04514 tree_cons (NULL_TREE, V4SF_type_node,
04515 endlink)));
04516
04517 tree int_ftype_v16qi_v16qi
04518 = build_function_type (integer_type_node,
04519 tree_cons (NULL_TREE, V16QI_type_node,
04520 tree_cons (NULL_TREE, V16QI_type_node,
04521 endlink)));
04522
04523 tree int_ftype_int_v4si_v4si
04524 = build_function_type
04525 (integer_type_node,
04526 tree_cons (NULL_TREE, integer_type_node,
04527 tree_cons (NULL_TREE, V4SI_type_node,
04528 tree_cons (NULL_TREE, V4SI_type_node,
04529 endlink))));
04530
04531 tree int_ftype_int_v4sf_v4sf
04532 = build_function_type
04533 (integer_type_node,
04534 tree_cons (NULL_TREE, integer_type_node,
04535 tree_cons (NULL_TREE, V4SF_type_node,
04536 tree_cons (NULL_TREE, V4SF_type_node,
04537 endlink))));
04538
04539 tree int_ftype_int_v8hi_v8hi
04540 = build_function_type
04541 (integer_type_node,
04542 tree_cons (NULL_TREE, integer_type_node,
04543 tree_cons (NULL_TREE, V8HI_type_node,
04544 tree_cons (NULL_TREE, V8HI_type_node,
04545 endlink))));
04546
04547 tree int_ftype_int_v16qi_v16qi
04548 = build_function_type
04549 (integer_type_node,
04550 tree_cons (NULL_TREE, integer_type_node,
04551 tree_cons (NULL_TREE, V16QI_type_node,
04552 tree_cons (NULL_TREE, V16QI_type_node,
04553 endlink))));
04554
04555 tree v16qi_ftype_int_pvoid
04556 = build_function_type (V16QI_type_node,
04557 tree_cons (NULL_TREE, integer_type_node,
04558 tree_cons (NULL_TREE, pvoid_type_node,
04559 endlink)));
04560
04561 tree v4si_ftype_int_pvoid
04562 = build_function_type (V4SI_type_node,
04563 tree_cons (NULL_TREE, integer_type_node,
04564 tree_cons (NULL_TREE, pvoid_type_node,
04565 endlink)));
04566
04567 tree v8hi_ftype_int_pvoid
04568 = build_function_type (V8HI_type_node,
04569 tree_cons (NULL_TREE, integer_type_node,
04570 tree_cons (NULL_TREE, pvoid_type_node,
04571 endlink)));
04572
04573 tree int_ftype_v8hi_v8hi
04574 = build_function_type (integer_type_node,
04575 tree_cons (NULL_TREE, V8HI_type_node,
04576 tree_cons (NULL_TREE, V8HI_type_node,
04577 endlink)));
04578
04579 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4sf", v4sf_ftype_pfloat, ALTIVEC_BUILTIN_LD_INTERNAL_4sf);
04580 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4sf", void_ftype_pfloat_v4sf, ALTIVEC_BUILTIN_ST_INTERNAL_4sf);
04581 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4si", v4si_ftype_pint, ALTIVEC_BUILTIN_LD_INTERNAL_4si);
04582 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4si", void_ftype_pint_v4si, ALTIVEC_BUILTIN_ST_INTERNAL_4si);
04583 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_8hi", v8hi_ftype_pshort, ALTIVEC_BUILTIN_LD_INTERNAL_8hi);
04584 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_8hi", void_ftype_pshort_v8hi, ALTIVEC_BUILTIN_ST_INTERNAL_8hi);
04585 def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_16qi", v16qi_ftype_pchar, ALTIVEC_BUILTIN_LD_INTERNAL_16qi);
04586 def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_16qi", void_ftype_pchar_v16qi, ALTIVEC_BUILTIN_ST_INTERNAL_16qi);
04587 def_builtin (MASK_ALTIVEC, "__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
04588 def_builtin (MASK_ALTIVEC, "__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
04589 def_builtin (MASK_ALTIVEC, "__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
04590 def_builtin (MASK_ALTIVEC, "__builtin_altivec_dss", void_ftype_qi, ALTIVEC_BUILTIN_DSS);
04591 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsl", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVSL);
04592 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsr", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVSR);
04593 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEBX);
04594 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEHX);
04595 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEWX);
04596 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVXL);
04597 def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVX);
04598 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVX);
04599 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_int_pvoid, ALTIVEC_BUILTIN_STVEBX);
04600 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_int_pvoid, ALTIVEC_BUILTIN_STVEHX);
04601 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvewx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVEWX);
04602 def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVXL);
04603
04604
04605 d = (struct builtin_description *) bdesc_3arg;
04606 for (i = 0; i < sizeof (bdesc_3arg) / sizeof *d; i++, d++)
04607 {
04608
04609 enum machine_mode mode0, mode1, mode2, mode3;
04610 tree type;
04611
04612 if (d->name == 0)
04613 continue;
04614
04615 mode0 = insn_data[d->icode].operand[0].mode;
04616 mode1 = insn_data[d->icode].operand[1].mode;
04617 mode2 = insn_data[d->icode].operand[2].mode;
04618 mode3 = insn_data[d->icode].operand[3].mode;
04619
04620
04621 if (mode0 == mode1 && mode1 == mode2 && mode2 == mode3)
04622 {
04623 switch (mode0)
04624 {
04625 case V4SImode:
04626 type = v4si_ftype_v4si_v4si_v4si;
04627 break;
04628 case V4SFmode:
04629 type = v4sf_ftype_v4sf_v4sf_v4sf;
04630 break;
04631 case V8HImode:
04632 type = v8hi_ftype_v8hi_v8hi_v8hi;
04633 break;
04634 case V16QImode:
04635 type = v16qi_ftype_v16qi_v16qi_v16qi;
04636 break;
04637 default:
04638 abort();
04639 }
04640 }
04641 else if (mode0 == mode1 && mode1 == mode2 && mode3 == V16QImode)
04642 {
04643 switch (mode0)
04644 {
04645 case V4SImode:
04646 type = v4si_ftype_v4si_v4si_v16qi;
04647 break;
04648 case V4SFmode:
04649 type = v4sf_ftype_v4sf_v4sf_v16qi;
04650 break;
04651 case V8HImode:
04652 type = v8hi_ftype_v8hi_v8hi_v16qi;
04653 break;
04654 case V16QImode:
04655 type = v16qi_ftype_v16qi_v16qi_v16qi;
04656 break;
04657 default:
04658 abort();
04659 }
04660 }
04661 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode
04662 && mode3 == V4SImode)
04663 type = v4si_ftype_v16qi_v16qi_v4si;
04664 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode
04665 && mode3 == V4SImode)
04666 type = v4si_ftype_v8hi_v8hi_v4si;
04667 else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode
04668 && mode3 == V4SImode)
04669 type = v4sf_ftype_v4sf_v4sf_v4si;
04670
04671
04672 else if (mode0 == V16QImode && mode1 == mode0 && mode2 == mode0
04673 && mode3 == QImode)
04674 type = v16qi_ftype_v16qi_v16qi_char;
04675
04676
04677 else if (mode0 == V8HImode && mode1 == mode0 && mode2 == mode0
04678 && mode3 == QImode)
04679 type = v8hi_ftype_v8hi_v8hi_char;
04680
04681
04682 else if (mode0 == V4SImode && mode1 == mode0 && mode2 == mode0
04683 && mode3 == QImode)
04684 type = v4si_ftype_v4si_v4si_char;
04685
04686
04687 else if (mode0 == V4SFmode && mode1 == mode0 && mode2 == mode0
04688 && mode3 == QImode)
04689 type = v4sf_ftype_v4sf_v4sf_char;
04690
04691 else
04692 abort ();
04693
04694 def_builtin (d->mask, d->name, type, d->code);
04695 }
04696
04697
04698 d = (struct builtin_description *) bdesc_dst;
04699 for (i = 0; i < sizeof (bdesc_dst) / sizeof *d; i++, d++)
04700 def_builtin (d->mask, d->name, void_ftype_pvoid_int_char, d->code);
04701
04702
04703 dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
04704 for (i = 0; i < sizeof (bdesc_altivec_preds) / sizeof *dp; i++, dp++)
04705 {
04706 enum machine_mode mode1;
04707 tree type;
04708
04709 mode1 = insn_data[dp->icode].operand[1].mode;
04710
04711 switch (mode1)
04712 {
04713 case V4SImode:
04714 type = int_ftype_int_v4si_v4si;
04715 break;
04716 case V8HImode:
04717 type = int_ftype_int_v8hi_v8hi;
04718 break;
04719 case V16QImode:
04720 type = int_ftype_int_v16qi_v16qi;
04721 break;
04722 case V4SFmode:
04723 type = int_ftype_int_v4sf_v4sf;
04724 break;
04725 default:
04726 abort ();
04727 }
04728
04729 def_builtin (dp->mask, dp->name, type, dp->code);
04730 }
04731
04732
04733 d = (struct builtin_description *) bdesc_2arg;
04734 for (i = 0; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
04735 {
04736 enum machine_mode mode0, mode1, mode2;
04737 tree type;
04738
04739 if (d->name == 0)
04740 continue;
04741
04742 mode0 = insn_data[d->icode].operand[0].mode;
04743 mode1 = insn_data[d->icode].operand[1].mode;
04744 mode2 = insn_data[d->icode].operand[2].mode;
04745
04746
04747 if (mode0 == mode1 && mode1 == mode2)
04748 {
04749 switch (mode0)
04750 {
04751 case V4SFmode:
04752 type = v4sf_ftype_v4sf_v4sf;
04753 break;
04754 case V4SImode:
04755 type = v4si_ftype_v4si_v4si;
04756 break;
04757 case V16QImode:
04758 type = v16qi_ftype_v16qi_v16qi;
04759 break;
04760 case V8HImode:
04761 type = v8hi_ftype_v8hi_v8hi;
04762 break;
04763 default:
04764 abort ();
04765 }
04766 }
04767
04768
04769
04770
04771 else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
04772 type = v4si_ftype_v4sf_v4sf;
04773
04774
04775 else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
04776 type = v8hi_ftype_v16qi_v16qi;
04777
04778
04779 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode)
04780 type = v4si_ftype_v8hi_v8hi;
04781
04782
04783 else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
04784 type = v8hi_ftype_v4si_v4si;
04785
04786
04787 else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
04788 type = v16qi_ftype_v8hi_v8hi;
04789
04790
04791 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
04792 type = v4si_ftype_v16qi_v4si;
04793
04794
04795 else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode)
04796 type = v4si_ftype_v16qi_v16qi;
04797
04798
04799 else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
04800 type = v4si_ftype_v8hi_v4si;
04801
04802
04803 else if (mode0 == V4SImode && mode1 == V4SImode && mode2 == QImode)
04804 type = v4si_ftype_v4si_char;
04805
04806
04807 else if (mode0 == V8HImode && mode1 == V8HImode && mode2 == QImode)
04808 type = v8hi_ftype_v8hi_char;
04809
04810
04811 else if (mode0 == V16QImode && mode1 == V16QImode && mode2 == QImode)
04812 type = v16qi_ftype_v16qi_char;
04813
04814
04815 else if (mode0 == V4SFmode && mode1 == V4SImode && mode2 == QImode)
04816 type = v4sf_ftype_v4si_char;
04817
04818
04819 else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode)
04820 type = v4si_ftype_v4sf_char;
04821
04822
04823 else if (mode0 == SImode)
04824 {
04825 switch (mode1)
04826 {
04827 case V4SImode:
04828 type = int_ftype_v4si_v4si;
04829 break;
04830 case V4SFmode:
04831 type = int_ftype_v4sf_v4sf;
04832 break;
04833 case V16QImode:
04834 type = int_ftype_v16qi_v16qi;
04835 break;
04836 case V8HImode:
04837 type = int_ftype_v8hi_v8hi;
04838 break;
04839 default:
04840 abort ();
04841 }
04842 }
04843
04844 else
04845 abort ();
04846
04847 def_builtin (d->mask, d->name, type, d->code);
04848 }
04849
04850
04851 d = (struct builtin_description *) bdesc_abs;
04852 for (i = 0; i < sizeof (bdesc_abs) / sizeof *d; i++, d++)
04853 {
04854 enum machine_mode mode0;
04855 tree type;
04856
04857 mode0 = insn_data[d->icode].operand[0].mode;
04858
04859 switch (mode0)
04860 {
04861 case V4SImode:
04862 type = v4si_ftype_v4si;
04863 break;
04864 case V8HImode:
04865 type = v8hi_ftype_v8hi;
04866 break;
04867 case V16QImode:
04868 type = v16qi_ftype_v16qi;
04869 break;
04870 case V4SFmode:
04871 type = v4sf_ftype_v4sf;
04872 break;
04873 default:
04874 abort ();
04875 }
04876
04877 def_builtin (d->mask, d->name, type, d->code);
04878 }
04879
04880
04881 d = (struct builtin_description *) bdesc_1arg;
04882 for (i = 0; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++)
04883 {
04884 enum machine_mode mode0, mode1;
04885 tree type;
04886
04887 if (d->name == 0)
04888 continue;
04889
04890 mode0 = insn_data[d->icode].operand[0].mode;
04891 mode1 = insn_data[d->icode].operand[1].mode;
04892
04893 if (mode0 == V4SImode && mode1 == QImode)
04894 type = v4si_ftype_char;
04895 else if (mode0 == V8HImode && mode1 == QImode)
04896 type = v8hi_ftype_char;
04897 else if (mode0 == V16QImode && mode1 == QImode)
04898 type = v16qi_ftype_char;
04899 else if (mode0 == V4SFmode && mode1 == V4SFmode)
04900 type = v4sf_ftype_v4sf;
04901 else if (mode0 == V8HImode && mode1 == V16QImode)
04902 type = v8hi_ftype_v16qi;
04903 else if (mode0 == V4SImode && mode1 == V8HImode)
04904 type = v4si_ftype_v8hi;
04905 else
04906 abort ();
04907
04908 def_builtin (d->mask, d->name, type, d->code);
04909 }
04910 }
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921 #define MAX_MOVE_REG 4
04922
04923 int
04924 expand_block_move (operands)
04925 rtx operands[];
04926 {
04927 rtx orig_dest = operands[0];
04928 rtx orig_src = operands[1];
04929 rtx bytes_rtx = operands[2];
04930 rtx align_rtx = operands[3];
04931 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
04932 int align;
04933 int bytes;
04934 int offset;
04935 int move_bytes;
04936
04937
04938 if (! constp)
04939 return 0;
04940
04941
04942 if (GET_CODE (align_rtx) != CONST_INT)
04943 abort ();
04944 align = INTVAL (align_rtx);
04945
04946
04947 bytes = INTVAL (bytes_rtx);
04948 if (bytes <= 0)
04949 return 1;
04950
04951
04952
04953 if (bytes > (TARGET_POWERPC64 ? 64 : 32))
04954 return 0;
04955
04956 if (TARGET_STRING)
04957 {
04958 for (offset = 0; bytes > 0; offset += move_bytes, bytes -= move_bytes)
04959 {
04960 union {
04961 rtx (*movstrsi) PARAMS ((rtx, rtx, rtx, rtx));
04962 rtx (*mov) PARAMS ((rtx, rtx));
04963 } gen_func;
04964 enum machine_mode mode = BLKmode;
04965 rtx src, dest;
04966
04967 if (bytes > 24
04968 && ! fixed_regs[5]
04969 && ! fixed_regs[6]
04970 && ! fixed_regs[7]
04971 && ! fixed_regs[8]
04972 && ! fixed_regs[9]
04973 && ! fixed_regs[10]
04974 && ! fixed_regs[11]
04975 && ! fixed_regs[12])
04976 {
04977 move_bytes = (bytes > 32) ? 32 : bytes;
04978 gen_func.movstrsi = gen_movstrsi_8reg;
04979 }
04980 else if (bytes > 16
04981 && ! fixed_regs[5]
04982 && ! fixed_regs[6]
04983 && ! fixed_regs[7]
04984 && ! fixed_regs[8]
04985 && ! fixed_regs[9]
04986 && ! fixed_regs[10])
04987 {
04988 move_bytes = (bytes > 24) ? 24 : bytes;
04989 gen_func.movstrsi = gen_movstrsi_6reg;
04990 }
04991 else if (bytes > 8
04992 && ! fixed_regs[5]
04993 && ! fixed_regs[6]
04994 && ! fixed_regs[7]
04995 && ! fixed_regs[8])
04996 {
04997 move_bytes = (bytes > 16) ? 16 : bytes;
04998 gen_func.movstrsi = gen_movstrsi_4reg;
04999 }
05000 else if (bytes >= 8 && TARGET_POWERPC64
05001
05002
05003 && (align >= 8 || (! STRICT_ALIGNMENT && align >= 4)))
05004 {
05005 move_bytes = 8;
05006 mode = DImode;
05007 gen_func.mov = gen_movdi;
05008 }
05009 else if (bytes > 4 && !TARGET_POWERPC64)
05010 {
05011 move_bytes = (bytes > 8) ? 8 : bytes;
05012 gen_func.movstrsi = gen_movstrsi_2reg;
05013 }
05014 else if (bytes >= 4 && (align >= 4 || ! STRICT_ALIGNMENT))
05015 {
05016 move_bytes = 4;
05017 mode = SImode;
05018 gen_func.mov = gen_movsi;
05019 }
05020 else if (bytes == 2 && (align >= 2 || ! STRICT_ALIGNMENT))
05021 {
05022 move_bytes = 2;
05023 mode = HImode;
05024 gen_func.mov = gen_movhi;
05025 }
05026 else if (bytes == 1)
05027 {
05028 move_bytes = 1;
05029 mode = QImode;
05030 gen_func.mov = gen_movqi;
05031 }
05032 else
05033 {
05034 move_bytes = (bytes > 4) ? 4 : bytes;
05035 gen_func.movstrsi = gen_movstrsi_1reg;
05036 }
05037
05038 src = adjust_address (orig_src, mode, offset);
05039 dest = adjust_address (orig_dest, mode, offset);
05040
05041 if (mode == BLKmode)
05042 {
05043
05044
05045 if (!REG_P (XEXP (src, 0)))
05046 {
05047 rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
05048 src = replace_equiv_address (src, src_reg);
05049 }
05050 set_mem_size (src, GEN_INT (move_bytes));
05051
05052 if (!REG_P (XEXP (dest, 0)))
05053 {
05054 rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
05055 dest = replace_equiv_address (dest, dest_reg);
05056 }
05057 set_mem_size (dest, GEN_INT (move_bytes));
05058
05059 emit_insn ((*gen_func.movstrsi) (dest, src,
05060 GEN_INT (move_bytes & 31),
05061 align_rtx));
05062 }
05063 else
05064 {
05065 rtx tmp_reg = gen_reg_rtx (mode);
05066
05067 emit_insn ((*gen_func.mov) (tmp_reg, src));
05068 emit_insn ((*gen_func.mov) (dest, tmp_reg));
05069 }
05070 }
05071 }
05072
05073 else
05074 {
05075 rtx stores[MAX_MOVE_REG];
05076 int num_reg = 0;
05077 int i;
05078
05079 for (offset = 0; bytes > 0; offset += move_bytes, bytes -= move_bytes)
05080 {
05081 rtx (*gen_mov_func) PARAMS ((rtx, rtx));
05082 enum machine_mode mode;
05083 rtx src, dest, tmp_reg;
05084
05085
05086
05087 if (bytes >= 8 && TARGET_POWERPC64
05088
05089
05090 && (align >= 8 || (! STRICT_ALIGNMENT && align >= 4)))
05091 {
05092 move_bytes = 8;
05093 mode = DImode;
05094 gen_mov_func = gen_movdi;
05095 }
05096 else if (bytes >= 4 && (align >= 4 || ! STRICT_ALIGNMENT))
05097 {
05098 move_bytes = 4;
05099 mode = SImode;
05100 gen_mov_func = gen_movsi;
05101 }
05102 else if (bytes >= 2 && (align >= 2 || ! STRICT_ALIGNMENT))
05103 {
05104 move_bytes = 2;
05105 mode = HImode;
05106 gen_mov_func = gen_movhi;
05107 }
05108 else
05109 {
05110 move_bytes = 1;
05111 mode = QImode;
05112 gen_mov_func = gen_movqi;
05113 }
05114
05115 src = adjust_address (orig_src, mode, offset);
05116 dest = adjust_address (orig_dest, mode, offset);
05117 tmp_reg = gen_reg_rtx (mode);
05118
05119 emit_insn ((*gen_mov_func) (tmp_reg, src));
05120 stores[num_reg++] = (*gen_mov_func) (dest, tmp_reg);
05121
05122 if (num_reg >= MAX_MOVE_REG)
05123 {
05124 for (i = 0; i < num_reg; i++)
05125 emit_insn (stores[i]);
05126 num_reg = 0;
05127 }
05128 }
05129
05130 for (i = 0; i < num_reg; i++)
05131 emit_insn (stores[i]);
05132 }
05133
05134 return 1;
05135 }
05136
05137
05138
05139
05140
05141 int
05142 load_multiple_operation (op, mode)
05143 rtx op;
05144 enum machine_mode mode ATTRIBUTE_UNUSED;
05145 {
05146 int count = XVECLEN (op, 0);
05147 unsigned int dest_regno;
05148 rtx src_addr;
05149 int i;
05150
05151
05152 if (count <= 1
05153 || GET_CODE (XVECEXP (op, 0, 0)) != SET
05154 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
05155 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
05156 return 0;
05157
05158 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
05159 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
05160
05161 for (i = 1; i < count; i++)
05162 {
05163 rtx elt = XVECEXP (op, 0, i);
05164
05165 if (GET_CODE (elt) != SET
05166 || GET_CODE (SET_DEST (elt)) != REG
05167 || GET_MODE (SET_DEST (elt)) != SImode
05168 || REGNO (SET_DEST (elt)) != dest_regno + i
05169 || GET_CODE (SET_SRC (elt)) != MEM
05170 || GET_MODE (SET_SRC (elt)) != SImode
05171 || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
05172 || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
05173 || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
05174 || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
05175 return 0;
05176 }
05177
05178 return 1;
05179 }
05180
05181
05182
05183
05184 int
05185 store_multiple_operation (op, mode)
05186 rtx op;
05187 enum machine_mode mode ATTRIBUTE_UNUSED;
05188 {
05189 int count = XVECLEN (op, 0) - 1;
05190 unsigned int src_regno;
05191 rtx dest_addr;
05192 int i;
05193
05194
05195 if (count <= 1
05196 || GET_CODE (XVECEXP (op, 0, 0)) != SET
05197 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
05198 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
05199 return 0;
05200
05201 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
05202 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
05203
05204 for (i = 1; i < count; i++)
05205 {
05206 rtx elt = XVECEXP (op, 0, i + 1);
05207
05208 if (GET_CODE (elt) != SET
05209 || GET_CODE (SET_SRC (elt)) != REG
05210 || GET_MODE (SET_SRC (elt)) != SImode
05211 || REGNO (SET_SRC (elt)) != src_regno + i
05212 || GET_CODE (SET_DEST (elt)) != MEM
05213 || GET_MODE (SET_DEST (elt)) != SImode
05214 || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
05215 || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
05216 || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
05217 || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
05218 return 0;
05219 }
05220
05221 return 1;
05222 }
05223
05224
05225
05226
05227
05228
05229 const char *
05230 rs6000_output_load_multiple (operands)
05231 rtx operands[3];
05232 {
05233
05234
05235 int i, j;
05236 int words = XVECLEN (operands[0], 0);
05237 rtx xop[10];
05238
05239 if (XVECLEN (operands[0], 0) == 1)
05240 return "{l|lwz} %2,0(%1)";
05241
05242 for (i = 0; i < words; i++)
05243 if (refers_to_regno_p (REGNO (operands[2]) + i,
05244 REGNO (operands[2]) + i + 1, operands[1], 0))
05245 {
05246 if (i == words-1)
05247 {
05248 xop[0] = GEN_INT (4 * (words-1));
05249 xop[1] = operands[1];
05250 xop[2] = operands[2];
05251 output_asm_insn ("{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,%0(%1)", xop);
05252 return "";
05253 }
05254 else if (i == 0)
05255 {
05256 xop[0] = GEN_INT (4 * (words-1));
05257 xop[1] = operands[1];
05258 xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
05259 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);
05260 return "";
05261 }
05262 else
05263 {
05264 for (j = 0; j < words; j++)
05265 if (j != i)
05266 {
05267 xop[0] = GEN_INT (j * 4);
05268 xop[1] = operands[1];
05269 xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + j);
05270 output_asm_insn ("{l|lwz} %2,%0(%1)", xop);
05271 }
05272 xop[0] = GEN_INT (i * 4);
05273 xop[1] = operands[1];
05274 output_asm_insn ("{l|lwz} %1,%0(%1)", xop);
05275 return "";
05276 }
05277 }
05278
05279 return "{lsi|lswi} %2,%1,%N0";
05280 }
05281
05282
05283
05284 int
05285 vrsave_operation (op, mode)
05286 rtx op;
05287 enum machine_mode mode ATTRIBUTE_UNUSED;
05288 {
05289 int count = XVECLEN (op, 0);
05290 unsigned int dest_regno, src_regno;
05291 int i;
05292
05293 if (count <= 1
05294 || GET_CODE (XVECEXP (op, 0, 0)) != SET
05295 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
05296 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC_VOLATILE)
05297 return 0;
05298
05299 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
05300 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
05301
05302 if (dest_regno != VRSAVE_REGNO
05303 && src_regno != VRSAVE_REGNO)
05304 return 0;
05305
05306 for (i = 1; i < count; i++)
05307 {
05308 rtx elt = XVECEXP (op, 0, i);
05309
05310 if (GET_CODE (elt) != CLOBBER
05311 && GET_CODE (elt) != SET)
05312 return 0;
05313 }
05314
05315 return 1;
05316 }
05317
05318
05319
05320 int
05321 mtcrf_operation (op, mode)
05322 rtx op;
05323 enum machine_mode mode ATTRIBUTE_UNUSED;
05324 {
05325 int count = XVECLEN (op, 0);
05326 int i;
05327 rtx src_reg;
05328
05329
05330 if (count < 1
05331 || GET_CODE (XVECEXP (op, 0, 0)) != SET
05332 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
05333 || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
05334 return 0;
05335 src_reg = XVECEXP (SET_SRC (XVECEXP (op, 0, 0)), 0, 0);
05336
05337 if (GET_CODE (src_reg) != REG
05338 || GET_MODE (src_reg) != SImode
05339 || ! INT_REGNO_P (REGNO (src_reg)))
05340 return 0;
05341
05342 for (i = 0; i < count; i++)
05343 {
05344 rtx exp = XVECEXP (op, 0, i);
05345 rtx unspec;
05346 int maskval;
05347
05348 if (GET_CODE (exp) != SET
05349 || GET_CODE (SET_DEST (exp)) != REG
05350 || GET_MODE (SET_DEST (exp)) != CCmode
05351 || ! CR_REGNO_P (REGNO (SET_DEST (exp))))
05352 return 0;
05353 unspec = SET_SRC (exp);
05354 maskval = 1 << (MAX_CR_REGNO - REGNO (SET_DEST (exp)));
05355
05356 if (GET_CODE (unspec) != UNSPEC
05357 || XINT (unspec, 1) != 20
05358 || XVECLEN (unspec, 0) != 2
05359 || XVECEXP (unspec, 0, 0) != src_reg
05360 || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
05361 || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
05362 return 0;
05363 }
05364 return 1;
05365 }
05366
05367
05368
05369 int
05370 lmw_operation (op, mode)
05371 rtx op;
05372 enum machine_mode mode ATTRIBUTE_UNUSED;
05373 {
05374 int count = XVECLEN (op, 0);
05375 unsigned int dest_regno;
05376 rtx src_addr;
05377 unsigned int base_regno;
05378 HOST_WIDE_INT offset;
05379 int i;
05380
05381
05382 if (count <= 1
05383 || GET_CODE (XVECEXP (op, 0, 0)) != SET
05384 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
05385 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
05386 return 0;
05387
05388 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
05389 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
05390
05391 if (dest_regno > 31
05392 || count != 32 - (int) dest_regno)
05393 return 0;
05394
05395 if (LEGITIMATE_INDIRECT_ADDRESS_P (src_addr, 0))
05396 {
05397 offset = 0;
05398 base_regno = REGNO (src_addr);
05399 if (base_regno == 0)
05400 return 0;
05401 }
05402 else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, src_addr, 0))
05403 {
05404 offset = INTVAL (XEXP (src_addr, 1));
05405 base_regno = REGNO (XEXP (src_addr, 0));
05406 }
05407 else
05408 return 0;
05409
05410 for (i = 0; i < count; i++)
05411 {
05412 rtx elt = XVECEXP (op, 0, i);
05413 rtx newaddr;
05414 rtx addr_reg;
05415 HOST_WIDE_INT newoffset;
05416
05417 if (GET_CODE (elt) != SET
05418 || GET_CODE (SET_DEST (elt)) != REG
05419 || GET_MODE (SET_DEST (elt)) != SImode
05420 || REGNO (SET_DEST (elt)) != dest_regno + i
05421 || GET_CODE (SET_SRC (elt)) != MEM
05422 || GET_MODE (SET_SRC (elt)) != SImode)
05423 return 0;
05424 newaddr = XEXP (SET_SRC (elt), 0);
05425 if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr, 0))
05426 {
05427 newoffset = 0;
05428 addr_reg = newaddr;
05429 }
05430 else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr, 0))
05431 {
05432 addr_reg = XEXP (newaddr, 0);
05433 newoffset = INTVAL (XEXP (newaddr, 1));
05434 }
05435 else
05436 return 0;
05437 if (REGNO (addr_reg) != base_regno
05438 || newoffset != offset + 4 * i)
05439 return 0;
05440 }
05441
05442 return 1;
05443 }
05444
05445
05446
05447 int
05448 stmw_operation (op, mode)
05449 rtx op;
05450 enum machine_mode mode ATTRIBUTE_UNUSED;
05451 {
05452 int count = XVECLEN (op, 0);
05453 unsigned int src_regno;
05454 rtx dest_addr;
05455 unsigned int base_regno;
05456 HOST_WIDE_INT offset;
05457 int i;
05458
05459
05460 if (count <= 1
05461 || GET_CODE (XVECEXP (op, 0, 0)) != SET
05462 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
05463 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
05464 return 0;
05465
05466 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
05467 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
05468
05469 if (src_regno > 31
05470 || count != 32 - (int) src_regno)
05471 return 0;
05472
05473 if (LEGITIMATE_INDIRECT_ADDRESS_P (dest_addr, 0))
05474 {
05475 offset = 0;
05476 base_regno = REGNO (dest_addr);
05477 if (base_regno == 0)
05478 return 0;
05479 }
05480 else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, dest_addr, 0))
05481 {
05482 offset = INTVAL (XEXP (dest_addr, 1));
05483 base_regno = REGNO (XEXP (dest_addr, 0));
05484 }
05485 else
05486 return 0;
05487
05488 for (i = 0; i < count; i++)
05489 {
05490 rtx elt = XVECEXP (op, 0, i);
05491 rtx newaddr;
05492 rtx addr_reg;
05493 HOST_WIDE_INT newoffset;
05494
05495 if (GET_CODE (elt) != SET
05496 || GET_CODE (SET_SRC (elt)) != REG
05497 || GET_MODE (SET_SRC (elt)) != SImode
05498 || REGNO (SET_SRC (elt)) != src_regno + i
05499 || GET_CODE (SET_DEST (elt)) != MEM
05500 || GET_MODE (SET_DEST (elt)) != SImode)
05501 return 0;
05502 newaddr = XEXP (SET_DEST (elt), 0);
05503 if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr, 0))
05504 {
05505 newoffset = 0;
05506 addr_reg = newaddr;
05507 }
05508 else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr, 0))
05509 {
05510 addr_reg = XEXP (newaddr, 0);
05511 newoffset = INTVAL (XEXP (newaddr, 1));
05512 }
05513 else
05514 return 0;
05515 if (REGNO (addr_reg) != base_regno
05516 || newoffset != offset + 4 * i)
05517 return 0;
05518 }
05519
05520 return 1;
05521 }
05522
05523
05524
05525
05526
05527 static void
05528 validate_condition_mode (code, mode)
05529 enum rtx_code code;
05530 enum machine_mode mode;
05531 {
05532 if (GET_RTX_CLASS (code) != '<'
05533 || GET_MODE_CLASS (mode) != MODE_CC)
05534 abort ();
05535
05536
05537 if ((code == GT || code == LT || code == GE || code == LE)
05538 && mode == CCUNSmode)
05539 abort ();
05540
05541 if ((code == GTU || code == LTU || code == GEU || code == LEU)
05542 && mode != CCUNSmode)
05543 abort ();
05544
05545 if (mode != CCFPmode
05546 && (code == ORDERED || code == UNORDERED
05547 || code == UNEQ || code == LTGT
05548 || code == UNGT || code == UNLT
05549 || code == UNGE || code == UNLE))
05550 abort ();
05551
05552
05553
05554 if (mode == CCFPmode
05555 && ! flag_unsafe_math_optimizations
05556 && (code == LE || code == GE
05557 || code == UNEQ || code == LTGT
05558 || code == UNGT || code == UNLT))
05559 abort ();
05560
05561
05562 if (mode == CCEQmode
05563 && code != EQ && code != NE)
05564 abort ();
05565 }
05566
05567
05568
05569
05570 int
05571 branch_comparison_operator (op, mode)
05572 rtx op;
05573 enum machine_mode mode ATTRIBUTE_UNUSED;
05574 {
05575 enum rtx_code code = GET_CODE (op);
05576 enum machine_mode cc_mode;
05577
05578 if (GET_RTX_CLASS (code) != '<')
05579 return 0;
05580
05581 cc_mode = GET_MODE (XEXP (op, 0));
05582 if (GET_MODE_CLASS (cc_mode) != MODE_CC)
05583 return 0;
05584
05585 validate_condition_mode (code, cc_mode);
05586
05587 return 1;
05588 }
05589
05590
05591
05592
05593
05594 int
05595 branch_positive_comparison_operator (op, mode)
05596 rtx op;
05597 enum machine_mode mode;
05598 {
05599 enum rtx_code code;
05600
05601 if (! branch_comparison_operator (op, mode))
05602 return 0;
05603
05604 code = GET_CODE (op);
05605 return (code == EQ || code == LT || code == GT
05606 || code == LTU || code == GTU
05607 || code == UNORDERED);
05608 }
05609
05610
05611
05612
05613
05614 int
05615 scc_comparison_operator (op, mode)
05616 rtx op;
05617 enum machine_mode mode;
05618 {
05619 enum rtx_code code = GET_CODE (op);
05620 enum machine_mode cc_mode;
05621
05622 if (GET_MODE (op) != mode && mode != VOIDmode)
05623 return 0;
05624
05625 if (GET_RTX_CLASS (code) != '<')
05626 return 0;
05627
05628 cc_mode = GET_MODE (XEXP (op, 0));
05629 if (GET_MODE_CLASS (cc_mode) != MODE_CC)
05630 return 0;
05631
05632 validate_condition_mode (code, cc_mode);
05633
05634 if (code == NE && cc_mode != CCFPmode)
05635 return 0;
05636
05637 return 1;
05638 }
05639
05640 int
05641 trap_comparison_operator (op, mode)
05642 rtx op;
05643 enum machine_mode mode;
05644 {
05645 if (mode != VOIDmode && mode != GET_MODE (op))
05646 return 0;
05647 return GET_RTX_CLASS (GET_CODE (op)) == '<';
05648 }
05649
05650 int
05651 boolean_operator (op, mode)
05652 rtx op;
05653 enum machine_mode mode ATTRIBUTE_UNUSED;
05654 {
05655 enum rtx_code code = GET_CODE (op);
05656 return (code == AND || code == IOR || code == XOR);
05657 }
05658
05659 int
05660 boolean_or_operator (op, mode)
05661 rtx op;
05662 enum machine_mode mode ATTRIBUTE_UNUSED;
05663 {
05664 enum rtx_code code = GET_CODE (op);
05665 return (code == IOR || code == XOR);
05666 }
05667
05668 int
05669 min_max_operator (op, mode)
05670 rtx op;
05671 enum machine_mode mode ATTRIBUTE_UNUSED;
05672 {
05673 enum rtx_code code = GET_CODE (op);
05674 return (code == SMIN || code == SMAX || code == UMIN || code == UMAX);
05675 }
05676
05677
05678
05679
05680
05681 int
05682 includes_lshift_p (shiftop, andop)
05683 rtx shiftop;
05684 rtx andop;
05685 {
05686 unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
05687
05688 shift_mask <<= INTVAL (shiftop);
05689
05690 return (INTVAL (andop) & 0xffffffff & ~shift_mask) == 0;
05691 }
05692
05693
05694
05695 int
05696 includes_rshift_p (shiftop, andop)
05697 rtx shiftop;
05698 rtx andop;
05699 {
05700 unsigned HOST_WIDE_INT shift_mask = ~(unsigned HOST_WIDE_INT) 0;
05701
05702 shift_mask >>= INTVAL (shiftop);
05703
05704 return (INTVAL (andop) & 0xffffffff & ~shift_mask) == 0;
05705 }
05706
05707
05708
05709
05710
05711 int
05712 includes_rldic_lshift_p (shiftop, andop)
05713 rtx shiftop;
05714 rtx andop;
05715 {
05716 if (GET_CODE (andop) == CONST_INT)
05717 {
05718 HOST_WIDE_INT c, lsb, shift_mask;
05719
05720 c = INTVAL (andop);
05721 if (c == 0 || c == ~0)
05722 return 0;
05723
05724 shift_mask = ~0;
05725 shift_mask <<= INTVAL (shiftop);
05726
05727
05728 lsb = c & -c;
05729
05730
05731 if (-lsb != shift_mask)
05732 return 0;
05733
05734
05735 c = ~c;
05736
05737
05738 c &= -lsb;
05739
05740
05741 lsb = c & -c;
05742 return c == -lsb;
05743 }
05744 else if (GET_CODE (andop) == CONST_DOUBLE
05745 && (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
05746 {
05747 HOST_WIDE_INT low, high, lsb;
05748 HOST_WIDE_INT shift_mask_low, shift_mask_high;
05749
05750 low = CONST_DOUBLE_LOW (andop);
05751 if (HOST_BITS_PER_WIDE_INT < 64)
05752 high = CONST_DOUBLE_HIGH (andop);
05753
05754 if ((low == 0 && (HOST_BITS_PER_WIDE_INT >= 64 || high == 0))
05755 || (low == ~0 && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0)))
05756 return 0;
05757
05758 if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
05759 {
05760 shift_mask_high = ~0;
05761 if (INTVAL (shiftop) > 32)
05762 shift_mask_high <<= INTVAL (shiftop) - 32;
05763
05764 lsb = high & -high;
05765
05766 if (-lsb != shift_mask_high || INTVAL (shiftop) < 32)
05767 return 0;
05768
05769 high = ~high;
05770 high &= -lsb;
05771
05772 lsb = high & -high;
05773 return high == -lsb;
05774 }
05775
05776 shift_mask_low = ~0;
05777 shift_mask_low <<= INTVAL (shiftop);
05778
05779 lsb = low & -low;
05780
05781 if (-lsb != shift_mask_low)
05782 return 0;
05783
05784 if (HOST_BITS_PER_WIDE_INT < 64)
05785 high = ~high;
05786 low = ~low;
05787 low &= -lsb;
05788
05789 if (HOST_BITS_PER_WIDE_INT < 64 && low == 0)
05790 {
05791 lsb = high & -high;
05792 return high == -lsb;
05793 }
05794
05795 lsb = low & -low;
05796 return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0);
05797 }
05798 else
05799 return 0;
05800 }
05801
05802
05803
05804
05805
05806 int
05807 includes_rldicr_lshift_p (shiftop, andop)
05808 rtx shiftop;
05809 rtx andop;
05810 {
05811 if (GET_CODE (andop) == CONST_INT)
05812 {
05813 HOST_WIDE_INT c, lsb, shift_mask;
05814
05815 shift_mask = ~0;
05816 shift_mask <<= INTVAL (shiftop);
05817 c = INTVAL (andop);
05818
05819
05820 lsb = c & -c;
05821
05822
05823
05824 if ((lsb & shift_mask) == 0)
05825 return 0;
05826
05827
05828 return c == -lsb && lsb != 1;
05829 }
05830 else if (GET_CODE (andop) == CONST_DOUBLE
05831 && (GET_MODE (andop) == VOIDmode || GET_MODE (andop) == DImode))
05832 {
05833 HOST_WIDE_INT low, lsb, shift_mask_low;
05834
05835 low = CONST_DOUBLE_LOW (andop);
05836
05837 if (HOST_BITS_PER_WIDE_INT < 64)
05838 {
05839 HOST_WIDE_INT high, shift_mask_high;
05840
05841 high = CONST_DOUBLE_HIGH (andop);
05842
05843 if (low == 0)
05844 {
05845 shift_mask_high = ~0;
05846 if (INTVAL (shiftop) > 32)
05847 shift_mask_high <<= INTVAL (shiftop) - 32;
05848
05849 lsb = high & -high;
05850
05851 if ((lsb & shift_mask_high) == 0)
05852 return 0;
05853
05854 return high == -lsb;
05855 }
05856 if (high != ~0)
05857 return 0;
05858 }
05859
05860 shift_mask_low = ~0;
05861 shift_mask_low <<= INTVAL (shiftop);
05862
05863 lsb = low & -low;
05864
05865 if ((lsb & shift_mask_low) == 0)
05866 return 0;
05867
05868 return low == -lsb && lsb != 1;
05869 }
05870 else
05871 return 0;
05872 }
05873
05874
05875
05876
05877
05878
05879
05880 int
05881 registers_ok_for_quad_peep (reg1, reg2)
05882 rtx reg1, reg2;
05883 {
05884
05885 if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
05886 return 0;
05887
05888 return (REGNO (reg1) == REGNO (reg2) - 1);
05889 }
05890
05891
05892
05893
05894
05895 int
05896 addrs_ok_for_quad_peep (addr1, addr2)
05897 rtx addr1;
05898 rtx addr2;
05899 {
05900 unsigned int reg1;
05901 int offset1;
05902
05903
05904 if (GET_CODE (addr1) == PLUS)
05905 {
05906
05907 if (GET_CODE (XEXP (addr1, 0)) != REG)
05908 return 0;
05909 else
05910 {
05911 reg1 = REGNO (XEXP (addr1, 0));
05912
05913 if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
05914 return 0;
05915 offset1 = INTVAL (XEXP (addr1, 1));
05916 }
05917 }
05918 else if (GET_CODE (addr1) != REG)
05919 return 0;
05920 else
05921 {
05922 reg1 = REGNO (addr1);
05923
05924 offset1 = 0;
05925 }
05926
05927
05928 if (GET_CODE (addr2) != PLUS)
05929 return 0;
05930
05931 if (GET_CODE (XEXP (addr2, 0)) != REG
05932 || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
05933 return 0;
05934
05935 if (reg1 != REGNO (XEXP (addr2, 0)))
05936 return 0;
05937
05938
05939 if (INTVAL (XEXP (addr2, 1)) != offset1 + 8)
05940 return 0;
05941
05942
05943
05944 return 1;
05945 }
05946
05947
05948
05949
05950
05951 enum reg_class
05952 secondary_reload_class (class, mode, in)
05953 enum reg_class class;
05954 enum machine_mode mode ATTRIBUTE_UNUSED;
05955 rtx in;
05956 {
05957 int regno;
05958
05959 if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN && flag_pic))
05960 {
05961
05962
05963
05964
05965
05966
05967
05968 if (class != BASE_REGS
05969 && (GET_CODE (in) == SYMBOL_REF
05970 || GET_CODE (in) == HIGH
05971 || GET_CODE (in) == LABEL_REF
05972 || GET_CODE (in) == CONST))
05973 return BASE_REGS;
05974 }
05975
05976 if (GET_CODE (in) == REG)
05977 {
05978 regno = REGNO (in);
05979 if (regno >= FIRST_PSEUDO_REGISTER)
05980 {
05981 regno = true_regnum (in);
05982 if (regno >= FIRST_PSEUDO_REGISTER)
05983 regno = -1;
05984 }
05985 }
05986 else if (GET_CODE (in) == SUBREG)
05987 {
05988 regno = true_regnum (in);
05989 if (regno >= FIRST_PSEUDO_REGISTER)
05990 regno = -1;
05991 }
05992 else
05993 regno = -1;
05994
05995
05996
05997 if (class == GENERAL_REGS || class == BASE_REGS
05998 || (regno >= 0 && INT_REGNO_P (regno)))
05999 return NO_REGS;
06000
06001
06002 if ((regno == -1 || FP_REGNO_P (regno))
06003 && (class == FLOAT_REGS || class == NON_SPECIAL_REGS))
06004 return NO_REGS;
06005
06006
06007 if ((regno == -1 || ALTIVEC_REGNO_P (regno))
06008 && class == ALTIVEC_REGS)
06009 return NO_REGS;
06010
06011
06012 if ((class == CR_REGS || class == CR0_REGS)
06013 && regno >= 0 && CR_REGNO_P (regno))
06014 return NO_REGS;
06015
06016
06017 return GENERAL_REGS;
06018 }
06019
06020
06021
06022
06023
06024
06025
06026
06027
06028 int
06029 ccr_bit (op, scc_p)
06030 rtx op;
06031 int scc_p;
06032 {
06033 enum rtx_code code = GET_CODE (op);
06034 enum machine_mode cc_mode;
06035 int cc_regnum;
06036 int base_bit;
06037 rtx reg;
06038
06039 if (GET_RTX_CLASS (code) != '<')
06040 return -1;
06041
06042 reg = XEXP (op, 0);
06043
06044 if (GET_CODE (reg) != REG
06045 || ! CR_REGNO_P (REGNO (reg)))
06046 abort ();
06047
06048 cc_mode = GET_MODE (reg);
06049 cc_regnum = REGNO (reg);
06050 base_bit = 4 * (cc_regnum - CR0_REGNO);
06051
06052 validate_condition_mode (code, cc_mode);
06053
06054 switch (code)
06055 {
06056 case NE:
06057 return scc_p ? base_bit + 3 : base_bit + 2;
06058 case EQ:
06059 return base_bit + 2;
06060 case GT: case GTU: case UNLE:
06061 return base_bit + 1;
06062 case LT: case LTU: case UNGE:
06063 return base_bit;
06064 case ORDERED: case UNORDERED:
06065 return base_bit + 3;
06066
06067 case GE: case GEU:
06068
06069
06070
06071 return scc_p ? base_bit + 3 : base_bit;
06072
06073 case LE: case LEU:
06074 return scc_p ? base_bit + 3 : base_bit + 1;
06075
06076 default:
06077 abort ();
06078 }
06079 }
06080
06081
06082
06083 struct rtx_def *
06084 rs6000_got_register (value)
06085 rtx value ATTRIBUTE_UNUSED;
06086 {
06087
06088
06089
06090 if (no_new_pseudos && ! regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM])
06091 regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
06092
06093 current_function_uses_pic_offset_table = 1;
06094
06095 return pic_offset_table_rtx;
06096 }
06097
06098
06099
06100
06101
06102 static void
06103 rs6000_init_machine_status (p)
06104 struct function *p;
06105 {
06106 p->machine = (machine_function *) xcalloc (1, sizeof (machine_function));
06107 }
06108
06109 static void
06110 rs6000_free_machine_status (p)
06111 struct function *p;
06112 {
06113 if (p->machine == NULL)
06114 return;
06115
06116 free (p->machine);
06117 p->machine = NULL;
06118 }
06119
06120
06121
06122
06123 #if TARGET_ELF
06124 #define SMALL_DATA_RELOC ((rs6000_sdata == SDATA_EABI) ? "sda21" : "sdarel")
06125 #define SMALL_DATA_REG ((rs6000_sdata == SDATA_EABI) ? 0 : 13)
06126 #else
06127 #define SMALL_DATA_RELOC "sda21"
06128 #define SMALL_DATA_REG 0
06129 #endif
06130
06131 void
06132 print_operand (file, x, code)
06133 FILE *file;
06134 rtx x;
06135 int code;
06136 {
06137 int i;
06138 HOST_WIDE_INT val;
06139
06140
06141 #define INT_P(X) \
06142 ((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
06143 && GET_MODE (X) == VOIDmode)
06144
06145 #define INT_LOWPART(X) \
06146 (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
06147
06148 switch (code)
06149 {
06150 case '.':
06151
06152
06153 asm_fprintf (file, RS6000_CALL_GLUE);
06154 return;
06155
06156
06157
06158 case 'A':
06159
06160
06161
06162
06163 if (GET_CODE (x) == CONST_INT && (INTVAL (x) & 31) == 0)
06164 putc ('l', file);
06165 else
06166 putc ('r', file);
06167 return;
06168
06169 case 'b':
06170
06171
06172 if (INT_P (x))
06173 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 0xffff);
06174 else
06175 print_operand (file, x, 0);
06176 return;
06177
06178 case 'B':
06179
06180
06181 putc (((INT_LOWPART(x) & 1) == 0 ? 'r' : 'l'), file);
06182 return;
06183
06184
06185
06186
06187 case 'D':
06188
06189
06190
06191
06192
06193
06194
06195 if (GET_CODE (x) == LE || GET_CODE (x) == GE
06196 || GET_CODE (x) == LEU || GET_CODE (x) == GEU)
06197 {
06198 int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
06199
06200 fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3,
06201 base_bit + 2,
06202 base_bit + (GET_CODE (x) == GE || GET_CODE (x) == GEU));
06203 }
06204
06205 else if (GET_CODE (x) == NE)
06206 {
06207 int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
06208
06209 fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3,
06210 base_bit + 2, base_bit + 2);
06211 }
06212 return;
06213
06214 case 'E':
06215
06216 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
06217 output_operand_lossage ("invalid %%E value");
06218 else
06219 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 2);
06220 return;
06221
06222 case 'f':
06223
06224
06225 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
06226 output_operand_lossage ("invalid %%f value");
06227 else
06228 fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO));
06229 return;
06230
06231 case 'F':
06232
06233
06234 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
06235 output_operand_lossage ("invalid %%F value");
06236 else
06237 fprintf (file, "%d", 32 - 4 * (REGNO (x) - CR0_REGNO));
06238 return;
06239
06240 case 'G':
06241
06242
06243 if (GET_CODE (x) != CONST_INT)
06244 output_operand_lossage ("invalid %%G value");
06245 else if (INTVAL (x) >= 0)
06246 putc ('z', file);
06247 else
06248 putc ('m', file);
06249 return;
06250
06251 case 'h':
06252
06253
06254 if (INT_P (x))
06255 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 31);
06256 else
06257 print_operand (file, x, 0);
06258 return;
06259
06260 case 'H':
06261
06262
06263 if (INT_P (x))
06264 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INT_LOWPART (x) & 63);
06265 else
06266 print_operand (file, x, 0);
06267 return;
06268
06269 case 'I':
06270
06271 if (INT_P (x))
06272 putc ('i', file);
06273 return;
06274
06275 case 'j':
06276
06277 i = ccr_bit (x, 0);
06278 if (i == -1)
06279 output_operand_lossage ("invalid %%j code");
06280 else
06281 fprintf (file, "%d", i);
06282 return;
06283
06284 case 'J':
06285
06286
06287 i = ccr_bit (x, 1);
06288 if (i == -1)
06289 output_operand_lossage ("invalid %%J code");
06290 else
06291
06292 fprintf (file, "%d", i == 31 ? 0 : i + 1);
06293 return;
06294
06295 case 'k':
06296
06297
06298 if (! INT_P (x))
06299 output_operand_lossage ("invalid %%k value");
06300 else
06301 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INT_LOWPART (x));
06302 return;
06303
06304 case 'K':
06305
06306
06307
06308 if (GET_CODE (x) != CONST)
06309 {
06310 print_operand_address (file, x);
06311 fputs ("@l", file);
06312 }
06313 else
06314 {
06315 if (GET_CODE (XEXP (x, 0)) != PLUS
06316 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
06317 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
06318 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
06319 output_operand_lossage ("invalid %%K value");
06320 print_operand_address (file, XEXP (XEXP (x, 0), 0));
06321 fputs ("@l", file);
06322 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
06323 }
06324 return;
06325
06326
06327
06328 case 'L':
06329
06330
06331 if (GET_CODE (x) == REG)
06332 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
06333 else if (GET_CODE (x) == MEM)
06334 {
06335
06336
06337 if (GET_CODE (XEXP (x, 0)) == PRE_INC
06338 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
06339 output_address (plus_constant (XEXP (XEXP (x, 0), 0),
06340 UNITS_PER_WORD));
06341 else
06342 output_address (XEXP (adjust_address_nv (x, SImode,
06343 UNITS_PER_WORD),
06344 0));
06345
06346 if (small_data_operand (x, GET_MODE (x)))
06347 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
06348 reg_names[SMALL_DATA_REG]);
06349 }
06350 return;
06351
06352 case 'm':
06353
06354 if (! mask_operand (x, SImode))
06355 output_operand_lossage ("invalid %%m value");
06356
06357 val = INT_LOWPART (x);
06358
06359
06360
06361
06362 if ((val & 0x80000000) && ((val & 1) == 0))
06363 {
06364 putc ('0', file);
06365 return;
06366 }
06367 else if ((val & 0x80000000) == 0)
06368 {
06369 for (i = 1; i < 32; i++)
06370 if ((val <<= 1) & 0x80000000)
06371 break;
06372 fprintf (file, "%d", i);
06373 return;
06374 }
06375
06376
06377
06378 for (i = 0; i < 32; i++)
06379 if (((val >>= 1) & 1) == 0)
06380 break;
06381
06382
06383
06384 fprintf (file, "%d", 31 - i);
06385 return;
06386
06387 case 'M':
06388
06389 if (! mask_operand (x, SImode))
06390 output_operand_lossage ("invalid %%M value");
06391
06392 val = INT_LOWPART (x);
06393
06394
06395
06396
06397 if ((val & 1) && ((val & 0x80000000) == 0))
06398 {
06399 fputs ("31", file);
06400 return;
06401 }
06402 else if ((val & 1) == 0)
06403 {
06404 for (i = 0; i < 32; i++)
06405 if ((val >>= 1) & 1)
06406 break;
06407
06408
06409
06410 fprintf (file, "%d", 30 - i);
06411 return;
06412 }
06413
06414
06415
06416 for (i = 0; i < 32; i++)
06417 if (((val <<= 1) & 0x80000000) == 0)
06418 break;
06419
06420 fprintf (file, "%d", i);
06421 return;
06422
06423
06424
06425 case 'N':
06426
06427 if (GET_CODE (x) != PARALLEL)
06428 output_operand_lossage ("invalid %%N value");
06429 else
06430 fprintf (file, "%d", XVECLEN (x, 0) * 4);
06431 return;
06432
06433 case 'O':
06434
06435 if (GET_CODE (x) != PARALLEL)
06436 output_operand_lossage ("invalid %%O value");
06437 else
06438 fprintf (file, "%d", (XVECLEN (x, 0) - 1) * 4);
06439 return;
06440
06441 case 'p':
06442
06443 if (! INT_P (x)
06444 || INT_LOWPART (x) < 0
06445 || (i = exact_log2 (INT_LOWPART (x))) < 0)
06446 output_operand_lossage ("invalid %%p value");
06447 else
06448 fprintf (file, "%d", i);
06449 return;
06450
06451 case 'P':
06452
06453
06454 if (GET_CODE (x) != MEM || GET_CODE (XEXP (x, 0)) != REG
06455 || REGNO (XEXP (x, 0)) >= 32)
06456 output_operand_lossage ("invalid %%P value");
06457 else
06458 fprintf (file, "%d", REGNO (XEXP (x, 0)));
06459 return;
06460
06461 case 'q':
06462
06463
06464
06465
06466
06467 {
06468 const char *const *t = 0;
06469 const char *s;
06470 enum rtx_code code = GET_CODE (x);
06471 static const char * const tbl[3][3] = {
06472 { "and", "andc", "nor" },
06473 { "or", "orc", "nand" },
06474 { "xor", "eqv", "xor" } };
06475
06476 if (code == AND)
06477 t = tbl[0];
06478 else if (code == IOR)
06479 t = tbl[1];
06480 else if (code == XOR)
06481 t = tbl[2];
06482 else
06483 output_operand_lossage ("invalid %%q value");
06484
06485 if (GET_CODE (XEXP (x, 0)) != NOT)
06486 s = t[0];
06487 else
06488 {
06489 if (GET_CODE (XEXP (x, 1)) == NOT)
06490 s = t[2];
06491 else
06492 s = t[1];
06493 }
06494
06495 fputs (s, file);
06496 }
06497 return;
06498
06499 case 'R':
06500
06501 if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
06502 output_operand_lossage ("invalid %%R value");
06503 else
06504 fprintf (file, "%d", 128 >> (REGNO (x) - CR0_REGNO));
06505 return;
06506
06507 case 's':
06508
06509 if (! INT_P (x))
06510 output_operand_lossage ("invalid %%s value");
06511 else
06512 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (32 - INT_LOWPART (x)) & 31);
06513 return;
06514
06515 case 'S':
06516
06517
06518
06519 if (! mask64_operand (x, DImode))
06520 output_operand_lossage ("invalid %%S value");
06521
06522 val = INT_LOWPART (x);
06523
06524 if (val & 1)
06525 {
06526 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
06527 if (!((val >>= 1) & 1))
06528 break;
06529
06530 #if HOST_BITS_PER_WIDE_INT == 32
06531 if (GET_CODE (x) == CONST_DOUBLE && i == 32)
06532 {
06533 val = CONST_DOUBLE_HIGH (x);
06534
06535 if (val == 0)
06536 --i;
06537 else
06538 for (i = 32; i < 64; i++)
06539 if (!((val >>= 1) & 1))
06540 break;
06541 }
06542 #endif
06543
06544
06545 if (i > 63)
06546 output_operand_lossage ("%%S computed all 1's mask");
06547
06548 fprintf (file, "%d", 63 - i);
06549 return;
06550 }
06551 else
06552 {
06553 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
06554 if ((val >>= 1) & 1)
06555 break;
06556
06557 #if HOST_BITS_PER_WIDE_INT == 32
06558 if (GET_CODE (x) == CONST_DOUBLE && i == 32)
06559 {
06560 val = CONST_DOUBLE_HIGH (x);
06561
06562 if (val == (HOST_WIDE_INT) -1)
06563 --i;
06564 else
06565 for (i = 32; i < 64; i++)
06566 if ((val >>= 1) & 1)
06567 break;
06568 }
06569 #endif
06570
06571
06572 if (i > 62)
06573 output_operand_lossage ("%%S computed all 0's mask");
06574
06575 fprintf (file, "%d", 62 - i);
06576 return;
06577 }
06578
06579 case 'T':
06580
06581 if (GET_CODE (x) != REG || (REGNO (x) != LINK_REGISTER_REGNUM
06582 && REGNO (x) != COUNT_REGISTER_REGNUM))
06583 output_operand_lossage ("invalid %%T value");
06584 else if (REGNO (x) == LINK_REGISTER_REGNUM)
06585 fputs (TARGET_NEW_MNEMONICS ? "lr" : "r", file);
06586 else
06587 fputs ("ctr", file);
06588 return;
06589
06590 case 'u':
06591
06592 if (! INT_P (x))
06593 output_operand_lossage ("invalid %%u value");
06594 else
06595 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
06596 (INT_LOWPART (x) >> 16) & 0xffff);
06597 return;
06598
06599 case 'v':
06600
06601 if (! INT_P (x))
06602 output_operand_lossage ("invalid %%v value");
06603 else
06604 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
06605 (INT_LOWPART (x) >> 16) & 0xffff);
06606 return;
06607
06608 case 'U':
06609
06610 if (GET_CODE (x) == MEM
06611 && (GET_CODE (XEXP (x, 0)) == PRE_INC
06612 || GET_CODE (XEXP (x, 0)) == PRE_DEC))
06613 putc ('u', file);
06614 return;
06615
06616 case 'V':
06617
06618 switch (GET_CODE (x))
06619 {
06620 case EQ:
06621 fputs ("eq", file);
06622 break;
06623 case NE:
06624 fputs ("ne", file);
06625 break;
06626 case LT:
06627 fputs ("lt", file);
06628 break;
06629 case LE:
06630 fputs ("le", file);
06631 break;
06632 case GT:
06633 fputs ("gt", file);
06634 break;
06635 case GE:
06636 fputs ("ge", file);
06637 break;
06638 case LTU:
06639 fputs ("llt", file);
06640 break;
06641 case LEU:
06642 fputs ("lle", file);
06643 break;
06644 case GTU:
06645 fputs ("lgt", file);
06646 break;
06647 case GEU:
06648 fputs ("lge", file);
06649 break;
06650 default:
06651 abort ();
06652 }
06653 break;
06654
06655 case 'w':
06656
06657
06658 if (INT_P (x))
06659 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06660 ((INT_LOWPART (x) & 0xffff) ^ 0x8000) - 0x8000);
06661 else
06662 print_operand (file, x, 0);
06663 return;
06664
06665 case 'W':
06666
06667 val = (GET_CODE (x) == CONST_INT
06668 ? INTVAL (x) : CONST_DOUBLE_HIGH (x));
06669
06670 if (val < 0)
06671 i = -1;
06672 else
06673 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
06674 if ((val <<= 1) < 0)
06675 break;
06676
06677 #if HOST_BITS_PER_WIDE_INT == 32
06678 if (GET_CODE (x) == CONST_INT && i >= 0)
06679 i += 32;
06680 else if (GET_CODE (x) == CONST_DOUBLE && i == 32)
06681 {
06682 val = CONST_DOUBLE_LOW (x);
06683
06684 if (val == 0)
06685 abort ();
06686 else if (val < 0)
06687 --i;
06688 else
06689 for ( ; i < 64; i++)
06690 if ((val <<= 1) < 0)
06691 break;
06692 }
06693 #endif
06694
06695 fprintf (file, "%d", i + 1);
06696 return;
06697
06698 case 'X':
06699 if (GET_CODE (x) == MEM
06700 && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0), 0))
06701 putc ('x', file);
06702 return;
06703
06704 case 'Y':
06705
06706 if (GET_CODE (x) == REG)
06707 fprintf (file, "%s", reg_names[REGNO (x) + 2]);
06708 else if (GET_CODE (x) == MEM)
06709 {
06710 if (GET_CODE (XEXP (x, 0)) == PRE_INC
06711 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
06712 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8));
06713 else
06714 output_address (XEXP (adjust_address_nv (x, SImode, 8), 0));
06715 if (small_data_operand (x, GET_MODE (x)))
06716 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
06717 reg_names[SMALL_DATA_REG]);
06718 }
06719 return;
06720
06721 case 'z':
06722
06723
06724
06725
06726
06727 if (GET_CODE (x) != SYMBOL_REF)
06728 abort ();
06729
06730 if (XSTR (x, 0)[0] != '.')
06731 {
06732 switch (DEFAULT_ABI)
06733 {
06734 default:
06735 abort ();
06736
06737 case ABI_AIX:
06738 putc ('.', file);
06739 break;
06740
06741 case ABI_V4:
06742 case ABI_AIX_NODESC:
06743 case ABI_DARWIN:
06744 break;
06745 }
06746 }
06747 #if TARGET_AIX
06748 RS6000_OUTPUT_BASENAME (file, XSTR (x, 0));
06749 #else
06750 assemble_name (file, XSTR (x, 0));
06751 #endif
06752 return;
06753
06754 case 'Z':
06755
06756 if (GET_CODE (x) == REG)
06757 fprintf (file, "%s", reg_names[REGNO (x) + 3]);
06758 else if (GET_CODE (x) == MEM)
06759 {
06760 if (GET_CODE (XEXP (x, 0)) == PRE_INC
06761 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
06762 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12));
06763 else
06764 output_address (XEXP (adjust_address_nv (x, SImode, 12), 0));
06765 if (small_data_operand (x, GET_MODE (x)))
06766 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
06767 reg_names[SMALL_DATA_REG]);
06768 }
06769 return;
06770
06771
06772 case 'y':
06773 {
06774 rtx tmp;
06775
06776 if (GET_CODE (x) != MEM)
06777 abort ();
06778
06779 tmp = XEXP (x, 0);
06780
06781 if (GET_CODE (tmp) == REG)
06782 fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
06783 else if (GET_CODE (tmp) == PLUS && GET_CODE (XEXP (tmp, 1)) == REG)
06784 {
06785 if (REGNO (XEXP (tmp, 0)) == 0)
06786 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 1)) ],
06787 reg_names[ REGNO (XEXP (tmp, 0)) ]);
06788 else
06789 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 0)) ],
06790 reg_names[ REGNO (XEXP (tmp, 1)) ]);
06791 }
06792 else
06793 abort ();
06794 break;
06795 }
06796
06797 case 0:
06798 if (GET_CODE (x) == REG)
06799 fprintf (file, "%s", reg_names[REGNO (x)]);
06800 else if (GET_CODE (x) == MEM)
06801 {
06802
06803
06804 if (GET_CODE (XEXP (x, 0)) == PRE_INC)
06805 fprintf (file, "%d(%s)", GET_MODE_SIZE (GET_MODE (x)),
06806 reg_names[REGNO (XEXP (XEXP (x, 0), 0))]);
06807 else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)
06808 fprintf (file, "%d(%s)", - GET_MODE_SIZE (GET_MODE (x)),
06809 reg_names[REGNO (XEXP (XEXP (x, 0), 0))]);
06810 else
06811 output_address (XEXP (x, 0));
06812 }
06813 else
06814 output_addr_const (file, x);
06815 return;
06816
06817 default:
06818 output_operand_lossage ("invalid %%xn code");
06819 }
06820 }
06821
06822
06823
06824 void
06825 print_operand_address (file, x)
06826 FILE *file;
06827 rtx x;
06828 {
06829 if (GET_CODE (x) == REG)
06830 fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);
06831 else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST
06832 || GET_CODE (x) == LABEL_REF)
06833 {
06834 output_addr_const (file, x);
06835 if (small_data_operand (x, GET_MODE (x)))
06836 fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
06837 reg_names[SMALL_DATA_REG]);
06838 else if (TARGET_TOC)
06839 abort ();
06840 }
06841 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
06842 {
06843 if (REGNO (XEXP (x, 0)) == 0)
06844 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
06845 reg_names[ REGNO (XEXP (x, 0)) ]);
06846 else
06847 fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ],
06848 reg_names[ REGNO (XEXP (x, 1)) ]);
06849 }
06850 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
06851 {
06852 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (XEXP (x, 1)));
06853 fprintf (file, "(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
06854 }
06855 #if TARGET_ELF
06856 else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
06857 && CONSTANT_P (XEXP (x, 1)))
06858 {
06859 output_addr_const (file, XEXP (x, 1));
06860 fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
06861 }
06862 #endif
06863 #if TARGET_MACHO
06864 else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
06865 && CONSTANT_P (XEXP (x, 1)))
06866 {
06867 fprintf (file, "lo16(");
06868 output_addr_const (file, XEXP (x, 1));
06869 fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
06870 }
06871 #endif
06872 else if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (x))
06873 {
06874 if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC))
06875 {
06876 rtx contains_minus = XEXP (x, 1);
06877 rtx minus, symref;
06878 const char *name;
06879
06880
06881
06882 while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
06883 contains_minus = XEXP (contains_minus, 0);
06884
06885 minus = XEXP (contains_minus, 0);
06886 symref = XEXP (minus, 0);
06887 XEXP (contains_minus, 0) = symref;
06888 if (TARGET_ELF)
06889 {
06890 char *newname;
06891
06892 name = XSTR (symref, 0);
06893 newname = alloca (strlen (name) + sizeof ("@toc"));
06894 strcpy (newname, name);
06895 strcat (newname, "@toc");
06896 XSTR (symref, 0) = newname;
06897 }
06898 output_addr_const (file, XEXP (x, 1));
06899 if (TARGET_ELF)
06900 XSTR (symref, 0) = name;
06901 XEXP (contains_minus, 0) = minus;
06902 }
06903 else
06904 output_addr_const (file, XEXP (x, 1));
06905
06906 fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
06907 }
06908 else
06909 abort ();
06910 }
06911
06912
06913
06914
06915
06916
06917 static bool
06918 rs6000_assemble_integer (x, size, aligned_p)
06919 rtx x;
06920 unsigned int size;
06921 int aligned_p;
06922 {
06923 #ifdef RELOCATABLE_NEEDS_FIXUP
06924
06925 if (size == 4 && aligned_p)
06926 {
06927 extern int in_toc_section PARAMS ((void));
06928 static int recurse = 0;
06929
06930
06931
06932 if (TARGET_RELOCATABLE
06933 && !in_toc_section ()
06934 && !in_text_section ()
06935 && !recurse
06936 && GET_CODE (x) != CONST_INT
06937 && GET_CODE (x) != CONST_DOUBLE
06938 && CONSTANT_P (x))
06939 {
06940 char buf[256];
06941
06942 recurse = 1;
06943 ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", fixuplabelno);
06944 fixuplabelno++;
06945 ASM_OUTPUT_LABEL (asm_out_file, buf);
06946 fprintf (asm_out_file, "\t.long\t(");
06947 output_addr_const (asm_out_file, x);
06948 fprintf (asm_out_file, ")@fixup\n");
06949 fprintf (asm_out_file, "\t.section\t\".fixup\",\"aw\"\n");
06950 ASM_OUTPUT_ALIGN (asm_out_file, 2);
06951 fprintf (asm_out_file, "\t.long\t");
06952 assemble_name (asm_out_file, buf);
06953 fprintf (asm_out_file, "\n\t.previous\n");
06954 recurse = 0;
06955 return true;
06956 }
06957
06958
06959
06960 else if (GET_CODE (x) == SYMBOL_REF
06961 && XSTR (x, 0)[0] == '.'
06962 && DEFAULT_ABI == ABI_AIX)
06963 {
06964 const char *name = XSTR (x, 0);
06965 while (*name == '.')
06966 name++;
06967
06968 fprintf (asm_out_file, "\t.long\t%s\n", name);
06969 return true;
06970 }
06971 }
06972 #endif
06973 return default_assemble_integer (x, size, aligned_p);
06974 }
06975
06976 enum rtx_code
06977 rs6000_reverse_condition (mode, code)
06978 enum machine_mode mode;
06979 enum rtx_code code;
06980 {
06981
06982
06983 if (mode == CCFPmode && !flag_unsafe_math_optimizations)
06984 return reverse_condition_maybe_unordered (code);
06985 else
06986 return reverse_condition (code);
06987 }
06988
06989
06990
06991
06992 static rtx
06993 rs6000_generate_compare (code)
06994 enum rtx_code code;
06995 {
06996 enum machine_mode comp_mode;
06997 rtx compare_result;
06998
06999 if (rs6000_compare_fp_p)
07000 comp_mode = CCFPmode;
07001 else if (code == GTU || code == LTU
07002 || code == GEU || code == LEU)
07003 comp_mode = CCUNSmode;
07004 else
07005 comp_mode = CCmode;
07006
07007
07008 compare_result = gen_reg_rtx (comp_mode);
07009 emit_insn (gen_rtx_SET (VOIDmode, compare_result,
07010 gen_rtx_COMPARE (comp_mode,
07011 rs6000_compare_op0,
07012 rs6000_compare_op1)));
07013
07014
07015
07016 if (rs6000_compare_fp_p
07017 && ! flag_unsafe_math_optimizations
07018 && (code == LE || code == GE
07019 || code == UNEQ || code == LTGT
07020 || code == UNGT || code == UNLT))
07021 {
07022 enum rtx_code or1, or2;
07023 rtx or1_rtx, or2_rtx, compare2_rtx;
07024 rtx or_result = gen_reg_rtx (CCEQmode);
07025
07026 switch (code)
07027 {
07028 case LE: or1 = LT; or2 = EQ; break;
07029 case GE: or1 = GT; or2 = EQ; break;
07030 case UNEQ: or1 = UNORDERED; or2 = EQ; break;
07031 case LTGT: or1 = LT; or2 = GT; break;
07032 case UNGT: or1 = UNORDERED; or2 = GT; break;
07033 case UNLT: or1 = UNORDERED; or2 = LT; break;
07034 default: abort ();
07035 }
07036 validate_condition_mode (or1, comp_mode);
07037 validate_condition_mode (or2, comp_mode);
07038 or1_rtx = gen_rtx (or1, SImode, compare_result, const0_rtx);
07039 or2_rtx = gen_rtx (or2, SImode, compare_result, const0_rtx);
07040 compare2_rtx = gen_rtx_COMPARE (CCEQmode,
07041 gen_rtx_IOR (SImode, or1_rtx, or2_rtx),
07042 const_true_rtx);
07043 emit_insn (gen_rtx_SET (VOIDmode, or_result, compare2_rtx));
07044
07045 compare_result = or_result;
07046 code = EQ;
07047 }
07048
07049 validate_condition_mode (code, GET_MODE (compare_result));
07050
07051 return gen_rtx (code, VOIDmode, compare_result, const0_rtx);
07052 }
07053
07054
07055
07056
07057 void
07058 rs6000_emit_sCOND (code, result)
07059 enum rtx_code code;
07060 rtx result;
07061 {
07062 rtx condition_rtx;
07063 enum machine_mode op_mode;
07064
07065 condition_rtx = rs6000_generate_compare (code);
07066
07067 op_mode = GET_MODE (rs6000_compare_op0);
07068 if (op_mode == VOIDmode)
07069 op_mode = GET_MODE (rs6000_compare_op1);
07070
07071 if (TARGET_POWERPC64 && (op_mode == DImode || rs6000_compare_fp_p))
07072 {
07073 PUT_MODE (condition_rtx, DImode);
07074 convert_move (result, condition_rtx, 0);
07075 }
07076 else
07077 {
07078 PUT_MODE (condition_rtx, SImode);
07079 emit_insn (gen_rtx_SET (VOIDmode, result, condition_rtx));
07080 }
07081 }
07082
07083
07084
07085 void
07086 rs6000_emit_cbranch (code, loc)
07087 enum rtx_code code;
07088 rtx loc;
07089 {
07090 rtx condition_rtx, loc_ref;
07091
07092 condition_rtx = rs6000_generate_compare (code);
07093 loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
07094 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
07095 gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
07096 loc_ref, pc_rtx)));
07097 }
07098
07099
07100
07101
07102
07103
07104
07105
07106
07107
07108
07109
07110
07111 char *
07112 output_cbranch (op, label, reversed, insn)
07113 rtx op;
07114 const char * label;
07115 int reversed;
07116 rtx insn;
07117 {
07118 static char string[64];
07119 enum rtx_code code = GET_CODE (op);
07120 rtx cc_reg = XEXP (op, 0);
07121 enum machine_mode mode = GET_MODE (cc_reg);
07122 int cc_regno = REGNO (cc_reg) - CR0_REGNO;
07123 int need_longbranch = label != NULL && get_attr_length (insn) == 8;
07124 int really_reversed = reversed ^ need_longbranch;
07125 char *s = string;
07126 const char *ccode;
07127 const char *pred;
07128 rtx note;
07129
07130 validate_condition_mode (code, mode);
07131
07132
07133
07134
07135 if (really_reversed)
07136 {
07137
07138
07139 if (mode == CCFPmode)
07140 code = reverse_condition_maybe_unordered (code);
07141 else
07142 code = reverse_condition (code);
07143 }
07144
07145 switch (code)
07146 {
07147
07148
07149 case NE: case LTGT:
07150 ccode = "ne"; break;
07151 case EQ: case UNEQ:
07152 ccode = "eq"; break;
07153 case GE: case GEU:
07154 ccode = "ge"; break;
07155 case GT: case GTU: case UNGT:
07156 ccode = "gt"; break;
07157 case LE: case LEU:
07158 ccode = "le"; break;
07159 case LT: case LTU: case UNLT:
07160 ccode = "lt"; break;
07161 case UNORDERED: ccode = "un"; break;
07162 case ORDERED: ccode = "nu"; break;
07163 case UNGE: ccode = "nl"; break;
07164 case UNLE: ccode = "ng"; break;
07165 default:
07166 abort ();
07167 }
07168
07169
07170
07171 note = find_reg_note (insn, REG_BR_PROB, NULL_RTX);
07172 if (note != NULL_RTX)
07173 {
07174
07175 int prob = INTVAL (XEXP (note, 0)) - REG_BR_PROB_BASE / 2;
07176
07177
07178 if (abs (prob) > REG_BR_PROB_BASE / 20
07179 && ((prob > 0) ^ need_longbranch))
07180 pred = "+";
07181 else
07182 pred = "-";
07183 }
07184 else
07185 pred = "";
07186
07187 if (label == NULL)
07188 s += sprintf (s, "{b%sr|b%slr%s} ", ccode, ccode, pred);
07189 else
07190 s += sprintf (s, "{b%s|b%s%s} ", ccode, ccode, pred);
07191
07192
07193
07194 if (reg_names[cc_regno + CR0_REGNO][0] == '%')
07195 *s++ = '%';
07196 s += sprintf (s, "%s", reg_names[cc_regno + CR0_REGNO]);
07197
07198 if (label != NULL)
07199 {
07200
07201
07202 if (need_longbranch)
07203 s += sprintf (s, ",$+8\n\tb %s", label);
07204 else
07205 s += sprintf (s, ",%s", label);
07206 }
07207
07208 return string;
07209 }
07210
07211
07212
07213
07214
07215 int
07216 rs6000_emit_cmove (dest, op, true_cond, false_cond)
07217 rtx dest;
07218 rtx op;
07219 rtx true_cond;
07220 rtx false_cond;
07221 {
07222 enum rtx_code code = GET_CODE (op);
07223 rtx op0 = rs6000_compare_op0;
07224 rtx op1 = rs6000_compare_op1;
07225 REAL_VALUE_TYPE c1;
07226 enum machine_mode compare_mode = GET_MODE (op0);
07227 enum machine_mode result_mode = GET_MODE (dest);
07228 rtx temp;
07229
07230
07231 if (GET_MODE (op1) != compare_mode)
07232 return 0;
07233 if (GET_MODE (true_cond) != result_mode)
07234 return 0;
07235 if (GET_MODE (false_cond) != result_mode)
07236 return 0;
07237
07238
07239
07240
07241
07242 if (! rs6000_compare_fp_p)
07243 return 0;
07244
07245
07246
07247 if (code == UNLT || code == UNGT || code == UNORDERED || code == NE
07248 || code == LTGT || code == LT)
07249 {
07250 code = reverse_condition_maybe_unordered (code);
07251 temp = true_cond;
07252 true_cond = false_cond;
07253 false_cond = temp;
07254 }
07255
07256
07257
07258 if (code == UNEQ)
07259 return 0;
07260
07261 if (GET_CODE (op1) == CONST_DOUBLE)
07262 REAL_VALUE_FROM_CONST_DOUBLE (c1, op1);
07263
07264
07265
07266
07267
07268
07269 if (! flag_unsafe_math_optimizations
07270 && code != GT && code != UNGE
07271 && (GET_CODE (op1) != CONST_DOUBLE || target_isinf (c1))
07272
07273 && ((! rtx_equal_p (op0, false_cond) && ! rtx_equal_p (op1, false_cond))
07274 || (! rtx_equal_p (op0, true_cond)
07275 && ! rtx_equal_p (op1, true_cond))))
07276 return 0;
07277
07278
07279
07280 temp = gen_reg_rtx (compare_mode);
07281 emit_insn (gen_rtx_SET (VOIDmode, temp,
07282 gen_rtx_MINUS (compare_mode, op0, op1)));
07283 op0 = temp;
07284 op1 = CONST0_RTX (compare_mode);
07285
07286
07287
07288 if (flag_unsafe_math_optimizations)
07289 switch (code)
07290 {
07291 case GT:
07292 code = LE;
07293 temp = true_cond;
07294 true_cond = false_cond;
07295 false_cond = temp;
07296 break;
07297 case UNGE:
07298 code = GE;
07299 break;
07300 case UNEQ:
07301 code = EQ;
07302 break;
07303 default:
07304 break;
07305 }
07306
07307
07308 switch (code)
07309 {
07310 case GE:
07311 break;
07312
07313 case LE:
07314 temp = gen_reg_rtx (compare_mode);
07315 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
07316 op0 = temp;
07317 break;
07318
07319 case ORDERED:
07320 temp = gen_reg_rtx (compare_mode);
07321 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_ABS (compare_mode, op0)));
07322 op0 = temp;
07323 break;
07324
07325 case EQ:
07326 temp = gen_reg_rtx (compare_mode);
07327 emit_insn (gen_rtx_SET (VOIDmode, temp,
07328 gen_rtx_NEG (compare_mode,
07329 gen_rtx_ABS (compare_mode, op0))));
07330 op0 = temp;
07331 break;
07332
07333 case UNGE:
07334 temp = gen_reg_rtx (result_mode);
07335 emit_insn (gen_rtx_SET (VOIDmode, temp,
07336 gen_rtx_IF_THEN_ELSE (result_mode,
07337 gen_rtx_GE (VOIDmode,
07338 op0, op1),
07339 true_cond, false_cond)));
07340 false_cond = temp;
07341 true_cond = false_cond;
07342
07343 temp = gen_reg_rtx (compare_mode);
07344 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
07345 op0 = temp;
07346 break;
07347
07348 case GT:
07349 temp = gen_reg_rtx (result_mode);
07350 emit_insn (gen_rtx_SET (VOIDmode, temp,
07351 gen_rtx_IF_THEN_ELSE (result_mode,
07352 gen_rtx_GE (VOIDmode,
07353 op0, op1),
07354 true_cond, false_cond)));
07355 true_cond = temp;
07356 false_cond = true_cond;
07357
07358 temp = gen_reg_rtx (compare_mode);
07359 emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode, op0)));
07360 op0 = temp;
07361 break;
07362
07363 default:
07364 abort ();
07365 }
07366
07367 emit_insn (gen_rtx_SET (VOIDmode, dest,
07368 gen_rtx_IF_THEN_ELSE (result_mode,
07369 gen_rtx_GE (VOIDmode,
07370 op0, op1),
07371 true_cond, false_cond)));
07372 return 1;
07373 }
07374
07375 void
07376 rs6000_emit_minmax (dest, code, op0, op1)
07377 rtx dest;
07378 enum rtx_code code;
07379 rtx op0;
07380 rtx op1;
07381 {
07382 enum machine_mode mode = GET_MODE (op0);
07383 rtx target;
07384 if (code == SMAX || code == UMAX)
07385 target = emit_conditional_move (dest, GE, op0, op1, mode,
07386 op0, op1, mode, 0);
07387 else
07388 target = emit_conditional_move (dest, GE, op0, op1, mode,
07389 op1, op0, mode, 0);
07390 if (target == NULL_RTX)
07391 abort ();
07392 if (target != dest)
07393 emit_move_insn (dest, target);
07394 }
07395
07396
07397
07398
07399
07400
07401
07402 int
07403 first_reg_to_save ()
07404 {
07405 int first_reg;
07406
07407
07408 for (first_reg = 13; first_reg <= 31; first_reg++)
07409 if (regs_ever_live[first_reg]
07410 && (! call_used_regs[first_reg]
07411 || (first_reg == RS6000_PIC_OFFSET_TABLE_REGNUM
07412 && ((DEFAULT_ABI == ABI_V4 && flag_pic == 1)
07413 || (DEFAULT_ABI == ABI_DARWIN && flag_pic)))))
07414 break;
07415
07416 #if TARGET_MACHO
07417 if (flag_pic && current_function_uses_pic_offset_table &&
07418 (first_reg > RS6000_PIC_OFFSET_TABLE_REGNUM))
07419 return RS6000_PIC_OFFSET_TABLE_REGNUM;
07420 #endif
07421
07422 return first_reg;
07423 }
07424
07425
07426
07427 int
07428 first_fp_reg_to_save ()
07429 {
07430 int first_reg;
07431
07432
07433 for (first_reg = 14 + 32; first_reg <= 63; first_reg++)
07434 if (regs_ever_live[first_reg])
07435 break;
07436
07437 return first_reg;
07438 }
07439
07440
07441
07442 static int
07443 first_altivec_reg_to_save ()
07444 {
07445 int i;
07446
07447
07448 if (! TARGET_ALTIVEC_ABI)
07449 return LAST_ALTIVEC_REGNO + 1;
07450
07451
07452 for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i)
07453 if (regs_ever_live[i])
07454 break;
07455
07456 return i;
07457 }
07458
07459
07460
07461
07462
07463 static unsigned int
07464 compute_vrsave_mask ()
07465 {
07466 unsigned int i, mask = 0;
07467
07468
07469 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
07470 if (regs_ever_live[i])
07471 mask |= ALTIVEC_REG_BIT (i);
07472
07473 if (mask == 0)
07474 return mask;
07475
07476
07477
07478
07479
07480
07481
07482
07483
07484
07485 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
07486 if (call_used_regs[i])
07487 mask |= ALTIVEC_REG_BIT (i);
07488
07489
07490
07491
07492
07493
07494 for (i = cfun->args_info.vregno; i >= ALTIVEC_ARG_MIN_REG; --i)
07495 mask &= ~ALTIVEC_REG_BIT (i);
07496
07497
07498 {
07499 bool yes = false;
07500 diddle_return_value (is_altivec_return_reg, &yes);
07501 if (yes)
07502 mask &= ~ALTIVEC_REG_BIT (ALTIVEC_ARG_RETURN);
07503 }
07504
07505 return mask;
07506 }
07507
07508 static void
07509 is_altivec_return_reg (reg, xyes)
07510 rtx reg;
07511 void *xyes;
07512 {
07513 bool *yes = (bool *) xyes;
07514 if (REGNO (reg) == ALTIVEC_ARG_RETURN)
07515 *yes = true;
07516 }
07517
07518
07519
07520
07521
07522
07523
07524
07525
07526
07527
07528
07529
07530
07531
07532
07533
07534
07535
07536
07537
07538
07539
07540
07541
07542
07543
07544
07545
07546
07547
07548
07549
07550
07551
07552
07553
07554
07555
07556
07557
07558
07559
07560
07561
07562
07563
07564
07565
07566
07567
07568
07569
07570
07571
07572
07573
07574
07575
07576
07577
07578
07579
07580
07581
07582
07583
07584
07585
07586
07587
07588
07589
07590
07591
07592
07593
07594
07595
07596
07597
07598
07599
07600
07601
07602
07603
07604
07605
07606
07607
07608
07609 #ifndef ABI_STACK_BOUNDARY
07610 #define ABI_STACK_BOUNDARY STACK_BOUNDARY
07611 #endif
07612
07613 rs6000_stack_t *
07614 rs6000_stack_info ()
07615 {
07616 static rs6000_stack_t info, zero_info;
07617 rs6000_stack_t *info_ptr = &info;
07618 int reg_size = TARGET_POWERPC64 ? 8 : 4;
07619 enum rs6000_abi abi;
07620 int ehrd_size;
07621 int total_raw_size;
07622
07623
07624 info = zero_info;
07625
07626
07627 info_ptr->abi = abi = DEFAULT_ABI;
07628
07629
07630 info_ptr->first_gp_reg_save = first_reg_to_save ();
07631
07632
07633 if (((TARGET_TOC && TARGET_MINIMAL_TOC)
07634 || (flag_pic == 1 && abi == ABI_V4)
07635 || (flag_pic && abi == ABI_DARWIN))
07636 && info_ptr->first_gp_reg_save > RS6000_PIC_OFFSET_TABLE_REGNUM)
07637 info_ptr->gp_size = reg_size * (32 - RS6000_PIC_OFFSET_TABLE_REGNUM);
07638 else
07639 info_ptr->gp_size = reg_size * (32 - info_ptr->first_gp_reg_save);
07640
07641 info_ptr->first_fp_reg_save = first_fp_reg_to_save ();
07642 info_ptr->fp_size = 8 * (64 - info_ptr->first_fp_reg_save);
07643
07644 info_ptr->first_altivec_reg_save = first_altivec_reg_to_save ();
07645 info_ptr->altivec_size = 16 * (LAST_ALTIVEC_REGNO + 1
07646 - info_ptr->first_altivec_reg_save);
07647
07648
07649 info_ptr->calls_p = (! current_function_is_leaf
07650 || cfun->machine->ra_needs_full_frame);
07651
07652
07653 if (rs6000_ra_ever_killed ()
07654 || (DEFAULT_ABI == ABI_AIX && current_function_profile)
07655 #ifdef TARGET_RELOCATABLE
07656 || (TARGET_RELOCATABLE && (get_pool_size () != 0))
07657 #endif
07658 || (info_ptr->first_fp_reg_save != 64
07659 && !FP_SAVE_INLINE (info_ptr->first_fp_reg_save))
07660 || info_ptr->first_altivec_reg_save <= LAST_ALTIVEC_REGNO
07661 || (abi == ABI_V4 && current_function_calls_alloca)
07662 || (DEFAULT_ABI == ABI_DARWIN
07663 && flag_pic
07664 && current_function_uses_pic_offset_table)
07665 || info_ptr->calls_p)
07666 {
07667 info_ptr->lr_save_p = 1;
07668 regs_ever_live[LINK_REGISTER_REGNUM] = 1;
07669 }
07670
07671
07672 if (regs_ever_live[CR2_REGNO]
07673 || regs_ever_live[CR3_REGNO]
07674 || regs_ever_live[CR4_REGNO])
07675 {
07676 info_ptr->cr_save_p = 1;
07677 if (abi == ABI_V4)
07678 info_ptr->cr_size = reg_size;
07679 }
07680
07681
07682
07683
07684 if (current_function_calls_eh_return)
07685 {
07686 unsigned int i;
07687 for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
07688 continue;
07689 ehrd_size = i * UNITS_PER_WORD;
07690 }
07691 else
07692 ehrd_size = 0;
07693
07694
07695 info_ptr->reg_size = reg_size;
07696 info_ptr->fixed_size = RS6000_SAVE_AREA;
07697 info_ptr->varargs_size = RS6000_VARARGS_AREA;
07698 info_ptr->vars_size = RS6000_ALIGN (get_frame_size (), 8);
07699 info_ptr->parm_size = RS6000_ALIGN (current_function_outgoing_args_size,
07700 8);
07701
07702 if (TARGET_ALTIVEC_ABI)
07703 {
07704 info_ptr->vrsave_mask = compute_vrsave_mask ();
07705 info_ptr->vrsave_size = info_ptr->vrsave_mask ? 4 : 0;
07706 }
07707 else
07708 {
07709 info_ptr->vrsave_mask = 0;
07710 info_ptr->vrsave_size = 0;
07711 }
07712
07713
07714 switch (abi)
07715 {
07716 case ABI_NONE:
07717 default:
07718 abort ();
07719
07720 case ABI_AIX:
07721 case ABI_AIX_NODESC:
07722 case ABI_DARWIN:
07723 info_ptr->fp_save_offset = - info_ptr->fp_size;
07724 info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
07725
07726 if (TARGET_ALTIVEC_ABI)
07727 {
07728 info_ptr->vrsave_save_offset
07729 = info_ptr->gp_save_offset - info_ptr->vrsave_size;
07730
07731
07732 if (info_ptr->altivec_size != 0)
07733 info_ptr->altivec_padding_size
07734 = 16 - (-info_ptr->vrsave_save_offset % 16);
07735 else
07736 info_ptr->altivec_padding_size = 0;
07737
07738 info_ptr->altivec_save_offset
07739 = info_ptr->vrsave_save_offset
07740 - info_ptr->altivec_padding_size
07741 - info_ptr->altivec_size;
07742
07743
07744 info_ptr->ehrd_offset = info_ptr->altivec_save_offset - ehrd_size;
07745 }
07746 else
07747 info_ptr->ehrd_offset = info_ptr->gp_save_offset - ehrd_size;
07748 info_ptr->cr_save_offset = reg_size;
07749 info_ptr->lr_save_offset = 2*reg_size;
07750 break;
07751
07752 case ABI_V4:
07753 info_ptr->fp_save_offset = - info_ptr->fp_size;
07754 info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
07755 info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size;
07756
07757 if (TARGET_ALTIVEC_ABI)
07758 {
07759 info_ptr->vrsave_save_offset
07760 = info_ptr->cr_save_offset - info_ptr->vrsave_size;
07761
07762
07763 if (info_ptr->altivec_size != 0)
07764 info_ptr->altivec_padding_size
07765 = 16 - (-info_ptr->vrsave_save_offset % 16);
07766 else
07767 info_ptr->altivec_padding_size = 0;
07768
07769 info_ptr->altivec_save_offset
07770 = info_ptr->vrsave_save_offset
07771 - info_ptr->altivec_padding_size
07772 - info_ptr->altivec_size;
07773
07774
07775 info_ptr->toc_save_offset
07776 = info_ptr->altivec_save_offset - info_ptr->toc_size;
07777 }
07778 else
07779 info_ptr->toc_save_offset = info_ptr->cr_save_offset - info_ptr->toc_size;
07780 info_ptr->ehrd_offset = info_ptr->toc_save_offset - ehrd_size;
07781 info_ptr->lr_save_offset = reg_size;
07782 break;
07783 }
07784
07785 info_ptr->save_size = RS6000_ALIGN (info_ptr->fp_size
07786 + info_ptr->gp_size
07787 + info_ptr->altivec_size
07788 + info_ptr->altivec_padding_size
07789 + info_ptr->vrsave_size
07790 + ehrd_size
07791 + info_ptr->cr_size
07792 + info_ptr->lr_size
07793 + info_ptr->vrsave_size
07794 + info_ptr->toc_size,
07795 (TARGET_ALTIVEC_ABI || ABI_DARWIN)
07796 ? 16 : 8);
07797
07798 total_raw_size = (info_ptr->vars_size
07799 + info_ptr->parm_size
07800 + info_ptr->save_size
07801 + info_ptr->varargs_size
07802 + info_ptr->fixed_size);
07803
07804 info_ptr->total_size =
07805 RS6000_ALIGN (total_raw_size, ABI_STACK_BOUNDARY / BITS_PER_UNIT);
07806
07807
07808
07809
07810
07811
07812
07813
07814
07815
07816
07817
07818
07819 if (info_ptr->calls_p)
07820 info_ptr->push_p = 1;
07821
07822 else if (abi == ABI_V4)
07823 info_ptr->push_p = total_raw_size > info_ptr->fixed_size;
07824
07825 else
07826 info_ptr->push_p = (frame_pointer_needed
07827 || (abi != ABI_DARWIN && write_symbols != NO_DEBUG)
07828 || ((total_raw_size - info_ptr->fixed_size)
07829 > (TARGET_32BIT ? 220 : 288)));
07830
07831
07832 if (info_ptr->fp_size == 0)
07833 info_ptr->fp_save_offset = 0;
07834
07835 if (info_ptr->gp_size == 0)
07836 info_ptr->gp_save_offset = 0;
07837
07838 if (! TARGET_ALTIVEC_ABI || info_ptr->altivec_size == 0)
07839 info_ptr->altivec_save_offset = 0;
07840
07841 if (! TARGET_ALTIVEC_ABI || info_ptr->vrsave_mask == 0)
07842 info_ptr->vrsave_save_offset = 0;
07843
07844 if (! info_ptr->lr_save_p)
07845 info_ptr->lr_save_offset = 0;
07846
07847 if (! info_ptr->cr_save_p)
07848 info_ptr->cr_save_offset = 0;
07849
07850 if (! info_ptr->toc_save_p)
07851 info_ptr->toc_save_offset = 0;
07852
07853 return info_ptr;
07854 }
07855
07856 void
07857 debug_stack_info (info)
07858 rs6000_stack_t *info;
07859 {
07860 const char *abi_string;
07861
07862 if (! info)
07863 info = rs6000_stack_info ();
07864
07865 fprintf (stderr, "\nStack information for function %s:\n",
07866 ((current_function_decl && DECL_NAME (current_function_decl))
07867 ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
07868 : "<unknown>"));
07869
07870 switch (info->abi)
07871 {
07872 default: abi_string = "Unknown"; break;
07873 case ABI_NONE: abi_string = "NONE"; break;
07874 case ABI_AIX:
07875 case ABI_AIX_NODESC: abi_string = "AIX"; break;
07876 case ABI_DARWIN: abi_string = "Darwin"; break;
07877 case ABI_V4: abi_string = "V.4"; break;
07878 }
07879
07880 fprintf (stderr, "\tABI = %5s\n", abi_string);
07881
07882 if (TARGET_ALTIVEC_ABI)
07883 fprintf (stderr, "\tALTIVEC ABI extensions enabled.\n");
07884
07885 if (info->first_gp_reg_save != 32)
07886 fprintf (stderr, "\tfirst_gp_reg_save = %5d\n", info->first_gp_reg_save);
07887
07888 if (info->first_fp_reg_save != 64)
07889 fprintf (stderr, "\tfirst_fp_reg_save = %5d\n", info->first_fp_reg_save);
07890
07891 if (info->first_altivec_reg_save <= LAST_ALTIVEC_REGNO)
07892 fprintf (stderr, "\tfirst_altivec_reg_save = %5d\n",
07893 info->first_altivec_reg_save);
07894
07895 if (info->lr_save_p)
07896 fprintf (stderr, "\tlr_save_p = %5d\n", info->lr_save_p);
07897
07898 if (info->cr_save_p)
07899 fprintf (stderr, "\tcr_save_p = %5d\n", info->cr_save_p);
07900
07901 if (info->toc_save_p)
07902 fprintf (stderr, "\ttoc_save_p = %5d\n", info->toc_save_p);
07903
07904 if (info->vrsave_mask)
07905 fprintf (stderr, "\tvrsave_mask = 0x%x\n", info->vrsave_mask);
07906
07907 if (info->push_p)
07908 fprintf (stderr, "\tpush_p = %5d\n", info->push_p);
07909
07910 if (info->calls_p)
07911 fprintf (stderr, "\tcalls_p = %5d\n", info->calls_p);
07912
07913 if (info->gp_save_offset)
07914 fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset);
07915
07916 if (info->fp_save_offset)
07917 fprintf (stderr, "\tfp_save_offset = %5d\n", info->fp_save_offset);
07918
07919 if (info->altivec_save_offset)
07920 fprintf (stderr, "\taltivec_save_offset = %5d\n",
07921 info->altivec_save_offset);
07922
07923 if (info->vrsave_save_offset)
07924 fprintf (stderr, "\tvrsave_save_offset = %5d\n",
07925 info->vrsave_save_offset);
07926
07927 if (info->lr_save_offset)
07928 fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset);
07929
07930 if (info->cr_save_offset)
07931 fprintf (stderr, "\tcr_save_offset = %5d\n", info->cr_save_offset);
07932
07933 if (info->toc_save_offset)
07934 fprintf (stderr, "\ttoc_save_offset = %5d\n", info->toc_save_offset);
07935
07936 if (info->varargs_save_offset)
07937 fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset);
07938
07939 if (info->total_size)
07940 fprintf (stderr, "\ttotal_size = %5d\n", info->total_size);
07941
07942 if (info->varargs_size)
07943 fprintf (stderr, "\tvarargs_size = %5d\n", info->varargs_size);
07944
07945 if (info->vars_size)
07946 fprintf (stderr, "\tvars_size = %5d\n", info->vars_size);
07947
07948 if (info->parm_size)
07949 fprintf (stderr, "\tparm_size = %5d\n", info->parm_size);
07950
07951 if (info->fixed_size)
07952 fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size);
07953
07954 if (info->gp_size)
07955 fprintf (stderr, "\tgp_size = %5d\n", info->gp_size);
07956
07957 if (info->fp_size)
07958 fprintf (stderr, "\tfp_size = %5d\n", info->fp_size);
07959
07960 if (info->altivec_size)
07961 fprintf (stderr, "\taltivec_size = %5d\n", info->altivec_size);
07962
07963 if (info->vrsave_size)
07964 fprintf (stderr, "\tvrsave_size = %5d\n", info->vrsave_size);
07965
07966 if (info->altivec_padding_size)
07967 fprintf (stderr, "\taltivec_padding_size= %5d\n",
07968 info->altivec_padding_size);
07969
07970 if (info->lr_size)
07971 fprintf (stderr, "\tlr_size = %5d\n", info->lr_size);
07972
07973 if (info->cr_size)
07974 fprintf (stderr, "\tcr_size = %5d\n", info->cr_size);
07975
07976 if (info->toc_size)
07977 fprintf (stderr, "\ttoc_size = %5d\n", info->toc_size);
07978
07979 if (info->save_size)
07980 fprintf (stderr, "\tsave_size = %5d\n", info->save_size);
07981
07982 if (info->reg_size != 4)
07983 fprintf (stderr, "\treg_size = %5d\n", info->reg_size);
07984
07985 fprintf (stderr, "\n");
07986 }
07987
07988 rtx
07989 rs6000_return_addr (count, frame)
07990 int count;
07991 rtx frame;
07992 {
07993
07994
07995
07996 if (count != 0
07997 || flag_pic != 0
07998 || DEFAULT_ABI == ABI_AIX
07999 || DEFAULT_ABI == ABI_AIX_NODESC)
08000 {
08001 cfun->machine->ra_needs_full_frame = 1;
08002
08003 return
08004 gen_rtx_MEM
08005 (Pmode,
08006 memory_address
08007 (Pmode,
08008 plus_constant (copy_to_reg
08009 (gen_rtx_MEM (Pmode,
08010 memory_address (Pmode, frame))),
08011 RETURN_ADDRESS_OFFSET)));
08012 }
08013
08014 return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
08015 }
08016
08017 static int
08018 rs6000_ra_ever_killed ()
08019 {
08020 rtx top;
08021
08022 #ifdef ASM_OUTPUT_MI_THUNK
08023 if (current_function_is_thunk)
08024 return 0;
08025 #endif
08026 if (!has_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM)
08027 || cfun->machine->ra_needs_full_frame)
08028 return regs_ever_live[LINK_REGISTER_REGNUM];
08029
08030 push_topmost_sequence ();
08031 top = get_insns ();
08032 pop_topmost_sequence ();
08033
08034 return reg_set_between_p (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
08035 top, NULL_RTX);
08036 }
08037
08038
08039 static void
08040 rs6000_maybe_dead (insn)
08041 rtx insn;
08042 {
08043 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
08044 const0_rtx,
08045 REG_NOTES (insn));
08046 }
08047
08048
08049
08050
08051
08052 void
08053 rs6000_emit_load_toc_table (fromprolog)
08054 int fromprolog;
08055 {
08056 rtx dest;
08057 dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
08058
08059 if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
08060 {
08061 rtx temp = (fromprolog
08062 ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
08063 : gen_reg_rtx (Pmode));
08064 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_si (temp)));
08065 rs6000_maybe_dead (emit_move_insn (dest, temp));
08066 }
08067 else if (TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2)
08068 {
08069 char buf[30];
08070 rtx tempLR = (fromprolog
08071 ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
08072 : gen_reg_rtx (Pmode));
08073 rtx temp0 = (fromprolog
08074 ? gen_rtx_REG (Pmode, 0)
08075 : gen_reg_rtx (Pmode));
08076 rtx symF;
08077
08078
08079 if (! toc_initialized)
08080 {
08081 toc_section ();
08082 function_section (current_function_decl);
08083 }
08084
08085 if (fromprolog)
08086 {
08087 rtx symL;
08088
08089 ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
08090 symF = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
08091
08092 ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
08093 symL = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
08094
08095 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_1 (tempLR,
08096 symF)));
08097 rs6000_maybe_dead (emit_move_insn (dest, tempLR));
08098 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_2 (temp0, dest,
08099 symL,
08100 symF)));
08101 }
08102 else
08103 {
08104 rtx tocsym;
08105 static int reload_toc_labelno = 0;
08106
08107 tocsym = gen_rtx_SYMBOL_REF (Pmode, toc_label_name);
08108
08109 ASM_GENERATE_INTERNAL_LABEL (buf, "LCG", reload_toc_labelno++);
08110 symF = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
08111
08112 rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_1b (tempLR,
08113 symF,
08114 tocsym)));
08115 rs6000_maybe_dead (emit_move_insn (dest, tempLR));
08116 rs6000_maybe_dead (emit_move_insn (temp0,
08117 gen_rtx_MEM (Pmode, dest)));
08118 }
08119 rs6000_maybe_dead (emit_insn (gen_addsi3 (dest, temp0, dest)));
08120 }
08121 else if (TARGET_ELF && !TARGET_AIX && flag_pic == 0 && TARGET_MINIMAL_TOC)
08122 {
08123
08124 char buf[30];
08125 rtx realsym;
08126 ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
08127 realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
08128
08129 rs6000_maybe_dead (emit_insn (gen_elf_high (dest, realsym)));
08130 rs6000_maybe_dead (emit_insn (gen_elf_low (dest, dest, realsym)));
08131 }
08132 else if (DEFAULT_ABI == ABI_AIX)
08133 {
08134 if (TARGET_32BIT)
08135 rs6000_maybe_dead (emit_insn (gen_load_toc_aix_si (dest)));
08136 else
08137 rs6000_maybe_dead (emit_insn (gen_load_toc_aix_di (dest)));
08138 }
08139 else
08140 abort ();
08141 }
08142
08143 int
08144 get_TOC_alias_set ()
08145 {
08146 static int set = -1;
08147 if (set == -1)
08148 set = new_alias_set ();
08149 return set;
08150 }
08151
08152
08153
08154
08155
08156 int
08157 uses_TOC ()
08158 {
08159 rtx insn;
08160
08161 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
08162 if (INSN_P (insn))
08163 {
08164 rtx pat = PATTERN (insn);
08165 int i;
08166
08167 if (GET_CODE (pat) == PARALLEL)
08168 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
08169 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == UNSPEC
08170 && XINT (XVECEXP (PATTERN (insn), 0, i), 1) == 7)
08171 return 1;
08172 }
08173 return 0;
08174 }
08175
08176 rtx
08177 create_TOC_reference (symbol)
08178 rtx symbol;
08179 {
08180 return gen_rtx_PLUS (Pmode,
08181 gen_rtx_REG (Pmode, TOC_REGISTER),
08182 gen_rtx_CONST (Pmode,
08183 gen_rtx_MINUS (Pmode, symbol,
08184 gen_rtx_SYMBOL_REF (Pmode, toc_label_name))));
08185 }
08186
08187 #if TARGET_AIX
08188
08189
08190
08191
08192
08193
08194
08195
08196 static rtx insn_after_throw;
08197
08198
08199 void
08200 rs6000_aix_emit_builtin_unwind_init ()
08201 {
08202 rtx mem;
08203 rtx stack_top = gen_reg_rtx (Pmode);
08204 rtx opcode_addr = gen_reg_rtx (Pmode);
08205
08206 insn_after_throw = gen_reg_rtx (SImode);
08207
08208 mem = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
08209 emit_move_insn (stack_top, mem);
08210
08211 mem = gen_rtx_MEM (Pmode,
08212 gen_rtx_PLUS (Pmode, stack_top,
08213 GEN_INT (2 * GET_MODE_SIZE (Pmode))));
08214 emit_move_insn (opcode_addr, mem);
08215 emit_move_insn (insn_after_throw, gen_rtx_MEM (SImode, opcode_addr));
08216 }
08217
08218
08219
08220
08221
08222
08223
08224
08225
08226
08227
08228
08229
08230
08231
08232
08233
08234
08235
08236
08237
08238
08239
08240
08241
08242
08243
08244
08245
08246
08247
08248
08249
08250
08251
08252
08253
08254 void
08255 rs6000_emit_eh_toc_restore (stacksize)
08256 rtx stacksize;
08257 {
08258 rtx top_of_stack;
08259 rtx bottom_of_stack = gen_reg_rtx (Pmode);
08260 rtx tocompare = gen_reg_rtx (SImode);
08261 rtx opcode = gen_reg_rtx (SImode);
08262 rtx opcode_addr = gen_reg_rtx (Pmode);
08263 rtx mem;
08264 rtx loop_start = gen_label_rtx ();
08265 rtx no_toc_restore_needed = gen_label_rtx ();
08266 rtx loop_exit = gen_label_rtx ();
08267
08268 mem = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
08269 set_mem_alias_set (mem, rs6000_sr_alias_set);
08270 emit_move_insn (bottom_of_stack, mem);
08271
08272 top_of_stack = expand_binop (Pmode, add_optab,
08273 bottom_of_stack, stacksize,
08274 NULL_RTX, 1, OPTAB_WIDEN);
08275
08276 emit_move_insn (tocompare,
08277 GEN_INT (trunc_int_for_mode (TARGET_32BIT
08278 ? 0x80410014
08279 : 0xE8410028, SImode)));
08280
08281 if (insn_after_throw == NULL_RTX)
08282 abort ();
08283 emit_move_insn (opcode, insn_after_throw);
08284
08285 emit_note (NULL, NOTE_INSN_LOOP_BEG);
08286 emit_label (loop_start);
08287
08288 do_compare_rtx_and_jump (opcode, tocompare, NE, 1,
08289 SImode, NULL_RTX, NULL_RTX,
08290 no_toc_restore_needed);
08291
08292 mem = gen_rtx_MEM (Pmode,
08293 gen_rtx_PLUS (Pmode, bottom_of_stack,
08294 GEN_INT (5 * GET_MODE_SIZE (Pmode))));
08295 emit_move_insn (gen_rtx_REG (Pmode, 2), mem);
08296
08297 emit_label (no_toc_restore_needed);
08298 do_compare_rtx_and_jump (top_of_stack, bottom_of_stack, EQ, 1,
08299 Pmode, NULL_RTX, NULL_RTX,
08300 loop_exit);
08301
08302 mem = gen_rtx_MEM (Pmode, bottom_of_stack);
08303 set_mem_alias_set (mem, rs6000_sr_alias_set);
08304 emit_move_insn (bottom_of_stack, mem);
08305
08306 mem = gen_rtx_MEM (Pmode,
08307 gen_rtx_PLUS (Pmode, bottom_of_stack,
08308 GEN_INT (2 * GET_MODE_SIZE (Pmode))));
08309 emit_move_insn (opcode_addr, mem);
08310 emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
08311
08312 emit_note (NULL, NOTE_INSN_LOOP_CONT);
08313 emit_jump (loop_start);
08314 emit_note (NULL, NOTE_INSN_LOOP_END);
08315 emit_label (loop_exit);
08316 }
08317 #endif
08318
08319
08320
08321
08322 static void
08323 rs6000_emit_stack_tie ()
08324 {
08325 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM));
08326
08327 set_mem_alias_set (mem, rs6000_sr_alias_set);
08328 emit_insn (gen_stack_tie (mem));
08329 }
08330
08331
08332
08333
08334
08335 static void
08336 rs6000_emit_allocate_stack (size, copy_r12)
08337 HOST_WIDE_INT size;
08338 int copy_r12;
08339 {
08340 rtx insn;
08341 rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
08342 rtx tmp_reg = gen_rtx_REG (Pmode, 0);
08343 rtx todec = GEN_INT (-size);
08344
08345 if (current_function_limit_stack)
08346 {
08347 if (REG_P (stack_limit_rtx)
08348 && REGNO (stack_limit_rtx) > 1
08349 && REGNO (stack_limit_rtx) <= 31)
08350 {
08351 emit_insn (Pmode == SImode
08352 ? gen_addsi3 (tmp_reg,
08353 stack_limit_rtx,
08354 GEN_INT (size))
08355 : gen_adddi3 (tmp_reg,
08356 stack_limit_rtx,
08357 GEN_INT (size)));
08358
08359 emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
08360 const0_rtx));
08361 }
08362 else if (GET_CODE (stack_limit_rtx) == SYMBOL_REF
08363 && TARGET_32BIT
08364 && DEFAULT_ABI == ABI_V4)
08365 {
08366 rtx toload = gen_rtx_CONST (VOIDmode,
08367 gen_rtx_PLUS (Pmode,
08368 stack_limit_rtx,
08369 GEN_INT (size)));
08370
08371 emit_insn (gen_elf_high (tmp_reg, toload));
08372 emit_insn (gen_elf_low (tmp_reg, tmp_reg, toload));
08373 emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
08374 const0_rtx));
08375 }
08376 else
08377 warning ("stack limit expression is not supported");
08378 }
08379
08380 if (copy_r12 || ! TARGET_UPDATE)
08381 emit_move_insn (gen_rtx_REG (Pmode, 12), stack_reg);
08382
08383 if (TARGET_UPDATE)
08384 {
08385 if (size > 32767)
08386 {
08387
08388 if (get_last_insn() == NULL_RTX)
08389 emit_note (0, NOTE_INSN_DELETED);
08390 insn = emit_move_insn (tmp_reg, todec);
08391 try_split (PATTERN (insn), insn, 0);
08392 todec = tmp_reg;
08393 }
08394
08395 if (Pmode == SImode)
08396 insn = emit_insn (gen_movsi_update (stack_reg, stack_reg,
08397 todec, stack_reg));
08398 else
08399 insn = emit_insn (gen_movdi_update (stack_reg, stack_reg,
08400 todec, stack_reg));
08401 }
08402 else
08403 {
08404 if (Pmode == SImode)
08405 insn = emit_insn (gen_addsi3 (stack_reg, stack_reg, todec));
08406 else
08407 insn = emit_insn (gen_adddi3 (stack_reg, stack_reg, todec));
08408 emit_move_insn (gen_rtx_MEM (Pmode, stack_reg),
08409 gen_rtx_REG (Pmode, 12));
08410 }
08411
08412 RTX_FRAME_RELATED_P (insn) = 1;
08413 REG_NOTES (insn) =
08414 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
08415 gen_rtx_SET (VOIDmode, stack_reg,
08416 gen_rtx_PLUS (Pmode, stack_reg,
08417 GEN_INT (-size))),
08418 REG_NOTES (insn));
08419 }
08420
08421
08422
08423
08424
08425
08426
08427
08428
08429
08430 static void
08431 altivec_frame_fixup (insn, reg, val)
08432 rtx insn, reg;
08433 HOST_WIDE_INT val;
08434 {
08435 rtx real;
08436
08437 real = copy_rtx (PATTERN (insn));
08438
08439 real = replace_rtx (real, reg, GEN_INT (val));
08440
08441 RTX_FRAME_RELATED_P (insn) = 1;
08442 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
08443 real,
08444 REG_NOTES (insn));
08445 }
08446
08447
08448
08449
08450
08451
08452
08453 static void
08454 rs6000_frame_related (insn, reg, val, reg2, rreg)
08455 rtx insn;
08456 rtx reg;
08457 HOST_WIDE_INT val;
08458 rtx reg2;
08459 rtx rreg;
08460 {
08461 rtx real, temp;
08462
08463 real = copy_rtx (PATTERN (insn));
08464
08465 real = replace_rtx (real, reg,
08466 gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
08467 STACK_POINTER_REGNUM),
08468 GEN_INT (val)));
08469
08470
08471
08472
08473
08474 if (GET_CODE (real) == SET)
08475 {
08476 rtx set = real;
08477
08478 temp = simplify_rtx (SET_SRC (set));
08479 if (temp)
08480 SET_SRC (set) = temp;
08481 temp = simplify_rtx (SET_DEST (set));
08482 if (temp)
08483 SET_DEST (set) = temp;
08484 if (GET_CODE (SET_DEST (set)) == MEM)
08485 {
08486 temp = simplify_rtx (XEXP (SET_DEST (set), 0));
08487 if (temp)
08488 XEXP (SET_DEST (set), 0) = temp;
08489 }
08490 }
08491 else if (GET_CODE (real) == PARALLEL)
08492 {
08493 int i;
08494 for (i = 0; i < XVECLEN (real, 0); i++)
08495 if (GET_CODE (XVECEXP (real, 0, i)) == SET)
08496 {
08497 rtx set = XVECEXP (real, 0, i);
08498
08499 temp = simplify_rtx (SET_SRC (set));
08500 if (temp)
08501 SET_SRC (set) = temp;
08502 temp = simplify_rtx (SET_DEST (set));
08503 if (temp)
08504 SET_DEST (set) = temp;
08505 if (GET_CODE (SET_DEST (set)) == MEM)
08506 {
08507 temp = simplify_rtx (XEXP (SET_DEST (set), 0));
08508 if (temp)
08509 XEXP (SET_DEST (set), 0) = temp;
08510 }
08511 RTX_FRAME_RELATED_P (set) = 1;
08512 }
08513 }
08514 else
08515 abort ();
08516
08517 if (reg2 != NULL_RTX)
08518 real = replace_rtx (real, reg2, rreg);
08519
08520 RTX_FRAME_RELATED_P (insn) = 1;
08521 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
08522 real,
08523 REG_NOTES (insn));
08524 }
08525
08526
08527
08528
08529 static rtx
08530 generate_set_vrsave (reg, info, epiloguep)
08531 rtx reg;
08532 rs6000_stack_t *info;
08533 int epiloguep;
08534 {
08535 int nclobs, i;
08536 rtx insn, clobs[TOTAL_ALTIVEC_REGS + 1];
08537 rtx vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
08538
08539 clobs[0]
08540 = gen_rtx_SET (VOIDmode,
08541 vrsave,
08542 gen_rtx_UNSPEC_VOLATILE (SImode,
08543 gen_rtvec (2, reg, vrsave),
08544 30));
08545
08546 nclobs = 1;
08547
08548
08549
08550
08551
08552
08553
08554
08555
08556
08557
08558
08559
08560
08561
08562 for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
08563 if (info->vrsave_mask != 0 && ALTIVEC_REG_BIT (i) != 0)
08564 {
08565 if (!epiloguep || call_used_regs [i])
08566 clobs[nclobs++] = gen_rtx_CLOBBER (VOIDmode,
08567 gen_rtx_REG (V4SImode, i));
08568 else
08569 {
08570 rtx reg = gen_rtx_REG (V4SImode, i);
08571
08572 clobs[nclobs++]
08573 = gen_rtx_SET (VOIDmode,
08574 reg,
08575 gen_rtx_UNSPEC (V4SImode,
08576 gen_rtvec (1, reg), 27));
08577 }
08578 }
08579
08580 insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nclobs));
08581
08582 for (i = 0; i < nclobs; ++i)
08583 XVECEXP (insn, 0, i) = clobs[i];
08584
08585 return insn;
08586 }
08587
08588
08589
08590 void
08591 rs6000_emit_prologue ()
08592 {
08593 rs6000_stack_t *info = rs6000_stack_info ();
08594 enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
08595 int reg_size = TARGET_POWERPC64 ? 8 : 4;
08596 rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
08597 rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 12);
08598 rtx frame_reg_rtx = sp_reg_rtx;
08599 rtx cr_save_rtx = NULL;
08600 rtx insn;
08601 int saving_FPRs_inline;
08602 int using_store_multiple;
08603 HOST_WIDE_INT sp_offset = 0;
08604
08605 using_store_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
08606 && info->first_gp_reg_save < 31);
08607 saving_FPRs_inline = (info->first_fp_reg_save == 64
08608 || FP_SAVE_INLINE (info->first_fp_reg_save));
08609
08610
08611 if (info->push_p && DEFAULT_ABI == ABI_V4)
08612 {
08613 if (info->total_size < 32767)
08614 sp_offset = info->total_size;
08615 else
08616 frame_reg_rtx = frame_ptr_rtx;
08617 rs6000_emit_allocate_stack (info->total_size,
08618 (frame_reg_rtx != sp_reg_rtx
08619 && (info->cr_save_p
08620 || info->lr_save_p
08621 || info->first_fp_reg_save < 64
08622 || info->first_gp_reg_save < 32
08623 )));
08624 if (frame_reg_rtx != sp_reg_rtx)
08625 rs6000_emit_stack_tie ();
08626 }
08627
08628
08629 if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
08630 {
08631 int i;
08632
08633
08634
08635 for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
08636 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
08637 {
08638 rtx areg, savereg, mem;
08639 int offset;
08640
08641 offset = info->altivec_save_offset + sp_offset
08642 + 16 * (i - info->first_altivec_reg_save);
08643
08644 savereg = gen_rtx_REG (V4SImode, i);
08645
08646 areg = gen_rtx_REG (Pmode, 0);
08647 emit_move_insn (areg, GEN_INT (offset));
08648
08649
08650 mem = gen_rtx_MEM (V4SImode,
08651 gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
08652
08653 set_mem_alias_set (mem, rs6000_sr_alias_set);
08654
08655 insn = emit_move_insn (mem, savereg);
08656
08657 altivec_frame_fixup (insn, areg, offset);
08658 }
08659 }
08660
08661
08662
08663
08664
08665
08666
08667
08668 if (TARGET_ALTIVEC && info->vrsave_mask != 0)
08669 {
08670 rtx reg, mem, vrsave;
08671 int offset;
08672
08673
08674 reg = gen_rtx_REG (SImode, 12);
08675 vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
08676 if (TARGET_MACHO)
08677 emit_insn (gen_get_vrsave_internal (reg));
08678 else
08679 emit_insn (gen_rtx_SET (VOIDmode, reg, vrsave));
08680
08681
08682 offset = info->vrsave_save_offset + sp_offset;
08683 mem
08684 = gen_rtx_MEM (SImode,
08685 gen_rtx_PLUS (Pmode, frame_reg_rtx, GEN_INT (offset)));
08686 set_mem_alias_set (mem, rs6000_sr_alias_set);
08687 insn = emit_move_insn (mem, reg);
08688
08689
08690 emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
08691
08692 insn = emit_insn (generate_set_vrsave (reg, info, 0));
08693 }
08694
08695
08696 if (info->lr_save_p)
08697 emit_move_insn (gen_rtx_REG (Pmode, 0),
08698 gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
08699
08700
08701 if (info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
08702 {
08703 cr_save_rtx = gen_rtx_REG (SImode, 12);
08704 emit_insn (gen_movesi_from_cr (cr_save_rtx));
08705 }
08706
08707
08708
08709 if (saving_FPRs_inline)
08710 {
08711 int i;
08712 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
08713 if ((regs_ever_live[info->first_fp_reg_save+i]
08714 && ! call_used_regs[info->first_fp_reg_save+i]))
08715 {
08716 rtx addr, reg, mem;
08717 reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
08718 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
08719 GEN_INT (info->fp_save_offset
08720 + sp_offset
08721 + 8 * i));
08722 mem = gen_rtx_MEM (DFmode, addr);
08723 set_mem_alias_set (mem, rs6000_sr_alias_set);
08724
08725 insn = emit_move_insn (mem, reg);
08726 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
08727 NULL_RTX, NULL_RTX);
08728 }
08729 }
08730 else if (info->first_fp_reg_save != 64)
08731 {
08732 int i;
08733 char rname[30];
08734 const char *alloc_rname;
08735 rtvec p;
08736 p = rtvec_alloc (2 + 64 - info->first_fp_reg_save);
08737
08738 RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode,
08739 gen_rtx_REG (Pmode,
08740 LINK_REGISTER_REGNUM));
08741 sprintf (rname, "%s%d%s", SAVE_FP_PREFIX,
08742 info->first_fp_reg_save - 32, SAVE_FP_SUFFIX);
08743 alloc_rname = ggc_strdup (rname);
08744 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
08745 gen_rtx_SYMBOL_REF (Pmode,
08746 alloc_rname));
08747 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
08748 {
08749 rtx addr, reg, mem;
08750 reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
08751 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
08752 GEN_INT (info->fp_save_offset
08753 + sp_offset + 8*i));
08754 mem = gen_rtx_MEM (DFmode, addr);
08755 set_mem_alias_set (mem, rs6000_sr_alias_set);
08756
08757 RTVEC_ELT (p, i + 2) = gen_rtx_SET (VOIDmode, mem, reg);
08758 }
08759 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
08760 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
08761 NULL_RTX, NULL_RTX);
08762 }
08763
08764
08765
08766 if (using_store_multiple)
08767 {
08768 rtvec p, dwarfp;
08769 int i;
08770 p = rtvec_alloc (32 - info->first_gp_reg_save);
08771 dwarfp = rtvec_alloc (32 - info->first_gp_reg_save);
08772 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
08773 {
08774 rtx addr, reg, mem;
08775 reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
08776 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
08777 GEN_INT (info->gp_save_offset
08778 + sp_offset
08779 + reg_size * i));
08780 mem = gen_rtx_MEM (reg_mode, addr);
08781 set_mem_alias_set (mem, rs6000_sr_alias_set);
08782
08783 RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, mem, reg);
08784 }
08785 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
08786 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
08787 NULL_RTX, NULL_RTX);
08788 }
08789 else
08790 {
08791 int i;
08792 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
08793 if ((regs_ever_live[info->first_gp_reg_save+i]
08794 && ! call_used_regs[info->first_gp_reg_save+i])
08795 || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
08796 && ((DEFAULT_ABI == ABI_V4 && flag_pic == 1)
08797 || (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
08798 {
08799 rtx addr, reg, mem;
08800 reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
08801 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
08802 GEN_INT (info->gp_save_offset
08803 + sp_offset
08804 + reg_size * i));
08805 mem = gen_rtx_MEM (reg_mode, addr);
08806 set_mem_alias_set (mem, rs6000_sr_alias_set);
08807
08808 insn = emit_move_insn (mem, reg);
08809 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
08810 NULL_RTX, NULL_RTX);
08811 }
08812 }
08813
08814
08815
08816 if (current_function_calls_eh_return)
08817 {
08818 unsigned int i, regno;
08819
08820 for (i = 0; ; ++i)
08821 {
08822 rtx addr, reg, mem;
08823
08824 regno = EH_RETURN_DATA_REGNO (i);
08825 if (regno == INVALID_REGNUM)
08826 break;
08827
08828 reg = gen_rtx_REG (reg_mode, regno);
08829 addr = plus_constant (frame_reg_rtx,
08830 info->ehrd_offset + sp_offset
08831 + reg_size * (int) i);
08832 mem = gen_rtx_MEM (reg_mode, addr);
08833 set_mem_alias_set (mem, rs6000_sr_alias_set);
08834
08835 insn = emit_move_insn (mem, reg);
08836 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
08837 NULL_RTX, NULL_RTX);
08838 }
08839 }
08840
08841
08842 if (info->lr_save_p)
08843 {
08844 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
08845 GEN_INT (info->lr_save_offset + sp_offset));
08846 rtx reg = gen_rtx_REG (Pmode, 0);
08847 rtx mem = gen_rtx_MEM (Pmode, addr);
08848
08849
08850
08851 insn = emit_move_insn (mem, reg);
08852 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
08853 reg, gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
08854 }
08855
08856
08857 if (info->cr_save_p)
08858 {
08859 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
08860 GEN_INT (info->cr_save_offset + sp_offset));
08861 rtx mem = gen_rtx_MEM (SImode, addr);
08862
08863 set_mem_alias_set (mem, rs6000_sr_alias_set);
08864
08865
08866
08867 if (REGNO (frame_reg_rtx) == 12)
08868 {
08869 cr_save_rtx = gen_rtx_REG (SImode, 0);
08870 emit_insn (gen_movesi_from_cr (cr_save_rtx));
08871 }
08872 insn = emit_move_insn (mem, cr_save_rtx);
08873
08874
08875
08876
08877
08878
08879
08880 rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
08881 cr_save_rtx, gen_rtx_REG (SImode, CR2_REGNO));
08882 }
08883
08884
08885
08886 if (info->push_p && DEFAULT_ABI != ABI_V4)
08887 rs6000_emit_allocate_stack (info->total_size, FALSE);
08888
08889
08890 if (frame_pointer_needed)
08891 {
08892 insn = emit_move_insn (gen_rtx_REG (reg_mode, FRAME_POINTER_REGNUM),
08893 sp_reg_rtx);
08894 RTX_FRAME_RELATED_P (insn) = 1;
08895 }
08896
08897
08898 if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
08899 || (DEFAULT_ABI == ABI_V4 && flag_pic == 1
08900 && regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM]))
08901 {
08902
08903
08904
08905
08906 int save_LR_around_toc_setup = (TARGET_ELF && flag_pic != 0
08907 && ! info->lr_save_p
08908 && EXIT_BLOCK_PTR->pred != NULL);
08909 if (save_LR_around_toc_setup)
08910 emit_move_insn (gen_rtx_REG (Pmode, 11),
08911 gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
08912
08913 rs6000_emit_load_toc_table (TRUE);
08914
08915 if (save_LR_around_toc_setup)
08916 emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
08917 gen_rtx_REG (Pmode, 11));
08918 }
08919
08920 if (DEFAULT_ABI == ABI_DARWIN
08921 && flag_pic && current_function_uses_pic_offset_table)
08922 {
08923 rtx dest = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
08924
08925 rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (dest)));
08926
08927 rs6000_maybe_dead (
08928 emit_move_insn (gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM),
08929 gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)));
08930 }
08931 }
08932
08933
08934
08935 static void
08936 rs6000_output_function_prologue (file, size)
08937 FILE *file;
08938 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
08939 {
08940 rs6000_stack_t *info = rs6000_stack_info ();
08941
08942 if (TARGET_DEBUG_STACK)
08943 debug_stack_info (info);
08944
08945
08946
08947 if (info->first_fp_reg_save < 64
08948 && !FP_SAVE_INLINE (info->first_fp_reg_save))
08949 fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n",
08950 SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX,
08951 RESTORE_FP_PREFIX, info->first_fp_reg_save - 32,
08952 RESTORE_FP_SUFFIX);
08953
08954
08955 if (! TARGET_POWER && ! TARGET_POWERPC && ! common_mode_defined)
08956 {
08957 fputs ("\t.extern __mulh\n", file);
08958 fputs ("\t.extern __mull\n", file);
08959 fputs ("\t.extern __divss\n", file);
08960 fputs ("\t.extern __divus\n", file);
08961 fputs ("\t.extern __quoss\n", file);
08962 fputs ("\t.extern __quous\n", file);
08963 common_mode_defined = 1;
08964 }
08965
08966 if (! HAVE_prologue)
08967 {
08968 start_sequence ();
08969
08970
08971
08972 emit_note (0, NOTE_INSN_DELETED);
08973 rs6000_emit_prologue ();
08974 emit_note (0, NOTE_INSN_DELETED);
08975
08976
08977 {
08978 rtx insn;
08979 unsigned addr = 0;
08980 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
08981 {
08982 INSN_ADDRESSES_NEW (insn, addr);
08983 addr += 4;
08984 }
08985 }
08986
08987 if (TARGET_DEBUG_STACK)
08988 debug_rtx_list (get_insns (), 100);
08989 final (get_insns (), file, FALSE, FALSE);
08990 end_sequence ();
08991 }
08992
08993 rs6000_pic_labelno++;
08994 }
08995
08996
08997
08998
08999
09000
09001
09002
09003 void
09004 rs6000_emit_epilogue (sibcall)
09005 int sibcall;
09006 {
09007 rs6000_stack_t *info;
09008 int restoring_FPRs_inline;
09009 int using_load_multiple;
09010 int using_mfcr_multiple;
09011 int use_backchain_to_restore_sp;
09012 int sp_offset = 0;
09013 rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
09014 rtx frame_reg_rtx = sp_reg_rtx;
09015 enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
09016 int reg_size = TARGET_POWERPC64 ? 8 : 4;
09017 int i;
09018
09019 info = rs6000_stack_info ();
09020 using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
09021 && info->first_gp_reg_save < 31);
09022 restoring_FPRs_inline = (sibcall
09023 || current_function_calls_eh_return
09024 || info->first_fp_reg_save == 64
09025 || FP_SAVE_INLINE (info->first_fp_reg_save));
09026 use_backchain_to_restore_sp = (frame_pointer_needed
09027 || current_function_calls_alloca
09028 || info->total_size > 32767);
09029 using_mfcr_multiple = (rs6000_cpu == PROCESSOR_PPC601
09030 || rs6000_cpu == PROCESSOR_PPC603
09031 || rs6000_cpu == PROCESSOR_PPC750
09032 || optimize_size);
09033
09034
09035
09036
09037 if (use_backchain_to_restore_sp)
09038 {
09039
09040
09041 if (DEFAULT_ABI == ABI_V4)
09042 frame_reg_rtx = gen_rtx_REG (Pmode, 11);
09043
09044 emit_move_insn (frame_reg_rtx,
09045 gen_rtx_MEM (Pmode, sp_reg_rtx));
09046
09047 }
09048 else if (info->push_p)
09049 {
09050 if (DEFAULT_ABI == ABI_V4)
09051 sp_offset = info->total_size;
09052 else
09053 {
09054 emit_insn (TARGET_32BIT
09055 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
09056 GEN_INT (info->total_size))
09057 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
09058 GEN_INT (info->total_size)));
09059 }
09060 }
09061
09062
09063 if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
09064 {
09065 int i;
09066
09067 for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
09068 if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
09069 {
09070 rtx addr, areg, mem;
09071
09072 areg = gen_rtx_REG (Pmode, 0);
09073 emit_move_insn
09074 (areg, GEN_INT (info->altivec_save_offset
09075 + sp_offset
09076 + 16 * (i - info->first_altivec_reg_save)));
09077
09078
09079 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
09080 mem = gen_rtx_MEM (V4SImode, addr);
09081 set_mem_alias_set (mem, rs6000_sr_alias_set);
09082
09083 emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
09084 }
09085 }
09086
09087
09088 if (TARGET_ALTIVEC_ABI && info->vrsave_mask != 0)
09089 {
09090 rtx addr, mem, reg;
09091
09092 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
09093 GEN_INT (info->vrsave_save_offset + sp_offset));
09094 mem = gen_rtx_MEM (SImode, addr);
09095 set_mem_alias_set (mem, rs6000_sr_alias_set);
09096 reg = gen_rtx_REG (SImode, 12);
09097 emit_move_insn (reg, mem);
09098
09099 emit_insn (generate_set_vrsave (reg, info, 1));
09100 }
09101
09102
09103 if (info->lr_save_p)
09104 {
09105 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
09106 GEN_INT (info->lr_save_offset + sp_offset));
09107 rtx mem = gen_rtx_MEM (Pmode, addr);
09108
09109 set_mem_alias_set (mem, rs6000_sr_alias_set);
09110
09111 emit_move_insn (gen_rtx_REG (Pmode, 0), mem);
09112 }
09113
09114
09115 if (info->cr_save_p)
09116 {
09117 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
09118 GEN_INT (info->cr_save_offset + sp_offset));
09119 rtx mem = gen_rtx_MEM (SImode, addr);
09120
09121 set_mem_alias_set (mem, rs6000_sr_alias_set);
09122
09123 emit_move_insn (gen_rtx_REG (SImode, 12), mem);
09124 }
09125
09126
09127 if (info->lr_save_p)
09128 emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
09129 gen_rtx_REG (Pmode, 0));
09130
09131
09132 if (current_function_calls_eh_return)
09133 {
09134 unsigned int i, regno;
09135
09136 for (i = 0; ; ++i)
09137 {
09138 rtx addr, mem;
09139
09140 regno = EH_RETURN_DATA_REGNO (i);
09141 if (regno == INVALID_REGNUM)
09142 break;
09143
09144 addr = plus_constant (frame_reg_rtx,
09145 info->ehrd_offset + sp_offset
09146 + reg_size * (int) i);
09147 mem = gen_rtx_MEM (reg_mode, addr);
09148 set_mem_alias_set (mem, rs6000_sr_alias_set);
09149
09150 emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
09151 }
09152 }
09153
09154
09155
09156 if (using_load_multiple)
09157 {
09158 rtvec p;
09159 p = rtvec_alloc (32 - info->first_gp_reg_save);
09160 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
09161 {
09162 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
09163 GEN_INT (info->gp_save_offset
09164 + sp_offset
09165 + reg_size * i));
09166 rtx mem = gen_rtx_MEM (reg_mode, addr);
09167
09168 set_mem_alias_set (mem, rs6000_sr_alias_set);
09169
09170 RTVEC_ELT (p, i) =
09171 gen_rtx_SET (VOIDmode,
09172 gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
09173 mem);
09174 }
09175 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
09176 }
09177 else
09178 for (i = 0; i < 32 - info->first_gp_reg_save; i++)
09179 if ((regs_ever_live[info->first_gp_reg_save+i]
09180 && ! call_used_regs[info->first_gp_reg_save+i])
09181 || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
09182 && ((DEFAULT_ABI == ABI_V4 && flag_pic == 1)
09183 || (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
09184 {
09185 rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
09186 GEN_INT (info->gp_save_offset
09187 + sp_offset
09188 + reg_size * i));
09189 rtx mem = gen_rtx_MEM (reg_mode, addr);
09190
09191 set_mem_alias_set (mem, rs6000_sr_alias_set);
09192
09193 emit_move_insn (gen_rtx_REG (reg_mode,
09194 info->first_gp_reg_save + i),
09195 mem);
09196 }
09197
09198
09199 if (restoring_FPRs_inline)
09200 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
09201 if ((regs_ever_live[info->first_fp_reg_save+i]
09202 && ! call_used_regs[info->first_fp_reg_save+i]))
09203 {
09204 rtx addr, mem;
09205 addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
09206 GEN_INT (info->fp_save_offset
09207 + sp_offset
09208 + 8 * i));
09209 mem = gen_rtx_MEM (DFmode, addr);
09210 set_mem_alias_set (mem, rs6000_sr_alias_set);
09211
09212 emit_move_insn (gen_rtx_REG (DFmode,
09213 info->first_fp_reg_save + i),
09214 mem);
09215 }
09216
09217
09218 if (info->cr_save_p)
09219 {
09220 rtx r12_rtx = gen_rtx_REG (SImode, 12);
09221 int count = 0;
09222
09223 if (using_mfcr_multiple)
09224 {
09225 for (i = 0; i < 8; i++)
09226 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
09227 count++;
09228 if (count == 0)
09229 abort ();
09230 }
09231
09232 if (using_mfcr_multiple && count > 1)
09233 {
09234 rtvec p;
09235 int ndx;
09236
09237 p = rtvec_alloc (count);
09238
09239 ndx = 0;
09240 for (i = 0; i < 8; i++)
09241 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
09242 {
09243 rtvec r = rtvec_alloc (2);
09244 RTVEC_ELT (r, 0) = r12_rtx;
09245 RTVEC_ELT (r, 1) = GEN_INT (1 << (7-i));
09246 RTVEC_ELT (p, ndx) =
09247 gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO+i),
09248 gen_rtx_UNSPEC (CCmode, r, 20));
09249 ndx++;
09250 }
09251 emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
09252 if (ndx != count)
09253 abort ();
09254 }
09255 else
09256 for (i = 0; i < 8; i++)
09257 if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
09258 {
09259 emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode,
09260 CR0_REGNO+i),
09261 r12_rtx));
09262 }
09263 }
09264
09265
09266
09267
09268
09269
09270
09271 if (DEFAULT_ABI == ABI_V4)
09272 {
09273 if (frame_reg_rtx != sp_reg_rtx)
09274 rs6000_emit_stack_tie ();
09275
09276 if (use_backchain_to_restore_sp)
09277 {
09278 emit_move_insn (sp_reg_rtx, frame_reg_rtx);
09279 }
09280 else if (sp_offset != 0)
09281 {
09282 emit_insn (Pmode == SImode
09283 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
09284 GEN_INT (sp_offset))
09285 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
09286 GEN_INT (sp_offset)));
09287 }
09288 }
09289
09290 if (current_function_calls_eh_return)
09291 {
09292 rtx sa = EH_RETURN_STACKADJ_RTX;
09293 emit_insn (Pmode == SImode
09294 ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, sa)
09295 : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, sa));
09296 }
09297
09298 if (!sibcall)
09299 {
09300 rtvec p;
09301 if (! restoring_FPRs_inline)
09302 p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
09303 else
09304 p = rtvec_alloc (2);
09305
09306 RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
09307 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
09308 gen_rtx_REG (Pmode,
09309 LINK_REGISTER_REGNUM));
09310
09311
09312
09313 if (! restoring_FPRs_inline)
09314 {
09315 int i;
09316 char rname[30];
09317 const char *alloc_rname;
09318
09319 sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX,
09320 info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
09321 alloc_rname = ggc_strdup (rname);
09322 RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
09323 gen_rtx_SYMBOL_REF (Pmode,
09324 alloc_rname));
09325
09326 for (i = 0; i < 64 - info->first_fp_reg_save; i++)
09327 {
09328 rtx addr, mem;
09329 addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
09330 GEN_INT (info->fp_save_offset + 8*i));
09331 mem = gen_rtx_MEM (DFmode, addr);
09332 set_mem_alias_set (mem, rs6000_sr_alias_set);
09333
09334 RTVEC_ELT (p, i+3) =
09335 gen_rtx_SET (VOIDmode,
09336 gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
09337 mem);
09338 }
09339 }
09340
09341 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
09342 }
09343 }
09344
09345
09346
09347 static void
09348 rs6000_output_function_epilogue (file, size)
09349 FILE *file;
09350 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
09351 {
09352 rs6000_stack_t *info = rs6000_stack_info ();
09353 int optional_tbtab = (optimize_size || TARGET_ELF) ? 0 : 1;
09354
09355 if (! HAVE_epilogue)
09356 {
09357 rtx insn = get_last_insn ();
09358
09359
09360 if (GET_CODE (insn) == NOTE)
09361 insn = prev_nonnote_insn (insn);
09362 if (insn == 0 || GET_CODE (insn) != BARRIER)
09363 {
09364
09365
09366 start_sequence ();
09367
09368
09369
09370 emit_note (0, NOTE_INSN_DELETED);
09371 rs6000_emit_epilogue (FALSE);
09372 emit_note (0, NOTE_INSN_DELETED);
09373
09374
09375 {
09376 rtx insn;
09377 unsigned addr = 0;
09378 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
09379 {
09380 INSN_ADDRESSES_NEW (insn, addr);
09381 addr += 4;
09382 }
09383 }
09384
09385 if (TARGET_DEBUG_STACK)
09386 debug_rtx_list (get_insns (), 100);
09387 final (get_insns (), file, FALSE, FALSE);
09388 end_sequence ();
09389 }
09390 }
09391
09392
09393
09394
09395
09396
09397
09398
09399
09400
09401
09402
09403
09404
09405
09406 if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive)
09407 {
09408 const char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
09409 const char *language_string = lang_hooks.name;
09410 int fixed_parms = 0, float_parms = 0, parm_info = 0;
09411 int i;
09412
09413 while (*fname == '.')
09414 fname++;
09415
09416
09417
09418 if (*fname == '*')
09419 ++fname;
09420 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
09421 ASM_OUTPUT_LABEL (file, fname);
09422
09423
09424
09425
09426
09427
09428
09429
09430
09431
09432
09433
09434 fputs ("\t.long 0\n", file);
09435
09436
09437 fputs ("\t.byte 0,", file);
09438
09439
09440
09441
09442
09443
09444
09445 if (! strcmp (language_string, "GNU C")
09446 || ! strcmp (language_string, "GNU Objective-C"))
09447 i = 0;
09448 else if (! strcmp (language_string, "GNU F77"))
09449 i = 1;
09450 else if (! strcmp (language_string, "GNU Ada"))
09451 i = 3;
09452 else if (! strcmp (language_string, "GNU Pascal"))
09453 i = 2;
09454 else if (! strcmp (language_string, "GNU C++"))
09455 i = 9;
09456 else if (! strcmp (language_string, "GNU Java"))
09457 i = 13;
09458 else if (! strcmp (language_string, "GNU CHILL"))
09459 i = 44;
09460 else
09461 abort ();
09462 fprintf (file, "%d,", i);
09463
09464
09465
09466
09467
09468
09469
09470 fprintf (file, "%d,",
09471 (optional_tbtab << 5) | ((info->first_fp_reg_save != 64) << 1));
09472
09473
09474
09475
09476
09477
09478
09479 fprintf (file, "%d,",
09480 ((optional_tbtab << 6)
09481 | ((optional_tbtab & frame_pointer_needed) << 5)
09482 | (info->cr_save_p << 1)
09483 | (info->lr_save_p)));
09484
09485
09486
09487 fprintf (file, "%d,",
09488 (info->push_p << 7) | (64 - info->first_fp_reg_save));
09489
09490
09491 fprintf (file, "%d,", (32 - first_reg_to_save ()));
09492
09493 if (optional_tbtab)
09494 {
09495
09496
09497 tree decl;
09498 int next_parm_info_bit = 31;
09499
09500 for (decl = DECL_ARGUMENTS (current_function_decl);
09501 decl; decl = TREE_CHAIN (decl))
09502 {
09503 rtx parameter = DECL_INCOMING_RTL (decl);
09504 enum machine_mode mode = GET_MODE (parameter);
09505
09506 if (GET_CODE (parameter) == REG)
09507 {
09508 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
09509 {
09510 int bits;
09511
09512 float_parms++;
09513
09514 if (mode == SFmode)
09515 bits = 0x2;
09516 else if (mode == DFmode)
09517 bits = 0x3;
09518 else
09519 abort ();
09520
09521
09522 if (next_parm_info_bit > 0)
09523 parm_info |= (bits << (next_parm_info_bit - 1));
09524 next_parm_info_bit -= 2;
09525 }
09526 else
09527 {
09528 fixed_parms += ((GET_MODE_SIZE (mode)
09529 + (UNITS_PER_WORD - 1))
09530 / UNITS_PER_WORD);
09531 next_parm_info_bit -= 1;
09532 }
09533 }
09534 }
09535 }
09536
09537
09538
09539
09540 fprintf (file, "%d,", fixed_parms);
09541
09542
09543
09544
09545
09546
09547
09548
09549 fprintf (file, "%d\n", ((float_parms << 1) | (! optimize)));
09550
09551 if (! optional_tbtab)
09552 return;
09553
09554
09555
09556
09557
09558
09559
09560
09561
09562
09563 if (fixed_parms || float_parms)
09564 fprintf (file, "\t.long %d\n", parm_info);
09565
09566
09567 fputs ("\t.long ", file);
09568 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
09569 #if TARGET_AIX
09570 RS6000_OUTPUT_BASENAME (file, fname);
09571 #else
09572 assemble_name (file, fname);
09573 #endif
09574 fputs ("-.", file);
09575 #if TARGET_AIX
09576 RS6000_OUTPUT_BASENAME (file, fname);
09577 #else
09578 assemble_name (file, fname);
09579 #endif
09580 putc ('\n', file);
09581
09582
09583
09584
09585
09586
09587
09588
09589
09590
09591
09592
09593 fprintf (file, "\t.short %d\n", (int) strlen (fname));
09594
09595
09596 assemble_string (fname, strlen (fname));
09597
09598
09599
09600 if (frame_pointer_needed)
09601 fputs ("\t.byte 31\n", file);
09602
09603 fputs ("\t.align 2\n", file);
09604 }
09605 return;
09606 }
09607
09608
09609
09610
09611
09612
09613
09614
09615
09616
09617
09618
09619
09620
09621
09622
09623
09624
09625
09626
09627
09628
09629
09630
09631
09632
09633
09634
09635
09636
09637
09638
09639
09640 void
09641 output_mi_thunk (file, thunk_fndecl, delta, function)
09642 FILE *file;
09643 tree thunk_fndecl ATTRIBUTE_UNUSED;
09644 int delta;
09645 tree function;
09646 {
09647 const char *this_reg =
09648 reg_names[ aggregate_value_p (TREE_TYPE (TREE_TYPE (function))) ? 4 : 3 ];
09649 const char *prefix;
09650 const char *fname;
09651 const char *r0 = reg_names[0];
09652 const char *toc = reg_names[2];
09653 const char *schain = reg_names[11];
09654 const char *r12 = reg_names[12];
09655 char buf[512];
09656 static int labelno = 0;
09657
09658
09659 if (delta >= -32768 && delta <= 32767)
09660 {
09661 if (! TARGET_NEW_MNEMONICS)
09662 fprintf (file, "\tcal %s,%d(%s)\n", this_reg, delta, this_reg);
09663 else
09664 fprintf (file, "\taddi %s,%s,%d\n", this_reg, this_reg, delta);
09665 }
09666
09667
09668 else if (TARGET_64BIT && (delta < -2147483647 - 1 || delta > 2147483647))
09669 abort ();
09670
09671
09672 else if ((delta & 0xffff) == 0)
09673 asm_fprintf (file, "\t{cau|addis} %s,%s,%d\n", this_reg, this_reg,
09674 delta >> 16);
09675
09676
09677 else
09678 {
09679
09680
09681 int delta_low = ((delta & 0xffff) ^ 0x8000) - 0x8000;
09682 int delta_high = (delta - delta_low) >> 16;
09683
09684 asm_fprintf (file, "\t{cau|addis} %s,%s,%d\n", this_reg, this_reg,
09685 delta_high);
09686
09687 if (! TARGET_NEW_MNEMONICS)
09688 fprintf (file, "\tcal %s,%d(%s)\n", this_reg, delta_low, this_reg);
09689 else
09690 fprintf (file, "\taddi %s,%s,%d\n", this_reg, this_reg, delta_low);
09691 }
09692
09693
09694 switch (DEFAULT_ABI)
09695 {
09696 default:
09697 abort ();
09698
09699 case ABI_AIX:
09700 prefix = ".";
09701 break;
09702
09703 case ABI_V4:
09704 case ABI_AIX_NODESC:
09705 prefix = "";
09706 break;
09707 }
09708
09709
09710
09711
09712 fname = XSTR (XEXP (DECL_RTL (function), 0), 0);
09713
09714 if (current_file_function_operand (XEXP (DECL_RTL (function), 0), VOIDmode)
09715 && ! lookup_attribute ("longcall",
09716 TYPE_ATTRIBUTES (TREE_TYPE (function))))
09717 {
09718 fprintf (file, "\tb %s", prefix);
09719 assemble_name (file, fname);
09720 if (DEFAULT_ABI == ABI_V4 && flag_pic) fputs ("@local", file);
09721 putc ('\n', file);
09722 }
09723
09724 else
09725 {
09726 switch (DEFAULT_ABI)
09727 {
09728 default:
09729 abort ();
09730
09731 case ABI_AIX:
09732
09733 ASM_GENERATE_INTERNAL_LABEL (buf, "Lthunk", labelno);
09734 toc_section ();
09735 ASM_OUTPUT_INTERNAL_LABEL (file, "Lthunk", labelno);
09736 labelno++;
09737
09738 if (TARGET_MINIMAL_TOC)
09739 fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file);
09740 else
09741 {
09742 fputs ("\t.tc ", file);
09743 assemble_name (file, fname);
09744 fputs ("[TC],", file);
09745 }
09746 assemble_name (file, fname);
09747 putc ('\n', file);
09748 if (TARGET_ELF)
09749 function_section (current_function_decl);
09750 else
09751 text_section ();
09752 if (TARGET_MINIMAL_TOC)
09753 asm_fprintf (file, (TARGET_32BIT)
09754 ? "\t{l|lwz} %s,%s(%s)\n" : "\tld %s,%s(%s)\n", r12,
09755 TARGET_ELF ? ".LCTOC0@toc" : ".LCTOC..1", toc);
09756 asm_fprintf (file, (TARGET_32BIT) ? "\t{l|lwz} %s," : "\tld %s,", r12);
09757 assemble_name (file, buf);
09758 if (TARGET_ELF && TARGET_MINIMAL_TOC)
09759 fputs ("-(.LCTOC1)", file);
09760 asm_fprintf (file, "(%s)\n", TARGET_MINIMAL_TOC ? r12 : toc);
09761 asm_fprintf (file,
09762 (TARGET_32BIT) ? "\t{l|lwz} %s,0(%s)\n" : "\tld %s,0(%s)\n",
09763 r0, r12);
09764
09765 asm_fprintf (file,
09766 (TARGET_32BIT) ? "\t{l|lwz} %s,4(%s)\n" : "\tld %s,8(%s)\n",
09767 toc, r12);
09768
09769 asm_fprintf (file, "\tmtctr %s\n", r0);
09770 asm_fprintf (file,
09771 (TARGET_32BIT) ? "\t{l|lwz} %s,8(%s)\n" : "\tld %s,16(%s)\n",
09772 schain, r12);
09773
09774 asm_fprintf (file, "\tbctr\n");
09775 break;
09776
09777 case ABI_AIX_NODESC:
09778 case ABI_V4:
09779 fprintf (file, "\tb %s", prefix);
09780 assemble_name (file, fname);
09781 if (flag_pic) fputs ("@plt", file);
09782 putc ('\n', file);
09783 break;
09784
09785 #if TARGET_MACHO
09786 case ABI_DARWIN:
09787 fprintf (file, "\tb %s", prefix);
09788 if (flag_pic && !machopic_name_defined_p (fname))
09789 assemble_name (file, machopic_stub_name (fname));
09790 else
09791 assemble_name (file, fname);
09792 putc ('\n', file);
09793 break;
09794 #endif
09795 }
09796 }
09797 }
09798
09799
09800
09801
09802
09803
09804
09805
09806
09807
09808
09809
09810
09811
09812
09813
09814
09815
09816
09817
09818
09819
09820
09821
09822
09823
09824
09825
09826
09827
09828
09829 struct toc_hash_struct
09830 {
09831
09832
09833 rtx key;
09834 enum machine_mode key_mode;
09835 int labelno;
09836 };
09837
09838 static htab_t toc_hash_table;
09839
09840
09841
09842 static unsigned
09843 rs6000_hash_constant (k)
09844 rtx k;
09845 {
09846 unsigned result = (GET_CODE (k) << 3) ^ GET_MODE (k);
09847 const char *format = GET_RTX_FORMAT (GET_CODE (k));
09848 int flen = strlen (format);
09849 int fidx;
09850
09851 if (GET_CODE (k) == LABEL_REF)
09852 return result * 1231 + X0INT (XEXP (k, 0), 3);
09853
09854 if (GET_CODE (k) == CONST_DOUBLE)
09855 fidx = 1;
09856 else if (GET_CODE (k) == CODE_LABEL)
09857 fidx = 3;
09858 else
09859 fidx = 0;
09860
09861 for (; fidx < flen; fidx++)
09862 switch (format[fidx])
09863 {
09864 case 's':
09865 {
09866 unsigned i, len;
09867 const char *str = XSTR (k, fidx);
09868 len = strlen (str);
09869 result = result * 613 + len;
09870 for (i = 0; i < len; i++)
09871 result = result * 613 + (unsigned) str[i];
09872 break;
09873 }
09874 case 'u':
09875 case 'e':
09876 result = result * 1231 + rs6000_hash_constant (XEXP (k, fidx));
09877 break;
09878 case 'i':
09879 case 'n':
09880 result = result * 613 + (unsigned) XINT (k, fidx);
09881 break;
09882 case 'w':
09883 if (sizeof (unsigned) >= sizeof (HOST_WIDE_INT))
09884 result = result * 613 + (unsigned) XWINT (k, fidx);
09885 else
09886 {
09887 size_t i;
09888 for (i = 0; i < sizeof(HOST_WIDE_INT)/sizeof(unsigned); i++)
09889 result = result * 613 + (unsigned) (XWINT (k, fidx)
09890 >> CHAR_BIT * i);
09891 }
09892 break;
09893 default:
09894 abort ();
09895 }
09896 return result;
09897 }
09898
09899 static unsigned
09900 toc_hash_function (hash_entry)
09901 const void * hash_entry;
09902 {
09903 const struct toc_hash_struct *thc =
09904 (const struct toc_hash_struct *) hash_entry;
09905 return rs6000_hash_constant (thc->key) ^ thc->key_mode;
09906 }
09907
09908
09909
09910 static int
09911 toc_hash_eq (h1, h2)
09912 const void * h1;
09913 const void * h2;
09914 {
09915 rtx r1 = ((const struct toc_hash_struct *) h1)->key;
09916 rtx r2 = ((const struct toc_hash_struct *) h2)->key;
09917
09918 if (((const struct toc_hash_struct *) h1)->key_mode
09919 != ((const struct toc_hash_struct *) h2)->key_mode)
09920 return 0;
09921
09922
09923
09924
09925 if (r1 == r2)
09926 return 1;
09927 if (GET_CODE (r1) != GET_CODE (r2)
09928 || GET_MODE (r1) != GET_MODE (r2))
09929 return 0;
09930 if (GET_CODE (r1) == CONST_DOUBLE)
09931 {
09932 int format_len = strlen (GET_RTX_FORMAT (CONST_DOUBLE));
09933 int i;
09934 for (i = 1; i < format_len; i++)
09935 if (XWINT (r1, i) != XWINT (r2, i))
09936 return 0;
09937
09938 return 1;
09939 }
09940 else if (GET_CODE (r1) == LABEL_REF)
09941 return (CODE_LABEL_NUMBER (XEXP (r1, 0))
09942 == CODE_LABEL_NUMBER (XEXP (r2, 0)));
09943 else
09944 return rtx_equal_p (r1, r2);
09945 }
09946
09947
09948
09949 static int
09950 toc_hash_mark_entry (hash_slot, unused)
09951 void ** hash_slot;
09952 void * unused ATTRIBUTE_UNUSED;
09953 {
09954 const struct toc_hash_struct * hash_entry =
09955 *(const struct toc_hash_struct **) hash_slot;
09956 rtx r = hash_entry->key;
09957 ggc_set_mark (hash_entry);
09958
09959 if (GET_CODE (r) == LABEL_REF)
09960 {
09961 ggc_set_mark (r);
09962 ggc_set_mark (XEXP (r, 0));
09963 }
09964 else
09965 ggc_mark_rtx (r);
09966 return 1;
09967 }
09968
09969
09970
09971 static void
09972 toc_hash_mark_table (vht)
09973 void *vht;
09974 {
09975 htab_t *ht = vht;
09976
09977 htab_traverse (*ht, toc_hash_mark_entry, (void *)0);
09978 }
09979
09980
09981
09982
09983
09984
09985 #define VTABLE_NAME_P(NAME) \
09986 (strncmp ("_vt.", name, strlen("_vt.")) == 0 \
09987 || strncmp ("_ZTV", name, strlen ("_ZTV")) == 0 \
09988 || strncmp ("_ZTT", name, strlen ("_ZTT")) == 0 \
09989 || strncmp ("_ZTC", name, strlen ("_ZTC")) == 0)
09990
09991 void
09992 rs6000_output_symbol_ref (file, x)
09993 FILE *file;
09994 rtx x;
09995 {
09996
09997
09998
09999
10000
10001
10002 const char *name = XSTR (x, 0);
10003
10004 if (VTABLE_NAME_P (name))
10005 {
10006 RS6000_OUTPUT_BASENAME (file, name);
10007 }
10008 else
10009 assemble_name (file, name);
10010 }
10011
10012
10013
10014
10015 void
10016 output_toc (file, x, labelno, mode)
10017 FILE *file;
10018 rtx x;
10019 int labelno;
10020 enum machine_mode mode;
10021 {
10022 char buf[256];
10023 const char *name = buf;
10024 const char *real_name;
10025 rtx base = x;
10026 int offset = 0;
10027
10028 if (TARGET_NO_TOC)
10029 abort ();
10030
10031
10032
10033
10034 if (TARGET_TOC)
10035 {
10036 struct toc_hash_struct *h;
10037 void * * found;
10038
10039 h = ggc_alloc (sizeof (*h));
10040 h->key = x;
10041 h->key_mode = mode;
10042 h->labelno = labelno;
10043
10044 found = htab_find_slot (toc_hash_table, h, 1);
10045 if (*found == NULL)
10046 *found = h;
10047 else
10048
10049 {
10050 fputs ("\t.set ", file);
10051 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
10052 fprintf (file, "%d,", labelno);
10053 ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
10054 fprintf (file, "%d\n", ((*(const struct toc_hash_struct **)
10055 found)->labelno));
10056 return;
10057 }
10058 }
10059
10060
10061
10062 if (GET_CODE (x) == CONST_DOUBLE
10063 && STRICT_ALIGNMENT
10064 && GET_MODE_BITSIZE (mode) >= 64
10065 && ! (TARGET_NO_FP_IN_TOC && ! TARGET_MINIMAL_TOC)) {
10066 ASM_OUTPUT_ALIGN (file, 3);
10067 }
10068
10069 ASM_OUTPUT_INTERNAL_LABEL (file, "LC", labelno);
10070
10071
10072
10073
10074 if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
10075 {
10076 REAL_VALUE_TYPE rv;
10077 long k[2];
10078
10079 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
10080 REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
10081
10082 if (TARGET_64BIT)
10083 {
10084 if (TARGET_MINIMAL_TOC)
10085 fputs (DOUBLE_INT_ASM_OP, file);
10086 else
10087 fprintf (file, "\t.tc FD_%lx_%lx[TC],",
10088 k[0] & 0xffffffff, k[1] & 0xffffffff);
10089 fprintf (file, "0x%lx%08lx\n",
10090 k[0] & 0xffffffff, k[1] & 0xffffffff);
10091 return;
10092 }
10093 else
10094 {
10095 if (TARGET_MINIMAL_TOC)
10096 fputs ("\t.long ", file);
10097 else
10098 fprintf (file, "\t.tc FD_%lx_%lx[TC],",
10099 k[0] & 0xffffffff, k[1] & 0xffffffff);
10100 fprintf (file, "0x%lx,0x%lx\n",
10101 k[0] & 0xffffffff, k[1] & 0xffffffff);
10102 return;
10103 }
10104 }
10105 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
10106 {
10107 REAL_VALUE_TYPE rv;
10108 long l;
10109
10110 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
10111 REAL_VALUE_TO_TARGET_SINGLE (rv, l);
10112
10113 if (TARGET_64BIT)
10114 {
10115 if (TARGET_MINIMAL_TOC)
10116 fputs (DOUBLE_INT_ASM_OP, file);
10117 else
10118 fprintf (file, "\t.tc FS_%lx[TC],", l & 0xffffffff);
10119 fprintf (file, "0x%lx00000000\n", l & 0xffffffff);
10120 return;
10121 }
10122 else
10123 {
10124 if (TARGET_MINIMAL_TOC)
10125 fputs ("\t.long ", file);
10126 else
10127 fprintf (file, "\t.tc FS_%lx[TC],", l & 0xffffffff);
10128 fprintf (file, "0x%lx\n", l & 0xffffffff);
10129 return;
10130 }
10131 }
10132 else if (GET_MODE (x) == VOIDmode
10133 && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
10134 {
10135 unsigned HOST_WIDE_INT low;
10136 HOST_WIDE_INT high;
10137
10138 if (GET_CODE (x) == CONST_DOUBLE)
10139 {
10140 low = CONST_DOUBLE_LOW (x);
10141 high = CONST_DOUBLE_HIGH (x);
10142 }
10143 else
10144 #if HOST_BITS_PER_WIDE_INT == 32
10145 {
10146 low = INTVAL (x);
10147 high = (low & 0x80000000) ? ~0 : 0;
10148 }
10149 #else
10150 {
10151 low = INTVAL (x) & 0xffffffff;
10152 high = (HOST_WIDE_INT) INTVAL (x) >> 32;
10153 }
10154 #endif
10155
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166 if (TARGET_64BIT && POINTER_SIZE < GET_MODE_BITSIZE (mode))
10167 abort ();
10168
10169 if (POINTER_SIZE > GET_MODE_BITSIZE (mode))
10170 {
10171 #if HOST_BITS_PER_WIDE_INT == 32
10172 lshift_double (low, high, POINTER_SIZE - GET_MODE_BITSIZE (mode),
10173 POINTER_SIZE, &low, &high, 0);
10174 #else
10175 low |= high << 32;
10176 low <<= POINTER_SIZE - GET_MODE_BITSIZE (mode);
10177 high = (HOST_WIDE_INT) low >> 32;
10178 low &= 0xffffffff;
10179 #endif
10180 }
10181
10182 if (TARGET_64BIT)
10183 {
10184 if (TARGET_MINIMAL_TOC)
10185 fputs (DOUBLE_INT_ASM_OP, file);
10186 else
10187 fprintf (file, "\t.tc ID_%lx_%lx[TC],",
10188 (long) high & 0xffffffff, (long) low & 0xffffffff);
10189 fprintf (file, "0x%lx%08lx\n",
10190 (long) high & 0xffffffff, (long) low & 0xffffffff);
10191 return;
10192 }
10193 else
10194 {
10195 if (POINTER_SIZE < GET_MODE_BITSIZE (mode))
10196 {
10197 if (TARGET_MINIMAL_TOC)
10198 fputs ("\t.long ", file);
10199 else
10200 fprintf (file, "\t.tc ID_%lx_%lx[TC],",
10201 (long) high & 0xffffffff, (long) low & 0xffffffff);
10202 fprintf (file, "0x%lx,0x%lx\n",
10203 (long) high & 0xffffffff, (long) low & 0xffffffff);
10204 }
10205 else
10206 {
10207 if (TARGET_MINIMAL_TOC)
10208 fputs ("\t.long ", file);
10209 else
10210 fprintf (file, "\t.tc IS_%lx[TC],", (long) low & 0xffffffff);
10211 fprintf (file, "0x%lx\n", (long) low & 0xffffffff);
10212 }
10213 return;
10214 }
10215 }
10216
10217 if (GET_CODE (x) == CONST)
10218 {
10219 if (GET_CODE (XEXP (x, 0)) != PLUS)
10220 abort ();
10221
10222 base = XEXP (XEXP (x, 0), 0);
10223 offset = INTVAL (XEXP (XEXP (x, 0), 1));
10224 }
10225
10226 if (GET_CODE (base) == SYMBOL_REF)
10227 name = XSTR (base, 0);
10228 else if (GET_CODE (base) == LABEL_REF)
10229 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (base, 0)));
10230 else if (GET_CODE (base) == CODE_LABEL)
10231 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (base));
10232 else
10233 abort ();
10234
10235 STRIP_NAME_ENCODING (real_name, name);
10236 if (TARGET_MINIMAL_TOC)
10237 fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file);
10238 else
10239 {
10240 fprintf (file, "\t.tc %s", real_name);
10241
10242 if (offset < 0)
10243 fprintf (file, ".N%d", - offset);
10244 else if (offset)
10245 fprintf (file, ".P%d", offset);
10246
10247 fputs ("[TC],", file);
10248 }
10249
10250
10251
10252
10253
10254
10255
10256 if (VTABLE_NAME_P (name))
10257 {
10258 RS6000_OUTPUT_BASENAME (file, name);
10259 if (offset < 0)
10260 fprintf (file, "%d", offset);
10261 else if (offset > 0)
10262 fprintf (file, "+%d", offset);
10263 }
10264 else
10265 output_addr_const (file, x);
10266 putc ('\n', file);
10267 }
10268
10269
10270
10271
10272
10273
10274
10275
10276
10277 void
10278 output_ascii (file, p, n)
10279 FILE *file;
10280 const char *p;
10281 int n;
10282 {
10283 char c;
10284 int i, count_string;
10285 const char *for_string = "\t.byte \"";
10286 const char *for_decimal = "\t.byte ";
10287 const char *to_close = NULL;
10288
10289 count_string = 0;
10290 for (i = 0; i < n; i++)
10291 {
10292 c = *p++;
10293 if (c >= ' ' && c < 0177)
10294 {
10295 if (for_string)
10296 fputs (for_string, file);
10297 putc (c, file);
10298
10299
10300 if (c == '"')
10301 {
10302 putc (c, file);
10303 ++count_string;
10304 }
10305
10306 for_string = NULL;
10307 for_decimal = "\"\n\t.byte ";
10308 to_close = "\"\n";
10309 ++count_string;
10310
10311 if (count_string >= 512)
10312 {
10313 fputs (to_close, file);
10314
10315 for_string = "\t.byte \"";
10316 for_decimal = "\t.byte ";
10317 to_close = NULL;
10318 count_string = 0;
10319 }
10320 }
10321 else
10322 {
10323 if (for_decimal)
10324 fputs (for_decimal, file);
10325 fprintf (file, "%d", c);
10326
10327 for_string = "\n\t.byte \"";
10328 for_decimal = ", ";
10329 to_close = "\n";
10330 count_string = 0;
10331 }
10332 }
10333
10334
10335 if (to_close)
10336 fputs (to_close, file);
10337 }
10338
10339
10340
10341
10342
10343
10344
10345
10346
10347
10348
10349
10350
10351 void
10352 rs6000_gen_section_name (buf, filename, section_desc)
10353 char **buf;
10354 const char *filename;
10355 const char *section_desc;
10356 {
10357 const char *q, *after_last_slash, *last_period = 0;
10358 char *p;
10359 int len;
10360
10361 after_last_slash = filename;
10362 for (q = filename; *q; q++)
10363 {
10364 if (*q == '/')
10365 after_last_slash = q + 1;
10366 else if (*q == '.')
10367 last_period = q;
10368 }
10369
10370 len = strlen (after_last_slash) + strlen (section_desc) + 2;
10371 *buf = (char *) permalloc (len);
10372
10373 p = *buf;
10374 *p++ = '_';
10375
10376 for (q = after_last_slash; *q; q++)
10377 {
10378 if (q == last_period)
10379 {
10380 strcpy (p, section_desc);
10381 p += strlen (section_desc);
10382 }
10383
10384 else if (ISALNUM (*q))
10385 *p++ = *q;
10386 }
10387
10388 if (last_period == 0)
10389 strcpy (p, section_desc);
10390 else
10391 *p = '\0';
10392 }
10393
10394
10395
10396 void
10397 output_profile_hook (labelno)
10398 int labelno ATTRIBUTE_UNUSED;
10399 {
10400 if (DEFAULT_ABI == ABI_AIX)
10401 {
10402 #ifdef NO_PROFILE_COUNTERS
10403 emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 0);
10404 #else
10405 char buf[30];
10406 const char *label_name;
10407 rtx fun;
10408
10409 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
10410 STRIP_NAME_ENCODING (label_name, ggc_strdup (buf));
10411 fun = gen_rtx_SYMBOL_REF (Pmode, label_name);
10412
10413 emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1,
10414 fun, Pmode);
10415 #endif
10416 }
10417 else if (DEFAULT_ABI == ABI_DARWIN)
10418 {
10419 const char *mcount_name = RS6000_MCOUNT;
10420 int caller_addr_regno = LINK_REGISTER_REGNUM;
10421
10422
10423 current_function_uses_pic_offset_table = 1;
10424
10425 #if TARGET_MACHO
10426
10427
10428 if (flag_pic)
10429 {
10430 mcount_name = machopic_stub_name (mcount_name);
10431 if (current_function_uses_pic_offset_table)
10432 caller_addr_regno = 0;
10433 }
10434 #endif
10435 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mcount_name),
10436 0, VOIDmode, 1,
10437 gen_rtx_REG (Pmode, caller_addr_regno), Pmode);
10438 }
10439 }
10440
10441
10442
10443 void
10444 output_function_profiler (file, labelno)
10445 FILE *file;
10446 int labelno;
10447 {
10448 char buf[100];
10449 int save_lr = 8;
10450
10451 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
10452 switch (DEFAULT_ABI)
10453 {
10454 default:
10455 abort ();
10456
10457 case ABI_V4:
10458 save_lr = 4;
10459
10460
10461 case ABI_AIX_NODESC:
10462 if (!TARGET_32BIT)
10463 {
10464 warning ("no profiling of 64-bit code for this ABI");
10465 return;
10466 }
10467 fprintf (file, "\tmflr %s\n", reg_names[0]);
10468 if (flag_pic == 1)
10469 {
10470 fputs ("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n", file);
10471 asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
10472 reg_names[0], save_lr, reg_names[1]);
10473 asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
10474 asm_fprintf (file, "\t{l|lwz} %s,", reg_names[0]);
10475 assemble_name (file, buf);
10476 asm_fprintf (file, "@got(%s)\n", reg_names[12]);
10477 }
10478 else if (flag_pic > 1)
10479 {
10480 asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
10481 reg_names[0], save_lr, reg_names[1]);
10482
10483 fputs ("\tbl 1f\n\t.long ", file);
10484 assemble_name (file, buf);
10485 fputs ("-.\n1:", file);
10486 asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
10487 asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
10488 reg_names[0], reg_names[11]);
10489 asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
10490 reg_names[0], reg_names[0], reg_names[11]);
10491 }
10492 else
10493 {
10494 asm_fprintf (file, "\t{liu|lis} %s,", reg_names[12]);
10495 assemble_name (file, buf);
10496 fputs ("@ha\n", file);
10497 asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
10498 reg_names[0], save_lr, reg_names[1]);
10499 asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
10500 assemble_name (file, buf);
10501 asm_fprintf (file, "@l(%s)\n", reg_names[12]);
10502 }
10503
10504 if (current_function_needs_context && DEFAULT_ABI == ABI_AIX_NODESC)
10505 {
10506 asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
10507 reg_names[STATIC_CHAIN_REGNUM],
10508 12, reg_names[1]);
10509 fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
10510 asm_fprintf (file, "\t{l|lwz} %s,%d(%s)\n",
10511 reg_names[STATIC_CHAIN_REGNUM],
10512 12, reg_names[1]);
10513 }
10514 else
10515
10516 fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
10517 break;
10518
10519 case ABI_AIX:
10520 case ABI_DARWIN:
10521
10522 break;
10523 }
10524 }
10525
10526
10527
10528
10529 static int
10530 rs6000_adjust_cost (insn, link, dep_insn, cost)
10531 rtx insn;
10532 rtx link;
10533 rtx dep_insn ATTRIBUTE_UNUSED;
10534 int cost;
10535 {
10536 if (! recog_memoized (insn))
10537 return 0;
10538
10539 if (REG_NOTE_KIND (link) != 0)
10540 return 0;
10541
10542 if (REG_NOTE_KIND (link) == 0)
10543 {
10544
10545
10546 switch (get_attr_type (insn))
10547 {
10548 case TYPE_JMPREG:
10549
10550
10551
10552
10553
10554 return TARGET_POWER ? 5 : 4;
10555 case TYPE_BRANCH:
10556
10557
10558 if ((rs6000_cpu_attr == CPU_PPC750
10559 || rs6000_cpu_attr == CPU_PPC7400
10560 || rs6000_cpu_attr == CPU_PPC7450)
10561 && recog_memoized (dep_insn)
10562 && (INSN_CODE (dep_insn) >= 0)
10563 && (get_attr_type (dep_insn) == TYPE_COMPARE
10564 || get_attr_type (dep_insn) == TYPE_DELAYED_COMPARE
10565 || get_attr_type (dep_insn) == TYPE_FPCOMPARE
10566 || get_attr_type (dep_insn) == TYPE_CR_LOGICAL))
10567 return cost + 2;
10568 default:
10569 break;
10570 }
10571
10572 }
10573
10574 return cost;
10575 }
10576
10577
10578
10579
10580
10581
10582
10583 static int
10584 rs6000_adjust_priority (insn, priority)
10585 rtx insn ATTRIBUTE_UNUSED;
10586 int priority;
10587 {
10588
10589
10590
10591
10592
10593 #if 0
10594 if (! INSN_P (insn))
10595 return priority;
10596
10597 if (GET_CODE (PATTERN (insn)) == USE)
10598 return priority;
10599
10600 switch (rs6000_cpu_attr) {
10601 case CPU_PPC750:
10602 switch (get_attr_type (insn))
10603 {
10604 default:
10605 break;
10606
10607 case TYPE_IMUL:
10608 case TYPE_IDIV:
10609 fprintf (stderr, "priority was %#x (%d) before adjustment\n",
10610 priority, priority);
10611 if (priority >= 0 && priority < 0x01000000)
10612 priority >>= 3;
10613 break;
10614 }
10615 }
10616 #endif
10617
10618 return priority;
10619 }
10620
10621
10622
10623 static int
10624 rs6000_issue_rate ()
10625 {
10626 switch (rs6000_cpu_attr) {
10627 case CPU_RIOS1:
10628 case CPU_RS64A:
10629 case CPU_PPC601:
10630 case CPU_PPC7450:
10631 return 3;
10632 case CPU_PPC603:
10633 case CPU_PPC750:
10634 case CPU_PPC7400:
10635 return 2;
10636 case CPU_RIOS2:
10637 case CPU_PPC604:
10638 case CPU_PPC604E:
10639 case CPU_PPC620:
10640 case CPU_PPC630:
10641 return 4;
10642 default:
10643 return 1;
10644 }
10645 }
10646
10647
10648
10649
10650 int
10651 rs6000_trampoline_size ()
10652 {
10653 int ret = 0;
10654
10655 switch (DEFAULT_ABI)
10656 {
10657 default:
10658 abort ();
10659
10660 case ABI_AIX:
10661 ret = (TARGET_32BIT) ? 12 : 24;
10662 break;
10663
10664 case ABI_DARWIN:
10665 case ABI_V4:
10666 case ABI_AIX_NODESC:
10667 ret = (TARGET_32BIT) ? 40 : 48;
10668 break;
10669 }
10670
10671 return ret;
10672 }
10673
10674
10675
10676
10677
10678 void
10679 rs6000_initialize_trampoline (addr, fnaddr, cxt)
10680 rtx addr;
10681 rtx fnaddr;
10682 rtx cxt;
10683 {
10684 enum machine_mode pmode = Pmode;
10685 int regsize = (TARGET_32BIT) ? 4 : 8;
10686 rtx ctx_reg = force_reg (pmode, cxt);
10687
10688 switch (DEFAULT_ABI)
10689 {
10690 default:
10691 abort ();
10692
10693
10694 #define MEM_DEREF(addr) gen_rtx_MEM (pmode, memory_address (pmode, addr))
10695 #define MEM_PLUS(addr,offset) \
10696 gen_rtx_MEM (pmode, memory_address (pmode, plus_constant (addr, offset)))
10697
10698
10699 case ABI_AIX:
10700 {
10701 rtx fn_reg = gen_reg_rtx (pmode);
10702 rtx toc_reg = gen_reg_rtx (pmode);
10703 emit_move_insn (fn_reg, MEM_DEREF (fnaddr));
10704 emit_move_insn (toc_reg, MEM_PLUS (fnaddr, regsize));
10705 emit_move_insn (MEM_DEREF (addr), fn_reg);
10706 emit_move_insn (MEM_PLUS (addr, regsize), toc_reg);
10707 emit_move_insn (MEM_PLUS (addr, 2*regsize), ctx_reg);
10708 }
10709 break;
10710
10711
10712 case ABI_DARWIN:
10713 case ABI_V4:
10714 case ABI_AIX_NODESC:
10715 emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"),
10716 FALSE, VOIDmode, 4,
10717 addr, pmode,
10718 GEN_INT (rs6000_trampoline_size ()), SImode,
10719 fnaddr, pmode,
10720 ctx_reg, pmode);
10721 break;
10722 }
10723
10724 return;
10725 }
10726
10727
10728
10729
10730 const struct attribute_spec rs6000_attribute_table[] =
10731 {
10732
10733 { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
10734 { NULL, 0, 0, false, false, false, NULL }
10735 };
10736
10737
10738
10739
10740 static tree
10741 rs6000_handle_longcall_attribute (node, name, args, flags, no_add_attrs)
10742 tree *node;
10743 tree name;
10744 tree args ATTRIBUTE_UNUSED;
10745 int flags ATTRIBUTE_UNUSED;
10746 bool *no_add_attrs;
10747 {
10748 if (TREE_CODE (*node) != FUNCTION_TYPE
10749 && TREE_CODE (*node) != FIELD_DECL
10750 && TREE_CODE (*node) != TYPE_DECL)
10751 {
10752 warning ("`%s' attribute only applies to functions",
10753 IDENTIFIER_POINTER (name));
10754 *no_add_attrs = true;
10755 }
10756
10757 return NULL_TREE;
10758 }
10759
10760
10761
10762
10763 struct rtx_def *
10764 rs6000_longcall_ref (call_ref)
10765 rtx call_ref;
10766 {
10767 const char *call_name;
10768 tree node;
10769
10770 if (GET_CODE (call_ref) != SYMBOL_REF)
10771 return call_ref;
10772
10773
10774 call_name = XSTR (call_ref, 0);
10775 if (*call_name == '.')
10776 {
10777 while (*call_name == '.')
10778 call_name++;
10779
10780 node = get_identifier (call_name);
10781 call_ref = gen_rtx_SYMBOL_REF (VOIDmode, IDENTIFIER_POINTER (node));
10782 }
10783
10784 return force_reg (Pmode, call_ref);
10785 }
10786
10787
10788
10789
10790
10791
10792
10793
10794
10795
10796
10797 #ifdef USING_ELFOS_H
10798
10799 void
10800 rs6000_select_rtx_section (mode, x)
10801 enum machine_mode mode;
10802 rtx x;
10803 {
10804 if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
10805 toc_section ();
10806 else if (flag_pic
10807 && (GET_CODE (x) == SYMBOL_REF
10808 || GET_CODE (x) == LABEL_REF
10809 || GET_CODE (x) == CONST))
10810 data_section ();
10811 else
10812 const_section ();
10813 }
10814
10815
10816
10817
10818
10819
10820 void
10821 rs6000_select_section (decl, reloc)
10822 tree decl;
10823 int reloc;
10824 {
10825 int size = int_size_in_bytes (TREE_TYPE (decl));
10826 int needs_sdata;
10827 int readonly;
10828 static void (* const sec_funcs[4]) PARAMS ((void)) = {
10829 &const_section,
10830 &sdata2_section,
10831 &data_section,
10832 &sdata_section
10833 };
10834
10835 needs_sdata = (size > 0
10836 && size <= g_switch_value
10837 && rs6000_sdata != SDATA_NONE
10838 && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)));
10839
10840 if (TREE_CODE (decl) == STRING_CST)
10841 readonly = ! flag_writable_strings;
10842 else if (TREE_CODE (decl) == VAR_DECL)
10843 readonly = (! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc)
10844 && TREE_READONLY (decl)
10845 && ! TREE_SIDE_EFFECTS (decl)
10846 && DECL_INITIAL (decl)
10847 && DECL_INITIAL (decl) != error_mark_node
10848 && TREE_CONSTANT (DECL_INITIAL (decl)));
10849 else if (TREE_CODE (decl) == CONSTRUCTOR)
10850 readonly = (! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc)
10851 && ! TREE_SIDE_EFFECTS (decl)
10852 && TREE_CONSTANT (decl));
10853 else
10854 readonly = ! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc);
10855
10856 if (needs_sdata && rs6000_sdata != SDATA_EABI)
10857 readonly = 0;
10858
10859 (*sec_funcs[(readonly ? 0 : 2) + (needs_sdata ? 1 : 0)])();
10860 }
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870 void
10871 rs6000_unique_section (decl, reloc)
10872 tree decl;
10873 int reloc;
10874 {
10875 int len;
10876 int sec;
10877 const char *name;
10878 char *string;
10879 const char *prefix;
10880
10881 static const char *const prefixes[7][2] =
10882 {
10883 { ".rodata.", ".gnu.linkonce.r." },
10884 { ".sdata2.", ".gnu.linkonce.s2." },
10885 { ".data.", ".gnu.linkonce.d." },
10886 { ".sdata.", ".gnu.linkonce.s." },
10887 { ".bss.", ".gnu.linkonce.b." },
10888 { ".sbss.", ".gnu.linkonce.sb." },
10889 { ".text.", ".gnu.linkonce.t." }
10890 };
10891
10892 if (TREE_CODE (decl) == FUNCTION_DECL)
10893 sec = 6;
10894 else
10895 {
10896 int readonly;
10897 int needs_sdata;
10898 int size;
10899
10900 if (TREE_CODE (decl) == STRING_CST)
10901 readonly = ! flag_writable_strings;
10902 else if (TREE_CODE (decl) == VAR_DECL)
10903 readonly = (! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc)
10904 && TREE_READONLY (decl)
10905 && ! TREE_SIDE_EFFECTS (decl)
10906 && TREE_CONSTANT (DECL_INITIAL (decl)));
10907 else
10908 readonly = ! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc);
10909
10910 size = int_size_in_bytes (TREE_TYPE (decl));
10911 needs_sdata = (size > 0
10912 && size <= g_switch_value
10913 && rs6000_sdata != SDATA_NONE
10914 && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)));
10915
10916 if (DECL_INITIAL (decl) == 0
10917 || DECL_INITIAL (decl) == error_mark_node)
10918 sec = 4;
10919 else if (! readonly)
10920 sec = 2;
10921 else
10922 sec = 0;
10923
10924 if (needs_sdata)
10925 {
10926
10927 if (sec == 0 && rs6000_sdata != SDATA_EABI)
10928 sec = 2;
10929 sec += 1;
10930 }
10931 }
10932
10933 STRIP_NAME_ENCODING (name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
10934 prefix = prefixes[sec][DECL_ONE_ONLY (decl)];
10935 len = strlen (name) + strlen (prefix);
10936 string = alloca (len + 1);
10937
10938 sprintf (string, "%s%s", prefix, name);
10939
10940 DECL_SECTION_NAME (decl) = build_string (len, string);
10941 }
10942
10943
10944 static bool
10945 rs6000_binds_local_p (exp)
10946 tree exp;
10947 {
10948 bool local_p;
10949 tree attr;
10950
10951
10952 if (!DECL_P (exp))
10953 local_p = true;
10954
10955 else if (! TREE_PUBLIC (exp))
10956 local_p = true;
10957
10958 else if (DECL_EXTERNAL (exp))
10959 local_p = false;
10960
10961 else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
10962 local_p = false;
10963
10964
10965 else if (flag_pic || rs6000_flag_pic)
10966 local_p = false;
10967
10968
10969 else if (DECL_COMMON (exp)
10970 && (DECL_INITIAL (exp) == NULL
10971 || DECL_INITIAL (exp) == error_mark_node))
10972 local_p = false;
10973
10974
10975 else
10976 local_p = true;
10977
10978 return local_p;
10979 }
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990 void
10991 rs6000_encode_section_info (decl)
10992 tree decl;
10993 {
10994 if (TREE_CODE (decl) == FUNCTION_DECL)
10995 {
10996 rtx sym_ref = XEXP (DECL_RTL (decl), 0);
10997 if (rs6000_binds_local_p (decl))
10998 SYMBOL_REF_FLAG (sym_ref) = 1;
10999
11000 if (DEFAULT_ABI == ABI_AIX)
11001 {
11002 size_t len1 = (DEFAULT_ABI == ABI_AIX) ? 1 : 2;
11003 size_t len2 = strlen (XSTR (sym_ref, 0));
11004 char *str = alloca (len1 + len2 + 1);
11005 str[0] = '.';
11006 str[1] = '.';
11007 memcpy (str + len1, XSTR (sym_ref, 0), len2 + 1);
11008
11009 XSTR (sym_ref, 0) = ggc_alloc_string (str, len1 + len2);
11010 }
11011 }
11012 else if (rs6000_sdata != SDATA_NONE
11013 && DEFAULT_ABI == ABI_V4
11014 && TREE_CODE (decl) == VAR_DECL)
11015 {
11016 rtx sym_ref = XEXP (DECL_RTL (decl), 0);
11017 int size = int_size_in_bytes (TREE_TYPE (decl));
11018 tree section_name = DECL_SECTION_NAME (decl);
11019 const char *name = (char *)0;
11020 int len = 0;
11021
11022 if (rs6000_binds_local_p (decl))
11023 SYMBOL_REF_FLAG (sym_ref) = 1;
11024
11025 if (section_name)
11026 {
11027 if (TREE_CODE (section_name) == STRING_CST)
11028 {
11029 name = TREE_STRING_POINTER (section_name);
11030 len = TREE_STRING_LENGTH (section_name);
11031 }
11032 else
11033 abort ();
11034 }
11035
11036 if ((size > 0 && size <= g_switch_value)
11037 || (name
11038 && ((len == sizeof (".sdata") - 1
11039 && strcmp (name, ".sdata") == 0)
11040 || (len == sizeof (".sdata2") - 1
11041 && strcmp (name, ".sdata2") == 0)
11042 || (len == sizeof (".sbss") - 1
11043 && strcmp (name, ".sbss") == 0)
11044 || (len == sizeof (".sbss2") - 1
11045 && strcmp (name, ".sbss2") == 0)
11046 || (len == sizeof (".PPC.EMB.sdata0") - 1
11047 && strcmp (name, ".PPC.EMB.sdata0") == 0)
11048 || (len == sizeof (".PPC.EMB.sbss0") - 1
11049 && strcmp (name, ".PPC.EMB.sbss0") == 0))))
11050 {
11051 rtx sym_ref = XEXP (DECL_RTL (decl), 0);
11052 size_t len = strlen (XSTR (sym_ref, 0));
11053 char *str = alloca (len + 2);
11054
11055 str[0] = '@';
11056 memcpy (str + 1, XSTR (sym_ref, 0), len + 1);
11057 XSTR (sym_ref, 0) = ggc_alloc_string (str, len + 1);
11058 }
11059 }
11060 }
11061
11062 #endif
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072 struct rtx_def *
11073 find_addr_reg (addr)
11074 rtx addr;
11075 {
11076 while (GET_CODE (addr) == PLUS)
11077 {
11078 if (GET_CODE (XEXP (addr, 0)) == REG
11079 && REGNO (XEXP (addr, 0)) != 0)
11080 addr = XEXP (addr, 0);
11081 else if (GET_CODE (XEXP (addr, 1)) == REG
11082 && REGNO (XEXP (addr, 1)) != 0)
11083 addr = XEXP (addr, 1);
11084 else if (CONSTANT_P (XEXP (addr, 0)))
11085 addr = XEXP (addr, 1);
11086 else if (CONSTANT_P (XEXP (addr, 1)))
11087 addr = XEXP (addr, 0);
11088 else
11089 abort ();
11090 }
11091 if (GET_CODE (addr) == REG && REGNO (addr) != 0)
11092 return addr;
11093 abort ();
11094 }
11095
11096 void
11097 rs6000_fatal_bad_address (op)
11098 rtx op;
11099 {
11100 fatal_insn ("bad address", op);
11101 }
11102
11103
11104
11105
11106 static void
11107 rs6000_add_gc_roots ()
11108 {
11109 ggc_add_rtx_root (&rs6000_compare_op0, 1);
11110 ggc_add_rtx_root (&rs6000_compare_op1, 1);
11111
11112 toc_hash_table = htab_create (1021, toc_hash_function, toc_hash_eq, NULL);
11113 ggc_add_root (&toc_hash_table, 1, sizeof (toc_hash_table),
11114 toc_hash_mark_table);
11115
11116 #if TARGET_MACHO
11117 machopic_add_gc_roots ();
11118 #endif
11119 }
11120
11121 #if TARGET_MACHO
11122
11123 #if 0
11124
11125
11126
11127 int
11128 symbolic_operand (op)
11129 rtx op;
11130 {
11131 switch (GET_CODE (op))
11132 {
11133 case SYMBOL_REF:
11134 case LABEL_REF:
11135 return 1;
11136 case CONST:
11137 op = XEXP (op, 0);
11138 return (GET_CODE (op) == SYMBOL_REF ||
11139 (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
11140 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
11141 && GET_CODE (XEXP (op, 1)) == CONST_INT);
11142 default:
11143 return 0;
11144 }
11145 }
11146 #endif
11147
11148 #ifdef RS6000_LONG_BRANCH
11149
11150 static tree stub_list = 0;
11151
11152
11153
11154
11155 void
11156 add_compiler_stub (label_name, function_name, line_number)
11157 tree label_name;
11158 tree function_name;
11159 int line_number;
11160 {
11161 tree stub = build_tree_list (function_name, label_name);
11162 TREE_TYPE (stub) = build_int_2 (line_number, 0);
11163 TREE_CHAIN (stub) = stub_list;
11164 stub_list = stub;
11165 }
11166
11167 #define STUB_LABEL_NAME(STUB) TREE_VALUE (STUB)
11168 #define STUB_FUNCTION_NAME(STUB) TREE_PURPOSE (STUB)
11169 #define STUB_LINE_NUMBER(STUB) TREE_INT_CST_LOW (TREE_TYPE (STUB))
11170
11171
11172
11173
11174
11175 void
11176 output_compiler_stub ()
11177 {
11178 char tmp_buf[256];
11179 char label_buf[256];
11180 char *label;
11181 tree tmp_stub, stub;
11182
11183 if (!flag_pic)
11184 for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
11185 {
11186 fprintf (asm_out_file,
11187 "%s:\n", IDENTIFIER_POINTER(STUB_LABEL_NAME(stub)));
11188
11189 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
11190 if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
11191 fprintf (asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER(stub));
11192 #endif
11193
11194 if (IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))[0] == '*')
11195 strcpy (label_buf,
11196 IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))+1);
11197 else
11198 {
11199 label_buf[0] = '_';
11200 strcpy (label_buf+1,
11201 IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub)));
11202 }
11203
11204 strcpy (tmp_buf, "lis r12,hi16(");
11205 strcat (tmp_buf, label_buf);
11206 strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
11207 strcat (tmp_buf, label_buf);
11208 strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
11209 output_asm_insn (tmp_buf, 0);
11210
11211 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
11212 if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
11213 fprintf(asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER (stub));
11214 #endif
11215 }
11216
11217 stub_list = 0;
11218 }
11219
11220
11221
11222
11223 int
11224 no_previous_def (function_name)
11225 tree function_name;
11226 {
11227 tree stub;
11228 for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
11229 if (function_name == STUB_FUNCTION_NAME (stub))
11230 return 0;
11231 return 1;
11232 }
11233
11234
11235
11236
11237 tree
11238 get_prev_label (function_name)
11239 tree function_name;
11240 {
11241 tree stub;
11242 for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
11243 if (function_name == STUB_FUNCTION_NAME (stub))
11244 return STUB_LABEL_NAME (stub);
11245 return 0;
11246 }
11247
11248
11249
11250
11251
11252
11253 char *
11254 output_call (insn, call_dest, operand_number)
11255 rtx insn;
11256 rtx call_dest;
11257 int operand_number;
11258 {
11259 static char buf[256];
11260 if (GET_CODE (call_dest) == SYMBOL_REF && TARGET_LONG_BRANCH && !flag_pic)
11261 {
11262 tree labelname;
11263 tree funname = get_identifier (XSTR (call_dest, 0));
11264
11265 if (no_previous_def (funname))
11266 {
11267 int line_number;
11268 rtx label_rtx = gen_label_rtx ();
11269 char *label_buf, temp_buf[256];
11270 ASM_GENERATE_INTERNAL_LABEL (temp_buf, "L",
11271 CODE_LABEL_NUMBER (label_rtx));
11272 label_buf = temp_buf[0] == '*' ? temp_buf + 1 : temp_buf;
11273 labelname = get_identifier (label_buf);
11274 for (; insn && GET_CODE (insn) != NOTE; insn = PREV_INSN (insn));
11275 if (insn)
11276 line_number = NOTE_LINE_NUMBER (insn);
11277 add_compiler_stub (labelname, funname, line_number);
11278 }
11279 else
11280 labelname = get_prev_label (funname);
11281
11282 sprintf (buf, "jbsr %%z%d,%.246s",
11283 operand_number, IDENTIFIER_POINTER (labelname));
11284 return buf;
11285 }
11286 else
11287 {
11288 sprintf (buf, "bl %%z%d", operand_number);
11289 return buf;
11290 }
11291 }
11292
11293 #endif
11294
11295 #define GEN_LOCAL_LABEL_FOR_SYMBOL(BUF,SYMBOL,LENGTH,N) \
11296 do { \
11297 const char *const symbol_ = (SYMBOL); \
11298 char *buffer_ = (BUF); \
11299 if (symbol_[0] == '"') \
11300 { \
11301 sprintf(buffer_, "\"L%d$%s", (N), symbol_+1); \
11302 } \
11303 else if (name_needs_quotes(symbol_)) \
11304 { \
11305 sprintf(buffer_, "\"L%d$%s\"", (N), symbol_); \
11306 } \
11307 else \
11308 { \
11309 sprintf(buffer_, "L%d$%s", (N), symbol_); \
11310 } \
11311 } while (0)
11312
11313
11314
11315
11316 void
11317 machopic_output_stub (file, symb, stub)
11318 FILE *file;
11319 const char *symb, *stub;
11320 {
11321 unsigned int length;
11322 char *symbol_name, *lazy_ptr_name;
11323 char *local_label_0;
11324 static int label = 0;
11325
11326
11327 STRIP_NAME_ENCODING (symb, symb);
11328
11329 label += 1;
11330
11331 length = strlen (symb);
11332 symbol_name = alloca (length + 32);
11333 GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
11334
11335 lazy_ptr_name = alloca (length + 32);
11336 GEN_LAZY_PTR_NAME_FOR_SYMBOL (lazy_ptr_name, symb, length);
11337
11338 local_label_0 = alloca (length + 32);
11339 GEN_LOCAL_LABEL_FOR_SYMBOL (local_label_0, symb, length, 0);
11340
11341 if (flag_pic == 2)
11342 machopic_picsymbol_stub_section ();
11343 else
11344 machopic_symbol_stub_section ();
11345
11346 fprintf (file, "%s:\n", stub);
11347 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
11348
11349 if (flag_pic == 2)
11350 {
11351 fprintf (file, "\tmflr r0\n");
11352 fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
11353 fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
11354 fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
11355 lazy_ptr_name, local_label_0);
11356 fprintf (file, "\tmtlr r0\n");
11357 fprintf (file, "\tlwz r12,lo16(%s-%s)(r11)\n",
11358 lazy_ptr_name, local_label_0);
11359 fprintf (file, "\tmtctr r12\n");
11360 fprintf (file, "\taddi r11,r11,lo16(%s-%s)\n",
11361 lazy_ptr_name, local_label_0);
11362 fprintf (file, "\tbctr\n");
11363 }
11364 else
11365 fprintf (file, "non-pure not supported\n");
11366
11367 machopic_lazy_symbol_ptr_section ();
11368 fprintf (file, "%s:\n", lazy_ptr_name);
11369 fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
11370 fprintf (file, "\t.long dyld_stub_binding_helper\n");
11371 }
11372
11373
11374
11375
11376
11377
11378 #define SMALL_INT(X) ((unsigned) (INTVAL(X) + 0x8000) < 0x10000)
11379
11380 rtx
11381 rs6000_machopic_legitimize_pic_address (orig, mode, reg)
11382 rtx orig;
11383 enum machine_mode mode;
11384 rtx reg;
11385 {
11386 rtx base, offset;
11387
11388 if (reg == NULL && ! reload_in_progress && ! reload_completed)
11389 reg = gen_reg_rtx (Pmode);
11390
11391 if (GET_CODE (orig) == CONST)
11392 {
11393 if (GET_CODE (XEXP (orig, 0)) == PLUS
11394 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
11395 return orig;
11396
11397 if (GET_CODE (XEXP (orig, 0)) == PLUS)
11398 {
11399 base =
11400 rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
11401 Pmode, reg);
11402 offset =
11403 rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
11404 Pmode, reg);
11405 }
11406 else
11407 abort ();
11408
11409 if (GET_CODE (offset) == CONST_INT)
11410 {
11411 if (SMALL_INT (offset))
11412 return plus_constant (base, INTVAL (offset));
11413 else if (! reload_in_progress && ! reload_completed)
11414 offset = force_reg (Pmode, offset);
11415 else
11416 {
11417 rtx mem = force_const_mem (Pmode, orig);
11418 return machopic_legitimize_pic_address (mem, Pmode, reg);
11419 }
11420 }
11421 return gen_rtx (PLUS, Pmode, base, offset);
11422 }
11423
11424
11425 return machopic_legitimize_pic_address (orig, mode, reg);
11426 }
11427
11428
11429
11430
11431
11432
11433 void
11434 toc_section ()
11435 {
11436 }
11437
11438 #endif
11439
11440 #if TARGET_ELF
11441 static unsigned int
11442 rs6000_elf_section_type_flags (decl, name, reloc)
11443 tree decl;
11444 const char *name;
11445 int reloc;
11446 {
11447 unsigned int flags = default_section_type_flags (decl, name, reloc);
11448
11449 if (TARGET_RELOCATABLE)
11450 flags |= SECTION_WRITE;
11451
11452 return flags;
11453 }
11454
11455
11456
11457
11458
11459
11460
11461
11462 static void
11463 rs6000_elf_asm_out_constructor (symbol, priority)
11464 rtx symbol;
11465 int priority;
11466 {
11467 const char *section = ".ctors";
11468 char buf[16];
11469
11470 if (priority != DEFAULT_INIT_PRIORITY)
11471 {
11472 sprintf (buf, ".ctors.%.5u",
11473
11474
11475
11476 MAX_INIT_PRIORITY - priority);
11477 section = buf;
11478 }
11479
11480 named_section_flags (section, SECTION_WRITE);
11481 assemble_align (POINTER_SIZE);
11482
11483 if (TARGET_RELOCATABLE)
11484 {
11485 fputs ("\t.long (", asm_out_file);
11486 output_addr_const (asm_out_file, symbol);
11487 fputs (")@fixup\n", asm_out_file);
11488 }
11489 else
11490 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
11491 }
11492
11493 static void
11494 rs6000_elf_asm_out_destructor (symbol, priority)
11495 rtx symbol;
11496 int priority;
11497 {
11498 const char *section = ".dtors";
11499 char buf[16];
11500
11501 if (priority != DEFAULT_INIT_PRIORITY)
11502 {
11503 sprintf (buf, ".dtors.%.5u",
11504
11505
11506
11507 MAX_INIT_PRIORITY - priority);
11508 section = buf;
11509 }
11510
11511 named_section_flags (section, SECTION_WRITE);
11512 assemble_align (POINTER_SIZE);
11513
11514 if (TARGET_RELOCATABLE)
11515 {
11516 fputs ("\t.long (", asm_out_file);
11517 output_addr_const (asm_out_file, symbol);
11518 fputs (")@fixup\n", asm_out_file);
11519 }
11520 else
11521 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
11522 }
11523 #endif
11524
11525 #ifdef OBJECT_FORMAT_COFF
11526 static void
11527 xcoff_asm_named_section (name, flags)
11528 const char *name;
11529 unsigned int flags ATTRIBUTE_UNUSED;
11530 {
11531 fprintf (asm_out_file, "\t.csect %s\n", name);
11532 }
11533 #endif