00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "output.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "recog.h"
00037 #include "expr.h"
00038 #include "optabs.h"
00039 #include "reload.h"
00040 #include "obstack.h"
00041 #include "except.h"
00042 #include "function.h"
00043 #include "toplev.h"
00044 #include "ggc.h"
00045 #include "integrate.h"
00046 #include "tm_p.h"
00047 #include "target.h"
00048 #include "target-def.h"
00049 #include "debug.h"
00050
00051
00052
00053 enum processor_type alpha_cpu;
00054 static const char * const alpha_cpu_name[] =
00055 {
00056 "ev4", "ev5", "ev6"
00057 };
00058
00059
00060
00061 enum alpha_trap_precision alpha_tp;
00062
00063
00064
00065 enum alpha_fp_rounding_mode alpha_fprm;
00066
00067
00068
00069 enum alpha_fp_trap_mode alpha_fptm;
00070
00071
00072
00073 const char *alpha_cpu_string;
00074 const char *alpha_tune_string;
00075 const char *alpha_tp_string;
00076 const char *alpha_fprm_string;
00077 const char *alpha_fptm_string;
00078 const char *alpha_mlat_string;
00079
00080
00081
00082
00083 struct alpha_compare alpha_compare;
00084
00085
00086
00087
00088 static int inside_function = FALSE;
00089
00090
00091
00092 int alpha_memory_latency = 3;
00093
00094
00095
00096 static int alpha_function_needs_gp;
00097
00098
00099
00100 static int alpha_sr_alias_set;
00101
00102
00103
00104 static const char *alpha_fnname;
00105
00106
00107 int alpha_next_sequence_number = 1;
00108
00109
00110
00111 int alpha_this_literal_sequence_number;
00112 int alpha_this_gpdisp_sequence_number;
00113
00114
00115 static bool decl_in_text_section
00116 PARAMS ((tree));
00117 static int some_small_symbolic_operand_1
00118 PARAMS ((rtx *, void *));
00119 static int split_small_symbolic_operand_1
00120 PARAMS ((rtx *, void *));
00121 static bool local_symbol_p
00122 PARAMS ((rtx));
00123 static void alpha_set_memflags_1
00124 PARAMS ((rtx, int, int, int));
00125 static rtx alpha_emit_set_const_1
00126 PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT, int));
00127 static void alpha_expand_unaligned_load_words
00128 PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
00129 static void alpha_expand_unaligned_store_words
00130 PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
00131 static void alpha_sa_mask
00132 PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
00133 static int find_lo_sum
00134 PARAMS ((rtx *, void *));
00135 static int alpha_does_function_need_gp
00136 PARAMS ((void));
00137 static int alpha_ra_ever_killed
00138 PARAMS ((void));
00139 static const char *get_trap_mode_suffix
00140 PARAMS ((void));
00141 static const char *get_round_mode_suffix
00142 PARAMS ((void));
00143 static rtx set_frame_related_p
00144 PARAMS ((void));
00145 static const char *alpha_lookup_xfloating_lib_func
00146 PARAMS ((enum rtx_code));
00147 static int alpha_compute_xfloating_mode_arg
00148 PARAMS ((enum rtx_code, enum alpha_fp_rounding_mode));
00149 static void alpha_emit_xfloating_libcall
00150 PARAMS ((const char *, rtx, rtx[], int, rtx));
00151 static rtx alpha_emit_xfloating_compare
00152 PARAMS ((enum rtx_code, rtx, rtx));
00153 static void alpha_output_function_end_prologue
00154 PARAMS ((FILE *));
00155 static int alpha_adjust_cost
00156 PARAMS ((rtx, rtx, rtx, int));
00157 static int alpha_issue_rate
00158 PARAMS ((void));
00159 static int alpha_variable_issue
00160 PARAMS ((FILE *, int, rtx, int));
00161
00162 #if TARGET_ABI_UNICOSMK
00163 static void alpha_init_machine_status
00164 PARAMS ((struct function *p));
00165 static void alpha_mark_machine_status
00166 PARAMS ((struct function *p));
00167 static void alpha_free_machine_status
00168 PARAMS ((struct function *p));
00169 #endif
00170
00171 static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
00172 static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
00173 static void unicosmk_output_ssib PARAMS ((FILE *, const char *));
00174 static int unicosmk_need_dex PARAMS ((rtx));
00175
00176
00177 #if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK
00178 #define NUM_ARGS current_function_args_info.num_args
00179 #else
00180 #define NUM_ARGS current_function_args_info
00181 #endif
00182
00183 #define REG_PV 27
00184 #define REG_RA 26
00185
00186
00187 #if TARGET_ABI_OPEN_VMS
00188 const struct attribute_spec vms_attribute_table[];
00189 static unsigned int vms_section_type_flags PARAMS ((tree, const char *, int));
00190 static void vms_asm_named_section PARAMS ((const char *, unsigned int));
00191 static void vms_asm_out_constructor PARAMS ((rtx, int));
00192 static void vms_asm_out_destructor PARAMS ((rtx, int));
00193 # undef TARGET_ATTRIBUTE_TABLE
00194 # define TARGET_ATTRIBUTE_TABLE vms_attribute_table
00195 # undef TARGET_SECTION_TYPE_FLAGS
00196 # define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
00197 #endif
00198
00199 #if TARGET_ABI_UNICOSMK
00200 static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));
00201 static void unicosmk_insert_attributes PARAMS ((tree, tree *));
00202 static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *,
00203 int));
00204 # undef TARGET_INSERT_ATTRIBUTES
00205 # define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes
00206 # undef TARGET_SECTION_TYPE_FLAGS
00207 # define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
00208 #endif
00209
00210 #undef TARGET_ASM_ALIGNED_HI_OP
00211 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00212 #undef TARGET_ASM_ALIGNED_DI_OP
00213 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00214
00215
00216
00217 #ifndef OBJECT_FORMAT_ELF
00218 #undef TARGET_ASM_UNALIGNED_HI_OP
00219 #define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.word\t"
00220 #undef TARGET_ASM_UNALIGNED_SI_OP
00221 #define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.long\t"
00222 #undef TARGET_ASM_UNALIGNED_DI_OP
00223 #define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t"
00224 #endif
00225
00226 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
00227 #define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue
00228
00229 #undef TARGET_SCHED_ADJUST_COST
00230 #define TARGET_SCHED_ADJUST_COST alpha_adjust_cost
00231 #undef TARGET_SCHED_ISSUE_RATE
00232 #define TARGET_SCHED_ISSUE_RATE alpha_issue_rate
00233 #undef TARGET_SCHED_VARIABLE_ISSUE
00234 #define TARGET_SCHED_VARIABLE_ISSUE alpha_variable_issue
00235
00236 struct gcc_target targetm = TARGET_INITIALIZER;
00237
00238
00239
00240 void
00241 override_options ()
00242 {
00243 int i;
00244 static const struct cpu_table {
00245 const char *const name;
00246 const enum processor_type processor;
00247 const int flags;
00248 } cpu_table[] = {
00249 #define EV5_MASK (MASK_CPU_EV5)
00250 #define EV6_MASK (MASK_CPU_EV6|MASK_BWX|MASK_MAX|MASK_FIX)
00251 { "ev4", PROCESSOR_EV4, 0 },
00252 { "ev45", PROCESSOR_EV4, 0 },
00253 { "21064", PROCESSOR_EV4, 0 },
00254 { "ev5", PROCESSOR_EV5, EV5_MASK },
00255 { "21164", PROCESSOR_EV5, EV5_MASK },
00256 { "ev56", PROCESSOR_EV5, EV5_MASK|MASK_BWX },
00257 { "21164a", PROCESSOR_EV5, EV5_MASK|MASK_BWX },
00258 { "pca56", PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
00259 { "21164PC",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
00260 { "21164pc",PROCESSOR_EV5, EV5_MASK|MASK_BWX|MASK_MAX },
00261 { "ev6", PROCESSOR_EV6, EV6_MASK },
00262 { "21264", PROCESSOR_EV6, EV6_MASK },
00263 { "ev67", PROCESSOR_EV6, EV6_MASK|MASK_CIX },
00264 { "21264a", PROCESSOR_EV6, EV6_MASK|MASK_CIX },
00265 { 0, 0, 0 }
00266 };
00267
00268
00269 if (TARGET_ABI_UNICOSMK && flag_pic)
00270 {
00271 warning ("-f%s ignored for Unicos/Mk (not supported)",
00272 (flag_pic > 1) ? "PIC" : "pic");
00273 flag_pic = 0;
00274 }
00275
00276
00277
00278 if (TARGET_ABI_UNICOSMK)
00279 alpha_fprm = ALPHA_FPRM_DYN;
00280 else
00281 alpha_fprm = ALPHA_FPRM_NORM;
00282
00283 alpha_tp = ALPHA_TP_PROG;
00284 alpha_fptm = ALPHA_FPTM_N;
00285
00286
00287
00288
00289
00290
00291
00292 if (TARGET_IEEE)
00293 {
00294 if (TARGET_ABI_UNICOSMK)
00295 warning ("-mieee not supported on Unicos/Mk");
00296 else
00297 {
00298 alpha_tp = ALPHA_TP_INSN;
00299 alpha_fptm = ALPHA_FPTM_SU;
00300 }
00301 }
00302
00303 if (TARGET_IEEE_WITH_INEXACT)
00304 {
00305 if (TARGET_ABI_UNICOSMK)
00306 warning ("-mieee-with-inexact not supported on Unicos/Mk");
00307 else
00308 {
00309 alpha_tp = ALPHA_TP_INSN;
00310 alpha_fptm = ALPHA_FPTM_SUI;
00311 }
00312 }
00313
00314 if (alpha_tp_string)
00315 {
00316 if (! strcmp (alpha_tp_string, "p"))
00317 alpha_tp = ALPHA_TP_PROG;
00318 else if (! strcmp (alpha_tp_string, "f"))
00319 alpha_tp = ALPHA_TP_FUNC;
00320 else if (! strcmp (alpha_tp_string, "i"))
00321 alpha_tp = ALPHA_TP_INSN;
00322 else
00323 error ("bad value `%s' for -mtrap-precision switch", alpha_tp_string);
00324 }
00325
00326 if (alpha_fprm_string)
00327 {
00328 if (! strcmp (alpha_fprm_string, "n"))
00329 alpha_fprm = ALPHA_FPRM_NORM;
00330 else if (! strcmp (alpha_fprm_string, "m"))
00331 alpha_fprm = ALPHA_FPRM_MINF;
00332 else if (! strcmp (alpha_fprm_string, "c"))
00333 alpha_fprm = ALPHA_FPRM_CHOP;
00334 else if (! strcmp (alpha_fprm_string,"d"))
00335 alpha_fprm = ALPHA_FPRM_DYN;
00336 else
00337 error ("bad value `%s' for -mfp-rounding-mode switch",
00338 alpha_fprm_string);
00339 }
00340
00341 if (alpha_fptm_string)
00342 {
00343 if (strcmp (alpha_fptm_string, "n") == 0)
00344 alpha_fptm = ALPHA_FPTM_N;
00345 else if (strcmp (alpha_fptm_string, "u") == 0)
00346 alpha_fptm = ALPHA_FPTM_U;
00347 else if (strcmp (alpha_fptm_string, "su") == 0)
00348 alpha_fptm = ALPHA_FPTM_SU;
00349 else if (strcmp (alpha_fptm_string, "sui") == 0)
00350 alpha_fptm = ALPHA_FPTM_SUI;
00351 else
00352 error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
00353 }
00354
00355 alpha_cpu
00356 = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
00357 : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
00358
00359 if (alpha_cpu_string)
00360 {
00361 for (i = 0; cpu_table [i].name; i++)
00362 if (! strcmp (alpha_cpu_string, cpu_table [i].name))
00363 {
00364 alpha_cpu = cpu_table [i].processor;
00365 target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX
00366 | MASK_CPU_EV5 | MASK_CPU_EV6);
00367 target_flags |= cpu_table [i].flags;
00368 break;
00369 }
00370 if (! cpu_table [i].name)
00371 error ("bad value `%s' for -mcpu switch", alpha_cpu_string);
00372 }
00373
00374 if (alpha_tune_string)
00375 {
00376 for (i = 0; cpu_table [i].name; i++)
00377 if (! strcmp (alpha_tune_string, cpu_table [i].name))
00378 {
00379 alpha_cpu = cpu_table [i].processor;
00380 break;
00381 }
00382 if (! cpu_table [i].name)
00383 error ("bad value `%s' for -mcpu switch", alpha_tune_string);
00384 }
00385
00386
00387
00388 if (TARGET_ABI_UNICOSMK && alpha_fptm != ALPHA_FPTM_N)
00389 {
00390 warning ("trap mode not supported on Unicos/Mk");
00391 alpha_fptm = ALPHA_FPTM_N;
00392 }
00393
00394 if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
00395 && alpha_tp != ALPHA_TP_INSN && ! TARGET_CPU_EV6)
00396 {
00397 warning ("fp software completion requires -mtrap-precision=i");
00398 alpha_tp = ALPHA_TP_INSN;
00399 }
00400
00401 if (TARGET_CPU_EV6)
00402 {
00403
00404
00405
00406 alpha_tp = ALPHA_TP_PROG;
00407 }
00408
00409 if (TARGET_FLOAT_VAX)
00410 {
00411 if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN)
00412 {
00413 warning ("rounding mode not supported for VAX floats");
00414 alpha_fprm = ALPHA_FPRM_NORM;
00415 }
00416 if (alpha_fptm == ALPHA_FPTM_SUI)
00417 {
00418 warning ("trap mode not supported for VAX floats");
00419 alpha_fptm = ALPHA_FPTM_SU;
00420 }
00421 }
00422
00423 {
00424 char *end;
00425 int lat;
00426
00427 if (!alpha_mlat_string)
00428 alpha_mlat_string = "L1";
00429
00430 if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
00431 && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
00432 ;
00433 else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
00434 && ISDIGIT ((unsigned char)alpha_mlat_string[1])
00435 && alpha_mlat_string[2] == '\0')
00436 {
00437 static int const cache_latency[][4] =
00438 {
00439 { 3, 30, -1 },
00440 { 2, 12, 38 },
00441 { 3, 12, 30 },
00442 };
00443
00444 lat = alpha_mlat_string[1] - '0';
00445 if (lat <= 0 || lat > 3 || cache_latency[alpha_cpu][lat-1] == -1)
00446 {
00447 warning ("L%d cache latency unknown for %s",
00448 lat, alpha_cpu_name[alpha_cpu]);
00449 lat = 3;
00450 }
00451 else
00452 lat = cache_latency[alpha_cpu][lat-1];
00453 }
00454 else if (! strcmp (alpha_mlat_string, "main"))
00455 {
00456
00457
00458 lat = 150;
00459 }
00460 else
00461 {
00462 warning ("bad value `%s' for -mmemory-latency", alpha_mlat_string);
00463 lat = 3;
00464 }
00465
00466 alpha_memory_latency = lat;
00467 }
00468
00469
00470 if (!g_switch_set)
00471 g_switch_value = 8;
00472
00473
00474 if (flag_pic == 1)
00475 target_flags |= MASK_SMALL_DATA;
00476 else if (flag_pic == 2)
00477 target_flags &= ~MASK_SMALL_DATA;
00478
00479
00480
00481
00482 if (optimize > 0 && write_symbols != SDB_DEBUG)
00483 {
00484 if (align_loops <= 0)
00485 align_loops = 16;
00486 if (align_jumps <= 0)
00487 align_jumps = 16;
00488 }
00489 if (align_functions <= 0)
00490 align_functions = 16;
00491
00492
00493 alpha_sr_alias_set = new_alias_set ();
00494
00495
00496
00497 #if TARGET_ABI_UNICOSMK
00498
00499 init_machine_status = alpha_init_machine_status;
00500 mark_machine_status = alpha_mark_machine_status;
00501 free_machine_status = alpha_free_machine_status;
00502 #endif
00503 }
00504
00505
00506
00507 int
00508 zap_mask (value)
00509 HOST_WIDE_INT value;
00510 {
00511 int i;
00512
00513 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
00514 i++, value >>= 8)
00515 if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
00516 return 0;
00517
00518 return 1;
00519 }
00520
00521
00522
00523
00524 int
00525 reg_or_0_operand (op, mode)
00526 register rtx op;
00527 enum machine_mode mode;
00528 {
00529 return op == const0_rtx || register_operand (op, mode);
00530 }
00531
00532
00533
00534
00535 int
00536 reg_or_6bit_operand (op, mode)
00537 register rtx op;
00538 enum machine_mode mode;
00539 {
00540 return ((GET_CODE (op) == CONST_INT
00541 && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
00542 || register_operand (op, mode));
00543 }
00544
00545
00546
00547
00548 int
00549 reg_or_8bit_operand (op, mode)
00550 register rtx op;
00551 enum machine_mode mode;
00552 {
00553 return ((GET_CODE (op) == CONST_INT
00554 && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
00555 || register_operand (op, mode));
00556 }
00557
00558
00559
00560 int
00561 cint8_operand (op, mode)
00562 register rtx op;
00563 enum machine_mode mode ATTRIBUTE_UNUSED;
00564 {
00565 return ((GET_CODE (op) == CONST_INT
00566 && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));
00567 }
00568
00569
00570
00571 int
00572 add_operand (op, mode)
00573 register rtx op;
00574 enum machine_mode mode;
00575 {
00576 if (GET_CODE (op) == CONST_INT)
00577
00578 return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
00579 || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
00580
00581 return register_operand (op, mode);
00582 }
00583
00584
00585
00586
00587 int
00588 sext_add_operand (op, mode)
00589 register rtx op;
00590 enum machine_mode mode;
00591 {
00592 if (GET_CODE (op) == CONST_INT)
00593 return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
00594 || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
00595
00596 return reg_not_elim_operand (op, mode);
00597 }
00598
00599
00600
00601 int
00602 const48_operand (op, mode)
00603 register rtx op;
00604 enum machine_mode mode ATTRIBUTE_UNUSED;
00605 {
00606 return (GET_CODE (op) == CONST_INT
00607 && (INTVAL (op) == 4 || INTVAL (op) == 8));
00608 }
00609
00610
00611
00612 int
00613 and_operand (op, mode)
00614 register rtx op;
00615 enum machine_mode mode;
00616 {
00617 if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
00618 return (zap_mask (CONST_DOUBLE_LOW (op))
00619 && zap_mask (CONST_DOUBLE_HIGH (op)));
00620
00621 if (GET_CODE (op) == CONST_INT)
00622 return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
00623 || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
00624 || zap_mask (INTVAL (op)));
00625
00626 return register_operand (op, mode);
00627 }
00628
00629
00630
00631 int
00632 or_operand (op, mode)
00633 register rtx op;
00634 enum machine_mode mode;
00635 {
00636 if (GET_CODE (op) == CONST_INT)
00637 return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
00638 || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);
00639
00640 return register_operand (op, mode);
00641 }
00642
00643
00644
00645
00646 int
00647 mode_width_operand (op, mode)
00648 register rtx op;
00649 enum machine_mode mode ATTRIBUTE_UNUSED;
00650 {
00651 return (GET_CODE (op) == CONST_INT
00652 && (INTVAL (op) == 8 || INTVAL (op) == 16
00653 || INTVAL (op) == 32 || INTVAL (op) == 64));
00654 }
00655
00656
00657
00658
00659 int
00660 mode_mask_operand (op, mode)
00661 register rtx op;
00662 enum machine_mode mode ATTRIBUTE_UNUSED;
00663 {
00664 #if HOST_BITS_PER_WIDE_INT == 32
00665 if (GET_CODE (op) == CONST_DOUBLE)
00666 return (CONST_DOUBLE_LOW (op) == -1
00667 && (CONST_DOUBLE_HIGH (op) == -1
00668 || CONST_DOUBLE_HIGH (op) == 0));
00669 #else
00670 if (GET_CODE (op) == CONST_DOUBLE)
00671 return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);
00672 #endif
00673
00674 return (GET_CODE (op) == CONST_INT
00675 && (INTVAL (op) == 0xff
00676 || INTVAL (op) == 0xffff
00677 || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
00678 #if HOST_BITS_PER_WIDE_INT == 64
00679 || INTVAL (op) == -1
00680 #endif
00681 ));
00682 }
00683
00684
00685
00686 int
00687 mul8_operand (op, mode)
00688 register rtx op;
00689 enum machine_mode mode ATTRIBUTE_UNUSED;
00690 {
00691 return (GET_CODE (op) == CONST_INT
00692 && (unsigned HOST_WIDE_INT) INTVAL (op) < 64
00693 && (INTVAL (op) & 7) == 0);
00694 }
00695
00696
00697
00698 int
00699 fp0_operand (op, mode)
00700 register rtx op;
00701 enum machine_mode mode;
00702 {
00703 return (GET_MODE (op) == mode
00704 && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode));
00705 }
00706
00707
00708
00709 int
00710 reg_or_fp0_operand (op, mode)
00711 register rtx op;
00712 enum machine_mode mode;
00713 {
00714 return fp0_operand (op, mode) || register_operand (op, mode);
00715 }
00716
00717
00718
00719 int
00720 hard_fp_register_operand (op, mode)
00721 register rtx op;
00722 enum machine_mode mode;
00723 {
00724 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00725 return 0;
00726
00727 if (GET_CODE (op) == SUBREG)
00728 op = SUBREG_REG (op);
00729 return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS;
00730 }
00731
00732
00733
00734 int
00735 hard_int_register_operand (op, mode)
00736 register rtx op;
00737 enum machine_mode mode;
00738 {
00739 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00740 return 0;
00741
00742 if (GET_CODE (op) == SUBREG)
00743 op = SUBREG_REG (op);
00744 return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS;
00745 }
00746
00747
00748
00749
00750 int
00751 reg_or_cint_operand (op, mode)
00752 register rtx op;
00753 enum machine_mode mode;
00754 {
00755 return (GET_CODE (op) == CONST_INT
00756 || register_operand (op, mode));
00757 }
00758
00759
00760
00761
00762 int
00763 some_operand (op, mode)
00764 register rtx op;
00765 enum machine_mode mode;
00766 {
00767 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00768 return 0;
00769
00770 switch (GET_CODE (op))
00771 {
00772 case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF:
00773 case SYMBOL_REF: case CONST: case HIGH:
00774 return 1;
00775
00776 case SUBREG:
00777 return some_operand (SUBREG_REG (op), VOIDmode);
00778
00779 default:
00780 break;
00781 }
00782
00783 return 0;
00784 }
00785
00786
00787
00788 int
00789 some_ni_operand (op, mode)
00790 register rtx op;
00791 enum machine_mode mode;
00792 {
00793 if (GET_MODE (op) != mode && mode != VOIDmode)
00794 return 0;
00795
00796 if (GET_CODE (op) == SUBREG)
00797 op = SUBREG_REG (op);
00798
00799 return (GET_CODE (op) == REG || GET_CODE (op) == MEM);
00800 }
00801
00802
00803
00804 int
00805 input_operand (op, mode)
00806 register rtx op;
00807 enum machine_mode mode;
00808 {
00809 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00810 return 0;
00811
00812 if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)
00813 return 0;
00814
00815 switch (GET_CODE (op))
00816 {
00817 case LABEL_REF:
00818 case SYMBOL_REF:
00819 case CONST:
00820 if (TARGET_EXPLICIT_RELOCS)
00821 {
00822
00823
00824
00825
00826 return (small_symbolic_operand (op, mode)
00827 || global_symbolic_operand (op, mode));
00828 }
00829
00830
00831 return mode == ptr_mode || mode == DImode;
00832
00833 case HIGH:
00834 return (TARGET_EXPLICIT_RELOCS
00835 && local_symbolic_operand (XEXP (op, 0), mode));
00836
00837 case REG:
00838 case ADDRESSOF:
00839 return 1;
00840
00841 case SUBREG:
00842 if (register_operand (op, mode))
00843 return 1;
00844
00845 case MEM:
00846 return ((TARGET_BWX || (mode != HImode && mode != QImode))
00847 && general_operand (op, mode));
00848
00849 case CONST_DOUBLE:
00850 return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
00851
00852 case CONST_INT:
00853 return mode == QImode || mode == HImode || add_operand (op, mode);
00854
00855 case CONSTANT_P_RTX:
00856 return 1;
00857
00858 default:
00859 break;
00860 }
00861
00862 return 0;
00863 }
00864
00865
00866
00867
00868 int
00869 current_file_function_operand (op, mode)
00870 rtx op;
00871 enum machine_mode mode ATTRIBUTE_UNUSED;
00872 {
00873 if (GET_CODE (op) != SYMBOL_REF)
00874 return 0;
00875
00876
00877 if (op == XEXP (DECL_RTL (current_function_decl), 0))
00878 return 1;
00879
00880
00881
00882
00883
00884 if (SYMBOL_REF_FLAG (op) && decl_in_text_section (current_function_decl))
00885 return 1;
00886
00887 return 0;
00888 }
00889
00890
00891
00892 int
00893 direct_call_operand (op, mode)
00894 rtx op;
00895 enum machine_mode mode;
00896 {
00897
00898 if (! current_file_function_operand (op, mode))
00899 return 0;
00900
00901
00902
00903
00904
00905
00906 if (! TARGET_PROFILING_NEEDS_GP
00907 && ! current_function_profile)
00908 return 0;
00909
00910 return 1;
00911 }
00912
00913
00914
00915
00916 static bool
00917 local_symbol_p (op)
00918 rtx op;
00919 {
00920 const char *str = XSTR (op, 0);
00921
00922
00923
00924
00925
00926
00927 return (CONSTANT_POOL_ADDRESS_P (op)
00928
00929 || str[0] == '@'
00930
00931 || (str[0] == '*' && str[1] == '$'));
00932 }
00933
00934 int
00935 local_symbolic_operand (op, mode)
00936 rtx op;
00937 enum machine_mode mode;
00938 {
00939 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00940 return 0;
00941
00942 if (GET_CODE (op) == LABEL_REF)
00943 return 1;
00944
00945 if (GET_CODE (op) == CONST
00946 && GET_CODE (XEXP (op, 0)) == PLUS
00947 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
00948 op = XEXP (XEXP (op, 0), 0);
00949
00950 if (GET_CODE (op) != SYMBOL_REF)
00951 return 0;
00952
00953 return local_symbol_p (op);
00954 }
00955
00956
00957
00958
00959 int
00960 small_symbolic_operand (op, mode)
00961 rtx op;
00962 enum machine_mode mode ATTRIBUTE_UNUSED;
00963 {
00964 const char *str;
00965
00966 if (! TARGET_SMALL_DATA)
00967 return 0;
00968
00969 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00970 return 0;
00971
00972 if (GET_CODE (op) == CONST
00973 && GET_CODE (XEXP (op, 0)) == PLUS
00974 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
00975 op = XEXP (XEXP (op, 0), 0);
00976
00977 if (GET_CODE (op) != SYMBOL_REF)
00978 return 0;
00979
00980 if (CONSTANT_POOL_ADDRESS_P (op))
00981 return GET_MODE_SIZE (get_pool_mode (op)) <= (unsigned) g_switch_value;
00982 else
00983 {
00984 str = XSTR (op, 0);
00985 return str[0] == '@' && str[1] == 's';
00986 }
00987 }
00988
00989
00990
00991
00992 int
00993 global_symbolic_operand (op, mode)
00994 rtx op;
00995 enum machine_mode mode;
00996 {
00997 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
00998 return 0;
00999
01000 if (GET_CODE (op) == CONST
01001 && GET_CODE (XEXP (op, 0)) == PLUS
01002 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
01003 op = XEXP (XEXP (op, 0), 0);
01004
01005 if (GET_CODE (op) != SYMBOL_REF)
01006 return 0;
01007
01008 return ! local_symbol_p (op);
01009 }
01010
01011
01012
01013 int
01014 call_operand (op, mode)
01015 rtx op;
01016 enum machine_mode mode;
01017 {
01018 if (mode != Pmode)
01019 return 0;
01020
01021 if (GET_CODE (op) == REG)
01022 {
01023 if (TARGET_ABI_OSF)
01024 {
01025
01026
01027
01028 return (REGNO (op) == 27 || REGNO (op) > LAST_VIRTUAL_REGISTER);
01029 }
01030 else
01031 return 1;
01032 }
01033 if (TARGET_ABI_UNICOSMK)
01034 return 0;
01035 if (GET_CODE (op) == SYMBOL_REF)
01036 return 1;
01037
01038 return 0;
01039 }
01040
01041
01042
01043
01044 int
01045 symbolic_operand (op, mode)
01046 register rtx op;
01047 enum machine_mode mode;
01048 {
01049 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
01050 return 0;
01051 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
01052 return 1;
01053 if (GET_CODE (op) == CONST
01054 && GET_CODE (XEXP (op,0)) == PLUS
01055 && GET_CODE (XEXP (XEXP (op,0), 0)) == SYMBOL_REF
01056 && GET_CODE (XEXP (XEXP (op,0), 1)) == CONST_INT)
01057 return 1;
01058 return 0;
01059 }
01060
01061
01062
01063
01064 int
01065 alpha_comparison_operator (op, mode)
01066 register rtx op;
01067 enum machine_mode mode;
01068 {
01069 enum rtx_code code = GET_CODE (op);
01070
01071 if (mode != GET_MODE (op) && mode != VOIDmode)
01072 return 0;
01073
01074 return (code == EQ || code == LE || code == LT
01075 || code == LEU || code == LTU);
01076 }
01077
01078
01079
01080
01081 int
01082 alpha_zero_comparison_operator (op, mode)
01083 register rtx op;
01084 enum machine_mode mode;
01085 {
01086 enum rtx_code code = GET_CODE (op);
01087
01088 if (mode != GET_MODE (op) && mode != VOIDmode)
01089 return 0;
01090
01091 return (code == EQ || code == NE || code == LE || code == LT
01092 || code == LEU || code == LTU);
01093 }
01094
01095
01096
01097 int
01098 alpha_swapped_comparison_operator (op, mode)
01099 register rtx op;
01100 enum machine_mode mode;
01101 {
01102 enum rtx_code code = GET_CODE (op);
01103
01104 if ((mode != GET_MODE (op) && mode != VOIDmode)
01105 || GET_RTX_CLASS (code) != '<')
01106 return 0;
01107
01108 code = swap_condition (code);
01109 return (code == EQ || code == LE || code == LT
01110 || code == LEU || code == LTU);
01111 }
01112
01113
01114
01115 int
01116 signed_comparison_operator (op, mode)
01117 register rtx op;
01118 enum machine_mode mode ATTRIBUTE_UNUSED;
01119 {
01120 enum rtx_code code = GET_CODE (op);
01121
01122 if (mode != GET_MODE (op) && mode != VOIDmode)
01123 return 0;
01124
01125 return (code == EQ || code == NE
01126 || code == LE || code == LT
01127 || code == GE || code == GT);
01128 }
01129
01130
01131
01132
01133 int
01134 alpha_fp_comparison_operator (op, mode)
01135 register rtx op;
01136 enum machine_mode mode;
01137 {
01138 enum rtx_code code = GET_CODE (op);
01139
01140 if (mode != GET_MODE (op) && mode != VOIDmode)
01141 return 0;
01142
01143 return (code == EQ || code == LE || code == LT || code == UNORDERED);
01144 }
01145
01146
01147
01148 int
01149 divmod_operator (op, mode)
01150 register rtx op;
01151 enum machine_mode mode ATTRIBUTE_UNUSED;
01152 {
01153 switch (GET_CODE (op))
01154 {
01155 case DIV: case MOD: case UDIV: case UMOD:
01156 return 1;
01157
01158 default:
01159 break;
01160 }
01161
01162 return 0;
01163 }
01164
01165
01166
01167
01168
01169
01170
01171 int
01172 aligned_memory_operand (op, mode)
01173 register rtx op;
01174 enum machine_mode mode;
01175 {
01176 rtx base;
01177
01178 if (reload_in_progress)
01179 {
01180 rtx tmp = op;
01181 if (GET_CODE (tmp) == SUBREG)
01182 tmp = SUBREG_REG (tmp);
01183 if (GET_CODE (tmp) == REG
01184 && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
01185 {
01186 op = reg_equiv_memory_loc[REGNO (tmp)];
01187 if (op == 0)
01188 return 0;
01189 }
01190 }
01191
01192 if (GET_CODE (op) != MEM
01193 || GET_MODE (op) != mode)
01194 return 0;
01195 op = XEXP (op, 0);
01196
01197
01198
01199 if (reload_in_progress
01200 && GET_CODE (op) == PLUS
01201 && GET_CODE (XEXP (op, 0)) == PLUS)
01202 base = XEXP (XEXP (op, 0), 0);
01203 else
01204 {
01205 if (! memory_address_p (mode, op))
01206 return 0;
01207 base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
01208 }
01209
01210 return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) >= 32);
01211 }
01212
01213
01214
01215 int
01216 unaligned_memory_operand (op, mode)
01217 register rtx op;
01218 enum machine_mode mode;
01219 {
01220 rtx base;
01221
01222 if (reload_in_progress)
01223 {
01224 rtx tmp = op;
01225 if (GET_CODE (tmp) == SUBREG)
01226 tmp = SUBREG_REG (tmp);
01227 if (GET_CODE (tmp) == REG
01228 && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
01229 {
01230 op = reg_equiv_memory_loc[REGNO (tmp)];
01231 if (op == 0)
01232 return 0;
01233 }
01234 }
01235
01236 if (GET_CODE (op) != MEM
01237 || GET_MODE (op) != mode)
01238 return 0;
01239 op = XEXP (op, 0);
01240
01241
01242
01243 if (reload_in_progress
01244 && GET_CODE (op) == PLUS
01245 && GET_CODE (XEXP (op, 0)) == PLUS)
01246 base = XEXP (XEXP (op, 0), 0);
01247 else
01248 {
01249 if (! memory_address_p (mode, op))
01250 return 0;
01251 base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
01252 }
01253
01254 return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) < 32);
01255 }
01256
01257
01258
01259 int
01260 reg_or_unaligned_mem_operand (op, mode)
01261 rtx op;
01262 enum machine_mode mode;
01263 {
01264 return register_operand (op, mode) || unaligned_memory_operand (op, mode);
01265 }
01266
01267
01268
01269 int
01270 any_memory_operand (op, mode)
01271 register rtx op;
01272 enum machine_mode mode ATTRIBUTE_UNUSED;
01273 {
01274 return (GET_CODE (op) == MEM
01275 || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
01276 || (reload_in_progress && GET_CODE (op) == REG
01277 && REGNO (op) >= FIRST_PSEUDO_REGISTER)
01278 || (reload_in_progress && GET_CODE (op) == SUBREG
01279 && GET_CODE (SUBREG_REG (op)) == REG
01280 && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
01281 }
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 int
01295 reg_not_elim_operand (op, mode)
01296 register rtx op;
01297 enum machine_mode mode;
01298 {
01299 rtx inner = op;
01300 if (GET_CODE (op) == SUBREG)
01301 inner = SUBREG_REG (op);
01302 if (inner == frame_pointer_rtx || inner == arg_pointer_rtx)
01303 return 0;
01304
01305 return register_operand (op, mode);
01306 }
01307
01308
01309
01310
01311
01312 int
01313 normal_memory_operand (op, mode)
01314 register rtx op;
01315 enum machine_mode mode ATTRIBUTE_UNUSED;
01316 {
01317 if (reload_in_progress)
01318 {
01319 rtx tmp = op;
01320 if (GET_CODE (tmp) == SUBREG)
01321 tmp = SUBREG_REG (tmp);
01322 if (GET_CODE (tmp) == REG
01323 && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
01324 {
01325 op = reg_equiv_memory_loc[REGNO (tmp)];
01326
01327
01328
01329 if (op == 0)
01330 return 1;
01331 }
01332 }
01333
01334 return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) != AND;
01335 }
01336
01337
01338
01339
01340
01341 int
01342 reg_no_subreg_operand (op, mode)
01343 register rtx op;
01344 enum machine_mode mode;
01345 {
01346 if (GET_CODE (op) != REG)
01347 return 0;
01348 return register_operand (op, mode);
01349 }
01350
01351
01352
01353
01354
01355 int
01356 addition_operation (op, mode)
01357 register rtx op;
01358 enum machine_mode mode;
01359 {
01360 if (GET_MODE (op) != mode && mode != VOIDmode)
01361 return 0;
01362 if (GET_CODE (op) == PLUS
01363 && register_operand (XEXP (op, 0), mode)
01364 && GET_CODE (XEXP (op, 1)) == CONST_INT
01365 && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op, 1)), 'K'))
01366 return 1;
01367 return 0;
01368 }
01369
01370
01371
01372
01373 bool
01374 alpha_const_ok_for_letter_p (value, c)
01375 HOST_WIDE_INT value;
01376 int c;
01377 {
01378 switch (c)
01379 {
01380 case 'I':
01381
01382 return (unsigned HOST_WIDE_INT) value < 0x100;
01383 case 'J':
01384
01385 return value == 0;
01386 case 'K':
01387
01388 return (unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000;
01389 case 'L':
01390
01391 return ((value & 0xffff) == 0
01392 && ((value) >> 31 == -1 || value >> 31 == 0));
01393 case 'M':
01394
01395 return zap_mask (value);
01396 case 'N':
01397
01398 return (unsigned HOST_WIDE_INT) (~ value) < 0x100;
01399 case 'O':
01400
01401 return (unsigned HOST_WIDE_INT) (- value) < 0x100;
01402 case 'P':
01403
01404 return value == 1 || value == 2 || value == 3;
01405
01406 default:
01407 return false;
01408 }
01409 }
01410
01411
01412
01413
01414 bool
01415 alpha_const_double_ok_for_letter_p (value, c)
01416 rtx value;
01417 int c;
01418 {
01419 switch (c)
01420 {
01421 case 'G':
01422
01423 return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
01424 && value == CONST0_RTX (GET_MODE (value)));
01425
01426 case 'H':
01427
01428 return (GET_MODE (value) == VOIDmode
01429 && zap_mask (CONST_DOUBLE_LOW (value))
01430 && zap_mask (CONST_DOUBLE_HIGH (value)));
01431
01432 default:
01433 return false;
01434 }
01435 }
01436
01437
01438
01439
01440 bool
01441 alpha_extra_constraint (value, c)
01442 rtx value;
01443 int c;
01444 {
01445 switch (c)
01446 {
01447 case 'Q':
01448 return normal_memory_operand (value, VOIDmode);
01449 case 'R':
01450 return direct_call_operand (value, Pmode);
01451 case 'S':
01452 return (GET_CODE (value) == CONST_INT
01453 && (unsigned HOST_WIDE_INT) INTVAL (value) < 64);
01454 case 'T':
01455 return GET_CODE (value) == HIGH;
01456 case 'U':
01457 return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
01458
01459 default:
01460 return false;
01461 }
01462 }
01463
01464
01465
01466 int
01467 direct_return ()
01468 {
01469 return (! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK
01470 && reload_completed
01471 && alpha_sa_size () == 0
01472 && get_frame_size () == 0
01473 && current_function_outgoing_args_size == 0
01474 && current_function_pretend_args_size == 0);
01475 }
01476
01477
01478
01479 rtx
01480 alpha_tablejump_addr_vec (insn)
01481 rtx insn;
01482 {
01483 rtx tmp;
01484
01485 tmp = JUMP_LABEL (insn);
01486 if (!tmp)
01487 return NULL_RTX;
01488 tmp = NEXT_INSN (tmp);
01489 if (!tmp)
01490 return NULL_RTX;
01491 if (GET_CODE (tmp) == JUMP_INSN
01492 && GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)
01493 return PATTERN (tmp);
01494 return NULL_RTX;
01495 }
01496
01497
01498
01499 rtx
01500 alpha_tablejump_best_label (insn)
01501 rtx insn;
01502 {
01503 rtx jump_table = alpha_tablejump_addr_vec (insn);
01504 rtx best_label = NULL_RTX;
01505
01506
01507
01508
01509 if (jump_table)
01510 {
01511 int n_labels = XVECLEN (jump_table, 1);
01512 int best_count = -1;
01513 int i, j;
01514
01515 for (i = 0; i < n_labels; i++)
01516 {
01517 int count = 1;
01518
01519 for (j = i + 1; j < n_labels; j++)
01520 if (XEXP (XVECEXP (jump_table, 1, i), 0)
01521 == XEXP (XVECEXP (jump_table, 1, j), 0))
01522 count++;
01523
01524 if (count > best_count)
01525 best_count = count, best_label = XVECEXP (jump_table, 1, i);
01526 }
01527 }
01528
01529 return best_label ? best_label : const0_rtx;
01530 }
01531
01532
01533
01534
01535
01536
01537
01538 static bool
01539 decl_in_text_section (decl)
01540 tree decl;
01541 {
01542 return (DECL_SECTION_NAME (decl) == NULL_TREE
01543 && ! (flag_function_sections
01544 || (targetm.have_named_sections
01545 && DECL_ONE_ONLY (decl))));
01546 }
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556 void
01557 alpha_encode_section_info (decl)
01558 tree decl;
01559 {
01560 const char *symbol_str;
01561 bool is_local, is_small;
01562
01563 if (TREE_CODE (decl) == FUNCTION_DECL)
01564 {
01565
01566
01567 if (TREE_PUBLIC (decl))
01568 return;
01569
01570
01571 if (! decl_in_text_section (decl))
01572 return;
01573
01574 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
01575 return;
01576 }
01577
01578
01579 if (! TARGET_EXPLICIT_RELOCS)
01580 return;
01581
01582
01583 if (TREE_CODE (decl) != VAR_DECL
01584 || GET_CODE (DECL_RTL (decl)) != MEM
01585 || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
01586 return;
01587
01588 symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
01589
01590
01591
01592 if (DECL_EXTERNAL (decl))
01593 is_local = false;
01594
01595 else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
01596 is_local = false;
01597 else if (! TREE_PUBLIC (decl))
01598 is_local = true;
01599
01600
01601 else if (flag_pic)
01602 is_local = false;
01603
01604
01605 else if (DECL_COMMON (decl)
01606 && (DECL_INITIAL (decl) == NULL
01607 || DECL_INITIAL (decl) == error_mark_node))
01608 is_local = false;
01609
01610
01611 else
01612 is_local = true;
01613
01614
01615
01616 is_small = false;
01617 if (DECL_SECTION_NAME (decl))
01618 {
01619 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
01620 if (strcmp (section, ".sdata") == 0
01621 || strcmp (section, ".sbss") == 0)
01622 is_small = true;
01623 }
01624 else
01625 {
01626 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
01627
01628
01629
01630
01631
01632
01633 if (TREE_ASM_WRITTEN (decl))
01634 ;
01635
01636
01637
01638 else if (size > 0 && size <= g_switch_value)
01639 is_small = true;
01640 }
01641
01642
01643 if (is_local)
01644 {
01645 const char *string;
01646 char *newstr;
01647 size_t len;
01648
01649 if (symbol_str[0] == '@')
01650 {
01651 if (symbol_str[1] == (is_small ? 's' : 'v'))
01652 return;
01653 symbol_str += 2;
01654 }
01655
01656 len = strlen (symbol_str) + 1;
01657 newstr = alloca (len + 2);
01658
01659 newstr[0] = '@';
01660 newstr[1] = (is_small ? 's' : 'v');
01661 memcpy (newstr + 2, symbol_str, len);
01662
01663 string = ggc_alloc_string (newstr, len + 2 - 1);
01664 XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;
01665 }
01666 else if (symbol_str[0] == '@')
01667 {
01668
01669
01670
01671 }
01672 }
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683 bool
01684 alpha_legitimate_address_p (mode, x, strict)
01685 enum machine_mode mode;
01686 rtx x;
01687 int strict;
01688 {
01689
01690 if (mode == DImode
01691 && GET_CODE (x) == AND
01692 && GET_CODE (XEXP (x, 1)) == CONST_INT
01693 && INTVAL (XEXP (x, 1)) == -8)
01694 x = XEXP (x, 0);
01695
01696
01697 if (GET_CODE (x) == SUBREG
01698 && (GET_MODE_SIZE (GET_MODE (x))
01699 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
01700 x = SUBREG_REG (x);
01701
01702
01703 if (REG_P (x)
01704 && (strict
01705 ? STRICT_REG_OK_FOR_BASE_P (x)
01706 : NONSTRICT_REG_OK_FOR_BASE_P (x)))
01707 return true;
01708
01709
01710 if (CONSTANT_ADDRESS_P (x))
01711 return true;
01712
01713
01714 if (GET_CODE (x) == PLUS)
01715 {
01716 rtx ofs = XEXP (x, 1);
01717 x = XEXP (x, 0);
01718
01719
01720 if (GET_CODE (x) == SUBREG
01721 && (GET_MODE_SIZE (GET_MODE (x))
01722 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
01723 x = SUBREG_REG (x);
01724
01725 if (REG_P (x))
01726 {
01727 if (! strict
01728 && NONSTRICT_REG_OK_FP_BASE_P (x)
01729 && GET_CODE (ofs) == CONST_INT)
01730 return true;
01731 if ((strict
01732 ? STRICT_REG_OK_FOR_BASE_P (x)
01733 : NONSTRICT_REG_OK_FOR_BASE_P (x))
01734 && CONSTANT_ADDRESS_P (ofs))
01735 return true;
01736 }
01737 else if (GET_CODE (x) == ADDRESSOF
01738 && GET_CODE (ofs) == CONST_INT)
01739 return true;
01740 }
01741
01742
01743
01744 else if (TARGET_EXPLICIT_RELOCS)
01745 {
01746 if (small_symbolic_operand (x, Pmode))
01747 return true;
01748
01749 if (GET_CODE (x) == LO_SUM)
01750 {
01751 rtx ofs = XEXP (x, 1);
01752 x = XEXP (x, 0);
01753
01754
01755 if (GET_CODE (x) == SUBREG
01756 && (GET_MODE_SIZE (GET_MODE (x))
01757 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
01758 x = SUBREG_REG (x);
01759
01760
01761 if (! (REG_P (x)
01762 && (strict
01763 ? STRICT_REG_OK_FOR_BASE_P (x)
01764 : NONSTRICT_REG_OK_FOR_BASE_P (x))))
01765 return false;
01766
01767
01768 if (local_symbolic_operand (ofs, Pmode))
01769 return true;
01770 }
01771 }
01772
01773 return false;
01774 }
01775
01776
01777
01778
01779 rtx
01780 alpha_legitimize_address (x, scratch, mode)
01781 rtx x;
01782 rtx scratch;
01783 enum machine_mode mode ATTRIBUTE_UNUSED;
01784 {
01785 HOST_WIDE_INT addend;
01786
01787
01788
01789
01790 if (GET_CODE (x) == PLUS
01791 && GET_CODE (XEXP (x, 0)) == REG
01792 && GET_CODE (XEXP (x, 1)) == CONST_INT
01793 && ! CONSTANT_ADDRESS_P (XEXP (x, 1)))
01794 {
01795 addend = INTVAL (XEXP (x, 1));
01796 x = XEXP (x, 0);
01797 goto split_addend;
01798 }
01799
01800
01801
01802
01803
01804 if (!no_new_pseudos
01805 && GET_CODE (x) == CONST
01806 && GET_CODE (XEXP (x, 0)) == PLUS
01807 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
01808 {
01809 addend = INTVAL (XEXP (XEXP (x, 0), 1));
01810 x = force_reg (Pmode, XEXP (XEXP (x, 0), 0));
01811 goto split_addend;
01812 }
01813
01814
01815
01816
01817 if (!no_new_pseudos
01818 && GET_CODE (x) == PLUS
01819 && GET_CODE (XEXP (x, 0)) == REG
01820 && GET_CODE (XEXP (x, 1)) == CONST
01821 && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
01822 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)
01823 {
01824 addend = INTVAL (XEXP (XEXP (XEXP (x, 1), 0), 1));
01825 x = expand_simple_binop (Pmode, PLUS, XEXP (x, 0),
01826 XEXP (XEXP (XEXP (x, 1), 0), 0),
01827 NULL_RTX, 1, OPTAB_LIB_WIDEN);
01828 goto split_addend;
01829 }
01830
01831
01832 if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
01833 {
01834 if (local_symbolic_operand (x, Pmode))
01835 {
01836 if (small_symbolic_operand (x, Pmode))
01837 return x;
01838 else
01839 {
01840 if (!no_new_pseudos)
01841 scratch = gen_reg_rtx (Pmode);
01842 emit_insn (gen_rtx_SET (VOIDmode, scratch,
01843 gen_rtx_HIGH (Pmode, x)));
01844 return gen_rtx_LO_SUM (Pmode, scratch, x);
01845 }
01846 }
01847 }
01848
01849 return NULL;
01850
01851 split_addend:
01852 {
01853 HOST_WIDE_INT low, high;
01854
01855 low = ((addend & 0xffff) ^ 0x8000) - 0x8000;
01856 addend -= low;
01857 high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000;
01858 addend -= high;
01859
01860 if (addend)
01861 x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),
01862 (no_new_pseudos ? scratch : NULL_RTX),
01863 1, OPTAB_LIB_WIDEN);
01864 if (high)
01865 x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),
01866 (no_new_pseudos ? scratch : NULL_RTX),
01867 1, OPTAB_LIB_WIDEN);
01868
01869 return plus_constant (x, low);
01870 }
01871 }
01872
01873
01874
01875
01876
01877
01878 int
01879 some_small_symbolic_operand (x, mode)
01880 rtx x;
01881 enum machine_mode mode ATTRIBUTE_UNUSED;
01882 {
01883 return for_each_rtx (&x, some_small_symbolic_operand_1, NULL);
01884 }
01885
01886 static int
01887 some_small_symbolic_operand_1 (px, data)
01888 rtx *px;
01889 void *data ATTRIBUTE_UNUSED;
01890 {
01891 rtx x = *px;
01892
01893
01894 if (GET_CODE (x) == LO_SUM)
01895 return -1;
01896
01897 return small_symbolic_operand (x, Pmode) != 0;
01898 }
01899
01900 rtx
01901 split_small_symbolic_operand (x)
01902 rtx x;
01903 {
01904 x = copy_insn (x);
01905 for_each_rtx (&x, split_small_symbolic_operand_1, NULL);
01906 return x;
01907 }
01908
01909 static int
01910 split_small_symbolic_operand_1 (px, data)
01911 rtx *px;
01912 void *data ATTRIBUTE_UNUSED;
01913 {
01914 rtx x = *px;
01915
01916
01917 if (GET_CODE (x) == LO_SUM)
01918 return -1;
01919
01920 if (small_symbolic_operand (x, Pmode))
01921 {
01922 x = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, x);
01923 *px = x;
01924 return -1;
01925 }
01926
01927 return 0;
01928 }
01929
01930
01931
01932
01933 rtx
01934 alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels)
01935 rtx x;
01936 enum machine_mode mode ATTRIBUTE_UNUSED;
01937 int opnum;
01938 int type;
01939 int ind_levels ATTRIBUTE_UNUSED;
01940 {
01941
01942 if (GET_CODE (x) == PLUS
01943 && GET_CODE (XEXP (x, 0)) == PLUS
01944 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
01945 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01946 && GET_CODE (XEXP (x, 1)) == CONST_INT)
01947 {
01948 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01949 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01950 opnum, type);
01951 return x;
01952 }
01953
01954
01955
01956
01957 if (GET_CODE (x) == PLUS
01958 && GET_CODE (XEXP (x, 0)) == REG
01959 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
01960 && REGNO_OK_FOR_BASE_P (REGNO (XEXP (x, 0)))
01961 && GET_CODE (XEXP (x, 1)) == CONST_INT)
01962 {
01963 HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
01964 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
01965 HOST_WIDE_INT high
01966 = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
01967
01968
01969 if (high + low != val)
01970 return NULL_RTX;
01971
01972
01973
01974 x = gen_rtx_PLUS (GET_MODE (x),
01975 gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
01976 GEN_INT (high)),
01977 GEN_INT (low));
01978
01979 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01980 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01981 opnum, type);
01982 return x;
01983 }
01984
01985 return NULL_RTX;
01986 }
01987
01988
01989
01990
01991
01992
01993 void
01994 get_aligned_mem (ref, paligned_mem, pbitnum)
01995 rtx ref;
01996 rtx *paligned_mem, *pbitnum;
01997 {
01998 rtx base;
01999 HOST_WIDE_INT offset = 0;
02000
02001 if (GET_CODE (ref) != MEM)
02002 abort ();
02003
02004 if (reload_in_progress
02005 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
02006 {
02007 base = find_replacement (&XEXP (ref, 0));
02008
02009 if (! memory_address_p (GET_MODE (ref), base))
02010 abort ();
02011 }
02012 else
02013 {
02014 base = XEXP (ref, 0);
02015 }
02016
02017 if (GET_CODE (base) == PLUS)
02018 offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
02019
02020 *paligned_mem
02021 = widen_memory_access (ref, SImode, (offset & ~3) - offset);
02022
02023 if (WORDS_BIG_ENDIAN)
02024 *pbitnum = GEN_INT (32 - (GET_MODE_BITSIZE (GET_MODE (ref))
02025 + (offset & 3) * 8));
02026 else
02027 *pbitnum = GEN_INT ((offset & 3) * 8);
02028 }
02029
02030
02031
02032
02033 rtx
02034 get_unaligned_address (ref, extra_offset)
02035 rtx ref;
02036 int extra_offset;
02037 {
02038 rtx base;
02039 HOST_WIDE_INT offset = 0;
02040
02041 if (GET_CODE (ref) != MEM)
02042 abort ();
02043
02044 if (reload_in_progress
02045 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
02046 {
02047 base = find_replacement (&XEXP (ref, 0));
02048
02049 if (! memory_address_p (GET_MODE (ref), base))
02050 abort ();
02051 }
02052 else
02053 {
02054 base = XEXP (ref, 0);
02055 }
02056
02057 if (GET_CODE (base) == PLUS)
02058 offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
02059
02060 return plus_constant (base, offset + extra_offset);
02061 }
02062
02063
02064
02065
02066
02067
02068 enum reg_class
02069 alpha_preferred_reload_class(x, class)
02070 rtx x;
02071 enum reg_class class;
02072 {
02073
02074 if (x == CONST0_RTX (GET_MODE (x)))
02075 return class;
02076
02077
02078 if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
02079 {
02080 if (class == FLOAT_REGS)
02081 return NO_REGS;
02082 if (class == ALL_REGS)
02083 return GENERAL_REGS;
02084 return class;
02085 }
02086
02087
02088
02089
02090 if (CONSTANT_P (x))
02091 return (class == ALL_REGS ? GENERAL_REGS : class);
02092
02093 return class;
02094 }
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107 enum reg_class
02108 secondary_reload_class (class, mode, x, in)
02109 enum reg_class class;
02110 enum machine_mode mode;
02111 rtx x;
02112 int in;
02113 {
02114 if ((mode == QImode || mode == HImode) && ! TARGET_BWX)
02115 {
02116 if (GET_CODE (x) == MEM
02117 || (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
02118 || (GET_CODE (x) == SUBREG
02119 && (GET_CODE (SUBREG_REG (x)) == MEM
02120 || (GET_CODE (SUBREG_REG (x)) == REG
02121 && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER))))
02122 {
02123 if (!in || !aligned_memory_operand(x, mode))
02124 return GENERAL_REGS;
02125 }
02126 }
02127
02128 if (class == FLOAT_REGS)
02129 {
02130 if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
02131 return GENERAL_REGS;
02132
02133 if (GET_CODE (x) == SUBREG
02134 && (GET_MODE_SIZE (GET_MODE (x))
02135 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
02136 return GENERAL_REGS;
02137
02138 if (in && INTEGRAL_MODE_P (mode)
02139 && ! (memory_operand (x, mode) || x == const0_rtx))
02140 return GENERAL_REGS;
02141 }
02142
02143 return NO_REGS;
02144 }
02145
02146
02147
02148
02149 static void
02150 alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
02151 rtx x;
02152 int in_struct_p, volatile_p, unchanging_p;
02153 {
02154 int i;
02155
02156 switch (GET_CODE (x))
02157 {
02158 case SEQUENCE:
02159 case PARALLEL:
02160 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
02161 alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
02162 unchanging_p);
02163 break;
02164
02165 case INSN:
02166 alpha_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p,
02167 unchanging_p);
02168 break;
02169
02170 case SET:
02171 alpha_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p,
02172 unchanging_p);
02173 alpha_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p,
02174 unchanging_p);
02175 break;
02176
02177 case MEM:
02178 MEM_IN_STRUCT_P (x) = in_struct_p;
02179 MEM_VOLATILE_P (x) = volatile_p;
02180 RTX_UNCHANGING_P (x) = unchanging_p;
02181
02182
02183
02184
02185
02186 break;
02187
02188 default:
02189 break;
02190 }
02191 }
02192
02193
02194
02195
02196
02197
02198
02199 void
02200 alpha_set_memflags (insn, ref)
02201 rtx insn;
02202 rtx ref;
02203 {
02204 int in_struct_p, volatile_p, unchanging_p;
02205
02206 if (GET_CODE (ref) != MEM)
02207 return;
02208
02209 in_struct_p = MEM_IN_STRUCT_P (ref);
02210 volatile_p = MEM_VOLATILE_P (ref);
02211 unchanging_p = RTX_UNCHANGING_P (ref);
02212
02213
02214
02215
02216 if (! in_struct_p && ! volatile_p && ! unchanging_p)
02217 return;
02218
02219 alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p);
02220 }
02221
02222
02223
02224
02225
02226
02227
02228 rtx
02229 alpha_emit_set_const (target, mode, c, n)
02230 rtx target;
02231 enum machine_mode mode;
02232 HOST_WIDE_INT c;
02233 int n;
02234 {
02235 rtx result = 0;
02236 rtx orig_target = target;
02237 int i;
02238
02239
02240
02241 if (no_new_pseudos && mode == SImode
02242 && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER
02243 && (result = alpha_emit_set_const_1 (target, mode, c, 1)) == 0)
02244 {
02245 target = gen_lowpart (DImode, target);
02246 mode = DImode;
02247 }
02248
02249
02250 for (i = 1; i <= n; i++)
02251 {
02252 result = alpha_emit_set_const_1 (target, mode, c, i);
02253 if (result)
02254 {
02255 rtx insn = get_last_insn ();
02256 rtx set = single_set (insn);
02257 if (! CONSTANT_P (SET_SRC (set)))
02258 set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c));
02259 break;
02260 }
02261 }
02262
02263
02264 if (result == target)
02265 result = orig_target;
02266
02267 return result;
02268 }
02269
02270
02271
02272 static rtx
02273 alpha_emit_set_const_1 (target, mode, c, n)
02274 rtx target;
02275 enum machine_mode mode;
02276 HOST_WIDE_INT c;
02277 int n;
02278 {
02279 HOST_WIDE_INT new;
02280 int i, bits;
02281
02282 rtx subtarget
02283 = (flag_expensive_optimizations && !no_new_pseudos ? 0 : target);
02284 rtx temp, insn;
02285
02286
02287
02288
02289
02290 if (HOST_BITS_PER_WIDE_INT != 64
02291 || c >> 31 == -1 || c >> 31 == 0)
02292 {
02293 HOST_WIDE_INT low = ((c & 0xffff) ^ 0x8000) - 0x8000;
02294 HOST_WIDE_INT tmp1 = c - low;
02295 HOST_WIDE_INT high = (((tmp1 >> 16) & 0xffff) ^ 0x8000) - 0x8000;
02296 HOST_WIDE_INT extra = 0;
02297
02298
02299
02300
02301 if ((high & 0x8000) != 0 && c >= 0)
02302 {
02303 extra = 0x4000;
02304 tmp1 -= 0x40000000;
02305 high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
02306 }
02307
02308 if (c == low || (low == 0 && extra == 0))
02309 {
02310
02311
02312
02313
02314
02315
02316 if (target == NULL)
02317 target = gen_reg_rtx (mode);
02318 emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
02319 return target;
02320 }
02321 else if (n >= 2 + (extra != 0))
02322 {
02323 temp = copy_to_suggested_reg (GEN_INT (high << 16), subtarget, mode);
02324
02325
02326
02327
02328
02329
02330
02331 if (extra != 0)
02332 {
02333 if (! subtarget)
02334 subtarget = gen_reg_rtx (mode);
02335 insn = gen_rtx_PLUS (mode, temp, GEN_INT (extra << 16));
02336 insn = gen_rtx_SET (VOIDmode, subtarget, insn);
02337 emit_insn (insn);
02338 temp = subtarget;
02339 }
02340
02341 if (target == NULL)
02342 target = gen_reg_rtx (mode);
02343 insn = gen_rtx_PLUS (mode, temp, GEN_INT (low));
02344 insn = gen_rtx_SET (VOIDmode, target, insn);
02345 emit_insn (insn);
02346 return target;
02347 }
02348 }
02349
02350
02351
02352
02353
02354
02355 if (n == 1 || (mode == SImode && no_new_pseudos))
02356 return 0;
02357
02358
02359
02360
02361
02362 for (i = 1; i < n; i++)
02363 {
02364
02365
02366
02367 new = ((c & 0xffff) ^ 0x8000) - 0x8000;
02368 if (new != 0
02369 && (temp = alpha_emit_set_const (subtarget, mode, c - new, i)) != 0)
02370 return expand_binop (mode, add_optab, temp, GEN_INT (new),
02371 target, 0, OPTAB_WIDEN);
02372
02373
02374 if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0)
02375 return expand_unop (mode, one_cmpl_optab, temp, target, 0);
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386 if ((bits = exact_log2 (c & - c)) > 0)
02387 for (; bits > 0; bits--)
02388 if ((temp = (alpha_emit_set_const
02389 (subtarget, mode, c >> bits, i))) != 0
02390 || ((temp = (alpha_emit_set_const
02391 (subtarget, mode,
02392 ((unsigned HOST_WIDE_INT) c) >> bits, i)))
02393 != 0))
02394 return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
02395 target, 0, OPTAB_WIDEN);
02396
02397
02398
02399
02400
02401
02402
02403 if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
02404 - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0)
02405 for (; bits > 0; bits--)
02406 if ((temp = alpha_emit_set_const (subtarget, mode,
02407 c << bits, i)) != 0
02408 || ((temp = (alpha_emit_set_const
02409 (subtarget, mode,
02410 ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
02411 i)))
02412 != 0))
02413 return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
02414 target, 1, OPTAB_WIDEN);
02415
02416
02417
02418
02419
02420 if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
02421 - floor_log2 (~ c) - 2)) > 0)
02422 for (; bits > 0; bits--)
02423 if ((temp = alpha_emit_set_const (subtarget, mode,
02424 c << bits, i)) != 0
02425 || ((temp = (alpha_emit_set_const
02426 (subtarget, mode,
02427 ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
02428 i)))
02429 != 0))
02430 return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
02431 target, 0, OPTAB_WIDEN);
02432 }
02433
02434 #if HOST_BITS_PER_WIDE_INT == 64
02435
02436
02437
02438
02439 new = c;
02440 for (i = 0; i < 64; i += 8)
02441 if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
02442 new |= (HOST_WIDE_INT) 0xff << i;
02443
02444
02445
02446
02447 if (mode == SImode)
02448 new = ((new & 0xffffffff) ^ 0x80000000) - 0x80000000;
02449
02450 if (new != c && new != -1
02451 && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0)
02452 return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
02453 target, 0, OPTAB_WIDEN);
02454 #endif
02455
02456 return 0;
02457 }
02458
02459
02460
02461
02462
02463
02464 rtx
02465 alpha_emit_set_long_const (target, c1, c2)
02466 rtx target;
02467 HOST_WIDE_INT c1, c2;
02468 {
02469 HOST_WIDE_INT d1, d2, d3, d4;
02470
02471
02472 #if HOST_BITS_PER_WIDE_INT >= 64
02473 if (c2 != -(c1 < 0))
02474 abort ();
02475 d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02476 c1 -= d1;
02477 d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02478 c1 = (c1 - d2) >> 32;
02479 d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02480 c1 -= d3;
02481 d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02482 if (c1 != d4)
02483 abort ();
02484 #else
02485 d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02486 c1 -= d1;
02487 d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02488 if (c1 != d2)
02489 abort ();
02490 c2 += (d2 < 0);
02491 d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
02492 c2 -= d3;
02493 d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02494 if (c2 != d4)
02495 abort ();
02496 #endif
02497
02498
02499 if (d4)
02500 {
02501 emit_move_insn (target, GEN_INT (d4));
02502 if (d3)
02503 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3)));
02504 }
02505 else
02506 emit_move_insn (target, GEN_INT (d3));
02507
02508
02509 emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
02510
02511
02512 if (d2)
02513 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2)));
02514 if (d1)
02515 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1)));
02516
02517 return target;
02518 }
02519
02520
02521
02522
02523 bool
02524 alpha_expand_mov (mode, operands)
02525 enum machine_mode mode;
02526 rtx *operands;
02527 {
02528
02529 if (GET_CODE (operands[0]) == MEM
02530 && ! reg_or_0_operand (operands[1], mode))
02531 operands[1] = force_reg (mode, operands[1]);
02532
02533
02534 if (mode == Pmode && symbolic_operand (operands[1], mode))
02535 {
02536 rtx tmp;
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547 if (TARGET_EXPLICIT_RELOCS && flag_inline_functions
02548 && rtx_equal_function_value_matters
02549 && global_symbolic_operand (operands[1], mode))
02550 {
02551 emit_insn (gen_movdi_er_maybe_g (operands[0], operands[1]));
02552 return true;
02553 }
02554
02555 tmp = alpha_legitimize_address (operands[1], operands[0], mode);
02556 if (tmp)
02557 {
02558 operands[1] = tmp;
02559 return false;
02560 }
02561 }
02562
02563
02564 if (! CONSTANT_P (operands[1]) || input_operand (operands[1], mode))
02565 return false;
02566
02567
02568 if (GET_CODE (operands[1]) == CONST_INT
02569 || GET_CODE (operands[1]) == CONST_DOUBLE)
02570 {
02571 HOST_WIDE_INT i0, i1;
02572 rtx temp = NULL_RTX;
02573
02574 if (GET_CODE (operands[1]) == CONST_INT)
02575 {
02576 i0 = INTVAL (operands[1]);
02577 i1 = -(i0 < 0);
02578 }
02579 else if (HOST_BITS_PER_WIDE_INT >= 64)
02580 {
02581 i0 = CONST_DOUBLE_LOW (operands[1]);
02582 i1 = -(i0 < 0);
02583 }
02584 else
02585 {
02586 i0 = CONST_DOUBLE_LOW (operands[1]);
02587 i1 = CONST_DOUBLE_HIGH (operands[1]);
02588 }
02589
02590 if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0))
02591 temp = alpha_emit_set_const (operands[0], mode, i0, 3);
02592
02593 if (!temp && TARGET_BUILD_CONSTANTS)
02594 temp = alpha_emit_set_long_const (operands[0], i0, i1);
02595
02596 if (temp)
02597 {
02598 if (rtx_equal_p (operands[0], temp))
02599 return true;
02600 operands[1] = temp;
02601 return false;
02602 }
02603 }
02604
02605
02606 operands[1] = force_const_mem (DImode, operands[1]);
02607 if (reload_in_progress)
02608 {
02609 emit_move_insn (operands[0], XEXP (operands[1], 0));
02610 operands[1] = copy_rtx (operands[1]);
02611 XEXP (operands[1], 0) = operands[0];
02612 }
02613 else
02614 operands[1] = validize_mem (operands[1]);
02615 return false;
02616 }
02617
02618
02619
02620
02621 bool
02622 alpha_expand_mov_nobwx (mode, operands)
02623 enum machine_mode mode;
02624 rtx *operands;
02625 {
02626
02627 if (GET_CODE (operands[0]) == MEM)
02628 operands[1] = force_reg (mode, operands[1]);
02629
02630
02631
02632
02633
02634 if (GET_CODE (operands[1]) == MEM
02635 || (GET_CODE (operands[1]) == SUBREG
02636 && GET_CODE (SUBREG_REG (operands[1])) == MEM)
02637 || (reload_in_progress && GET_CODE (operands[1]) == REG
02638 && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
02639 || (reload_in_progress && GET_CODE (operands[1]) == SUBREG
02640 && GET_CODE (SUBREG_REG (operands[1])) == REG
02641 && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
02642 {
02643 if (aligned_memory_operand (operands[1], mode))
02644 {
02645 if (reload_in_progress)
02646 {
02647 emit_insn ((mode == QImode
02648 ? gen_reload_inqi_help
02649 : gen_reload_inhi_help)
02650 (operands[0], operands[1],
02651 gen_rtx_REG (SImode, REGNO (operands[0]))));
02652 }
02653 else
02654 {
02655 rtx aligned_mem, bitnum;
02656 rtx scratch = gen_reg_rtx (SImode);
02657
02658 get_aligned_mem (operands[1], &aligned_mem, &bitnum);
02659
02660 emit_insn ((mode == QImode
02661 ? gen_aligned_loadqi
02662 : gen_aligned_loadhi)
02663 (operands[0], aligned_mem, bitnum, scratch));
02664 }
02665 }
02666 else
02667 {
02668
02669
02670
02671
02672 rtx temp1 = gen_reg_rtx (DImode);
02673 rtx temp2 = gen_reg_rtx (DImode);
02674 rtx seq = ((mode == QImode
02675 ? gen_unaligned_loadqi
02676 : gen_unaligned_loadhi)
02677 (operands[0], get_unaligned_address (operands[1], 0),
02678 temp1, temp2));
02679
02680 alpha_set_memflags (seq, operands[1]);
02681 emit_insn (seq);
02682 }
02683 return true;
02684 }
02685
02686 if (GET_CODE (operands[0]) == MEM
02687 || (GET_CODE (operands[0]) == SUBREG
02688 && GET_CODE (SUBREG_REG (operands[0])) == MEM)
02689 || (reload_in_progress && GET_CODE (operands[0]) == REG
02690 && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
02691 || (reload_in_progress && GET_CODE (operands[0]) == SUBREG
02692 && GET_CODE (SUBREG_REG (operands[0])) == REG
02693 && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
02694 {
02695 if (aligned_memory_operand (operands[0], mode))
02696 {
02697 rtx aligned_mem, bitnum;
02698 rtx temp1 = gen_reg_rtx (SImode);
02699 rtx temp2 = gen_reg_rtx (SImode);
02700
02701 get_aligned_mem (operands[0], &aligned_mem, &bitnum);
02702
02703 emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
02704 temp1, temp2));
02705 }
02706 else
02707 {
02708 rtx temp1 = gen_reg_rtx (DImode);
02709 rtx temp2 = gen_reg_rtx (DImode);
02710 rtx temp3 = gen_reg_rtx (DImode);
02711 rtx seq = ((mode == QImode
02712 ? gen_unaligned_storeqi
02713 : gen_unaligned_storehi)
02714 (get_unaligned_address (operands[0], 0),
02715 operands[1], temp1, temp2, temp3));
02716
02717 alpha_set_memflags (seq, operands[0]);
02718 emit_insn (seq);
02719 }
02720 return true;
02721 }
02722
02723 return false;
02724 }
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776 void
02777 alpha_emit_floatuns (operands)
02778 rtx operands[2];
02779 {
02780 rtx neglab, donelab, i0, i1, f0, in, out;
02781 enum machine_mode mode;
02782
02783 out = operands[0];
02784 in = force_reg (DImode, operands[1]);
02785 mode = GET_MODE (out);
02786 neglab = gen_label_rtx ();
02787 donelab = gen_label_rtx ();
02788 i0 = gen_reg_rtx (DImode);
02789 i1 = gen_reg_rtx (DImode);
02790 f0 = gen_reg_rtx (mode);
02791
02792 emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
02793
02794 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
02795 emit_jump_insn (gen_jump (donelab));
02796 emit_barrier ();
02797
02798 emit_label (neglab);
02799
02800 emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
02801 emit_insn (gen_anddi3 (i1, in, const1_rtx));
02802 emit_insn (gen_iordi3 (i0, i0, i1));
02803 emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
02804 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
02805
02806 emit_label (donelab);
02807 }
02808
02809
02810
02811 rtx
02812 alpha_emit_conditional_branch (code)
02813 enum rtx_code code;
02814 {
02815 enum rtx_code cmp_code, branch_code;
02816 enum machine_mode cmp_mode, branch_mode = VOIDmode;
02817 rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
02818 rtx tem;
02819
02820 if (alpha_compare.fp_p && GET_MODE (op0) == TFmode)
02821 {
02822 if (! TARGET_HAS_XFLOATING_LIBS)
02823 abort ();
02824
02825
02826
02827
02828
02829
02830
02831 switch (code)
02832 {
02833 case UNORDERED:
02834 cmp_code = EQ;
02835 code = LT;
02836 break;
02837 case ORDERED:
02838 cmp_code = EQ;
02839 code = GE;
02840 break;
02841 case NE:
02842 cmp_code = NE;
02843 code = NE;
02844 break;
02845 default:
02846 cmp_code = code;
02847 code = GT;
02848 break;
02849 }
02850
02851 op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
02852 op1 = const0_rtx;
02853 alpha_compare.fp_p = 0;
02854 }
02855
02856
02857
02858 switch (code)
02859 {
02860 case EQ: case LE: case LT: case LEU: case LTU:
02861 case UNORDERED:
02862
02863 cmp_code = code, branch_code = NE;
02864 break;
02865
02866 case NE:
02867 case ORDERED:
02868
02869 cmp_code = reverse_condition (code), branch_code = EQ;
02870 break;
02871
02872 case GE: case GT: case GEU: case GTU:
02873
02874 if (alpha_compare.fp_p)
02875 {
02876 cmp_code = swap_condition (code);
02877 branch_code = NE;
02878 tem = op0, op0 = op1, op1 = tem;
02879 }
02880 else
02881 {
02882 cmp_code = reverse_condition (code);
02883 branch_code = EQ;
02884 }
02885 break;
02886
02887 default:
02888 abort ();
02889 }
02890
02891 if (alpha_compare.fp_p)
02892 {
02893 cmp_mode = DFmode;
02894 if (flag_unsafe_math_optimizations)
02895 {
02896
02897
02898 if (op1 == CONST0_RTX (DFmode))
02899 cmp_code = NIL, branch_code = code;
02900 else if (op0 == CONST0_RTX (DFmode))
02901 {
02902
02903 tem = op0, op0 = op1, op1 = tem;
02904 branch_code = swap_condition (cmp_code);
02905 cmp_code = NIL;
02906 }
02907 }
02908 else
02909 {
02910
02911
02912
02913 branch_mode = CCmode;
02914 }
02915 }
02916 else
02917 {
02918 cmp_mode = DImode;
02919
02920
02921 if (code != LEU && code != LTU && code != GEU && code != GTU)
02922 {
02923
02924 if (op1 == const0_rtx)
02925 cmp_code = NIL, branch_code = code;
02926
02927
02928
02929
02930 else if (GET_CODE (op1) == CONST_INT)
02931 {
02932 HOST_WIDE_INT v = INTVAL (op1), n = -v;
02933
02934 if (! CONST_OK_FOR_LETTER_P (v, 'I')
02935 && (CONST_OK_FOR_LETTER_P (n, 'K')
02936 || CONST_OK_FOR_LETTER_P (n, 'L')))
02937 {
02938 cmp_code = PLUS, branch_code = code;
02939 op1 = GEN_INT (n);
02940 }
02941 }
02942 }
02943
02944 if (!reg_or_0_operand (op0, DImode))
02945 op0 = force_reg (DImode, op0);
02946 if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
02947 op1 = force_reg (DImode, op1);
02948 }
02949
02950
02951 tem = op0;
02952 if (cmp_code != NIL)
02953 {
02954 tem = gen_reg_rtx (cmp_mode);
02955 emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1));
02956 }
02957
02958
02959 memset (&alpha_compare, 0, sizeof (alpha_compare));
02960
02961
02962 return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
02963 }
02964
02965
02966
02967
02968 rtx
02969 alpha_emit_setcc (code)
02970 enum rtx_code code;
02971 {
02972 enum rtx_code cmp_code;
02973 rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
02974 int fp_p = alpha_compare.fp_p;
02975 rtx tmp;
02976
02977
02978 memset (&alpha_compare, 0, sizeof (alpha_compare));
02979
02980 if (fp_p && GET_MODE (op0) == TFmode)
02981 {
02982 if (! TARGET_HAS_XFLOATING_LIBS)
02983 abort ();
02984
02985
02986
02987
02988
02989
02990
02991 if (code == UNORDERED || code == ORDERED)
02992 cmp_code = EQ;
02993 else
02994 cmp_code = code;
02995
02996 op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
02997 op1 = const0_rtx;
02998 fp_p = 0;
02999
03000 if (code == UNORDERED)
03001 code = LT;
03002 else if (code == ORDERED)
03003 code = GE;
03004 else
03005 code = GT;
03006 }
03007
03008 if (fp_p && !TARGET_FIX)
03009 return NULL_RTX;
03010
03011
03012
03013
03014 cmp_code = NIL;
03015 switch (code)
03016 {
03017 case EQ: case LE: case LT: case LEU: case LTU:
03018 case UNORDERED:
03019
03020 if (fp_p)
03021 cmp_code = code, code = NE;
03022 break;
03023
03024 case NE:
03025 if (!fp_p && op1 == const0_rtx)
03026 break;
03027
03028
03029 case ORDERED:
03030 cmp_code = reverse_condition (code);
03031 code = EQ;
03032 break;
03033
03034 case GE: case GT: case GEU: case GTU:
03035
03036
03037 if (!fp_p && op1 == const0_rtx)
03038 break;
03039 code = swap_condition (code);
03040 if (fp_p)
03041 cmp_code = code, code = NE;
03042 tmp = op0, op0 = op1, op1 = tmp;
03043 break;
03044
03045 default:
03046 abort ();
03047 }
03048
03049 if (!fp_p)
03050 {
03051 if (!register_operand (op0, DImode))
03052 op0 = force_reg (DImode, op0);
03053 if (!reg_or_8bit_operand (op1, DImode))
03054 op1 = force_reg (DImode, op1);
03055 }
03056
03057
03058 if (cmp_code != NIL)
03059 {
03060 enum machine_mode mode = fp_p ? DFmode : DImode;
03061
03062 tmp = gen_reg_rtx (mode);
03063 emit_insn (gen_rtx_SET (VOIDmode, tmp,
03064 gen_rtx_fmt_ee (cmp_code, mode, op0, op1)));
03065
03066 op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp;
03067 op1 = const0_rtx;
03068 }
03069
03070
03071 return gen_rtx_fmt_ee (code, DImode, op0, op1);
03072 }
03073
03074
03075
03076
03077
03078
03079
03080
03081 rtx
03082 alpha_emit_conditional_move (cmp, mode)
03083 rtx cmp;
03084 enum machine_mode mode;
03085 {
03086 enum rtx_code code = GET_CODE (cmp);
03087 enum rtx_code cmov_code = NE;
03088 rtx op0 = alpha_compare.op0;
03089 rtx op1 = alpha_compare.op1;
03090 int fp_p = alpha_compare.fp_p;
03091 enum machine_mode cmp_mode
03092 = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
03093 enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
03094 enum machine_mode cmov_mode = VOIDmode;
03095 int local_fast_math = flag_unsafe_math_optimizations;
03096 rtx tem;
03097
03098
03099 memset (&alpha_compare, 0, sizeof (alpha_compare));
03100
03101 if (fp_p != FLOAT_MODE_P (mode))
03102 {
03103 enum rtx_code cmp_code;
03104
03105 if (! TARGET_FIX)
03106 return 0;
03107
03108
03109
03110
03111
03112
03113 switch (code)
03114 {
03115 case EQ: case LE: case LT: case LEU: case LTU:
03116
03117 cmp_code = code, code = NE;
03118 break;
03119
03120 case NE:
03121
03122 cmp_code = EQ, code = EQ;
03123 break;
03124
03125 case GE: case GT: case GEU: case GTU:
03126
03127
03128 if (!fp_p && op1 == const0_rtx)
03129 cmp_code = code, code = NE;
03130 else
03131 {
03132 cmp_code = swap_condition (code);
03133 code = NE;
03134 tem = op0, op0 = op1, op1 = tem;
03135 }
03136 break;
03137
03138 default:
03139 abort ();
03140 }
03141
03142 tem = gen_reg_rtx (cmp_op_mode);
03143 emit_insn (gen_rtx_SET (VOIDmode, tem,
03144 gen_rtx_fmt_ee (cmp_code, cmp_op_mode,
03145 op0, op1)));
03146
03147 cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode;
03148 op0 = gen_lowpart (cmp_op_mode, tem);
03149 op1 = CONST0_RTX (cmp_op_mode);
03150 fp_p = !fp_p;
03151 local_fast_math = 1;
03152 }
03153
03154
03155
03156 if (signed_comparison_operator (cmp, VOIDmode)
03157 && (!fp_p || local_fast_math)
03158 && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
03159 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
03160
03161
03162
03163
03164
03165
03166 if (no_new_pseudos)
03167 return NULL_RTX;
03168
03169 switch (code)
03170 {
03171 case EQ: case LE: case LT: case LEU: case LTU:
03172
03173 break;
03174
03175 case NE:
03176
03177 code = reverse_condition (code);
03178 cmov_code = EQ;
03179 break;
03180
03181 case GE: case GT: case GEU: case GTU:
03182
03183 if (op1 != CONST0_RTX (cmp_mode))
03184 {
03185 code = swap_condition (code);
03186 tem = op0, op0 = op1, op1 = tem;
03187 }
03188 break;
03189
03190 default:
03191 abort ();
03192 }
03193
03194 if (!fp_p)
03195 {
03196 if (!reg_or_0_operand (op0, DImode))
03197 op0 = force_reg (DImode, op0);
03198 if (!reg_or_8bit_operand (op1, DImode))
03199 op1 = force_reg (DImode, op1);
03200 }
03201
03202
03203
03204
03205 if (fp_p && !local_fast_math)
03206 cmov_mode = CCmode;
03207
03208 tem = gen_reg_rtx (cmp_op_mode);
03209 emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
03210 return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
03211 }
03212
03213
03214
03215
03216
03217
03218 int
03219 alpha_split_conditional_move (code, dest, cond, t_rtx, f_rtx)
03220 enum rtx_code code;
03221 rtx dest, cond, t_rtx, f_rtx;
03222 {
03223 HOST_WIDE_INT t, f, diff;
03224 enum machine_mode mode;
03225 rtx target, subtarget, tmp;
03226
03227 mode = GET_MODE (dest);
03228 t = INTVAL (t_rtx);
03229 f = INTVAL (f_rtx);
03230 diff = t - f;
03231
03232 if (((code == NE || code == EQ) && diff < 0)
03233 || (code == GE || code == GT))
03234 {
03235 code = reverse_condition (code);
03236 diff = t, t = f, f = diff;
03237 diff = t - f;
03238 }
03239
03240 subtarget = target = dest;
03241 if (mode != DImode)
03242 {
03243 target = gen_lowpart (DImode, dest);
03244 if (! no_new_pseudos)
03245 subtarget = gen_reg_rtx (DImode);
03246 else
03247 subtarget = target;
03248 }
03249
03250
03251
03252
03253 if (f == 0 && exact_log2 (diff) > 0
03254
03255
03256
03257 && (diff <= 8 || alpha_cpu == PROCESSOR_EV6))
03258 {
03259 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
03260 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
03261
03262 tmp = gen_rtx_ASHIFT (DImode, copy_rtx (subtarget),
03263 GEN_INT (exact_log2 (t)));
03264 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
03265 }
03266 else if (f == 0 && t == -1)
03267 {
03268 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
03269 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
03270
03271 emit_insn (gen_negdi2 (target, copy_rtx (subtarget)));
03272 }
03273 else if (diff == 1 || diff == 4 || diff == 8)
03274 {
03275 rtx add_op;
03276
03277 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
03278 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
03279
03280 if (diff == 1)
03281 emit_insn (gen_adddi3 (target, copy_rtx (subtarget), GEN_INT (f)));
03282 else
03283 {
03284 add_op = GEN_INT (f);
03285 if (sext_add_operand (add_op, mode))
03286 {
03287 tmp = gen_rtx_MULT (DImode, copy_rtx (subtarget),
03288 GEN_INT (diff));
03289 tmp = gen_rtx_PLUS (DImode, tmp, add_op);
03290 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
03291 }
03292 else
03293 return 0;
03294 }
03295 }
03296 else
03297 return 0;
03298
03299 return 1;
03300 }
03301
03302
03303
03304
03305 static const char *
03306 alpha_lookup_xfloating_lib_func (code)
03307 enum rtx_code code;
03308 {
03309 struct xfloating_op
03310 {
03311 const enum rtx_code code;
03312 const char *const func;
03313 };
03314
03315 static const struct xfloating_op vms_xfloating_ops[] =
03316 {
03317 { PLUS, "OTS$ADD_X" },
03318 { MINUS, "OTS$SUB_X" },
03319 { MULT, "OTS$MUL_X" },
03320 { DIV, "OTS$DIV_X" },
03321 { EQ, "OTS$EQL_X" },
03322 { NE, "OTS$NEQ_X" },
03323 { LT, "OTS$LSS_X" },
03324 { LE, "OTS$LEQ_X" },
03325 { GT, "OTS$GTR_X" },
03326 { GE, "OTS$GEQ_X" },
03327 { FIX, "OTS$CVTXQ" },
03328 { FLOAT, "OTS$CVTQX" },
03329 { UNSIGNED_FLOAT, "OTS$CVTQUX" },
03330 { FLOAT_EXTEND, "OTS$CVT_FLOAT_T_X" },
03331 { FLOAT_TRUNCATE, "OTS$CVT_FLOAT_X_T" },
03332 };
03333
03334 static const struct xfloating_op osf_xfloating_ops[] =
03335 {
03336 { PLUS, "_OtsAddX" },
03337 { MINUS, "_OtsSubX" },
03338 { MULT, "_OtsMulX" },
03339 { DIV, "_OtsDivX" },
03340 { EQ, "_OtsEqlX" },
03341 { NE, "_OtsNeqX" },
03342 { LT, "_OtsLssX" },
03343 { LE, "_OtsLeqX" },
03344 { GT, "_OtsGtrX" },
03345 { GE, "_OtsGeqX" },
03346 { FIX, "_OtsCvtXQ" },
03347 { FLOAT, "_OtsCvtQX" },
03348 { UNSIGNED_FLOAT, "_OtsCvtQUX" },
03349 { FLOAT_EXTEND, "_OtsConvertFloatTX" },
03350 { FLOAT_TRUNCATE, "_OtsConvertFloatXT" },
03351 };
03352
03353 const struct xfloating_op *ops;
03354 const long n = ARRAY_SIZE (osf_xfloating_ops);
03355 long i;
03356
03357
03358
03359 if (TARGET_FLOAT_VAX)
03360 {
03361 if (TARGET_ABI_OPEN_VMS)
03362 {
03363 if (code == FLOAT_EXTEND)
03364 return "OTS$CVT_FLOAT_G_X";
03365 if (code == FLOAT_TRUNCATE)
03366 return "OTS$CVT_FLOAT_X_G";
03367 }
03368 else
03369 {
03370 if (code == FLOAT_EXTEND)
03371 return "_OtsConvertFloatGX";
03372 if (code == FLOAT_TRUNCATE)
03373 return "_OtsConvertFloatXG";
03374 }
03375 }
03376
03377 if (TARGET_ABI_OPEN_VMS)
03378 ops = vms_xfloating_ops;
03379 else
03380 ops = osf_xfloating_ops;
03381
03382 for (i = 0; i < n; ++i)
03383 if (ops[i].code == code)
03384 return ops[i].func;
03385
03386 abort();
03387 }
03388
03389
03390
03391
03392 static int
03393 alpha_compute_xfloating_mode_arg (code, round)
03394 enum rtx_code code;
03395 enum alpha_fp_rounding_mode round;
03396 {
03397 int mode;
03398
03399 switch (round)
03400 {
03401 case ALPHA_FPRM_NORM:
03402 mode = 2;
03403 break;
03404 case ALPHA_FPRM_MINF:
03405 mode = 1;
03406 break;
03407 case ALPHA_FPRM_CHOP:
03408 mode = 0;
03409 break;
03410 case ALPHA_FPRM_DYN:
03411 mode = 4;
03412 break;
03413 default:
03414 abort ();
03415
03416
03417 }
03418
03419 if (code == FLOAT_TRUNCATE && alpha_fptm == ALPHA_FPTM_N)
03420 mode |= 0x10000;
03421
03422 return mode;
03423 }
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438 static void
03439 alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv)
03440 const char *func;
03441 rtx target;
03442 rtx operands[];
03443 int noperands;
03444 rtx equiv;
03445 {
03446 rtx usage = NULL_RTX, tmp, reg;
03447 int regno = 16, i;
03448
03449 start_sequence ();
03450
03451 for (i = 0; i < noperands; ++i)
03452 {
03453 switch (GET_MODE (operands[i]))
03454 {
03455 case TFmode:
03456 reg = gen_rtx_REG (TFmode, regno);
03457 regno += 2;
03458 break;
03459
03460 case DFmode:
03461 reg = gen_rtx_REG (DFmode, regno + 32);
03462 regno += 1;
03463 break;
03464
03465 case VOIDmode:
03466 if (GET_CODE (operands[i]) != CONST_INT)
03467 abort ();
03468
03469 case DImode:
03470 reg = gen_rtx_REG (DImode, regno);
03471 regno += 1;
03472 break;
03473
03474 default:
03475 abort ();
03476 }
03477
03478 emit_move_insn (reg, operands[i]);
03479 usage = alloc_EXPR_LIST (0, gen_rtx_USE (VOIDmode, reg), usage);
03480 }
03481
03482 switch (GET_MODE (target))
03483 {
03484 case TFmode:
03485 reg = gen_rtx_REG (TFmode, 16);
03486 break;
03487 case DFmode:
03488 reg = gen_rtx_REG (DFmode, 32);
03489 break;
03490 case DImode:
03491 reg = gen_rtx_REG (DImode, 0);
03492 break;
03493 default:
03494 abort ();
03495 }
03496
03497 tmp = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, (char *) func));
03498 tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
03499 const0_rtx, const0_rtx));
03500 CALL_INSN_FUNCTION_USAGE (tmp) = usage;
03501
03502 tmp = get_insns ();
03503 end_sequence ();
03504
03505 emit_libcall_block (tmp, target, reg, equiv);
03506 }
03507
03508
03509
03510 void
03511 alpha_emit_xfloating_arith (code, operands)
03512 enum rtx_code code;
03513 rtx operands[];
03514 {
03515 const char *func;
03516 int mode;
03517 rtx out_operands[3];
03518
03519 func = alpha_lookup_xfloating_lib_func (code);
03520 mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
03521
03522 out_operands[0] = operands[1];
03523 out_operands[1] = operands[2];
03524 out_operands[2] = GEN_INT (mode);
03525 alpha_emit_xfloating_libcall (func, operands[0], out_operands, 3,
03526 gen_rtx_fmt_ee (code, TFmode, operands[1],
03527 operands[2]));
03528 }
03529
03530
03531
03532 static rtx
03533 alpha_emit_xfloating_compare (code, op0, op1)
03534 enum rtx_code code;
03535 rtx op0, op1;
03536 {
03537 const char *func;
03538 rtx out, operands[2];
03539
03540 func = alpha_lookup_xfloating_lib_func (code);
03541
03542 operands[0] = op0;
03543 operands[1] = op1;
03544 out = gen_reg_rtx (DImode);
03545
03546
03547
03548 alpha_emit_xfloating_libcall (func, out, operands, 2,
03549 gen_rtx_fmt_ee (code, CCmode, op0, op1));
03550
03551 return out;
03552 }
03553
03554
03555
03556 void
03557 alpha_emit_xfloating_cvt (code, operands)
03558 enum rtx_code code;
03559 rtx operands[];
03560 {
03561 int noperands = 1, mode;
03562 rtx out_operands[2];
03563 const char *func;
03564
03565 func = alpha_lookup_xfloating_lib_func (code);
03566
03567 out_operands[0] = operands[1];
03568
03569 switch (code)
03570 {
03571 case FIX:
03572 mode = alpha_compute_xfloating_mode_arg (code, ALPHA_FPRM_CHOP);
03573 out_operands[1] = GEN_INT (mode);
03574 noperands = 2;
03575 break;
03576 case FLOAT_TRUNCATE:
03577 mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
03578 out_operands[1] = GEN_INT (mode);
03579 noperands = 2;
03580 break;
03581 default:
03582 break;
03583 }
03584
03585 alpha_emit_xfloating_libcall (func, operands[0], out_operands, noperands,
03586 gen_rtx_fmt_e (code, GET_MODE (operands[0]),
03587 operands[1]));
03588 }
03589
03590
03591
03592
03593
03594 void
03595 alpha_split_tfmode_pair (operands)
03596 rtx operands[4];
03597 {
03598 if (GET_CODE (operands[1]) == REG)
03599 {
03600 operands[3] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
03601 operands[2] = gen_rtx_REG (DImode, REGNO (operands[1]));
03602 }
03603 else if (GET_CODE (operands[1]) == MEM)
03604 {
03605 operands[3] = adjust_address (operands[1], DImode, 8);
03606 operands[2] = adjust_address (operands[1], DImode, 0);
03607 }
03608 else if (operands[1] == CONST0_RTX (TFmode))
03609 operands[2] = operands[3] = const0_rtx;
03610 else
03611 abort ();
03612
03613 if (GET_CODE (operands[0]) == REG)
03614 {
03615 operands[1] = gen_rtx_REG (DImode, REGNO (operands[0]) + 1);
03616 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
03617 }
03618 else if (GET_CODE (operands[0]) == MEM)
03619 {
03620 operands[1] = adjust_address (operands[0], DImode, 8);
03621 operands[0] = adjust_address (operands[0], DImode, 0);
03622 }
03623 else
03624 abort ();
03625 }
03626
03627
03628
03629
03630
03631 void
03632 alpha_split_tfmode_frobsign (operands, operation)
03633 rtx operands[3];
03634 rtx (*operation) PARAMS ((rtx, rtx, rtx));
03635 {
03636 rtx high_bit = operands[2];
03637 rtx scratch;
03638 int move;
03639
03640 alpha_split_tfmode_pair (operands);
03641
03642
03643 move = 1;
03644 if (rtx_equal_p (operands[0], operands[2]))
03645 move = 0;
03646 else if (rtx_equal_p (operands[1], operands[2]))
03647 {
03648 if (rtx_equal_p (operands[0], high_bit))
03649 move = 2;
03650 else
03651 move = -1;
03652 }
03653
03654 if (move < 0)
03655 emit_move_insn (operands[0], operands[2]);
03656
03657
03658
03659
03660
03661 scratch = operands[move < 2 ? 1 : 3];
03662
03663 emit_insn ((*operation) (scratch, high_bit, operands[3]));
03664
03665 if (move > 0)
03666 {
03667 emit_move_insn (operands[0], operands[2]);
03668 if (move > 1)
03669 emit_move_insn (operands[1], scratch);
03670 }
03671 }
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700 void
03701 alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
03702 rtx tgt, mem;
03703 HOST_WIDE_INT size, ofs;
03704 int sign;
03705 {
03706 rtx meml, memh, addr, extl, exth, tmp, mema;
03707 enum machine_mode mode;
03708
03709 meml = gen_reg_rtx (DImode);
03710 memh = gen_reg_rtx (DImode);
03711 addr = gen_reg_rtx (DImode);
03712 extl = gen_reg_rtx (DImode);
03713 exth = gen_reg_rtx (DImode);
03714
03715 mema = XEXP (mem, 0);
03716 if (GET_CODE (mema) == LO_SUM)
03717 mema = force_reg (Pmode, mema);
03718
03719
03720
03721
03722
03723 tmp = change_address (mem, DImode,
03724 gen_rtx_AND (DImode,
03725 plus_constant (mema, ofs),
03726 GEN_INT (-8)));
03727 set_mem_alias_set (tmp, 0);
03728 emit_move_insn (meml, tmp);
03729
03730 tmp = change_address (mem, DImode,
03731 gen_rtx_AND (DImode,
03732 plus_constant (mema, ofs + size - 1),
03733 GEN_INT (-8)));
03734 set_mem_alias_set (tmp, 0);
03735 emit_move_insn (memh, tmp);
03736
03737 if (WORDS_BIG_ENDIAN && sign && (size == 2 || size == 4))
03738 {
03739 emit_move_insn (addr, plus_constant (mema, -1));
03740
03741 emit_insn (gen_extqh_be (extl, meml, addr));
03742 emit_insn (gen_extxl_be (exth, memh, GEN_INT (64), addr));
03743
03744 addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
03745 addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (64 - size*8),
03746 addr, 1, OPTAB_WIDEN);
03747 }
03748 else if (sign && size == 2)
03749 {
03750 emit_move_insn (addr, plus_constant (mema, ofs+2));
03751
03752 emit_insn (gen_extxl_le (extl, meml, GEN_INT (64), addr));
03753 emit_insn (gen_extqh_le (exth, memh, addr));
03754
03755
03756
03757
03758 addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
03759 addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48),
03760 addr, 1, OPTAB_WIDEN);
03761 }
03762 else
03763 {
03764 if (WORDS_BIG_ENDIAN)
03765 {
03766 emit_move_insn (addr, plus_constant (mema, ofs+size-1));
03767 switch ((int) size)
03768 {
03769 case 2:
03770 emit_insn (gen_extwh_be (extl, meml, addr));
03771 mode = HImode;
03772 break;
03773
03774 case 4:
03775 emit_insn (gen_extlh_be (extl, meml, addr));
03776 mode = SImode;
03777 break;
03778
03779 case 8:
03780 emit_insn (gen_extqh_be (extl, meml, addr));
03781 mode = DImode;
03782 break;
03783
03784 default:
03785 abort ();
03786 }
03787 emit_insn (gen_extxl_be (exth, memh, GEN_INT (size*8), addr));
03788 }
03789 else
03790 {
03791 emit_move_insn (addr, plus_constant (mema, ofs));
03792 emit_insn (gen_extxl_le (extl, meml, GEN_INT (size*8), addr));
03793 switch ((int) size)
03794 {
03795 case 2:
03796 emit_insn (gen_extwh_le (exth, memh, addr));
03797 mode = HImode;
03798 break;
03799
03800 case 4:
03801 emit_insn (gen_extlh_le (exth, memh, addr));
03802 mode = SImode;
03803 break;
03804
03805 case 8:
03806 emit_insn (gen_extqh_le (exth, memh, addr));
03807 mode = DImode;
03808 break;
03809
03810 default:
03811 abort();
03812 }
03813 }
03814
03815 addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
03816 gen_lowpart (mode, exth), gen_lowpart (mode, tgt),
03817 sign, OPTAB_WIDEN);
03818 }
03819
03820 if (addr != tgt)
03821 emit_move_insn (tgt, gen_lowpart(GET_MODE (tgt), addr));
03822 }
03823
03824
03825
03826 void
03827 alpha_expand_unaligned_store (dst, src, size, ofs)
03828 rtx dst, src;
03829 HOST_WIDE_INT size, ofs;
03830 {
03831 rtx dstl, dsth, addr, insl, insh, meml, memh, dsta;
03832
03833 dstl = gen_reg_rtx (DImode);
03834 dsth = gen_reg_rtx (DImode);
03835 insl = gen_reg_rtx (DImode);
03836 insh = gen_reg_rtx (DImode);
03837
03838 dsta = XEXP (dst, 0);
03839 if (GET_CODE (dsta) == LO_SUM)
03840 dsta = force_reg (Pmode, dsta);
03841
03842
03843
03844
03845
03846 meml = change_address (dst, DImode,
03847 gen_rtx_AND (DImode,
03848 plus_constant (dsta, ofs),
03849 GEN_INT (-8)));
03850 set_mem_alias_set (meml, 0);
03851
03852 memh = change_address (dst, DImode,
03853 gen_rtx_AND (DImode,
03854 plus_constant (dsta, ofs + size - 1),
03855 GEN_INT (-8)));
03856 set_mem_alias_set (memh, 0);
03857
03858 emit_move_insn (dsth, memh);
03859 emit_move_insn (dstl, meml);
03860 if (WORDS_BIG_ENDIAN)
03861 {
03862 addr = copy_addr_to_reg (plus_constant (dsta, ofs+size-1));
03863
03864 if (src != const0_rtx)
03865 {
03866 switch ((int) size)
03867 {
03868 case 2:
03869 emit_insn (gen_inswl_be (insh, gen_lowpart (HImode,src), addr));
03870 break;
03871 case 4:
03872 emit_insn (gen_insll_be (insh, gen_lowpart (SImode,src), addr));
03873 break;
03874 case 8:
03875 emit_insn (gen_insql_be (insh, gen_lowpart (DImode,src), addr));
03876 break;
03877 }
03878 emit_insn (gen_insxh (insl, gen_lowpart (DImode, src),
03879 GEN_INT (size*8), addr));
03880 }
03881
03882 switch ((int) size)
03883 {
03884 case 2:
03885 emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
03886 break;
03887 case 4:
03888 emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffffffff), addr));
03889 break;
03890 case 8:
03891 {
03892 #if HOST_BITS_PER_WIDE_INT == 32
03893 rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
03894 #else
03895 rtx msk = constm1_rtx;
03896 #endif
03897 emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
03898 }
03899 break;
03900 }
03901
03902 emit_insn (gen_mskxh (dstl, dstl, GEN_INT (size*8), addr));
03903 }
03904 else
03905 {
03906 addr = copy_addr_to_reg (plus_constant (dsta, ofs));
03907
03908 if (src != const0_rtx)
03909 {
03910 emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
03911 GEN_INT (size*8), addr));
03912
03913 switch ((int) size)
03914 {
03915 case 2:
03916 emit_insn (gen_inswl_le (insl, gen_lowpart (HImode, src), addr));
03917 break;
03918 case 4:
03919 emit_insn (gen_insll_le (insl, gen_lowpart (SImode, src), addr));
03920 break;
03921 case 8:
03922 emit_insn (gen_insql_le (insl, src, addr));
03923 break;
03924 }
03925 }
03926
03927 emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
03928
03929 switch ((int) size)
03930 {
03931 case 2:
03932 emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
03933 break;
03934 case 4:
03935 emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffffffff), addr));
03936 break;
03937 case 8:
03938 {
03939 #if HOST_BITS_PER_WIDE_INT == 32
03940 rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
03941 #else
03942 rtx msk = constm1_rtx;
03943 #endif
03944 emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
03945 }
03946 break;
03947 }
03948 }
03949
03950 if (src != const0_rtx)
03951 {
03952 dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
03953 dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
03954 }
03955
03956 if (WORDS_BIG_ENDIAN)
03957 {
03958 emit_move_insn (meml, dstl);
03959 emit_move_insn (memh, dsth);
03960 }
03961 else
03962 {
03963
03964 emit_move_insn (memh, dsth);
03965 emit_move_insn (meml, dstl);
03966 }
03967 }
03968
03969
03970
03971
03972
03973
03974
03975 #define MAX_MOVE_WORDS 8
03976
03977
03978
03979 static void
03980 alpha_expand_unaligned_load_words (out_regs, smem, words, ofs)
03981 rtx *out_regs;
03982 rtx smem;
03983 HOST_WIDE_INT words, ofs;
03984 {
03985 rtx const im8 = GEN_INT (-8);
03986 rtx const i64 = GEN_INT (64);
03987 rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1];
03988 rtx sreg, areg, tmp, smema;
03989 HOST_WIDE_INT i;
03990
03991 smema = XEXP (smem, 0);
03992 if (GET_CODE (smema) == LO_SUM)
03993 smema = force_reg (Pmode, smema);
03994
03995
03996 for (i = 0; i < words; ++i)
03997 {
03998 data_regs[i] = out_regs[i];
03999 ext_tmps[i] = gen_reg_rtx (DImode);
04000 }
04001 data_regs[words] = gen_reg_rtx (DImode);
04002
04003 if (ofs != 0)
04004 smem = adjust_address (smem, GET_MODE (smem), ofs);
04005
04006
04007 for (i = 0; i < words; ++i)
04008 {
04009 tmp = change_address (smem, DImode,
04010 gen_rtx_AND (DImode,
04011 plus_constant (smema, 8*i),
04012 im8));
04013 set_mem_alias_set (tmp, 0);
04014 emit_move_insn (data_regs[i], tmp);
04015 }
04016
04017 tmp = change_address (smem, DImode,
04018 gen_rtx_AND (DImode,
04019 plus_constant (smema, 8*words - 1),
04020 im8));
04021 set_mem_alias_set (tmp, 0);
04022 emit_move_insn (data_regs[words], tmp);
04023
04024
04025
04026
04027
04028 sreg = copy_addr_to_reg (smema);
04029 areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL,
04030 1, OPTAB_WIDEN);
04031 if (WORDS_BIG_ENDIAN)
04032 emit_move_insn (sreg, plus_constant (sreg, 7));
04033 for (i = 0; i < words; ++i)
04034 {
04035 if (WORDS_BIG_ENDIAN)
04036 {
04037 emit_insn (gen_extqh_be (data_regs[i], data_regs[i], sreg));
04038 emit_insn (gen_extxl_be (ext_tmps[i], data_regs[i+1], i64, sreg));
04039 }
04040 else
04041 {
04042 emit_insn (gen_extxl_le (data_regs[i], data_regs[i], i64, sreg));
04043 emit_insn (gen_extqh_le (ext_tmps[i], data_regs[i+1], sreg));
04044 }
04045 emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
04046 gen_rtx_IF_THEN_ELSE (DImode,
04047 gen_rtx_EQ (DImode, areg,
04048 const0_rtx),
04049 const0_rtx, ext_tmps[i])));
04050 }
04051
04052
04053 for (i = 0; i < words; ++i)
04054 {
04055 out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i],
04056 ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN);
04057 }
04058 }
04059
04060
04061
04062
04063 static void
04064 alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
04065 rtx *data_regs;
04066 rtx dmem;
04067 HOST_WIDE_INT words, ofs;
04068 {
04069 rtx const im8 = GEN_INT (-8);
04070 rtx const i64 = GEN_INT (64);
04071 #if HOST_BITS_PER_WIDE_INT == 32
04072 rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode);
04073 #else
04074 rtx const im1 = constm1_rtx;
04075 #endif
04076 rtx ins_tmps[MAX_MOVE_WORDS];
04077 rtx st_tmp_1, st_tmp_2, dreg;
04078 rtx st_addr_1, st_addr_2, dmema;
04079 HOST_WIDE_INT i;
04080
04081 dmema = XEXP (dmem, 0);
04082 if (GET_CODE (dmema) == LO_SUM)
04083 dmema = force_reg (Pmode, dmema);
04084
04085
04086 if (data_regs != NULL)
04087 for (i = 0; i < words; ++i)
04088 ins_tmps[i] = gen_reg_rtx(DImode);
04089 st_tmp_1 = gen_reg_rtx(DImode);
04090 st_tmp_2 = gen_reg_rtx(DImode);
04091
04092 if (ofs != 0)
04093 dmem = adjust_address (dmem, GET_MODE (dmem), ofs);
04094
04095 st_addr_2 = change_address (dmem, DImode,
04096 gen_rtx_AND (DImode,
04097 plus_constant (dmema, words*8 - 1),
04098 im8));
04099 set_mem_alias_set (st_addr_2, 0);
04100
04101 st_addr_1 = change_address (dmem, DImode,
04102 gen_rtx_AND (DImode, dmema, im8));
04103 set_mem_alias_set (st_addr_1, 0);
04104
04105
04106 emit_move_insn (st_tmp_2, st_addr_2);
04107 emit_move_insn (st_tmp_1, st_addr_1);
04108
04109
04110 dreg = copy_addr_to_reg (dmema);
04111 if (WORDS_BIG_ENDIAN)
04112 emit_move_insn (dreg, plus_constant (dreg, 7));
04113 if (data_regs != NULL)
04114 {
04115 for (i = words-1; i >= 0; --i)
04116 {
04117 if (WORDS_BIG_ENDIAN)
04118 {
04119 emit_insn (gen_insql_be (ins_tmps[i], data_regs[i], dreg));
04120 emit_insn (gen_insxh (data_regs[i], data_regs[i], i64, dreg));
04121 }
04122 else
04123 {
04124 emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
04125 emit_insn (gen_insql_le (data_regs[i], data_regs[i], dreg));
04126 }
04127 }
04128 for (i = words-1; i > 0; --i)
04129 {
04130 ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i],
04131 ins_tmps[i-1], ins_tmps[i-1], 1,
04132 OPTAB_WIDEN);
04133 }
04134 }
04135
04136
04137 if (WORDS_BIG_ENDIAN)
04138 {
04139 emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, im1, dreg));
04140 emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
04141 }
04142 else
04143 {
04144 emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
04145 emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, im1, dreg));
04146 }
04147
04148 if (data_regs != NULL)
04149 {
04150 st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1],
04151 st_tmp_2, 1, OPTAB_WIDEN);
04152 st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0],
04153 st_tmp_1, 1, OPTAB_WIDEN);
04154 }
04155
04156
04157 if (WORDS_BIG_ENDIAN)
04158 emit_move_insn (st_addr_1, st_tmp_1);
04159 else
04160 emit_move_insn (st_addr_2, st_tmp_2);
04161 for (i = words-1; i > 0; --i)
04162 {
04163 rtx tmp = change_address (dmem, DImode,
04164 gen_rtx_AND (DImode,
04165 plus_constant(dmema,
04166 WORDS_BIG_ENDIAN ? i*8-1 : i*8),
04167 im8));
04168 set_mem_alias_set (tmp, 0);
04169 emit_move_insn (tmp, data_regs ? ins_tmps[i-1] : const0_rtx);
04170 }
04171 if (WORDS_BIG_ENDIAN)
04172 emit_move_insn (st_addr_2, st_tmp_2);
04173 else
04174 emit_move_insn (st_addr_1, st_tmp_1);
04175 }
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185 int
04186 alpha_expand_block_move (operands)
04187 rtx operands[];
04188 {
04189 rtx bytes_rtx = operands[2];
04190 rtx align_rtx = operands[3];
04191 HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
04192 HOST_WIDE_INT bytes = orig_bytes;
04193 HOST_WIDE_INT src_align = INTVAL (align_rtx) * BITS_PER_UNIT;
04194 HOST_WIDE_INT dst_align = src_align;
04195 rtx orig_src = operands[1];
04196 rtx orig_dst = operands[0];
04197 rtx data_regs[2 * MAX_MOVE_WORDS + 16];
04198 rtx tmp;
04199 unsigned int i, words, ofs, nregs = 0;
04200
04201 if (orig_bytes <= 0)
04202 return 1;
04203 else if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
04204 return 0;
04205
04206
04207
04208 tmp = XEXP (orig_src, 0);
04209 if (GET_CODE (tmp) == REG)
04210 src_align = MAX (src_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
04211 else if (GET_CODE (tmp) == PLUS
04212 && GET_CODE (XEXP (tmp, 0)) == REG
04213 && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
04214 {
04215 unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
04216 unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
04217
04218 if (a > src_align)
04219 {
04220 if (a >= 64 && c % 8 == 0)
04221 src_align = 64;
04222 else if (a >= 32 && c % 4 == 0)
04223 src_align = 32;
04224 else if (a >= 16 && c % 2 == 0)
04225 src_align = 16;
04226 }
04227 }
04228
04229 tmp = XEXP (orig_dst, 0);
04230 if (GET_CODE (tmp) == REG)
04231 dst_align = MAX (dst_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
04232 else if (GET_CODE (tmp) == PLUS
04233 && GET_CODE (XEXP (tmp, 0)) == REG
04234 && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
04235 {
04236 unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
04237 unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
04238
04239 if (a > dst_align)
04240 {
04241 if (a >= 64 && c % 8 == 0)
04242 dst_align = 64;
04243 else if (a >= 32 && c % 4 == 0)
04244 dst_align = 32;
04245 else if (a >= 16 && c % 2 == 0)
04246 dst_align = 16;
04247 }
04248 }
04249
04250
04251 if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF)
04252 {
04253 enum machine_mode mode;
04254
04255 tmp = XEXP (XEXP (orig_src, 0), 0);
04256
04257
04258
04259
04260 mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
04261 if (mode != BLKmode
04262 && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes)
04263 {
04264 if (mode == TImode)
04265 {
04266 data_regs[nregs] = gen_lowpart (DImode, tmp);
04267 data_regs[nregs + 1] = gen_highpart (DImode, tmp);
04268 nregs += 2;
04269 }
04270 else
04271 data_regs[nregs++] = gen_lowpart (mode, tmp);
04272
04273 goto src_done;
04274 }
04275
04276
04277 orig_src = replace_equiv_address (orig_src,
04278 copy_addr_to_reg (XEXP (orig_src, 0)));
04279 src_align = GET_MODE_BITSIZE (GET_MODE (tmp));
04280 }
04281
04282 ofs = 0;
04283 if (src_align >= 64 && bytes >= 8)
04284 {
04285 words = bytes / 8;
04286
04287 for (i = 0; i < words; ++i)
04288 data_regs[nregs + i] = gen_reg_rtx (DImode);
04289
04290 for (i = 0; i < words; ++i)
04291 emit_move_insn (data_regs[nregs + i],
04292 adjust_address (orig_src, DImode, ofs + i * 8));
04293
04294 nregs += words;
04295 bytes -= words * 8;
04296 ofs += words * 8;
04297 }
04298
04299 if (src_align >= 32 && bytes >= 4)
04300 {
04301 words = bytes / 4;
04302
04303 for (i = 0; i < words; ++i)
04304 data_regs[nregs + i] = gen_reg_rtx (SImode);
04305
04306 for (i = 0; i < words; ++i)
04307 emit_move_insn (data_regs[nregs + i],
04308 adjust_address (orig_src, SImode, ofs + i * 4));
04309
04310 nregs += words;
04311 bytes -= words * 4;
04312 ofs += words * 4;
04313 }
04314
04315 if (bytes >= 8)
04316 {
04317 words = bytes / 8;
04318
04319 for (i = 0; i < words+1; ++i)
04320 data_regs[nregs + i] = gen_reg_rtx (DImode);
04321
04322 alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
04323 words, ofs);
04324
04325 nregs += words;
04326 bytes -= words * 8;
04327 ofs += words * 8;
04328 }
04329
04330 if (! TARGET_BWX && bytes >= 4)
04331 {
04332 data_regs[nregs++] = tmp = gen_reg_rtx (SImode);
04333 alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
04334 bytes -= 4;
04335 ofs += 4;
04336 }
04337
04338 if (bytes >= 2)
04339 {
04340 if (src_align >= 16)
04341 {
04342 do {
04343 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
04344 emit_move_insn (tmp, adjust_address (orig_src, HImode, ofs));
04345 bytes -= 2;
04346 ofs += 2;
04347 } while (bytes >= 2);
04348 }
04349 else if (! TARGET_BWX)
04350 {
04351 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
04352 alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
04353 bytes -= 2;
04354 ofs += 2;
04355 }
04356 }
04357
04358 while (bytes > 0)
04359 {
04360 data_regs[nregs++] = tmp = gen_reg_rtx (QImode);
04361 emit_move_insn (tmp, adjust_address (orig_src, QImode, ofs));
04362 bytes -= 1;
04363 ofs += 1;
04364 }
04365
04366 src_done:
04367
04368 if (nregs > ARRAY_SIZE (data_regs))
04369 abort ();
04370
04371
04372
04373 i = 0, ofs = 0;
04374
04375 if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF)
04376 {
04377 enum machine_mode mode;
04378 tmp = XEXP (XEXP (orig_dst, 0), 0);
04379
04380 mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
04381 if (GET_MODE (tmp) == mode)
04382 {
04383 if (nregs == 1)
04384 {
04385 emit_move_insn (tmp, data_regs[0]);
04386 i = 1;
04387 goto dst_done;
04388 }
04389
04390 else if (nregs == 2 && mode == TImode)
04391 {
04392
04393
04394 if (GET_CODE (data_regs[0]) == SUBREG
04395 && GET_MODE (SUBREG_REG (data_regs[0])) == TImode)
04396 emit_move_insn (tmp, SUBREG_REG (data_regs[0]));
04397 else
04398 {
04399 rtx seq;
04400
04401 start_sequence ();
04402 emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]);
04403 emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]);
04404 seq = get_insns ();
04405 end_sequence ();
04406
04407 emit_no_conflict_block (seq, tmp, data_regs[0],
04408 data_regs[1], NULL_RTX);
04409 }
04410
04411 i = 2;
04412 goto dst_done;
04413 }
04414 }
04415
04416
04417
04418
04419
04420
04421 orig_dst = replace_equiv_address (orig_dst,
04422 copy_addr_to_reg (XEXP (orig_dst, 0)));
04423 dst_align = GET_MODE_BITSIZE (GET_MODE (tmp));
04424 }
04425
04426
04427 if (dst_align >= 64)
04428 {
04429 while (i < nregs && GET_MODE (data_regs[i]) == DImode)
04430 {
04431 emit_move_insn (adjust_address (orig_dst, DImode, ofs),
04432 data_regs[i]);
04433 ofs += 8;
04434 i++;
04435 }
04436 }
04437
04438 if (dst_align >= 32)
04439 {
04440
04441
04442 while (i < nregs && GET_MODE (data_regs[i]) == DImode)
04443 {
04444 tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
04445 NULL_RTX, 1, OPTAB_WIDEN);
04446
04447 emit_move_insn (adjust_address (orig_dst, SImode, ofs),
04448 gen_lowpart (SImode, data_regs[i]));
04449 emit_move_insn (adjust_address (orig_dst, SImode, ofs + 4),
04450 gen_lowpart (SImode, tmp));
04451 ofs += 8;
04452 i++;
04453 }
04454
04455 while (i < nregs && GET_MODE (data_regs[i]) == SImode)
04456 {
04457 emit_move_insn (adjust_address (orig_dst, SImode, ofs),
04458 data_regs[i]);
04459 ofs += 4;
04460 i++;
04461 }
04462 }
04463
04464 if (i < nregs && GET_MODE (data_regs[i]) == DImode)
04465 {
04466
04467
04468 for (words = 1; i + words < nregs; words++)
04469 if (GET_MODE (data_regs[i + words]) != DImode)
04470 break;
04471
04472 if (words == 1)
04473 alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs);
04474 else
04475 alpha_expand_unaligned_store_words (data_regs + i, orig_dst,
04476 words, ofs);
04477
04478 i += words;
04479 ofs += words * 8;
04480 }
04481
04482
04483
04484
04485 while (i < nregs && GET_MODE (data_regs[i]) == SImode)
04486 {
04487 alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs);
04488 ofs += 4;
04489 i++;
04490 }
04491
04492 if (dst_align >= 16)
04493 while (i < nregs && GET_MODE (data_regs[i]) == HImode)
04494 {
04495 emit_move_insn (adjust_address (orig_dst, HImode, ofs), data_regs[i]);
04496 i++;
04497 ofs += 2;
04498 }
04499 else
04500 while (i < nregs && GET_MODE (data_regs[i]) == HImode)
04501 {
04502 alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs);
04503 i++;
04504 ofs += 2;
04505 }
04506
04507 while (i < nregs && GET_MODE (data_regs[i]) == QImode)
04508 {
04509 emit_move_insn (adjust_address (orig_dst, QImode, ofs), data_regs[i]);
04510 i++;
04511 ofs += 1;
04512 }
04513
04514 dst_done:
04515
04516 if (i != nregs)
04517 abort ();
04518
04519 return 1;
04520 }
04521
04522 int
04523 alpha_expand_block_clear (operands)
04524 rtx operands[];
04525 {
04526 rtx bytes_rtx = operands[1];
04527 rtx align_rtx = operands[2];
04528 HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
04529 HOST_WIDE_INT bytes = orig_bytes;
04530 HOST_WIDE_INT align = INTVAL (align_rtx) * BITS_PER_UNIT;
04531 HOST_WIDE_INT alignofs = 0;
04532 rtx orig_dst = operands[0];
04533 rtx tmp;
04534 int i, words, ofs = 0;
04535
04536 if (orig_bytes <= 0)
04537 return 1;
04538 if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
04539 return 0;
04540
04541
04542 tmp = XEXP (orig_dst, 0);
04543 if (GET_CODE (tmp) == REG)
04544 align = MAX (align, REGNO_POINTER_ALIGN (REGNO (tmp)));
04545 else if (GET_CODE (tmp) == PLUS
04546 && GET_CODE (XEXP (tmp, 0)) == REG
04547 && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
04548 {
04549 HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
04550 int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
04551
04552 if (a > align)
04553 {
04554 if (a >= 64)
04555 align = a, alignofs = 8 - c % 8;
04556 else if (a >= 32)
04557 align = a, alignofs = 4 - c % 4;
04558 else if (a >= 16)
04559 align = a, alignofs = 2 - c % 2;
04560 }
04561 }
04562 else if (GET_CODE (tmp) == ADDRESSOF)
04563 {
04564 enum machine_mode mode;
04565
04566 mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
04567 if (GET_MODE (XEXP (tmp, 0)) == mode)
04568 {
04569 emit_move_insn (XEXP (tmp, 0), const0_rtx);
04570 return 1;
04571 }
04572
04573
04574 orig_dst = replace_equiv_address (orig_dst, copy_addr_to_reg (tmp));
04575 align = GET_MODE_BITSIZE (GET_MODE (XEXP (tmp, 0)));
04576 }
04577
04578
04579
04580 if (alignofs > 0)
04581 {
04582 #if HOST_BITS_PER_WIDE_INT >= 64
04583
04584
04585
04586 if ((!TARGET_BWX || alignofs == 7)
04587 && align >= 32
04588 && !(alignofs == 4 && bytes >= 4))
04589 {
04590 enum machine_mode mode = (align >= 64 ? DImode : SImode);
04591 int inv_alignofs = (align >= 64 ? 8 : 4) - alignofs;
04592 rtx mem, tmp;
04593 HOST_WIDE_INT mask;
04594
04595 mem = adjust_address (orig_dst, mode, ofs - inv_alignofs);
04596 set_mem_alias_set (mem, 0);
04597
04598 mask = ~(~(HOST_WIDE_INT)0 << (inv_alignofs * 8));
04599 if (bytes < alignofs)
04600 {
04601 mask |= ~(HOST_WIDE_INT)0 << ((inv_alignofs + bytes) * 8);
04602 ofs += bytes;
04603 bytes = 0;
04604 }
04605 else
04606 {
04607 bytes -= alignofs;
04608 ofs += alignofs;
04609 }
04610 alignofs = 0;
04611
04612 tmp = expand_binop (mode, and_optab, mem, GEN_INT (mask),
04613 NULL_RTX, 1, OPTAB_WIDEN);
04614
04615 emit_move_insn (mem, tmp);
04616 }
04617 #endif
04618
04619 if (TARGET_BWX && (alignofs & 1) && bytes >= 1)
04620 {
04621 emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
04622 bytes -= 1;
04623 ofs += 1;
04624 alignofs -= 1;
04625 }
04626 if (TARGET_BWX && align >= 16 && (alignofs & 3) == 2 && bytes >= 2)
04627 {
04628 emit_move_insn (adjust_address (orig_dst, HImode, ofs), const0_rtx);
04629 bytes -= 2;
04630 ofs += 2;
04631 alignofs -= 2;
04632 }
04633 if (alignofs == 4 && bytes >= 4)
04634 {
04635 emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
04636 bytes -= 4;
04637 ofs += 4;
04638 alignofs = 0;
04639 }
04640
04641
04642
04643 if (alignofs > 0)
04644 {
04645 alignofs = alignofs & -alignofs;
04646 align = MIN (align, alignofs * BITS_PER_UNIT);
04647 }
04648 }
04649
04650
04651
04652 if (align >= 64 && bytes >= 8)
04653 {
04654 words = bytes / 8;
04655
04656 for (i = 0; i < words; ++i)
04657 emit_move_insn (adjust_address (orig_dst, DImode, ofs + i * 8),
04658 const0_rtx);
04659
04660 bytes -= words * 8;
04661 ofs += words * 8;
04662 }
04663
04664
04665
04666
04667 if (align >= 32 && bytes > 16)
04668 {
04669 rtx orig_dsta;
04670
04671 emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
04672 bytes -= 4;
04673 ofs += 4;
04674
04675 orig_dsta = XEXP (orig_dst, 0);
04676 if (GET_CODE (orig_dsta) == LO_SUM)
04677 orig_dsta = force_reg (Pmode, orig_dsta);
04678
04679 words = bytes / 8;
04680 for (i = 0; i < words; ++i)
04681 {
04682 rtx mem
04683 = change_address (orig_dst, DImode,
04684 gen_rtx_AND (DImode,
04685 plus_constant (orig_dsta, ofs + i*8),
04686 GEN_INT (-8)));
04687 set_mem_alias_set (mem, 0);
04688 emit_move_insn (mem, const0_rtx);
04689 }
04690
04691
04692
04693
04694
04695 bytes -= words * 8 - 4;
04696 ofs += words * 8 - 4;
04697 }
04698
04699
04700
04701 if ((align >= 64 && bytes == 4)
04702 || (align == 32 && bytes >= 4))
04703 {
04704 words = bytes / 4;
04705
04706 for (i = 0; i < words; ++i)
04707 emit_move_insn (adjust_address (orig_dst, SImode, ofs + i * 4),
04708 const0_rtx);
04709
04710 bytes -= words * 4;
04711 ofs += words * 4;
04712 }
04713
04714
04715
04716 if (bytes >= 8)
04717 {
04718 words = bytes / 8;
04719
04720 alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs);
04721
04722 bytes -= words * 8;
04723 ofs += words * 8;
04724 }
04725
04726
04727
04728 #if HOST_BITS_PER_WIDE_INT >= 64
04729
04730
04731 words = 0;
04732 for (i = (TARGET_BWX ? 1 : 4); i * BITS_PER_UNIT <= align ; i <<= 1)
04733 if (bytes & i)
04734 words += 1;
04735
04736
04737
04738 if (TARGET_BWX ? words > 2 : bytes > 0)
04739 {
04740 if (align >= 64)
04741 {
04742 rtx mem, tmp;
04743 HOST_WIDE_INT mask;
04744
04745 mem = adjust_address (orig_dst, DImode, ofs);
04746 set_mem_alias_set (mem, 0);
04747
04748 mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
04749
04750 tmp = expand_binop (DImode, and_optab, mem, GEN_INT (mask),
04751 NULL_RTX, 1, OPTAB_WIDEN);
04752
04753 emit_move_insn (mem, tmp);
04754 return 1;
04755 }
04756 else if (align >= 32 && bytes < 4)
04757 {
04758 rtx mem, tmp;
04759 HOST_WIDE_INT mask;
04760
04761 mem = adjust_address (orig_dst, SImode, ofs);
04762 set_mem_alias_set (mem, 0);
04763
04764 mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
04765
04766 tmp = expand_binop (SImode, and_optab, mem, GEN_INT (mask),
04767 NULL_RTX, 1, OPTAB_WIDEN);
04768
04769 emit_move_insn (mem, tmp);
04770 return 1;
04771 }
04772 }
04773 #endif
04774
04775 if (!TARGET_BWX && bytes >= 4)
04776 {
04777 alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs);
04778 bytes -= 4;
04779 ofs += 4;
04780 }
04781
04782 if (bytes >= 2)
04783 {
04784 if (align >= 16)
04785 {
04786 do {
04787 emit_move_insn (adjust_address (orig_dst, HImode, ofs),
04788 const0_rtx);
04789 bytes -= 2;
04790 ofs += 2;
04791 } while (bytes >= 2);
04792 }
04793 else if (! TARGET_BWX)
04794 {
04795 alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs);
04796 bytes -= 2;
04797 ofs += 2;
04798 }
04799 }
04800
04801 while (bytes > 0)
04802 {
04803 emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
04804 bytes -= 1;
04805 ofs += 1;
04806 }
04807
04808 return 1;
04809 }
04810
04811
04812
04813
04814 static int
04815 alpha_adjust_cost (insn, link, dep_insn, cost)
04816 rtx insn;
04817 rtx link;
04818 rtx dep_insn;
04819 int cost;
04820 {
04821 rtx set, set_src;
04822 enum attr_type insn_type, dep_insn_type;
04823
04824
04825
04826
04827
04828 if (REG_NOTE_KIND (link) != 0)
04829 return 0;
04830
04831
04832 if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
04833 return cost;
04834
04835 insn_type = get_attr_type (insn);
04836 dep_insn_type = get_attr_type (dep_insn);
04837
04838
04839 if (dep_insn_type == TYPE_ILD
04840 || dep_insn_type == TYPE_FLD
04841 || dep_insn_type == TYPE_LDSYM)
04842 cost += alpha_memory_latency-1;
04843
04844 switch (alpha_cpu)
04845 {
04846 case PROCESSOR_EV4:
04847
04848
04849
04850 if ((insn_type == TYPE_IST || insn_type == TYPE_FST)
04851 && (set = single_set (dep_insn)) != 0
04852 && GET_CODE (PATTERN (insn)) == SET
04853 && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn))))
04854 {
04855 switch (dep_insn_type)
04856 {
04857 case TYPE_ILD:
04858 case TYPE_FLD:
04859
04860 return cost;
04861
04862 case TYPE_IMUL:
04863
04864 return cost - 1;
04865
04866 default:
04867
04868 return MAX (0, cost - 2);
04869 }
04870 }
04871
04872
04873
04874
04875
04876
04877 if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG)
04878 {
04879 switch (insn_type)
04880 {
04881 case TYPE_ILD:
04882 case TYPE_IST:
04883 case TYPE_FLD:
04884 case TYPE_FST:
04885 case TYPE_JSR:
04886 return cost;
04887 default:
04888 return 1;
04889 }
04890 }
04891
04892
04893
04894
04895 if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR)
04896 return 1;
04897 break;
04898
04899 case PROCESSOR_EV5:
04900
04901
04902
04903
04904 if ((dep_insn_type == TYPE_ICMP || dep_insn_type == TYPE_ILOG)
04905 && (set = single_set (dep_insn)) != 0)
04906 {
04907
04908 if (insn_type == TYPE_IBR)
04909 return 0;
04910
04911 if (insn_type == TYPE_ICMOV
04912 && GET_CODE (set_src = PATTERN (insn)) == SET
04913 && GET_CODE (set_src = SET_SRC (set_src)) == IF_THEN_ELSE
04914 && rtx_equal_p (SET_DEST (set), XEXP (set_src, 0)))
04915 return 0;
04916 }
04917
04918
04919
04920
04921
04922
04923
04924 if (insn_type == TYPE_IMUL)
04925 {
04926 switch (dep_insn_type)
04927 {
04928
04929 case TYPE_ILD:
04930 case TYPE_ICMOV:
04931 case TYPE_IMUL:
04932 case TYPE_MVI:
04933 return cost + 1;
04934
04935
04936 default:
04937 return cost + 2;
04938 }
04939 }
04940 break;
04941
04942 case PROCESSOR_EV6:
04943
04944
04945
04946 if ((insn_type == TYPE_FST || insn_type == TYPE_FTOI)
04947 && (dep_insn_type == TYPE_FADD ||
04948 dep_insn_type == TYPE_FMUL ||
04949 dep_insn_type == TYPE_FCMOV))
04950 return cost + 2;
04951
04952 break;
04953 }
04954
04955
04956 return cost;
04957 }
04958
04959
04960 static int
04961 alpha_issue_rate ()
04962 {
04963 return (alpha_cpu == PROCESSOR_EV4 ? 2 : 4);
04964 }
04965
04966 static int
04967 alpha_variable_issue (dump, verbose, insn, cim)
04968 FILE *dump ATTRIBUTE_UNUSED;
04969 int verbose ATTRIBUTE_UNUSED;
04970 rtx insn;
04971 int cim;
04972 {
04973 if (recog_memoized (insn) < 0 || get_attr_type (insn) == TYPE_MULTI)
04974 return 0;
04975
04976 return cim - 1;
04977 }
04978
04979
04980
04981
04982
04983 #if TARGET_ABI_UNICOSMK
04984 static void
04985 alpha_init_machine_status (p)
04986 struct function *p;
04987 {
04988 p->machine =
04989 (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
04990
04991 p->machine->first_ciw = NULL_RTX;
04992 p->machine->last_ciw = NULL_RTX;
04993 p->machine->ciw_count = 0;
04994 p->machine->addr_list = NULL_RTX;
04995 }
04996
04997 static void
04998 alpha_mark_machine_status (p)
04999 struct function *p;
05000 {
05001 struct machine_function *machine = p->machine;
05002
05003 if (machine)
05004 {
05005 ggc_mark_rtx (machine->first_ciw);
05006 ggc_mark_rtx (machine->addr_list);
05007 }
05008 }
05009
05010 static void
05011 alpha_free_machine_status (p)
05012 struct function *p;
05013 {
05014 free (p->machine);
05015 p->machine = NULL;
05016 }
05017 #endif
05018
05019
05020
05021
05022
05023 rtx
05024 alpha_return_addr (count, frame)
05025 int count;
05026 rtx frame ATTRIBUTE_UNUSED;
05027 {
05028 if (count != 0)
05029 return const0_rtx;
05030
05031 return get_hard_reg_initial_val (Pmode, REG_RA);
05032 }
05033
05034
05035
05036
05037 rtx
05038 alpha_gp_save_rtx ()
05039 {
05040 rtx r = get_hard_reg_initial_val (DImode, 29);
05041 if (GET_CODE (r) != MEM)
05042 r = gen_mem_addressof (r, NULL_TREE);
05043 return r;
05044 }
05045
05046 static int
05047 alpha_ra_ever_killed ()
05048 {
05049 rtx top;
05050
05051 if (!has_hard_reg_initial_val (Pmode, REG_RA))
05052 return regs_ever_live[REG_RA];
05053
05054 push_topmost_sequence ();
05055 top = get_insns ();
05056 pop_topmost_sequence ();
05057
05058 return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX);
05059 }
05060
05061
05062
05063
05064
05065 static const char *
05066 get_trap_mode_suffix ()
05067 {
05068 enum attr_trap_suffix s = get_attr_trap_suffix (current_output_insn);
05069
05070 switch (s)
05071 {
05072 case TRAP_SUFFIX_NONE:
05073 return NULL;
05074
05075 case TRAP_SUFFIX_SU:
05076 if (alpha_fptm >= ALPHA_FPTM_SU)
05077 return "su";
05078 return NULL;
05079
05080 case TRAP_SUFFIX_SUI:
05081 if (alpha_fptm >= ALPHA_FPTM_SUI)
05082 return "sui";
05083 return NULL;
05084
05085 case TRAP_SUFFIX_V_SV:
05086 switch (alpha_fptm)
05087 {
05088 case ALPHA_FPTM_N:
05089 return NULL;
05090 case ALPHA_FPTM_U:
05091 return "v";
05092 case ALPHA_FPTM_SU:
05093 case ALPHA_FPTM_SUI:
05094 return "sv";
05095 }
05096 break;
05097
05098 case TRAP_SUFFIX_V_SV_SVI:
05099 switch (alpha_fptm)
05100 {
05101 case ALPHA_FPTM_N:
05102 return NULL;
05103 case ALPHA_FPTM_U:
05104 return "v";
05105 case ALPHA_FPTM_SU:
05106 return "sv";
05107 case ALPHA_FPTM_SUI:
05108 return "svi";
05109 }
05110 break;
05111
05112 case TRAP_SUFFIX_U_SU_SUI:
05113 switch (alpha_fptm)
05114 {
05115 case ALPHA_FPTM_N:
05116 return NULL;
05117 case ALPHA_FPTM_U:
05118 return "u";
05119 case ALPHA_FPTM_SU:
05120 return "su";
05121 case ALPHA_FPTM_SUI:
05122 return "sui";
05123 }
05124 break;
05125 }
05126 abort ();
05127 }
05128
05129
05130
05131
05132 static const char *
05133 get_round_mode_suffix ()
05134 {
05135 enum attr_round_suffix s = get_attr_round_suffix (current_output_insn);
05136
05137 switch (s)
05138 {
05139 case ROUND_SUFFIX_NONE:
05140 return NULL;
05141 case ROUND_SUFFIX_NORMAL:
05142 switch (alpha_fprm)
05143 {
05144 case ALPHA_FPRM_NORM:
05145 return NULL;
05146 case ALPHA_FPRM_MINF:
05147 return "m";
05148 case ALPHA_FPRM_CHOP:
05149 return "c";
05150 case ALPHA_FPRM_DYN:
05151 return "d";
05152 }
05153 break;
05154
05155 case ROUND_SUFFIX_C:
05156 return "c";
05157 }
05158 abort ();
05159 }
05160
05161
05162
05163 void
05164 print_operand (file, x, code)
05165 FILE *file;
05166 rtx x;
05167 int code;
05168 {
05169 int i;
05170
05171 switch (code)
05172 {
05173 case '~':
05174
05175 assemble_name (file, alpha_fnname);
05176 break;
05177
05178 case '/':
05179 {
05180 const char *trap = get_trap_mode_suffix ();
05181 const char *round = get_round_mode_suffix ();
05182
05183 if (trap || round)
05184 fprintf (file, (TARGET_AS_SLASH_BEFORE_SUFFIX ? "/%s%s" : "%s%s"),
05185 (trap ? trap : ""), (round ? round : ""));
05186 break;
05187 }
05188
05189 case ',':
05190
05191 fputc ((TARGET_FLOAT_VAX ? 'f' : 's'), file);
05192 break;
05193
05194 case '-':
05195
05196 fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file);
05197 break;
05198
05199 case '#':
05200 if (alpha_this_literal_sequence_number == 0)
05201 alpha_this_literal_sequence_number = alpha_next_sequence_number++;
05202 fprintf (file, "%d", alpha_this_literal_sequence_number);
05203 break;
05204
05205 case '*':
05206 if (alpha_this_gpdisp_sequence_number == 0)
05207 alpha_this_gpdisp_sequence_number = alpha_next_sequence_number++;
05208 fprintf (file, "%d", alpha_this_gpdisp_sequence_number);
05209 break;
05210
05211 case 'H':
05212 if (GET_CODE (x) == HIGH)
05213 output_addr_const (file, XEXP (x, 0));
05214 else
05215 output_operand_lossage ("invalid %%H value");
05216 break;
05217
05218 case 'J':
05219 if (GET_CODE (x) == CONST_INT)
05220 {
05221 if (INTVAL (x) != 0)
05222 fprintf (file, "\t\t!lituse_jsr!%d", (int) INTVAL (x));
05223 }
05224 else
05225 output_operand_lossage ("invalid %%J value");
05226 break;
05227
05228 case 'r':
05229
05230 if (GET_CODE (x) == REG)
05231 fprintf (file, "%s", reg_names[REGNO (x)]);
05232 else if (x == CONST0_RTX (GET_MODE (x)))
05233 fprintf (file, "$31");
05234 else
05235 output_operand_lossage ("invalid %%r value");
05236 break;
05237
05238 case 'R':
05239
05240 if (GET_CODE (x) == REG)
05241 fprintf (file, "%s", reg_names[REGNO (x)]);
05242 else if (x == CONST0_RTX (GET_MODE (x)))
05243 fprintf (file, "$f31");
05244 else
05245 output_operand_lossage ("invalid %%R value");
05246 break;
05247
05248 case 'N':
05249
05250 if (GET_CODE (x) != CONST_INT)
05251 output_operand_lossage ("invalid %%N value");
05252
05253 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x));
05254 break;
05255
05256 case 'P':
05257
05258 if (GET_CODE (x) != CONST_INT)
05259 output_operand_lossage ("invalid %%P value");
05260
05261 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x));
05262 break;
05263
05264 case 'h':
05265
05266 if (GET_CODE (x) != CONST_INT)
05267 output_operand_lossage ("invalid %%h value");
05268
05269 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16);
05270 break;
05271
05272 case 'L':
05273
05274 if (GET_CODE (x) != CONST_INT)
05275 output_operand_lossage ("invalid %%L value");
05276
05277 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
05278 (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
05279 break;
05280
05281 case 'm':
05282
05283 if (GET_CODE (x) == CONST_DOUBLE)
05284 {
05285 HOST_WIDE_INT mask = 0;
05286 HOST_WIDE_INT value;
05287
05288 value = CONST_DOUBLE_LOW (x);
05289 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
05290 i++, value >>= 8)
05291 if (value & 0xff)
05292 mask |= (1 << i);
05293
05294 value = CONST_DOUBLE_HIGH (x);
05295 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
05296 i++, value >>= 8)
05297 if (value & 0xff)
05298 mask |= (1 << (i + sizeof (int)));
05299
05300 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff);
05301 }
05302
05303 else if (GET_CODE (x) == CONST_INT)
05304 {
05305 HOST_WIDE_INT mask = 0, value = INTVAL (x);
05306
05307 for (i = 0; i < 8; i++, value >>= 8)
05308 if (value & 0xff)
05309 mask |= (1 << i);
05310
05311 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask);
05312 }
05313 else
05314 output_operand_lossage ("invalid %%m value");
05315 break;
05316
05317 case 'M':
05318
05319 if (GET_CODE (x) != CONST_INT
05320 || (INTVAL (x) != 8 && INTVAL (x) != 16
05321 && INTVAL (x) != 32 && INTVAL (x) != 64))
05322 output_operand_lossage ("invalid %%M value");
05323
05324 fprintf (file, "%s",
05325 (INTVAL (x) == 8 ? "b"
05326 : INTVAL (x) == 16 ? "w"
05327 : INTVAL (x) == 32 ? "l"
05328 : "q"));
05329 break;
05330
05331 case 'U':
05332
05333 if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)
05334 fprintf (file, "b");
05335 else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)
05336 fprintf (file, "w");
05337 else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
05338 fprintf (file, "l");
05339 #if HOST_BITS_PER_WIDE_INT == 32
05340 else if (GET_CODE (x) == CONST_DOUBLE
05341 && CONST_DOUBLE_HIGH (x) == 0
05342 && CONST_DOUBLE_LOW (x) == -1)
05343 fprintf (file, "l");
05344 else if (GET_CODE (x) == CONST_DOUBLE
05345 && CONST_DOUBLE_HIGH (x) == -1
05346 && CONST_DOUBLE_LOW (x) == -1)
05347 fprintf (file, "q");
05348 #else
05349 else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1)
05350 fprintf (file, "q");
05351 else if (GET_CODE (x) == CONST_DOUBLE
05352 && CONST_DOUBLE_HIGH (x) == 0
05353 && CONST_DOUBLE_LOW (x) == -1)
05354 fprintf (file, "q");
05355 #endif
05356 else
05357 output_operand_lossage ("invalid %%U value");
05358 break;
05359
05360 case 's':
05361
05362
05363
05364 if (GET_CODE (x) != CONST_INT
05365 || (unsigned HOST_WIDE_INT) INTVAL (x) >= (WORDS_BIG_ENDIAN
05366 ? 56
05367 : 64)
05368 || (INTVAL (x) & 7) != 0)
05369 output_operand_lossage ("invalid %%s value");
05370
05371 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
05372 WORDS_BIG_ENDIAN
05373 ? (56 - INTVAL (x)) / 8
05374 : INTVAL (x) / 8);
05375 break;
05376
05377 case 'S':
05378
05379
05380 if (GET_CODE (x) != CONST_INT
05381 && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
05382 && (INTVAL (x) & 7) != 8)
05383 output_operand_lossage ("invalid %%s value");
05384
05385 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);
05386 break;
05387
05388 case 't':
05389 {
05390
05391
05392 int dex = unicosmk_need_dex (x);
05393 if (dex)
05394 fprintf (file, "DEX(%d)", dex);
05395 else
05396 output_addr_const (file, x);
05397 }
05398 break;
05399
05400 case 'C': case 'D': case 'c': case 'd':
05401
05402 {
05403 enum rtx_code c = GET_CODE (x);
05404
05405 if (GET_RTX_CLASS (c) != '<')
05406 output_operand_lossage ("invalid %%C value");
05407
05408 else if (code == 'D')
05409 c = reverse_condition (c);
05410 else if (code == 'c')
05411 c = swap_condition (c);
05412 else if (code == 'd')
05413 c = swap_condition (reverse_condition (c));
05414
05415 if (c == LEU)
05416 fprintf (file, "ule");
05417 else if (c == LTU)
05418 fprintf (file, "ult");
05419 else if (c == UNORDERED)
05420 fprintf (file, "un");
05421 else
05422 fprintf (file, "%s", GET_RTX_NAME (c));
05423 }
05424 break;
05425
05426 case 'E':
05427
05428 switch (GET_CODE (x))
05429 {
05430 case DIV:
05431 fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");
05432 break;
05433 case UDIV:
05434 fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");
05435 break;
05436 case MOD:
05437 fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");
05438 break;
05439 case UMOD:
05440 fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");
05441 break;
05442 default:
05443 output_operand_lossage ("invalid %%E value");
05444 break;
05445 }
05446 break;
05447
05448 case 'A':
05449
05450 if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
05451 fprintf (file, "_u");
05452 break;
05453
05454 case 0:
05455 if (GET_CODE (x) == REG)
05456 fprintf (file, "%s", reg_names[REGNO (x)]);
05457 else if (GET_CODE (x) == MEM)
05458 output_address (XEXP (x, 0));
05459 else
05460 output_addr_const (file, x);
05461 break;
05462
05463 default:
05464 output_operand_lossage ("invalid %%xn code");
05465 }
05466 }
05467
05468 void
05469 print_operand_address (file, addr)
05470 FILE *file;
05471 rtx addr;
05472 {
05473 int basereg = 31;
05474 HOST_WIDE_INT offset = 0;
05475
05476 if (GET_CODE (addr) == AND)
05477 addr = XEXP (addr, 0);
05478
05479 if (GET_CODE (addr) == PLUS
05480 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
05481 {
05482 offset = INTVAL (XEXP (addr, 1));
05483 addr = XEXP (addr, 0);
05484 }
05485
05486 if (GET_CODE (addr) == LO_SUM)
05487 {
05488 output_addr_const (file, XEXP (addr, 1));
05489 if (offset)
05490 {
05491 fputc ('+', file);
05492 fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
05493 }
05494
05495 addr = XEXP (addr, 0);
05496 if (GET_CODE (addr) == REG)
05497 basereg = REGNO (addr);
05498 else if (GET_CODE (addr) == SUBREG
05499 && GET_CODE (SUBREG_REG (addr)) == REG)
05500 basereg = subreg_regno (addr);
05501 else
05502 abort ();
05503
05504 fprintf (file, "($%d)\t\t!%s", basereg,
05505 (basereg == 29 ? "gprel" : "gprellow"));
05506 return;
05507 }
05508
05509 if (GET_CODE (addr) == REG)
05510 basereg = REGNO (addr);
05511 else if (GET_CODE (addr) == SUBREG
05512 && GET_CODE (SUBREG_REG (addr)) == REG)
05513 basereg = subreg_regno (addr);
05514 else if (GET_CODE (addr) == CONST_INT)
05515 offset = INTVAL (addr);
05516 else
05517 abort ();
05518
05519 fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
05520 fprintf (file, "($%d)", basereg);
05521 }
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531
05532
05533
05534
05535
05536 void
05537 alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
05538 rtx tramp, fnaddr, cxt;
05539 int fnofs, cxtofs, jmpofs;
05540 {
05541 rtx temp, temp1, addr;
05542
05543 enum machine_mode mode = TARGET_ABI_OPEN_VMS ? Pmode : ptr_mode;
05544
05545 #ifdef POINTERS_EXTEND_UNSIGNED
05546 fnaddr = convert_memory_address (mode, fnaddr);
05547 cxt = convert_memory_address (mode, cxt);
05548 #endif
05549
05550
05551 addr = memory_address (mode, plus_constant (tramp, fnofs));
05552 emit_move_insn (gen_rtx_MEM (mode, addr), fnaddr);
05553 addr = memory_address (mode, plus_constant (tramp, cxtofs));
05554 emit_move_insn (gen_rtx_MEM (mode, addr), cxt);
05555
05556
05557
05558 if (0 && jmpofs >= 0)
05559 {
05560
05561 temp = force_operand (plus_constant (tramp, jmpofs+4), NULL_RTX);
05562 temp = expand_binop (DImode, sub_optab, fnaddr, temp, temp, 1,
05563 OPTAB_WIDEN);
05564 temp = expand_shift (RSHIFT_EXPR, Pmode, temp,
05565 build_int_2 (2, 0), NULL_RTX, 1);
05566 temp = expand_and (SImode, gen_lowpart (SImode, temp),
05567 GEN_INT (0x3fff), 0);
05568
05569
05570 addr = memory_address (SImode, plus_constant (tramp, jmpofs));
05571 temp1 = force_reg (SImode, gen_rtx_MEM (SImode, addr));
05572 temp1 = expand_and (SImode, temp1, GEN_INT (0xffffc000), NULL_RTX);
05573 temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1,
05574 OPTAB_WIDEN);
05575 emit_move_insn (gen_rtx_MEM (SImode, addr), temp1);
05576 }
05577
05578 #ifdef TRANSFER_FROM_TRAMPOLINE
05579 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
05580 0, VOIDmode, 1, addr, Pmode);
05581 #endif
05582
05583 if (jmpofs >= 0)
05584 emit_insn (gen_imb ());
05585 }
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603 rtx
05604 function_arg (cum, mode, type, named)
05605 CUMULATIVE_ARGS cum;
05606 enum machine_mode mode;
05607 tree type;
05608 int named ATTRIBUTE_UNUSED;
05609 {
05610 int basereg;
05611 int num_args;
05612
05613
05614
05615 if (TARGET_FPREGS
05616 && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
05617 || GET_MODE_CLASS (mode) == MODE_FLOAT))
05618 basereg = 32 + 16;
05619 else
05620 basereg = 16;
05621
05622
05623
05624 #if TARGET_ABI_OPEN_VMS
05625 {
05626 if (mode == VOIDmode)
05627 return alpha_arg_info_reg_val (cum);
05628
05629 num_args = cum.num_args;
05630 if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type))
05631 return NULL_RTX;
05632 }
05633 #else
05634 #if TARGET_ABI_UNICOSMK
05635 {
05636 int size;
05637
05638
05639
05640
05641 if (mode == VOIDmode)
05642 {
05643 int i;
05644 HOST_WIDE_INT lo;
05645 HOST_WIDE_INT hi;
05646 rtx ciw;
05647
05648 lo = 0;
05649
05650 for (i = 0; i < cum.num_reg_words && i < 5; i++)
05651 if (cum.reg_args_type[i])
05652 lo |= (1 << (7 - i));
05653
05654 if (cum.num_reg_words == 6 && cum.reg_args_type[5])
05655 lo |= 7;
05656 else
05657 lo |= cum.num_reg_words;
05658
05659 #if HOST_BITS_PER_WIDE_INT == 32
05660 hi = (cum.num_args << 20) | cum.num_arg_words;
05661 #else
05662 lo = lo | ((HOST_WIDE_INT) cum.num_args << 52)
05663 | ((HOST_WIDE_INT) cum.num_arg_words << 32);
05664 hi = 0;
05665 #endif
05666 ciw = immed_double_const (lo, hi, DImode);
05667
05668 return gen_rtx_UNSPEC (DImode, gen_rtvec (1, ciw),
05669 UNSPEC_UMK_LOAD_CIW);
05670 }
05671
05672 size = ALPHA_ARG_SIZE (mode, type, named);
05673 num_args = cum.num_reg_words;
05674 if (MUST_PASS_IN_STACK (mode, type)
05675 || cum.num_reg_words + size > 6 || cum.force_stack)
05676 return NULL_RTX;
05677 else if (type && TYPE_MODE (type) == BLKmode)
05678 {
05679 rtx reg1, reg2;
05680
05681 reg1 = gen_rtx_REG (DImode, num_args + 16);
05682 reg1 = gen_rtx_EXPR_LIST (DImode, reg1, const0_rtx);
05683
05684
05685
05686 if (size == 0)
05687 return NULL_RTX;
05688 else if (size == 1)
05689 return gen_rtx_PARALLEL (mode, gen_rtvec (1, reg1));
05690 else
05691 {
05692 reg2 = gen_rtx_REG (DImode, num_args + 17);
05693 reg2 = gen_rtx_EXPR_LIST (DImode, reg2, GEN_INT (8));
05694 return gen_rtx_PARALLEL (mode, gen_rtvec (2, reg1, reg2));
05695 }
05696 }
05697 }
05698 #else
05699 {
05700 if (cum >= 6)
05701 return NULL_RTX;
05702 num_args = cum;
05703
05704
05705 if (type == void_type_node)
05706 basereg = 16;
05707 else if (MUST_PASS_IN_STACK (mode, type))
05708 return NULL_RTX;
05709 else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named))
05710 basereg = 16;
05711 }
05712 #endif
05713 #endif
05714
05715 return gen_rtx_REG (mode, num_args + basereg);
05716 }
05717
05718 tree
05719 alpha_build_va_list ()
05720 {
05721 tree base, ofs, record, type_decl;
05722
05723 if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
05724 return ptr_type_node;
05725
05726 record = make_lang_type (RECORD_TYPE);
05727 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
05728 TREE_CHAIN (record) = type_decl;
05729 TYPE_NAME (record) = type_decl;
05730
05731
05732
05733 ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
05734 integer_type_node);
05735 DECL_FIELD_CONTEXT (ofs) = record;
05736
05737 base = build_decl (FIELD_DECL, get_identifier ("__base"),
05738 ptr_type_node);
05739 DECL_FIELD_CONTEXT (base) = record;
05740 TREE_CHAIN (base) = ofs;
05741
05742 TYPE_FIELDS (record) = base;
05743 layout_type (record);
05744
05745 return record;
05746 }
05747
05748 void
05749 alpha_va_start (stdarg_p, valist, nextarg)
05750 int stdarg_p;
05751 tree valist;
05752 rtx nextarg ATTRIBUTE_UNUSED;
05753 {
05754 HOST_WIDE_INT offset;
05755 tree t, offset_field, base_field;
05756
05757 if (TREE_CODE (TREE_TYPE (valist)) == ERROR_MARK)
05758 return;
05759
05760 if (TARGET_ABI_UNICOSMK)
05761 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
05762
05763
05764
05765
05766
05767
05768
05769
05770
05771
05772 if (NUM_ARGS <= 5 + stdarg_p)
05773 offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
05774 else
05775 offset = -6 * UNITS_PER_WORD;
05776
05777 if (TARGET_ABI_OPEN_VMS)
05778 {
05779 nextarg = plus_constant (nextarg, offset);
05780 nextarg = plus_constant (nextarg, NUM_ARGS * UNITS_PER_WORD);
05781 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
05782 make_tree (ptr_type_node, nextarg));
05783 TREE_SIDE_EFFECTS (t) = 1;
05784
05785 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05786 }
05787 else
05788 {
05789 base_field = TYPE_FIELDS (TREE_TYPE (valist));
05790 offset_field = TREE_CHAIN (base_field);
05791
05792 base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
05793 valist, base_field);
05794 offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
05795 valist, offset_field);
05796
05797 t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
05798 t = build (PLUS_EXPR, ptr_type_node, t, build_int_2 (offset, 0));
05799 t = build (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
05800 TREE_SIDE_EFFECTS (t) = 1;
05801 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05802
05803 t = build_int_2 (NUM_ARGS * UNITS_PER_WORD, 0);
05804 t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
05805 TREE_SIDE_EFFECTS (t) = 1;
05806 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05807 }
05808 }
05809
05810 rtx
05811 alpha_va_arg (valist, type)
05812 tree valist, type;
05813 {
05814 rtx addr;
05815 tree t, type_size, rounded_size;
05816 tree offset_field, base_field, addr_tree, addend;
05817 tree wide_type, wide_ofs;
05818 int indirect = 0;
05819
05820 if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
05821 return std_expand_builtin_va_arg (valist, type);
05822
05823 if (type == error_mark_node
05824 || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
05825 || TREE_OVERFLOW (type_size))
05826 rounded_size = size_zero_node;
05827 else
05828 rounded_size = fold (build (MULT_EXPR, sizetype,
05829 fold (build (TRUNC_DIV_EXPR, sizetype,
05830 fold (build (PLUS_EXPR, sizetype,
05831 type_size,
05832 size_int (7))),
05833 size_int (8))),
05834 size_int (8)));
05835
05836 base_field = TYPE_FIELDS (TREE_TYPE (valist));
05837 offset_field = TREE_CHAIN (base_field);
05838
05839 base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
05840 valist, base_field);
05841 offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
05842 valist, offset_field);
05843
05844
05845
05846 if (MUST_PASS_IN_STACK (TYPE_MODE (type), type))
05847 {
05848 t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
05849 build (MAX_EXPR, TREE_TYPE (offset_field),
05850 offset_field, build_int_2 (6*8, 0)));
05851 TREE_SIDE_EFFECTS (t) = 1;
05852 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05853 }
05854
05855 wide_type = make_signed_type (64);
05856 wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
05857
05858 addend = wide_ofs;
05859
05860 if (TYPE_MODE (type) == TFmode || TYPE_MODE (type) == TCmode)
05861 {
05862 indirect = 1;
05863 rounded_size = size_int (UNITS_PER_WORD);
05864 }
05865 else if (FLOAT_TYPE_P (type))
05866 {
05867 tree fpaddend, cond;
05868
05869 fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
05870 addend, build_int_2 (-6*8, 0)));
05871
05872 cond = fold (build (LT_EXPR, integer_type_node,
05873 wide_ofs, build_int_2 (6*8, 0)));
05874
05875 addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
05876 fpaddend, addend));
05877 }
05878
05879 addr_tree = build (PLUS_EXPR, TREE_TYPE (base_field),
05880 base_field, addend);
05881
05882 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
05883 addr = copy_to_reg (addr);
05884
05885 t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
05886 build (PLUS_EXPR, TREE_TYPE (offset_field),
05887 offset_field, rounded_size));
05888 TREE_SIDE_EFFECTS (t) = 1;
05889 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05890
05891 if (indirect)
05892 {
05893 addr = force_reg (Pmode, addr);
05894 addr = gen_rtx_MEM (Pmode, addr);
05895 }
05896
05897 return addr;
05898 }
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911 enum alpha_procedure_types {PT_NULL = 0, PT_REGISTER = 1, PT_STACK = 2};
05912 static enum alpha_procedure_types alpha_procedure_type;
05913
05914
05915 static int vms_unwind_regno;
05916
05917
05918
05919
05920 static int vms_save_fp_regno;
05921
05922
05923 static int vms_base_regno;
05924
05925
05926
05927 static void
05928 alpha_sa_mask (imaskP, fmaskP)
05929 unsigned long *imaskP;
05930 unsigned long *fmaskP;
05931 {
05932 unsigned long imask = 0;
05933 unsigned long fmask = 0;
05934 unsigned int i;
05935
05936
05937
05938
05939
05940
05941 if (current_function_is_thunk && !no_new_pseudos)
05942 {
05943 *imaskP = 0;
05944 *fmaskP = 0;
05945 return;
05946 }
05947
05948 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
05949 imask |= (1L << HARD_FRAME_POINTER_REGNUM);
05950
05951
05952 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
05953 if (! fixed_regs[i] && ! call_used_regs[i]
05954 && regs_ever_live[i] && i != REG_RA
05955 && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
05956 {
05957 if (i < 32)
05958 imask |= (1L << i);
05959 else
05960 fmask |= (1L << (i - 32));
05961 }
05962
05963
05964 if (current_function_calls_eh_return)
05965 for (i = 0; ; ++i)
05966 {
05967 unsigned regno = EH_RETURN_DATA_REGNO (i);
05968 if (regno == INVALID_REGNUM)
05969 break;
05970 imask |= 1L << regno;
05971 }
05972
05973
05974
05975
05976 if (imask || fmask || alpha_ra_ever_killed ())
05977 imask |= (1L << REG_RA);
05978
05979 *imaskP = imask;
05980 *fmaskP = fmask;
05981 }
05982
05983 int
05984 alpha_sa_size ()
05985 {
05986 unsigned long mask[2];
05987 int sa_size = 0;
05988 int i, j;
05989
05990 alpha_sa_mask (&mask[0], &mask[1]);
05991
05992 if (TARGET_ABI_UNICOSMK)
05993 {
05994 if (mask[0] || mask[1])
05995 sa_size = 14;
05996 }
05997 else
05998 {
05999 for (j = 0; j < 2; ++j)
06000 for (i = 0; i < 32; ++i)
06001 if ((mask[j] >> i) & 1)
06002 sa_size++;
06003 }
06004
06005 if (TARGET_ABI_UNICOSMK)
06006 {
06007
06008
06009
06010
06011
06012
06013 alpha_procedure_type
06014 = (sa_size || get_frame_size() != 0
06015 || current_function_outgoing_args_size || current_function_varargs
06016 || current_function_stdarg || current_function_calls_alloca
06017 || frame_pointer_needed)
06018 ? PT_STACK : PT_REGISTER;
06019
06020
06021
06022 if (alpha_procedure_type == PT_STACK)
06023 sa_size = 14;
06024 }
06025 else if (TARGET_ABI_OPEN_VMS)
06026 {
06027
06028
06029
06030 if ((mask[0] >> REG_RA) & 1)
06031 alpha_procedure_type = PT_STACK;
06032 else if (get_frame_size() != 0)
06033 alpha_procedure_type = PT_REGISTER;
06034 else
06035 alpha_procedure_type = PT_NULL;
06036
06037
06038
06039 if (alpha_procedure_type == PT_STACK)
06040 sa_size -= 2;
06041
06042
06043
06044
06045
06046
06047 vms_base_regno
06048 = (frame_pointer_needed
06049 || current_function_has_nonlocal_label
06050 || alpha_procedure_type == PT_STACK
06051 || current_function_outgoing_args_size)
06052 ? REG_PV : HARD_FRAME_POINTER_REGNUM;
06053
06054
06055
06056
06057 vms_save_fp_regno = -1;
06058 if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
06059 for (i = 0; i < 32; i++)
06060 if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i])
06061 vms_save_fp_regno = i;
06062
06063 if (vms_save_fp_regno == -1 && alpha_procedure_type == PT_REGISTER)
06064 vms_base_regno = REG_PV, alpha_procedure_type = PT_STACK;
06065 else if (alpha_procedure_type == PT_NULL)
06066 vms_base_regno = REG_PV;
06067
06068
06069 vms_unwind_regno = (vms_base_regno == REG_PV
06070 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
06071
06072
06073 if (alpha_procedure_type == PT_STACK)
06074 sa_size += 2;
06075 }
06076 else
06077 {
06078
06079 if (sa_size & 1)
06080 sa_size++;
06081 }
06082
06083 return sa_size * 8;
06084 }
06085
06086 int
06087 alpha_pv_save_size ()
06088 {
06089 alpha_sa_size ();
06090 return alpha_procedure_type == PT_STACK ? 8 : 0;
06091 }
06092
06093 int
06094 alpha_using_fp ()
06095 {
06096 alpha_sa_size ();
06097 return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM;
06098 }
06099
06100 #if TARGET_ABI_OPEN_VMS
06101
06102 const struct attribute_spec vms_attribute_table[] =
06103 {
06104
06105 { "overlaid", 0, 0, true, false, false, NULL },
06106 { "global", 0, 0, true, false, false, NULL },
06107 { "initialize", 0, 0, true, false, false, NULL },
06108 { NULL, 0, 0, false, false, false, NULL }
06109 };
06110
06111 #endif
06112
06113 static int
06114 find_lo_sum (px, data)
06115 rtx *px;
06116 void *data ATTRIBUTE_UNUSED;
06117 {
06118 return GET_CODE (*px) == LO_SUM;
06119 }
06120
06121 static int
06122 alpha_does_function_need_gp ()
06123 {
06124 rtx insn;
06125
06126
06127 if (! TARGET_ABI_OSF)
06128 return 0;
06129
06130 if (TARGET_PROFILING_NEEDS_GP && current_function_profile)
06131 return 1;
06132
06133 if (current_function_is_thunk)
06134 return 1;
06135
06136
06137
06138
06139
06140 push_topmost_sequence ();
06141 insn = get_insns ();
06142 pop_topmost_sequence ();
06143
06144 for (; insn; insn = NEXT_INSN (insn))
06145 if (INSN_P (insn)
06146 && GET_CODE (PATTERN (insn)) != USE
06147 && GET_CODE (PATTERN (insn)) != CLOBBER)
06148 {
06149 enum attr_type type = get_attr_type (insn);
06150 if (type == TYPE_LDSYM || type == TYPE_JSR)
06151 return 1;
06152 if (TARGET_EXPLICIT_RELOCS
06153 && for_each_rtx (&PATTERN (insn), find_lo_sum, NULL) > 0)
06154 return 1;
06155 }
06156
06157 return 0;
06158 }
06159
06160
06161
06162
06163 #ifdef HAVE_STAMP_H
06164 #include <stamp.h>
06165 #endif
06166
06167 void
06168 alpha_write_verstamp (file)
06169 FILE *file ATTRIBUTE_UNUSED;
06170 {
06171 #ifdef MS_STAMP
06172 fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
06173 #endif
06174 }
06175
06176
06177
06178
06179 static rtx
06180 set_frame_related_p ()
06181 {
06182 rtx seq = gen_sequence ();
06183 end_sequence ();
06184
06185 if (GET_CODE (seq) == SEQUENCE)
06186 {
06187 int i = XVECLEN (seq, 0);
06188 while (--i >= 0)
06189 RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1;
06190 return emit_insn (seq);
06191 }
06192 else
06193 {
06194 seq = emit_insn (seq);
06195 RTX_FRAME_RELATED_P (seq) = 1;
06196 return seq;
06197 }
06198 }
06199
06200 #define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
06201
06202
06203
06204
06205
06206
06207
06208
06209
06210
06211
06212
06213
06214
06215
06216
06217
06218
06219 void
06220 alpha_expand_prologue ()
06221 {
06222
06223 unsigned long imask = 0;
06224 unsigned long fmask = 0;
06225
06226 HOST_WIDE_INT sa_size;
06227
06228 HOST_WIDE_INT frame_size;
06229
06230 HOST_WIDE_INT reg_offset;
06231 rtx sa_reg, mem;
06232 int i;
06233
06234 sa_size = alpha_sa_size ();
06235
06236 frame_size = get_frame_size ();
06237 if (TARGET_ABI_OPEN_VMS)
06238 frame_size = ALPHA_ROUND (sa_size
06239 + (alpha_procedure_type == PT_STACK ? 8 : 0)
06240 + frame_size
06241 + current_function_pretend_args_size);
06242 else if (TARGET_ABI_UNICOSMK)
06243
06244 frame_size = ALPHA_ROUND (sa_size
06245 + (alpha_procedure_type == PT_STACK ? 48 : 0))
06246 + ALPHA_ROUND (frame_size
06247 + current_function_outgoing_args_size);
06248 else
06249 frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
06250 + sa_size
06251 + ALPHA_ROUND (frame_size
06252 + current_function_pretend_args_size));
06253
06254 if (TARGET_ABI_OPEN_VMS)
06255 reg_offset = 8;
06256 else
06257 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
06258
06259 alpha_sa_mask (&imask, &fmask);
06260
06261
06262 if (TARGET_ABI_OSF)
06263 {
06264 alpha_function_needs_gp = alpha_does_function_need_gp ();
06265 if (alpha_function_needs_gp)
06266 emit_insn (gen_prologue_ldgp ());
06267 }
06268
06269
06270
06271
06272
06273 if (TARGET_PROFILING_NEEDS_GP && current_function_profile)
06274 emit_insn (gen_prologue_mcount ());
06275
06276 if (TARGET_ABI_UNICOSMK)
06277 unicosmk_gen_dsib (&imask);
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287
06288 if (frame_size <= 32768)
06289 {
06290 if (frame_size > 4096)
06291 {
06292 int probed = 4096;
06293
06294 do
06295 emit_insn (gen_probe_stack (GEN_INT (TARGET_ABI_UNICOSMK
06296 ? -probed + 64
06297 : -probed)));
06298 while ((probed += 8192) < frame_size);
06299
06300
06301 if (sa_size == 0 && probed + 4096 < frame_size)
06302 emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
06303 }
06304
06305 if (frame_size != 0)
06306 FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
06307 GEN_INT (TARGET_ABI_UNICOSMK
06308 ? -frame_size + 64
06309 : -frame_size))));
06310 }
06311 else
06312 {
06313
06314
06315
06316
06317
06318
06319 HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
06320 HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
06321 rtx ptr = gen_rtx_REG (DImode, 22);
06322 rtx count = gen_rtx_REG (DImode, 23);
06323 rtx seq;
06324
06325 emit_move_insn (count, GEN_INT (blocks));
06326 emit_insn (gen_adddi3 (ptr, stack_pointer_rtx,
06327 GEN_INT (TARGET_ABI_UNICOSMK ? 4096 - 64 : 4096)));
06328
06329
06330
06331 emit_insn (gen_prologue_stack_probe_loop (count, ptr));
06332
06333 if (leftover > 4096 && sa_size == 0)
06334 {
06335 rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover));
06336 MEM_VOLATILE_P (last) = 1;
06337 emit_move_insn (last, const0_rtx);
06338 }
06339
06340 if (TARGET_ABI_WINDOWS_NT)
06341 {
06342
06343
06344
06345
06346
06347
06348
06349
06350
06351 HOST_WIDE_INT lo, hi;
06352 lo = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
06353 hi = frame_size - lo;
06354
06355 emit_move_insn (ptr, GEN_INT (hi));
06356 emit_insn (gen_nt_lda (ptr, GEN_INT (lo)));
06357 seq = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
06358 ptr));
06359 }
06360 else
06361 {
06362 seq = emit_insn (gen_adddi3 (stack_pointer_rtx, ptr,
06363 GEN_INT (-leftover)));
06364 }
06365
06366
06367
06368
06369 RTX_FRAME_RELATED_P (seq) = 1;
06370 REG_NOTES (seq)
06371 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
06372 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
06373 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
06374 GEN_INT (TARGET_ABI_UNICOSMK
06375 ? -frame_size + 64
06376 : -frame_size))),
06377 REG_NOTES (seq));
06378 }
06379
06380 if (!TARGET_ABI_UNICOSMK)
06381 {
06382
06383 sa_reg = stack_pointer_rtx;
06384 if (reg_offset + sa_size > 0x8000)
06385 {
06386 int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
06387 HOST_WIDE_INT bias;
06388
06389 if (low + sa_size <= 0x8000)
06390 bias = reg_offset - low, reg_offset = low;
06391 else
06392 bias = reg_offset, reg_offset = 0;
06393
06394 sa_reg = gen_rtx_REG (DImode, 24);
06395 FRP (emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx,
06396 GEN_INT (bias))));
06397 }
06398
06399
06400 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
06401 {
06402 mem = gen_rtx_MEM (DImode, stack_pointer_rtx);
06403 set_mem_alias_set (mem, alpha_sr_alias_set);
06404 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV)));
06405 }
06406
06407
06408 if (imask & (1L << REG_RA))
06409 {
06410 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
06411 set_mem_alias_set (mem, alpha_sr_alias_set);
06412 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
06413 imask &= ~(1L << REG_RA);
06414 reg_offset += 8;
06415 }
06416
06417
06418 for (i = 0; i < 32; i++)
06419 if (imask & (1L << i))
06420 {
06421 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
06422 set_mem_alias_set (mem, alpha_sr_alias_set);
06423 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
06424 reg_offset += 8;
06425 }
06426
06427 for (i = 0; i < 32; i++)
06428 if (fmask & (1L << i))
06429 {
06430 mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
06431 set_mem_alias_set (mem, alpha_sr_alias_set);
06432 FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
06433 reg_offset += 8;
06434 }
06435 }
06436 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
06437 {
06438
06439
06440
06441
06442 reg_offset = -56;
06443 for (i = 9; i < 15; i++)
06444 if (imask & (1L << i))
06445 {
06446 mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
06447 reg_offset));
06448 set_mem_alias_set (mem, alpha_sr_alias_set);
06449 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
06450 reg_offset -= 8;
06451 }
06452 for (i = 2; i < 10; i++)
06453 if (fmask & (1L << i))
06454 {
06455 mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx,
06456 reg_offset));
06457 set_mem_alias_set (mem, alpha_sr_alias_set);
06458 FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
06459 reg_offset -= 8;
06460 }
06461 }
06462
06463 if (TARGET_ABI_OPEN_VMS)
06464 {
06465 if (alpha_procedure_type == PT_REGISTER)
06466
06467
06468 emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
06469 hard_frame_pointer_rtx);
06470
06471 if (alpha_procedure_type != PT_NULL && vms_base_regno != REG_PV)
06472 emit_insn (gen_force_movdi (gen_rtx_REG (DImode, vms_base_regno),
06473 gen_rtx_REG (DImode, REG_PV)));
06474
06475 if (alpha_procedure_type != PT_NULL
06476 && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
06477 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
06478
06479
06480 if (current_function_outgoing_args_size != 0)
06481 FRP (emit_move_insn
06482 (stack_pointer_rtx,
06483 plus_constant (hard_frame_pointer_rtx,
06484 - (ALPHA_ROUND
06485 (current_function_outgoing_args_size)))));
06486 }
06487 else if (!TARGET_ABI_UNICOSMK)
06488 {
06489
06490 if (frame_pointer_needed)
06491 {
06492 if (TARGET_CAN_FAULT_IN_PROLOGUE)
06493 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
06494 else
06495
06496
06497 FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx,
06498 stack_pointer_rtx, sa_reg)));
06499 }
06500 }
06501
06502
06503
06504
06505
06506
06507
06508
06509
06510
06511
06512 if (! TARGET_CAN_FAULT_IN_PROLOGUE)
06513 emit_insn (gen_blockage ());
06514 }
06515
06516
06517
06518 void
06519 alpha_start_function (file, fnname, decl)
06520 FILE *file;
06521 const char *fnname;
06522 tree decl ATTRIBUTE_UNUSED;
06523 {
06524 unsigned long imask = 0;
06525 unsigned long fmask = 0;
06526
06527 HOST_WIDE_INT sa_size;
06528
06529 HOST_WIDE_INT frame_size;
06530
06531 HOST_WIDE_INT reg_offset;
06532 char *entry_label = (char *) alloca (strlen (fnname) + 6);
06533 int i;
06534
06535
06536 if (TARGET_ABI_UNICOSMK)
06537 {
06538 tree name_tree;
06539 name_tree = get_identifier (fnname);
06540 TREE_ASM_WRITTEN (name_tree) = 1;
06541 }
06542
06543 alpha_fnname = fnname;
06544 sa_size = alpha_sa_size ();
06545
06546 frame_size = get_frame_size ();
06547 if (TARGET_ABI_OPEN_VMS)
06548 frame_size = ALPHA_ROUND (sa_size
06549 + (alpha_procedure_type == PT_STACK ? 8 : 0)
06550 + frame_size
06551 + current_function_pretend_args_size);
06552 else if (TARGET_ABI_UNICOSMK)
06553 frame_size = ALPHA_ROUND (sa_size
06554 + (alpha_procedure_type == PT_STACK ? 48 : 0))
06555 + ALPHA_ROUND (frame_size
06556 + current_function_outgoing_args_size);
06557 else
06558 frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
06559 + sa_size
06560 + ALPHA_ROUND (frame_size
06561 + current_function_pretend_args_size));
06562
06563 if (TARGET_ABI_OPEN_VMS)
06564 reg_offset = 8;
06565 else
06566 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
06567
06568 alpha_sa_mask (&imask, &fmask);
06569
06570
06571
06572
06573
06574
06575
06576
06577
06578 if (write_symbols == SDB_DEBUG)
06579 {
06580 #ifdef ASM_OUTPUT_SOURCE_FILENAME
06581 ASM_OUTPUT_SOURCE_FILENAME (file,
06582 DECL_SOURCE_FILE (current_function_decl));
06583 #endif
06584 #ifdef ASM_OUTPUT_SOURCE_LINE
06585 if (debug_info_level != DINFO_LEVEL_TERSE)
06586 ASM_OUTPUT_SOURCE_LINE (file,
06587 DECL_SOURCE_LINE (current_function_decl));
06588 #endif
06589 }
06590
06591
06592 if (TARGET_ABI_OPEN_VMS
06593 || (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive))
06594 {
06595 fputs ("\t.ent ", file);
06596 assemble_name (file, fnname);
06597 putc ('\n', file);
06598
06599
06600
06601 if (TARGET_ABI_OSF
06602 && ! alpha_function_needs_gp
06603 && ! current_function_is_thunk)
06604 {
06605 putc ('$', file);
06606 assemble_name (file, fnname);
06607 fputs ("..ng:\n", file);
06608 }
06609 }
06610
06611 strcpy (entry_label, fnname);
06612 if (TARGET_ABI_OPEN_VMS)
06613 strcat (entry_label, "..en");
06614
06615
06616
06617 if (TARGET_ABI_UNICOSMK && TREE_PUBLIC (decl))
06618 strcat (entry_label, ":");
06619
06620 ASM_OUTPUT_LABEL (file, entry_label);
06621 inside_function = TRUE;
06622
06623 if (TARGET_ABI_OPEN_VMS)
06624 fprintf (file, "\t.base $%d\n", vms_base_regno);
06625
06626 if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK && TARGET_IEEE_CONFORMANT
06627 && !flag_inhibit_size_directive)
06628 {
06629
06630
06631
06632 fputs ("\t.eflag 48\n", file);
06633 }
06634
06635
06636 alpha_auto_offset = -frame_size + current_function_pretend_args_size;
06637 alpha_arg_offset = -frame_size + 48;
06638
06639
06640
06641
06642 if (TARGET_ABI_UNICOSMK)
06643 ;
06644 else if (TARGET_ABI_OPEN_VMS)
06645 {
06646 fprintf (file, "\t.frame $%d,", vms_unwind_regno);
06647 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06648 frame_size >= ((HOST_WIDE_INT) 1 << 31) ? 0 : frame_size);
06649 fputs (",$26,", file);
06650 fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset);
06651 fputs ("\n", file);
06652 }
06653 else if (!flag_inhibit_size_directive)
06654 {
06655 fprintf (file, "\t.frame $%d,",
06656 (frame_pointer_needed
06657 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM));
06658 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06659 frame_size >= (1l << 31) ? 0 : frame_size);
06660 fprintf (file, ",$26,%d\n", current_function_pretend_args_size);
06661 }
06662
06663
06664 if (TARGET_ABI_UNICOSMK)
06665 ;
06666 else if (TARGET_ABI_OPEN_VMS)
06667 {
06668 if (imask)
06669
06670
06671 fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA));
06672 if (fmask)
06673 fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
06674 if (alpha_procedure_type == PT_REGISTER)
06675 fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno);
06676 }
06677 else if (!flag_inhibit_size_directive)
06678 {
06679 if (imask)
06680 {
06681 fprintf (file, "\t.mask 0x%lx,", imask);
06682 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06683 frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
06684 putc ('\n', file);
06685
06686 for (i = 0; i < 32; ++i)
06687 if (imask & (1L << i))
06688 reg_offset += 8;
06689 }
06690
06691 if (fmask)
06692 {
06693 fprintf (file, "\t.fmask 0x%lx,", fmask);
06694 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
06695 frame_size >= (1l << 31) ? 0 : reg_offset - frame_size);
06696 putc ('\n', file);
06697 }
06698 }
06699
06700 #if TARGET_ABI_OPEN_VMS
06701
06702
06703 readonly_section ();
06704 fprintf (file, "\t.align 3\n");
06705 assemble_name (file, fnname); fputs ("..na:\n", file);
06706 fputs ("\t.ascii \"", file);
06707 assemble_name (file, fnname);
06708 fputs ("\\0\"\n", file);
06709
06710 link_section ();
06711 fprintf (file, "\t.align 3\n");
06712 fputs ("\t.name ", file);
06713 assemble_name (file, fnname);
06714 fputs ("..na\n", file);
06715 ASM_OUTPUT_LABEL (file, fnname);
06716 fprintf (file, "\t.pdesc ");
06717 assemble_name (file, fnname);
06718 fprintf (file, "..en,%s\n",
06719 alpha_procedure_type == PT_STACK ? "stack"
06720 : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
06721 alpha_need_linkage (fnname, 1);
06722 text_section ();
06723 #endif
06724 }
06725
06726
06727
06728 static void
06729 alpha_output_function_end_prologue (file)
06730 FILE *file;
06731 {
06732 if (TARGET_ABI_UNICOSMK)
06733 ;
06734 else if (TARGET_ABI_OPEN_VMS)
06735 fputs ("\t.prologue\n", file);
06736 else if (TARGET_ABI_WINDOWS_NT)
06737 fputs ("\t.prologue 0\n", file);
06738 else if (!flag_inhibit_size_directive)
06739 fprintf (file, "\t.prologue %d\n",
06740 alpha_function_needs_gp || current_function_is_thunk);
06741 }
06742
06743
06744
06745
06746
06747
06748 #undef FRP
06749 #define FRP(exp) exp
06750
06751 void
06752 alpha_expand_epilogue ()
06753 {
06754
06755 unsigned long imask = 0;
06756 unsigned long fmask = 0;
06757
06758 HOST_WIDE_INT sa_size;
06759
06760 HOST_WIDE_INT frame_size;
06761
06762 HOST_WIDE_INT reg_offset;
06763 int fp_is_frame_pointer, fp_offset;
06764 rtx sa_reg, sa_reg_exp = NULL;
06765 rtx sp_adj1, sp_adj2, mem;
06766 rtx eh_ofs;
06767 int i;
06768
06769 sa_size = alpha_sa_size ();
06770
06771 frame_size = get_frame_size ();
06772 if (TARGET_ABI_OPEN_VMS)
06773 frame_size = ALPHA_ROUND (sa_size
06774 + (alpha_procedure_type == PT_STACK ? 8 : 0)
06775 + frame_size
06776 + current_function_pretend_args_size);
06777 else if (TARGET_ABI_UNICOSMK)
06778 frame_size = ALPHA_ROUND (sa_size
06779 + (alpha_procedure_type == PT_STACK ? 48 : 0))
06780 + ALPHA_ROUND (frame_size
06781 + current_function_outgoing_args_size);
06782 else
06783 frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
06784 + sa_size
06785 + ALPHA_ROUND (frame_size
06786 + current_function_pretend_args_size));
06787
06788 if (TARGET_ABI_OPEN_VMS)
06789 {
06790 if (alpha_procedure_type == PT_STACK)
06791 reg_offset = 8;
06792 else
06793 reg_offset = 0;
06794 }
06795 else
06796 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
06797
06798 alpha_sa_mask (&imask, &fmask);
06799
06800 fp_is_frame_pointer
06801 = ((TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
06802 || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed));
06803 fp_offset = 0;
06804 sa_reg = stack_pointer_rtx;
06805
06806 if (current_function_calls_eh_return)
06807 eh_ofs = EH_RETURN_STACKADJ_RTX;
06808 else
06809 eh_ofs = NULL_RTX;
06810
06811 if (!TARGET_ABI_UNICOSMK && sa_size)
06812 {
06813
06814 if ((TARGET_ABI_OPEN_VMS
06815 && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
06816 || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed))
06817 FRP (emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx));
06818
06819
06820 if (reg_offset + sa_size > 0x8000)
06821 {
06822 int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
06823 HOST_WIDE_INT bias;
06824
06825 if (low + sa_size <= 0x8000)
06826 bias = reg_offset - low, reg_offset = low;
06827 else
06828 bias = reg_offset, reg_offset = 0;
06829
06830 sa_reg = gen_rtx_REG (DImode, 22);
06831 sa_reg_exp = plus_constant (stack_pointer_rtx, bias);
06832
06833 FRP (emit_move_insn (sa_reg, sa_reg_exp));
06834 }
06835
06836
06837
06838 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
06839 if (! eh_ofs)
06840 set_mem_alias_set (mem, alpha_sr_alias_set);
06841 FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
06842
06843 reg_offset += 8;
06844 imask &= ~(1L << REG_RA);
06845
06846 for (i = 0; i < 32; ++i)
06847 if (imask & (1L << i))
06848 {
06849 if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
06850 fp_offset = reg_offset;
06851 else
06852 {
06853 mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
06854 set_mem_alias_set (mem, alpha_sr_alias_set);
06855 FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
06856 }
06857 reg_offset += 8;
06858 }
06859
06860 for (i = 0; i < 32; ++i)
06861 if (fmask & (1L << i))
06862 {
06863 mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
06864 set_mem_alias_set (mem, alpha_sr_alias_set);
06865 FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
06866 reg_offset += 8;
06867 }
06868 }
06869 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
06870 {
06871
06872
06873 reg_offset = -56;
06874
06875 for (i = 9; i < 15; i++)
06876 if (imask & (1L << i))
06877 {
06878 mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
06879 reg_offset));
06880 set_mem_alias_set (mem, alpha_sr_alias_set);
06881 FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
06882 reg_offset -= 8;
06883 }
06884
06885 for (i = 2; i < 10; i++)
06886 if (fmask & (1L << i))
06887 {
06888 mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
06889 reg_offset));
06890 set_mem_alias_set (mem, alpha_sr_alias_set);
06891 FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
06892 reg_offset -= 8;
06893 }
06894
06895
06896
06897 mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx, -8));
06898 set_mem_alias_set (mem, alpha_sr_alias_set);
06899 FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
06900 }
06901
06902 if (frame_size || eh_ofs)
06903 {
06904 sp_adj1 = stack_pointer_rtx;
06905
06906 if (eh_ofs)
06907 {
06908 sp_adj1 = gen_rtx_REG (DImode, 23);
06909 emit_move_insn (sp_adj1,
06910 gen_rtx_PLUS (Pmode, stack_pointer_rtx, eh_ofs));
06911 }
06912
06913
06914
06915
06916 if (frame_size < 32768
06917 && ! (TARGET_ABI_UNICOSMK && current_function_calls_alloca))
06918 sp_adj2 = GEN_INT (frame_size);
06919 else if (TARGET_ABI_UNICOSMK)
06920 {
06921 sp_adj1 = gen_rtx_REG (DImode, 23);
06922 FRP (emit_move_insn (sp_adj1, hard_frame_pointer_rtx));
06923 sp_adj2 = const0_rtx;
06924 }
06925 else if (frame_size < 0x40007fffL)
06926 {
06927 int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
06928
06929 sp_adj2 = plus_constant (sp_adj1, frame_size - low);
06930 if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2))
06931 sp_adj1 = sa_reg;
06932 else
06933 {
06934 sp_adj1 = gen_rtx_REG (DImode, 23);
06935 FRP (emit_move_insn (sp_adj1, sp_adj2));
06936 }
06937 sp_adj2 = GEN_INT (low);
06938 }
06939 else
06940 {
06941 rtx tmp = gen_rtx_REG (DImode, 23);
06942 FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3));
06943 if (!sp_adj2)
06944 {
06945
06946
06947 FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size,
06948 -(frame_size < 0)));
06949 if (!sp_adj2)
06950 abort ();
06951 }
06952 }
06953
06954
06955
06956
06957 if (TARGET_ABI_UNICOSMK)
06958 {
06959 emit_insn (gen_blockage ());
06960 mem = gen_rtx_MEM (DImode,
06961 plus_constant (hard_frame_pointer_rtx, -16));
06962 set_mem_alias_set (mem, alpha_sr_alias_set);
06963 FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
06964 }
06965 else if (fp_is_frame_pointer)
06966 {
06967 emit_insn (gen_blockage ());
06968 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, fp_offset));
06969 set_mem_alias_set (mem, alpha_sr_alias_set);
06970 FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
06971 }
06972 else if (TARGET_ABI_OPEN_VMS)
06973 {
06974 emit_insn (gen_blockage ());
06975 FRP (emit_move_insn (hard_frame_pointer_rtx,
06976 gen_rtx_REG (DImode, vms_save_fp_regno)));
06977 }
06978
06979
06980 emit_insn (gen_blockage ());
06981 if (sp_adj2 == const0_rtx)
06982 FRP (emit_move_insn (stack_pointer_rtx, sp_adj1));
06983 else
06984 FRP (emit_move_insn (stack_pointer_rtx,
06985 gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
06986 }
06987 else
06988 {
06989 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_REGISTER)
06990 {
06991 emit_insn (gen_blockage ());
06992 FRP (emit_move_insn (hard_frame_pointer_rtx,
06993 gen_rtx_REG (DImode, vms_save_fp_regno)));
06994 }
06995 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type != PT_STACK)
06996 {
06997
06998
06999
07000 emit_insn (gen_blockage ());
07001 FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
07002 hard_frame_pointer_rtx, GEN_INT (-1))));
07003 }
07004 }
07005 }
07006
07007
07008
07009 void
07010 alpha_end_function (file, fnname, decl)
07011 FILE *file;
07012 const char *fnname;
07013 tree decl ATTRIBUTE_UNUSED;
07014 {
07015
07016 if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive)
07017 {
07018 fputs ("\t.end ", file);
07019 assemble_name (file, fnname);
07020 putc ('\n', file);
07021 }
07022 inside_function = FALSE;
07023
07024
07025
07026
07027
07028
07029
07030
07031
07032
07033
07034 if (!DECL_WEAK (current_function_decl)
07035 && (!flag_pic || !TREE_PUBLIC (current_function_decl))
07036 && decl_in_text_section (current_function_decl))
07037 SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
07038
07039
07040 if (TARGET_ABI_UNICOSMK)
07041 {
07042 unicosmk_output_ssib (file, fnname);
07043 unicosmk_output_deferred_case_vectors (file);
07044 }
07045 }
07046
07047
07048
07049
07050
07051
07052
07053
07054
07055
07056 void
07057 alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
07058 FILE *file;
07059 tree thunk_fndecl ATTRIBUTE_UNUSED;
07060 HOST_WIDE_INT delta;
07061 tree function;
07062 {
07063 HOST_WIDE_INT hi, lo;
07064 rtx this, insn, funexp;
07065
07066
07067 emit_insn (gen_prologue_ldgp ());
07068 emit_note (NULL, NOTE_INSN_PROLOGUE_END);
07069
07070
07071
07072 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
07073 this = gen_rtx_REG (Pmode, 17);
07074 else
07075 this = gen_rtx_REG (Pmode, 16);
07076
07077
07078
07079 lo = ((delta & 0xffff) ^ 0x8000) - 0x8000;
07080 hi = (((delta - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
07081 if (hi + lo == delta)
07082 {
07083 if (hi)
07084 emit_insn (gen_adddi3 (this, this, GEN_INT (hi)));
07085 if (lo)
07086 emit_insn (gen_adddi3 (this, this, GEN_INT (lo)));
07087 }
07088 else
07089 {
07090 rtx tmp = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 0),
07091 delta, -(delta < 0));
07092 emit_insn (gen_adddi3 (this, this, tmp));
07093 }
07094
07095
07096 if (! TREE_USED (function))
07097 {
07098 assemble_external (function);
07099 TREE_USED (function) = 1;
07100 }
07101 funexp = XEXP (DECL_RTL (function), 0);
07102 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
07103 insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
07104 SIBLING_CALL_P (insn) = 1;
07105
07106
07107
07108
07109
07110 insn = get_insns ();
07111 shorten_branches (insn);
07112 final_start_function (insn, file, 1);
07113 final (insn, file, 1, 0);
07114 final_end_function ();
07115 }
07116
07117
07118
07119 #include "gstab.h"
07120
07121
07122
07123
07124 int sdb_label_count = 0;
07125
07126
07127
07128 static int sym_lineno = 0;
07129
07130
07131
07132 static int num_source_filenames = 0;
07133
07134
07135
07136 static const char *current_function_file = "";
07137
07138
07139
07140 long alpha_arg_offset;
07141 long alpha_auto_offset;
07142
07143
07144
07145 void
07146 alpha_output_filename (stream, name)
07147 FILE *stream;
07148 const char *name;
07149 {
07150 static int first_time = TRUE;
07151 char ltext_label_name[100];
07152
07153 if (first_time)
07154 {
07155 first_time = FALSE;
07156 ++num_source_filenames;
07157 current_function_file = name;
07158 fprintf (stream, "\t.file\t%d ", num_source_filenames);
07159 output_quoted_string (stream, name);
07160 fprintf (stream, "\n");
07161 if (!TARGET_GAS && write_symbols == DBX_DEBUG)
07162 fprintf (stream, "\t#@stabs\n");
07163 }
07164
07165 else if (write_symbols == DBX_DEBUG)
07166 {
07167 ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
07168 fprintf (stream, "%s", ASM_STABS_OP);
07169 output_quoted_string (stream, name);
07170 fprintf (stream, ",%d,0,0,%s\n", N_SOL, <ext_label_name[1]);
07171 }
07172
07173 else if (name != current_function_file
07174 && strcmp (name, current_function_file) != 0)
07175 {
07176 if (inside_function && ! TARGET_GAS)
07177 fprintf (stream, "\t#.file\t%d ", num_source_filenames);
07178 else
07179 {
07180 ++num_source_filenames;
07181 current_function_file = name;
07182 fprintf (stream, "\t.file\t%d ", num_source_filenames);
07183 }
07184
07185 output_quoted_string (stream, name);
07186 fprintf (stream, "\n");
07187 }
07188 }
07189
07190
07191
07192 void
07193 alpha_output_lineno (stream, line)
07194 FILE *stream;
07195 int line;
07196 {
07197 if (write_symbols == DBX_DEBUG)
07198 {
07199
07200 ++sym_lineno;
07201 fprintf (stream, "$LM%d:\n%s%d,0,%d,$LM%d\n",
07202 sym_lineno, ASM_STABN_OP, N_SLINE, line, sym_lineno);
07203 }
07204 else
07205 fprintf (stream, "\n\t.loc\t%d %d\n", num_source_filenames, line);
07206 }
07207
07208
07209
07210 struct shadow_summary
07211 {
07212 struct {
07213 unsigned int i : 31;
07214 unsigned int fp : 31;
07215 unsigned int mem : 1;
07216 } used, defd;
07217 };
07218
07219 static void summarize_insn PARAMS ((rtx, struct shadow_summary *, int));
07220 static void alpha_handle_trap_shadows PARAMS ((rtx));
07221
07222
07223
07224
07225
07226 static void
07227 summarize_insn (x, sum, set)
07228 rtx x;
07229 struct shadow_summary *sum;
07230 int set;
07231 {
07232 const char *format_ptr;
07233 int i, j;
07234
07235 if (x == 0)
07236 return;
07237
07238 switch (GET_CODE (x))
07239 {
07240
07241
07242 case SET:
07243 summarize_insn (SET_SRC (x), sum, 0);
07244 summarize_insn (SET_DEST (x), sum, 1);
07245 break;
07246
07247 case CLOBBER:
07248 summarize_insn (XEXP (x, 0), sum, 1);
07249 break;
07250
07251 case USE:
07252 summarize_insn (XEXP (x, 0), sum, 0);
07253 break;
07254
07255 case ASM_OPERANDS:
07256 for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
07257 summarize_insn (ASM_OPERANDS_INPUT (x, i), sum, 0);
07258 break;
07259
07260 case PARALLEL:
07261 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
07262 summarize_insn (XVECEXP (x, 0, i), sum, 0);
07263 break;
07264
07265 case SUBREG:
07266 summarize_insn (SUBREG_REG (x), sum, 0);
07267 break;
07268
07269 case REG:
07270 {
07271 int regno = REGNO (x);
07272 unsigned long mask = ((unsigned long) 1) << (regno % 32);
07273
07274 if (regno == 31 || regno == 63)
07275 break;
07276
07277 if (set)
07278 {
07279 if (regno < 32)
07280 sum->defd.i |= mask;
07281 else
07282 sum->defd.fp |= mask;
07283 }
07284 else
07285 {
07286 if (regno < 32)
07287 sum->used.i |= mask;
07288 else
07289 sum->used.fp |= mask;
07290 }
07291 }
07292 break;
07293
07294 case MEM:
07295 if (set)
07296 sum->defd.mem = 1;
07297 else
07298 sum->used.mem = 1;
07299
07300
07301 summarize_insn (XEXP (x, 0), sum, 0);
07302 break;
07303
07304 case CONST_INT: case CONST_DOUBLE:
07305 case SYMBOL_REF: case LABEL_REF: case CONST:
07306 case SCRATCH: case ASM_INPUT:
07307 break;
07308
07309
07310 case COMPARE: case PLUS: case MINUS: case MULT: case DIV:
07311 case MOD: case UDIV: case UMOD: case AND: case IOR:
07312 case XOR: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT:
07313 case ROTATERT: case SMIN: case SMAX: case UMIN: case UMAX:
07314 case NE: case EQ: case GE: case GT: case LE:
07315 case LT: case GEU: case GTU: case LEU: case LTU:
07316 summarize_insn (XEXP (x, 0), sum, 0);
07317 summarize_insn (XEXP (x, 1), sum, 0);
07318 break;
07319
07320 case NEG: case NOT: case SIGN_EXTEND: case ZERO_EXTEND:
07321 case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT:
07322 case FIX: case UNSIGNED_FLOAT: case UNSIGNED_FIX: case ABS:
07323 case SQRT: case FFS:
07324 summarize_insn (XEXP (x, 0), sum, 0);
07325 break;
07326
07327 default:
07328 format_ptr = GET_RTX_FORMAT (GET_CODE (x));
07329 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
07330 switch (format_ptr[i])
07331 {
07332 case 'e':
07333 summarize_insn (XEXP (x, i), sum, 0);
07334 break;
07335
07336 case 'E':
07337 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
07338 summarize_insn (XVECEXP (x, i, j), sum, 0);
07339 break;
07340
07341 case 'i':
07342 break;
07343
07344 default:
07345 abort ();
07346 }
07347 }
07348 }
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358
07359
07360
07361
07362
07363
07364
07365
07366
07367
07368
07369