00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "regs.h"
00031 #include "hard-reg-set.h"
00032 #include "real.h"
00033 #include "insn-config.h"
00034 #include "conditions.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "flags.h"
00038 #include "recog.h"
00039 #include "expr.h"
00040 #include "optabs.h"
00041 #include "reload.h"
00042 #include "obstack.h"
00043 #include "except.h"
00044 #include "function.h"
00045 #include "toplev.h"
00046 #include "ggc.h"
00047 #include "integrate.h"
00048 #include "tm_p.h"
00049 #include "target.h"
00050 #include "target-def.h"
00051 #include "debug.h"
00052 #include "langhooks.h"
00053 #include <splay-tree.h>
00054 #include "cfglayout.h"
00055 #include "tree-gimple.h"
00056 #include "tree-flow.h"
00057 #include "tree-stdarg.h"
00058
00059
00060 enum processor_type alpha_tune;
00061
00062
00063 enum processor_type alpha_cpu;
00064
00065 static const char * const alpha_cpu_name[] =
00066 {
00067 "ev4", "ev5", "ev6"
00068 };
00069
00070
00071
00072 enum alpha_trap_precision alpha_tp;
00073
00074
00075
00076 enum alpha_fp_rounding_mode alpha_fprm;
00077
00078
00079
00080 enum alpha_fp_trap_mode alpha_fptm;
00081
00082
00083
00084
00085 struct alpha_compare alpha_compare;
00086
00087
00088
00089
00090 static int inside_function = FALSE;
00091
00092
00093
00094 int alpha_memory_latency = 3;
00095
00096
00097
00098 static int alpha_function_needs_gp;
00099
00100
00101
00102 static GTY(()) int alpha_sr_alias_set;
00103
00104
00105
00106 static const char *alpha_fnname;
00107
00108
00109 extern GTY(()) int alpha_next_sequence_number;
00110 int alpha_next_sequence_number = 1;
00111
00112
00113
00114 extern GTY(()) int alpha_this_literal_sequence_number;
00115 extern GTY(()) int alpha_this_gpdisp_sequence_number;
00116 int alpha_this_literal_sequence_number;
00117 int alpha_this_gpdisp_sequence_number;
00118
00119
00120
00121 struct alpha_rtx_cost_data
00122 {
00123 unsigned char fp_add;
00124 unsigned char fp_mult;
00125 unsigned char fp_div_sf;
00126 unsigned char fp_div_df;
00127 unsigned char int_mult_si;
00128 unsigned char int_mult_di;
00129 unsigned char int_shift;
00130 unsigned char int_cmov;
00131 unsigned short int_div;
00132 };
00133
00134 static struct alpha_rtx_cost_data const alpha_rtx_cost_data[PROCESSOR_MAX] =
00135 {
00136 {
00137 COSTS_N_INSNS (6),
00138 COSTS_N_INSNS (6),
00139 COSTS_N_INSNS (34),
00140 COSTS_N_INSNS (63),
00141 COSTS_N_INSNS (23),
00142 COSTS_N_INSNS (23),
00143 COSTS_N_INSNS (2),
00144 COSTS_N_INSNS (2),
00145 COSTS_N_INSNS (97),
00146 },
00147 {
00148 COSTS_N_INSNS (4),
00149 COSTS_N_INSNS (4),
00150 COSTS_N_INSNS (15),
00151 COSTS_N_INSNS (22),
00152 COSTS_N_INSNS (8),
00153 COSTS_N_INSNS (12),
00154 COSTS_N_INSNS (1) + 1,
00155 COSTS_N_INSNS (1),
00156 COSTS_N_INSNS (83),
00157 },
00158 {
00159 COSTS_N_INSNS (4),
00160 COSTS_N_INSNS (4),
00161 COSTS_N_INSNS (12),
00162 COSTS_N_INSNS (15),
00163 COSTS_N_INSNS (7),
00164 COSTS_N_INSNS (7),
00165 COSTS_N_INSNS (1),
00166 COSTS_N_INSNS (2),
00167 COSTS_N_INSNS (86),
00168 },
00169 };
00170
00171
00172
00173
00174
00175
00176 static struct alpha_rtx_cost_data const alpha_rtx_cost_size =
00177 {
00178 COSTS_N_INSNS (1),
00179 COSTS_N_INSNS (1),
00180 COSTS_N_INSNS (1),
00181 COSTS_N_INSNS (1) + 1,
00182 COSTS_N_INSNS (1) + 1,
00183 COSTS_N_INSNS (1) + 2,
00184 COSTS_N_INSNS (1),
00185 COSTS_N_INSNS (1),
00186 COSTS_N_INSNS (6),
00187 };
00188
00189
00190 #if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK
00191 #define NUM_ARGS current_function_args_info.num_args
00192 #else
00193 #define NUM_ARGS current_function_args_info
00194 #endif
00195
00196 #define REG_PV 27
00197 #define REG_RA 26
00198
00199
00200 static struct machine_function *alpha_init_machine_status (void);
00201 static rtx alpha_emit_xfloating_compare (enum rtx_code *, rtx, rtx);
00202
00203 #if TARGET_ABI_OPEN_VMS
00204 static void alpha_write_linkage (FILE *, const char *, tree);
00205 #endif
00206
00207 static void unicosmk_output_deferred_case_vectors (FILE *);
00208 static void unicosmk_gen_dsib (unsigned long *);
00209 static void unicosmk_output_ssib (FILE *, const char *);
00210 static int unicosmk_need_dex (rtx);
00211
00212
00213
00214 static bool
00215 alpha_handle_option (size_t code, const char *arg, int value)
00216 {
00217 switch (code)
00218 {
00219 case OPT_mfp_regs:
00220 if (value == 0)
00221 target_flags |= MASK_SOFT_FP;
00222 break;
00223
00224 case OPT_mieee:
00225 case OPT_mieee_with_inexact:
00226 target_flags |= MASK_IEEE_CONFORMANT;
00227 break;
00228
00229 case OPT_mtls_size_:
00230 if (value != 16 && value != 32 && value != 64)
00231 error ("bad value %qs for -mtls-size switch", arg);
00232 break;
00233 }
00234
00235 return true;
00236 }
00237
00238 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
00239
00240
00241 static const char *
00242 alpha_mangle_fundamental_type (tree type)
00243 {
00244 if (TYPE_MAIN_VARIANT (type) == long_double_type_node
00245 && TARGET_LONG_DOUBLE_128)
00246 return "g";
00247
00248
00249 return NULL;
00250 }
00251 #endif
00252
00253
00254
00255 void
00256 override_options (void)
00257 {
00258 static const struct cpu_table {
00259 const char *const name;
00260 const enum processor_type processor;
00261 const int flags;
00262 } cpu_table[] = {
00263 { "ev4", PROCESSOR_EV4, 0 },
00264 { "ev45", PROCESSOR_EV4, 0 },
00265 { "21064", PROCESSOR_EV4, 0 },
00266 { "ev5", PROCESSOR_EV5, 0 },
00267 { "21164", PROCESSOR_EV5, 0 },
00268 { "ev56", PROCESSOR_EV5, MASK_BWX },
00269 { "21164a", PROCESSOR_EV5, MASK_BWX },
00270 { "pca56", PROCESSOR_EV5, MASK_BWX|MASK_MAX },
00271 { "21164PC",PROCESSOR_EV5, MASK_BWX|MASK_MAX },
00272 { "21164pc",PROCESSOR_EV5, MASK_BWX|MASK_MAX },
00273 { "ev6", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX },
00274 { "21264", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX },
00275 { "ev67", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX|MASK_CIX },
00276 { "21264a", PROCESSOR_EV6, MASK_BWX|MASK_MAX|MASK_FIX|MASK_CIX },
00277 { 0, 0, 0 }
00278 };
00279
00280 int i;
00281
00282
00283 if (TARGET_ABI_UNICOSMK && flag_pic)
00284 {
00285 warning (0, "-f%s ignored for Unicos/Mk (not supported)",
00286 (flag_pic > 1) ? "PIC" : "pic");
00287 flag_pic = 0;
00288 }
00289
00290
00291
00292 if (TARGET_ABI_UNICOSMK)
00293 alpha_fprm = ALPHA_FPRM_DYN;
00294 else
00295 alpha_fprm = ALPHA_FPRM_NORM;
00296
00297 alpha_tp = ALPHA_TP_PROG;
00298 alpha_fptm = ALPHA_FPTM_N;
00299
00300
00301
00302
00303
00304
00305
00306 if (TARGET_IEEE)
00307 {
00308 if (TARGET_ABI_UNICOSMK)
00309 warning (0, "-mieee not supported on Unicos/Mk");
00310 else
00311 {
00312 alpha_tp = ALPHA_TP_INSN;
00313 alpha_fptm = ALPHA_FPTM_SU;
00314 }
00315 }
00316
00317 if (TARGET_IEEE_WITH_INEXACT)
00318 {
00319 if (TARGET_ABI_UNICOSMK)
00320 warning (0, "-mieee-with-inexact not supported on Unicos/Mk");
00321 else
00322 {
00323 alpha_tp = ALPHA_TP_INSN;
00324 alpha_fptm = ALPHA_FPTM_SUI;
00325 }
00326 }
00327
00328 if (alpha_tp_string)
00329 {
00330 if (! strcmp (alpha_tp_string, "p"))
00331 alpha_tp = ALPHA_TP_PROG;
00332 else if (! strcmp (alpha_tp_string, "f"))
00333 alpha_tp = ALPHA_TP_FUNC;
00334 else if (! strcmp (alpha_tp_string, "i"))
00335 alpha_tp = ALPHA_TP_INSN;
00336 else
00337 error ("bad value %qs for -mtrap-precision switch", alpha_tp_string);
00338 }
00339
00340 if (alpha_fprm_string)
00341 {
00342 if (! strcmp (alpha_fprm_string, "n"))
00343 alpha_fprm = ALPHA_FPRM_NORM;
00344 else if (! strcmp (alpha_fprm_string, "m"))
00345 alpha_fprm = ALPHA_FPRM_MINF;
00346 else if (! strcmp (alpha_fprm_string, "c"))
00347 alpha_fprm = ALPHA_FPRM_CHOP;
00348 else if (! strcmp (alpha_fprm_string,"d"))
00349 alpha_fprm = ALPHA_FPRM_DYN;
00350 else
00351 error ("bad value %qs for -mfp-rounding-mode switch",
00352 alpha_fprm_string);
00353 }
00354
00355 if (alpha_fptm_string)
00356 {
00357 if (strcmp (alpha_fptm_string, "n") == 0)
00358 alpha_fptm = ALPHA_FPTM_N;
00359 else if (strcmp (alpha_fptm_string, "u") == 0)
00360 alpha_fptm = ALPHA_FPTM_U;
00361 else if (strcmp (alpha_fptm_string, "su") == 0)
00362 alpha_fptm = ALPHA_FPTM_SU;
00363 else if (strcmp (alpha_fptm_string, "sui") == 0)
00364 alpha_fptm = ALPHA_FPTM_SUI;
00365 else
00366 error ("bad value %qs for -mfp-trap-mode switch", alpha_fptm_string);
00367 }
00368
00369 if (alpha_cpu_string)
00370 {
00371 for (i = 0; cpu_table [i].name; i++)
00372 if (! strcmp (alpha_cpu_string, cpu_table [i].name))
00373 {
00374 alpha_tune = alpha_cpu = cpu_table [i].processor;
00375 target_flags &= ~ (MASK_BWX | MASK_MAX | MASK_FIX | MASK_CIX);
00376 target_flags |= cpu_table [i].flags;
00377 break;
00378 }
00379 if (! cpu_table [i].name)
00380 error ("bad value %qs for -mcpu switch", alpha_cpu_string);
00381 }
00382
00383 if (alpha_tune_string)
00384 {
00385 for (i = 0; cpu_table [i].name; i++)
00386 if (! strcmp (alpha_tune_string, cpu_table [i].name))
00387 {
00388 alpha_tune = cpu_table [i].processor;
00389 break;
00390 }
00391 if (! cpu_table [i].name)
00392 error ("bad value %qs for -mcpu switch", alpha_tune_string);
00393 }
00394
00395
00396
00397 if (TARGET_ABI_UNICOSMK && alpha_fptm != ALPHA_FPTM_N)
00398 {
00399 warning (0, "trap mode not supported on Unicos/Mk");
00400 alpha_fptm = ALPHA_FPTM_N;
00401 }
00402
00403 if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
00404 && alpha_tp != ALPHA_TP_INSN && alpha_cpu != PROCESSOR_EV6)
00405 {
00406 warning (0, "fp software completion requires -mtrap-precision=i");
00407 alpha_tp = ALPHA_TP_INSN;
00408 }
00409
00410 if (alpha_cpu == PROCESSOR_EV6)
00411 {
00412
00413
00414
00415 alpha_tp = ALPHA_TP_PROG;
00416 }
00417
00418 if (TARGET_FLOAT_VAX)
00419 {
00420 if (alpha_fprm == ALPHA_FPRM_MINF || alpha_fprm == ALPHA_FPRM_DYN)
00421 {
00422 warning (0, "rounding mode not supported for VAX floats");
00423 alpha_fprm = ALPHA_FPRM_NORM;
00424 }
00425 if (alpha_fptm == ALPHA_FPTM_SUI)
00426 {
00427 warning (0, "trap mode not supported for VAX floats");
00428 alpha_fptm = ALPHA_FPTM_SU;
00429 }
00430 if (target_flags_explicit & MASK_LONG_DOUBLE_128)
00431 warning (0, "128-bit long double not supported for VAX floats");
00432 target_flags &= ~MASK_LONG_DOUBLE_128;
00433 }
00434
00435 {
00436 char *end;
00437 int lat;
00438
00439 if (!alpha_mlat_string)
00440 alpha_mlat_string = "L1";
00441
00442 if (ISDIGIT ((unsigned char)alpha_mlat_string[0])
00443 && (lat = strtol (alpha_mlat_string, &end, 10), *end == '\0'))
00444 ;
00445 else if ((alpha_mlat_string[0] == 'L' || alpha_mlat_string[0] == 'l')
00446 && ISDIGIT ((unsigned char)alpha_mlat_string[1])
00447 && alpha_mlat_string[2] == '\0')
00448 {
00449 static int const cache_latency[][4] =
00450 {
00451 { 3, 30, -1 },
00452 { 2, 12, 38 },
00453 { 3, 12, 30 },
00454 };
00455
00456 lat = alpha_mlat_string[1] - '0';
00457 if (lat <= 0 || lat > 3 || cache_latency[alpha_tune][lat-1] == -1)
00458 {
00459 warning (0, "L%d cache latency unknown for %s",
00460 lat, alpha_cpu_name[alpha_tune]);
00461 lat = 3;
00462 }
00463 else
00464 lat = cache_latency[alpha_tune][lat-1];
00465 }
00466 else if (! strcmp (alpha_mlat_string, "main"))
00467 {
00468
00469
00470 lat = 150;
00471 }
00472 else
00473 {
00474 warning (0, "bad value %qs for -mmemory-latency", alpha_mlat_string);
00475 lat = 3;
00476 }
00477
00478 alpha_memory_latency = lat;
00479 }
00480
00481
00482 if (!g_switch_set)
00483 g_switch_value = 8;
00484
00485
00486 if (flag_pic == 1)
00487 target_flags |= MASK_SMALL_DATA;
00488 else if (flag_pic == 2)
00489 target_flags &= ~MASK_SMALL_DATA;
00490
00491
00492
00493
00494 if (optimize > 0 && write_symbols != SDB_DEBUG)
00495 {
00496 if (align_loops <= 0)
00497 align_loops = 16;
00498 if (align_jumps <= 0)
00499 align_jumps = 16;
00500 }
00501 if (align_functions <= 0)
00502 align_functions = 16;
00503
00504
00505 alpha_sr_alias_set = new_alias_set ();
00506
00507
00508
00509
00510 init_machine_status = alpha_init_machine_status;
00511
00512
00513 if (TARGET_FLOAT_VAX)
00514 {
00515 REAL_MODE_FORMAT (SFmode) = &vax_f_format;
00516 REAL_MODE_FORMAT (DFmode) = &vax_g_format;
00517 REAL_MODE_FORMAT (TFmode) = NULL;
00518 }
00519
00520 #ifdef TARGET_DEFAULT_LONG_DOUBLE_128
00521 if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
00522 target_flags |= MASK_LONG_DOUBLE_128;
00523 #endif
00524 }
00525
00526
00527
00528 int
00529 zap_mask (HOST_WIDE_INT value)
00530 {
00531 int i;
00532
00533 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
00534 i++, value >>= 8)
00535 if ((value & 0xff) != 0 && (value & 0xff) != 0xff)
00536 return 0;
00537
00538 return 1;
00539 }
00540
00541
00542
00543
00544 int
00545 tls_symbolic_operand_1 (rtx op, int size, int unspec)
00546 {
00547 op = XEXP (op, 0);
00548
00549 if (GET_CODE (op) != UNSPEC || XINT (op, 1) != unspec)
00550 return 0;
00551 op = XVECEXP (op, 0, 0);
00552
00553 if (GET_CODE (op) != SYMBOL_REF)
00554 return 0;
00555
00556 switch (SYMBOL_REF_TLS_MODEL (op))
00557 {
00558 case TLS_MODEL_LOCAL_DYNAMIC:
00559 return unspec == UNSPEC_DTPREL && size == alpha_tls_size;
00560 case TLS_MODEL_INITIAL_EXEC:
00561 return unspec == UNSPEC_TPREL && size == 64;
00562 case TLS_MODEL_LOCAL_EXEC:
00563 return unspec == UNSPEC_TPREL && size == alpha_tls_size;
00564 default:
00565 gcc_unreachable ();
00566 }
00567 }
00568
00569
00570
00571
00572 rtx
00573 resolve_reload_operand (rtx op)
00574 {
00575 if (reload_in_progress)
00576 {
00577 rtx tmp = op;
00578 if (GET_CODE (tmp) == SUBREG)
00579 tmp = SUBREG_REG (tmp);
00580 if (GET_CODE (tmp) == REG
00581 && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
00582 {
00583 op = reg_equiv_memory_loc[REGNO (tmp)];
00584 if (op == 0)
00585 return 0;
00586 }
00587 }
00588 return op;
00589 }
00590
00591
00592
00593
00594 bool
00595 alpha_const_ok_for_letter_p (HOST_WIDE_INT value, int c)
00596 {
00597 switch (c)
00598 {
00599 case 'I':
00600
00601 return (unsigned HOST_WIDE_INT) value < 0x100;
00602 case 'J':
00603
00604 return value == 0;
00605 case 'K':
00606
00607 return (unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000;
00608 case 'L':
00609
00610 return ((value & 0xffff) == 0
00611 && ((value) >> 31 == -1 || value >> 31 == 0));
00612 case 'M':
00613
00614 return zap_mask (value);
00615 case 'N':
00616
00617 return (unsigned HOST_WIDE_INT) (~ value) < 0x100;
00618 case 'O':
00619
00620 return (unsigned HOST_WIDE_INT) (- value) < 0x100;
00621 case 'P':
00622
00623 return value == 1 || value == 2 || value == 3;
00624
00625 default:
00626 return false;
00627 }
00628 }
00629
00630
00631
00632
00633 bool
00634 alpha_const_double_ok_for_letter_p (rtx value, int c)
00635 {
00636 switch (c)
00637 {
00638 case 'G':
00639
00640 return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
00641 && value == CONST0_RTX (GET_MODE (value)));
00642
00643 case 'H':
00644
00645 return (GET_MODE (value) == VOIDmode
00646 && zap_mask (CONST_DOUBLE_LOW (value))
00647 && zap_mask (CONST_DOUBLE_HIGH (value)));
00648
00649 default:
00650 return false;
00651 }
00652 }
00653
00654
00655
00656
00657 bool
00658 alpha_extra_constraint (rtx value, int c)
00659 {
00660 switch (c)
00661 {
00662 case 'Q':
00663 return normal_memory_operand (value, VOIDmode);
00664 case 'R':
00665 return direct_call_operand (value, Pmode);
00666 case 'S':
00667 return (GET_CODE (value) == CONST_INT
00668 && (unsigned HOST_WIDE_INT) INTVAL (value) < 64);
00669 case 'T':
00670 return GET_CODE (value) == HIGH;
00671 case 'U':
00672 return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
00673 case 'W':
00674 return (GET_CODE (value) == CONST_VECTOR
00675 && value == CONST0_RTX (GET_MODE (value)));
00676 default:
00677 return false;
00678 }
00679 }
00680
00681
00682
00683
00684
00685
00686 static bool
00687 alpha_scalar_mode_supported_p (enum machine_mode mode)
00688 {
00689 switch (mode)
00690 {
00691 case QImode:
00692 case HImode:
00693 case SImode:
00694 case DImode:
00695 case TImode:
00696 return true;
00697
00698 case SFmode:
00699 case DFmode:
00700 return true;
00701
00702 case TFmode:
00703 return TARGET_HAS_XFLOATING_LIBS;
00704
00705 default:
00706 return false;
00707 }
00708 }
00709
00710
00711
00712
00713
00714
00715 static bool
00716 alpha_vector_mode_supported_p (enum machine_mode mode)
00717 {
00718 return mode == V8QImode || mode == V4HImode || mode == V2SImode;
00719 }
00720
00721
00722
00723 int
00724 direct_return (void)
00725 {
00726 return (! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK
00727 && reload_completed
00728 && alpha_sa_size () == 0
00729 && get_frame_size () == 0
00730 && current_function_outgoing_args_size == 0
00731 && current_function_pretend_args_size == 0);
00732 }
00733
00734
00735
00736 rtx
00737 alpha_tablejump_addr_vec (rtx insn)
00738 {
00739 rtx tmp;
00740
00741 tmp = JUMP_LABEL (insn);
00742 if (!tmp)
00743 return NULL_RTX;
00744 tmp = NEXT_INSN (tmp);
00745 if (!tmp)
00746 return NULL_RTX;
00747 if (GET_CODE (tmp) == JUMP_INSN
00748 && GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)
00749 return PATTERN (tmp);
00750 return NULL_RTX;
00751 }
00752
00753
00754
00755 rtx
00756 alpha_tablejump_best_label (rtx insn)
00757 {
00758 rtx jump_table = alpha_tablejump_addr_vec (insn);
00759 rtx best_label = NULL_RTX;
00760
00761
00762
00763
00764 if (jump_table)
00765 {
00766 int n_labels = XVECLEN (jump_table, 1);
00767 int best_count = -1;
00768 int i, j;
00769
00770 for (i = 0; i < n_labels; i++)
00771 {
00772 int count = 1;
00773
00774 for (j = i + 1; j < n_labels; j++)
00775 if (XEXP (XVECEXP (jump_table, 1, i), 0)
00776 == XEXP (XVECEXP (jump_table, 1, j), 0))
00777 count++;
00778
00779 if (count > best_count)
00780 best_count = count, best_label = XVECEXP (jump_table, 1, i);
00781 }
00782 }
00783
00784 return best_label ? best_label : const0_rtx;
00785 }
00786
00787
00788
00789 static enum tls_model
00790 tls_symbolic_operand_type (rtx symbol)
00791 {
00792 enum tls_model model;
00793
00794 if (GET_CODE (symbol) != SYMBOL_REF)
00795 return 0;
00796 model = SYMBOL_REF_TLS_MODEL (symbol);
00797
00798
00799 if (model == TLS_MODEL_LOCAL_EXEC && alpha_tls_size == 64)
00800 model = TLS_MODEL_INITIAL_EXEC;
00801
00802 return model;
00803 }
00804
00805
00806
00807
00808 static bool
00809 decl_has_samegp (tree decl)
00810 {
00811
00812
00813 if (!(*targetm.binds_local_p) (decl))
00814 return false;
00815
00816
00817
00818
00819
00820 if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA)
00821 return true;
00822
00823
00824
00825
00826 return !TREE_PUBLIC (decl) || !DECL_EXTERNAL (decl);
00827 }
00828
00829
00830
00831 static bool
00832 alpha_in_small_data_p (tree exp)
00833 {
00834
00835 if (TREE_CODE (exp) == STRING_CST)
00836 return false;
00837
00838
00839 if (TREE_CODE (exp) == FUNCTION_DECL)
00840 return false;
00841
00842 if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
00843 {
00844 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
00845 if (strcmp (section, ".sdata") == 0
00846 || strcmp (section, ".sbss") == 0)
00847 return true;
00848 }
00849 else
00850 {
00851 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
00852
00853
00854
00855 if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value)
00856 return true;
00857 }
00858
00859 return false;
00860 }
00861
00862 #if TARGET_ABI_OPEN_VMS
00863 static bool
00864 alpha_linkage_symbol_p (const char *symname)
00865 {
00866 int symlen = strlen (symname);
00867
00868 if (symlen > 4)
00869 return strcmp (&symname [symlen - 4], "..lk") == 0;
00870
00871 return false;
00872 }
00873
00874 #define LINKAGE_SYMBOL_REF_P(X) \
00875 ((GET_CODE (X) == SYMBOL_REF \
00876 && alpha_linkage_symbol_p (XSTR (X, 0))) \
00877 || (GET_CODE (X) == CONST \
00878 && GET_CODE (XEXP (X, 0)) == PLUS \
00879 && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \
00880 && alpha_linkage_symbol_p (XSTR (XEXP (XEXP (X, 0), 0), 0))))
00881 #endif
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 bool
00893 alpha_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
00894 {
00895
00896 if (mode == DImode
00897 && GET_CODE (x) == AND
00898 && GET_CODE (XEXP (x, 1)) == CONST_INT
00899 && INTVAL (XEXP (x, 1)) == -8)
00900 x = XEXP (x, 0);
00901
00902
00903 if (GET_CODE (x) == SUBREG
00904 && (GET_MODE_SIZE (GET_MODE (x))
00905 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
00906 x = SUBREG_REG (x);
00907
00908
00909 if (REG_P (x)
00910 && (strict
00911 ? STRICT_REG_OK_FOR_BASE_P (x)
00912 : NONSTRICT_REG_OK_FOR_BASE_P (x)))
00913 return true;
00914
00915
00916 if (CONSTANT_ADDRESS_P (x))
00917 return true;
00918
00919 #if TARGET_ABI_OPEN_VMS
00920 if (LINKAGE_SYMBOL_REF_P (x))
00921 return true;
00922 #endif
00923
00924
00925 if (GET_CODE (x) == PLUS)
00926 {
00927 rtx ofs = XEXP (x, 1);
00928 x = XEXP (x, 0);
00929
00930
00931 if (GET_CODE (x) == SUBREG
00932 && (GET_MODE_SIZE (GET_MODE (x))
00933 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
00934 x = SUBREG_REG (x);
00935
00936 if (REG_P (x))
00937 {
00938 if (! strict
00939 && NONSTRICT_REG_OK_FP_BASE_P (x)
00940 && GET_CODE (ofs) == CONST_INT)
00941 return true;
00942 if ((strict
00943 ? STRICT_REG_OK_FOR_BASE_P (x)
00944 : NONSTRICT_REG_OK_FOR_BASE_P (x))
00945 && CONSTANT_ADDRESS_P (ofs))
00946 return true;
00947 }
00948 }
00949
00950
00951
00952 else if (TARGET_EXPLICIT_RELOCS)
00953 {
00954 if (small_symbolic_operand (x, Pmode))
00955 return true;
00956
00957 if (GET_CODE (x) == LO_SUM)
00958 {
00959 rtx ofs = XEXP (x, 1);
00960 x = XEXP (x, 0);
00961
00962
00963 if (GET_CODE (x) == SUBREG
00964 && (GET_MODE_SIZE (GET_MODE (x))
00965 < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
00966 x = SUBREG_REG (x);
00967
00968
00969 if (! (REG_P (x)
00970 && (strict
00971 ? STRICT_REG_OK_FOR_BASE_P (x)
00972 : NONSTRICT_REG_OK_FOR_BASE_P (x))))
00973 return false;
00974
00975
00976 if (local_symbolic_operand (ofs, Pmode)
00977 || dtp32_symbolic_operand (ofs, Pmode)
00978 || tp32_symbolic_operand (ofs, Pmode))
00979 return true;
00980 }
00981 }
00982
00983 return false;
00984 }
00985
00986
00987
00988 static GTY(()) rtx tls_get_addr_libfunc;
00989
00990 static rtx
00991 get_tls_get_addr (void)
00992 {
00993 if (!tls_get_addr_libfunc)
00994 tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
00995 return tls_get_addr_libfunc;
00996 }
00997
00998
00999
01000
01001 rtx
01002 alpha_legitimize_address (rtx x, rtx scratch,
01003 enum machine_mode mode ATTRIBUTE_UNUSED)
01004 {
01005 HOST_WIDE_INT addend;
01006
01007
01008
01009
01010 if (GET_CODE (x) == PLUS
01011 && GET_CODE (XEXP (x, 0)) == REG
01012 && GET_CODE (XEXP (x, 1)) == CONST_INT
01013 && ! CONSTANT_ADDRESS_P (XEXP (x, 1)))
01014 {
01015 addend = INTVAL (XEXP (x, 1));
01016 x = XEXP (x, 0);
01017 goto split_addend;
01018 }
01019
01020
01021
01022
01023
01024 if (!no_new_pseudos
01025 && GET_CODE (x) == CONST
01026 && GET_CODE (XEXP (x, 0)) == PLUS
01027 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
01028 {
01029 addend = INTVAL (XEXP (XEXP (x, 0), 1));
01030 x = force_reg (Pmode, XEXP (XEXP (x, 0), 0));
01031 goto split_addend;
01032 }
01033
01034
01035
01036
01037 if (!no_new_pseudos
01038 && GET_CODE (x) == PLUS
01039 && GET_CODE (XEXP (x, 0)) == REG
01040 && GET_CODE (XEXP (x, 1)) == CONST
01041 && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
01042 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)
01043 {
01044 addend = INTVAL (XEXP (XEXP (XEXP (x, 1), 0), 1));
01045 x = expand_simple_binop (Pmode, PLUS, XEXP (x, 0),
01046 XEXP (XEXP (XEXP (x, 1), 0), 0),
01047 NULL_RTX, 1, OPTAB_LIB_WIDEN);
01048 goto split_addend;
01049 }
01050
01051
01052 if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
01053 {
01054 rtx r0, r16, eqv, tga, tp, insn, dest, seq;
01055
01056 switch (tls_symbolic_operand_type (x))
01057 {
01058 case TLS_MODEL_NONE:
01059 break;
01060
01061 case TLS_MODEL_GLOBAL_DYNAMIC:
01062 start_sequence ();
01063
01064 r0 = gen_rtx_REG (Pmode, 0);
01065 r16 = gen_rtx_REG (Pmode, 16);
01066 tga = get_tls_get_addr ();
01067 dest = gen_reg_rtx (Pmode);
01068 seq = GEN_INT (alpha_next_sequence_number++);
01069
01070 emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
01071 insn = gen_call_value_osf_tlsgd (r0, tga, seq);
01072 insn = emit_call_insn (insn);
01073 CONST_OR_PURE_CALL_P (insn) = 1;
01074 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
01075
01076 insn = get_insns ();
01077 end_sequence ();
01078
01079 emit_libcall_block (insn, dest, r0, x);
01080 return dest;
01081
01082 case TLS_MODEL_LOCAL_DYNAMIC:
01083 start_sequence ();
01084
01085 r0 = gen_rtx_REG (Pmode, 0);
01086 r16 = gen_rtx_REG (Pmode, 16);
01087 tga = get_tls_get_addr ();
01088 scratch = gen_reg_rtx (Pmode);
01089 seq = GEN_INT (alpha_next_sequence_number++);
01090
01091 emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
01092 insn = gen_call_value_osf_tlsldm (r0, tga, seq);
01093 insn = emit_call_insn (insn);
01094 CONST_OR_PURE_CALL_P (insn) = 1;
01095 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
01096
01097 insn = get_insns ();
01098 end_sequence ();
01099
01100 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
01101 UNSPEC_TLSLDM_CALL);
01102 emit_libcall_block (insn, scratch, r0, eqv);
01103
01104 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL);
01105 eqv = gen_rtx_CONST (Pmode, eqv);
01106
01107 if (alpha_tls_size == 64)
01108 {
01109 dest = gen_reg_rtx (Pmode);
01110 emit_insn (gen_rtx_SET (VOIDmode, dest, eqv));
01111 emit_insn (gen_adddi3 (dest, dest, scratch));
01112 return dest;
01113 }
01114 if (alpha_tls_size == 32)
01115 {
01116 insn = gen_rtx_HIGH (Pmode, eqv);
01117 insn = gen_rtx_PLUS (Pmode, scratch, insn);
01118 scratch = gen_reg_rtx (Pmode);
01119 emit_insn (gen_rtx_SET (VOIDmode, scratch, insn));
01120 }
01121 return gen_rtx_LO_SUM (Pmode, scratch, eqv);
01122
01123 case TLS_MODEL_INITIAL_EXEC:
01124 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
01125 eqv = gen_rtx_CONST (Pmode, eqv);
01126 tp = gen_reg_rtx (Pmode);
01127 scratch = gen_reg_rtx (Pmode);
01128 dest = gen_reg_rtx (Pmode);
01129
01130 emit_insn (gen_load_tp (tp));
01131 emit_insn (gen_rtx_SET (VOIDmode, scratch, eqv));
01132 emit_insn (gen_adddi3 (dest, tp, scratch));
01133 return dest;
01134
01135 case TLS_MODEL_LOCAL_EXEC:
01136 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
01137 eqv = gen_rtx_CONST (Pmode, eqv);
01138 tp = gen_reg_rtx (Pmode);
01139
01140 emit_insn (gen_load_tp (tp));
01141 if (alpha_tls_size == 32)
01142 {
01143 insn = gen_rtx_HIGH (Pmode, eqv);
01144 insn = gen_rtx_PLUS (Pmode, tp, insn);
01145 tp = gen_reg_rtx (Pmode);
01146 emit_insn (gen_rtx_SET (VOIDmode, tp, insn));
01147 }
01148 return gen_rtx_LO_SUM (Pmode, tp, eqv);
01149
01150 default:
01151 gcc_unreachable ();
01152 }
01153
01154 if (local_symbolic_operand (x, Pmode))
01155 {
01156 if (small_symbolic_operand (x, Pmode))
01157 return x;
01158 else
01159 {
01160 if (!no_new_pseudos)
01161 scratch = gen_reg_rtx (Pmode);
01162 emit_insn (gen_rtx_SET (VOIDmode, scratch,
01163 gen_rtx_HIGH (Pmode, x)));
01164 return gen_rtx_LO_SUM (Pmode, scratch, x);
01165 }
01166 }
01167 }
01168
01169 return NULL;
01170
01171 split_addend:
01172 {
01173 HOST_WIDE_INT low, high;
01174
01175 low = ((addend & 0xffff) ^ 0x8000) - 0x8000;
01176 addend -= low;
01177 high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000;
01178 addend -= high;
01179
01180 if (addend)
01181 x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend),
01182 (no_new_pseudos ? scratch : NULL_RTX),
01183 1, OPTAB_LIB_WIDEN);
01184 if (high)
01185 x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high),
01186 (no_new_pseudos ? scratch : NULL_RTX),
01187 1, OPTAB_LIB_WIDEN);
01188
01189 return plus_constant (x, low);
01190 }
01191 }
01192
01193
01194
01195
01196
01197 static bool
01198 alpha_cannot_force_const_mem (rtx x)
01199 {
01200 enum rtx_code code = GET_CODE (x);
01201 return code == SYMBOL_REF || code == LABEL_REF || code == CONST;
01202 }
01203
01204
01205
01206
01207
01208 static bool
01209 alpha_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
01210 {
01211
01212
01213 if (!decl)
01214 return false;
01215
01216
01217
01218 return decl_has_samegp (decl);
01219 }
01220
01221 int
01222 some_small_symbolic_operand_int (rtx *px, void *data ATTRIBUTE_UNUSED)
01223 {
01224 rtx x = *px;
01225
01226
01227 if (GET_CODE (x) == LO_SUM)
01228 return -1;
01229
01230 return small_symbolic_operand (x, Pmode) != 0;
01231 }
01232
01233 static int
01234 split_small_symbolic_operand_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
01235 {
01236 rtx x = *px;
01237
01238
01239 if (GET_CODE (x) == LO_SUM)
01240 return -1;
01241
01242 if (small_symbolic_operand (x, Pmode))
01243 {
01244 x = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, x);
01245 *px = x;
01246 return -1;
01247 }
01248
01249 return 0;
01250 }
01251
01252 rtx
01253 split_small_symbolic_operand (rtx x)
01254 {
01255 x = copy_insn (x);
01256 for_each_rtx (&x, split_small_symbolic_operand_1, NULL);
01257 return x;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 static bool
01275 alpha_cannot_copy_insn_p (rtx insn)
01276 {
01277 if (!reload_completed || !TARGET_EXPLICIT_RELOCS)
01278 return false;
01279 if (recog_memoized (insn) >= 0)
01280 return get_attr_cannot_copy (insn);
01281 else
01282 return false;
01283 }
01284
01285
01286
01287
01288
01289 rtx
01290 alpha_legitimize_reload_address (rtx x,
01291 enum machine_mode mode ATTRIBUTE_UNUSED,
01292 int opnum, int type,
01293 int ind_levels ATTRIBUTE_UNUSED)
01294 {
01295
01296 if (GET_CODE (x) == PLUS
01297 && GET_CODE (XEXP (x, 0)) == PLUS
01298 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
01299 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01300 && GET_CODE (XEXP (x, 1)) == CONST_INT)
01301 {
01302 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01303 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01304 opnum, type);
01305 return x;
01306 }
01307
01308
01309
01310
01311 if (GET_CODE (x) == PLUS
01312 && GET_CODE (XEXP (x, 0)) == REG
01313 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
01314 && REGNO_OK_FOR_BASE_P (REGNO (XEXP (x, 0)))
01315 && GET_CODE (XEXP (x, 1)) == CONST_INT)
01316 {
01317 HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
01318 HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
01319 HOST_WIDE_INT high
01320 = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
01321
01322
01323 if (high + low != val)
01324 return NULL_RTX;
01325
01326
01327
01328 x = gen_rtx_PLUS (GET_MODE (x),
01329 gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
01330 GEN_INT (high)),
01331 GEN_INT (low));
01332
01333 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
01334 BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
01335 opnum, type);
01336 return x;
01337 }
01338
01339 return NULL_RTX;
01340 }
01341
01342
01343
01344
01345
01346 static bool
01347 alpha_rtx_costs (rtx x, int code, int outer_code, int *total)
01348 {
01349 enum machine_mode mode = GET_MODE (x);
01350 bool float_mode_p = FLOAT_MODE_P (mode);
01351 const struct alpha_rtx_cost_data *cost_data;
01352
01353 if (optimize_size)
01354 cost_data = &alpha_rtx_cost_size;
01355 else
01356 cost_data = &alpha_rtx_cost_data[alpha_tune];
01357
01358 switch (code)
01359 {
01360 case CONST_INT:
01361
01362
01363
01364
01365
01366 if (INTVAL (x) >= 0 && INTVAL (x) < 256)
01367 {
01368 *total = 0;
01369 return true;
01370 }
01371
01372
01373 case CONST_DOUBLE:
01374 if (x == CONST0_RTX (mode))
01375 *total = 0;
01376 else if ((outer_code == PLUS && add_operand (x, VOIDmode))
01377 || (outer_code == AND && and_operand (x, VOIDmode)))
01378 *total = 0;
01379 else if (add_operand (x, VOIDmode) || and_operand (x, VOIDmode))
01380 *total = 2;
01381 else
01382 *total = COSTS_N_INSNS (2);
01383 return true;
01384
01385 case CONST:
01386 case SYMBOL_REF:
01387 case LABEL_REF:
01388 if (TARGET_EXPLICIT_RELOCS && small_symbolic_operand (x, VOIDmode))
01389 *total = COSTS_N_INSNS (outer_code != MEM);
01390 else if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, VOIDmode))
01391 *total = COSTS_N_INSNS (1 + (outer_code != MEM));
01392 else if (tls_symbolic_operand_type (x))
01393
01394
01395 *total = COSTS_N_INSNS (15);
01396 else
01397
01398 *total = COSTS_N_INSNS (optimize_size ? 1 : alpha_memory_latency);
01399 return true;
01400
01401 case HIGH:
01402
01403 *total = 2;
01404 return true;
01405
01406 case PLUS:
01407 case MINUS:
01408 if (float_mode_p)
01409 *total = cost_data->fp_add;
01410 else if (GET_CODE (XEXP (x, 0)) == MULT
01411 && const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
01412 {
01413 *total = (rtx_cost (XEXP (XEXP (x, 0), 0), outer_code)
01414 + rtx_cost (XEXP (x, 1), outer_code) + COSTS_N_INSNS (1));
01415 return true;
01416 }
01417 return false;
01418
01419 case MULT:
01420 if (float_mode_p)
01421 *total = cost_data->fp_mult;
01422 else if (mode == DImode)
01423 *total = cost_data->int_mult_di;
01424 else
01425 *total = cost_data->int_mult_si;
01426 return false;
01427
01428 case ASHIFT:
01429 if (GET_CODE (XEXP (x, 1)) == CONST_INT
01430 && INTVAL (XEXP (x, 1)) <= 3)
01431 {
01432 *total = COSTS_N_INSNS (1);
01433 return false;
01434 }
01435
01436
01437 case ASHIFTRT:
01438 case LSHIFTRT:
01439 *total = cost_data->int_shift;
01440 return false;
01441
01442 case IF_THEN_ELSE:
01443 if (float_mode_p)
01444 *total = cost_data->fp_add;
01445 else
01446 *total = cost_data->int_cmov;
01447 return false;
01448
01449 case DIV:
01450 case UDIV:
01451 case MOD:
01452 case UMOD:
01453 if (!float_mode_p)
01454 *total = cost_data->int_div;
01455 else if (mode == SFmode)
01456 *total = cost_data->fp_div_sf;
01457 else
01458 *total = cost_data->fp_div_df;
01459 return false;
01460
01461 case MEM:
01462 *total = COSTS_N_INSNS (optimize_size ? 1 : alpha_memory_latency);
01463 return true;
01464
01465 case NEG:
01466 if (! float_mode_p)
01467 {
01468 *total = COSTS_N_INSNS (1);
01469 return false;
01470 }
01471
01472
01473 case ABS:
01474 if (! float_mode_p)
01475 {
01476 *total = COSTS_N_INSNS (1) + cost_data->int_cmov;
01477 return false;
01478 }
01479
01480
01481 case FLOAT:
01482 case UNSIGNED_FLOAT:
01483 case FIX:
01484 case UNSIGNED_FIX:
01485 case FLOAT_TRUNCATE:
01486 *total = cost_data->fp_add;
01487 return false;
01488
01489 case FLOAT_EXTEND:
01490 if (GET_CODE (XEXP (x, 0)) == MEM)
01491 *total = 0;
01492 else
01493 *total = cost_data->fp_add;
01494 return false;
01495
01496 default:
01497 return false;
01498 }
01499 }
01500
01501
01502
01503
01504
01505
01506 void
01507 get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum)
01508 {
01509 rtx base;
01510 HOST_WIDE_INT disp, offset;
01511
01512 gcc_assert (GET_CODE (ref) == MEM);
01513
01514 if (reload_in_progress
01515 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
01516 {
01517 base = find_replacement (&XEXP (ref, 0));
01518 gcc_assert (memory_address_p (GET_MODE (ref), base));
01519 }
01520 else
01521 base = XEXP (ref, 0);
01522
01523 if (GET_CODE (base) == PLUS)
01524 disp = INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
01525 else
01526 disp = 0;
01527
01528
01529
01530
01531
01532 if (MEM_ALIGN (ref) >= 32)
01533 offset = 0;
01534 else
01535 offset = disp & 3;
01536
01537
01538 *paligned_mem = widen_memory_access (ref, SImode, -offset);
01539
01540
01541 if (WORDS_BIG_ENDIAN)
01542 offset = 32 - (GET_MODE_BITSIZE (GET_MODE (ref)) + offset * 8);
01543 else
01544 offset *= 8;
01545 *pbitnum = GEN_INT (offset);
01546 }
01547
01548
01549
01550
01551 rtx
01552 get_unaligned_address (rtx ref)
01553 {
01554 rtx base;
01555 HOST_WIDE_INT offset = 0;
01556
01557 gcc_assert (GET_CODE (ref) == MEM);
01558
01559 if (reload_in_progress
01560 && ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
01561 {
01562 base = find_replacement (&XEXP (ref, 0));
01563
01564 gcc_assert (memory_address_p (GET_MODE (ref), base));
01565 }
01566 else
01567 base = XEXP (ref, 0);
01568
01569 if (GET_CODE (base) == PLUS)
01570 offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
01571
01572 return plus_constant (base, offset);
01573 }
01574
01575
01576
01577
01578 rtx
01579 get_unaligned_offset (rtx addr, HOST_WIDE_INT ofs)
01580 {
01581 if (GET_CODE (addr) == PLUS)
01582 {
01583 ofs += INTVAL (XEXP (addr, 1));
01584 addr = XEXP (addr, 0);
01585 }
01586
01587 return expand_simple_binop (Pmode, PLUS, addr, GEN_INT (ofs & 7),
01588 NULL_RTX, 1, OPTAB_LIB_WIDEN);
01589 }
01590
01591
01592
01593
01594
01595
01596 enum reg_class
01597 alpha_preferred_reload_class(rtx x, enum reg_class class)
01598 {
01599
01600 if (x == CONST0_RTX (GET_MODE (x)))
01601 return class;
01602
01603
01604 if (GET_CODE (x) == CONST_INT
01605 || GET_CODE (x) == CONST_DOUBLE
01606 || GET_CODE (x) == CONST_VECTOR)
01607 {
01608 if (class == FLOAT_REGS)
01609 return NO_REGS;
01610 if (class == ALL_REGS)
01611 return GENERAL_REGS;
01612 return class;
01613 }
01614
01615
01616
01617
01618 if (CONSTANT_P (x))
01619 return (class == ALL_REGS ? GENERAL_REGS : class);
01620
01621 return class;
01622 }
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635 enum reg_class
01636 alpha_secondary_reload_class (enum reg_class class, enum machine_mode mode,
01637 rtx x, int in)
01638 {
01639 if ((mode == QImode || mode == HImode) && ! TARGET_BWX)
01640 {
01641 if (GET_CODE (x) == MEM
01642 || (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
01643 || (GET_CODE (x) == SUBREG
01644 && (GET_CODE (SUBREG_REG (x)) == MEM
01645 || (GET_CODE (SUBREG_REG (x)) == REG
01646 && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER))))
01647 {
01648 if (!in || !aligned_memory_operand(x, mode))
01649 return GENERAL_REGS;
01650 }
01651 }
01652
01653 if (class == FLOAT_REGS)
01654 {
01655 if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
01656 return GENERAL_REGS;
01657
01658 if (GET_CODE (x) == SUBREG
01659 && (GET_MODE_SIZE (GET_MODE (x))
01660 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
01661 return GENERAL_REGS;
01662
01663 if (in && INTEGRAL_MODE_P (mode)
01664 && ! (memory_operand (x, mode) || x == const0_rtx))
01665 return GENERAL_REGS;
01666 }
01667
01668 return NO_REGS;
01669 }
01670
01671
01672
01673
01674 static int
01675 alpha_set_memflags_1 (rtx *xp, void *data)
01676 {
01677 rtx x = *xp, orig = (rtx) data;
01678
01679 if (GET_CODE (x) != MEM)
01680 return 0;
01681
01682 MEM_VOLATILE_P (x) = MEM_VOLATILE_P (orig);
01683 MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (orig);
01684 MEM_SCALAR_P (x) = MEM_SCALAR_P (orig);
01685 MEM_NOTRAP_P (x) = MEM_NOTRAP_P (orig);
01686 MEM_READONLY_P (x) = MEM_READONLY_P (orig);
01687
01688
01689
01690
01691
01692
01693
01694 return -1;
01695 }
01696
01697
01698
01699
01700
01701
01702
01703 void
01704 alpha_set_memflags (rtx insn, rtx ref)
01705 {
01706 rtx *base_ptr;
01707
01708 if (GET_CODE (ref) != MEM)
01709 return;
01710
01711
01712
01713
01714 if (!MEM_VOLATILE_P (ref)
01715 && !MEM_IN_STRUCT_P (ref)
01716 && !MEM_SCALAR_P (ref)
01717 && !MEM_NOTRAP_P (ref)
01718 && !MEM_READONLY_P (ref))
01719 return;
01720
01721 if (INSN_P (insn))
01722 base_ptr = &PATTERN (insn);
01723 else
01724 base_ptr = &insn;
01725 for_each_rtx (base_ptr, alpha_set_memflags_1, (void *) ref);
01726 }
01727
01728 static rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT,
01729 int, bool);
01730
01731
01732
01733
01734
01735 static rtx
01736 alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
01737 HOST_WIDE_INT c, int n, bool no_output)
01738 {
01739 HOST_WIDE_INT new;
01740 int i, bits;
01741
01742 rtx subtarget
01743 = (flag_expensive_optimizations && !no_new_pseudos ? 0 : target);
01744 rtx temp, insn;
01745
01746
01747
01748
01749
01750 if (HOST_BITS_PER_WIDE_INT != 64
01751 || c >> 31 == -1 || c >> 31 == 0)
01752 {
01753 HOST_WIDE_INT low = ((c & 0xffff) ^ 0x8000) - 0x8000;
01754 HOST_WIDE_INT tmp1 = c - low;
01755 HOST_WIDE_INT high = (((tmp1 >> 16) & 0xffff) ^ 0x8000) - 0x8000;
01756 HOST_WIDE_INT extra = 0;
01757
01758
01759
01760
01761 if ((high & 0x8000) != 0 && c >= 0)
01762 {
01763 extra = 0x4000;
01764 tmp1 -= 0x40000000;
01765 high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
01766 }
01767
01768 if (c == low || (low == 0 && extra == 0))
01769 {
01770
01771
01772
01773
01774
01775
01776 if (no_output)
01777 return pc_rtx;
01778 if (target == NULL)
01779 target = gen_reg_rtx (mode);
01780 emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
01781 return target;
01782 }
01783 else if (n >= 2 + (extra != 0))
01784 {
01785 if (no_output)
01786 return pc_rtx;
01787 if (no_new_pseudos)
01788 {
01789 emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (high << 16)));
01790 temp = target;
01791 }
01792 else
01793 temp = copy_to_suggested_reg (GEN_INT (high << 16),
01794 subtarget, mode);
01795
01796
01797
01798
01799
01800
01801
01802 if (extra != 0)
01803 {
01804 if (! subtarget)
01805 subtarget = gen_reg_rtx (mode);
01806 insn = gen_rtx_PLUS (mode, temp, GEN_INT (extra << 16));
01807 insn = gen_rtx_SET (VOIDmode, subtarget, insn);
01808 emit_insn (insn);
01809 temp = subtarget;
01810 }
01811
01812 if (target == NULL)
01813 target = gen_reg_rtx (mode);
01814 insn = gen_rtx_PLUS (mode, temp, GEN_INT (low));
01815 insn = gen_rtx_SET (VOIDmode, target, insn);
01816 emit_insn (insn);
01817 return target;
01818 }
01819 }
01820
01821
01822
01823
01824
01825
01826 if (n == 1 || (mode == SImode && no_new_pseudos))
01827 return 0;
01828
01829
01830
01831
01832
01833 for (i = 1; i < n; i++)
01834 {
01835
01836
01837
01838 new = ((c & 0xffff) ^ 0x8000) - 0x8000;
01839 if (new != 0)
01840 {
01841 temp = alpha_emit_set_const (subtarget, mode, c - new, i, no_output);
01842 if (temp)
01843 {
01844 if (no_output)
01845 return temp;
01846 return expand_binop (mode, add_optab, temp, GEN_INT (new),
01847 target, 0, OPTAB_WIDEN);
01848 }
01849 }
01850
01851
01852 temp = alpha_emit_set_const (subtarget, mode, ~c, i, no_output);
01853 if (temp)
01854 {
01855 if (no_output)
01856 return temp;
01857 return expand_unop (mode, one_cmpl_optab, temp, target, 0);
01858 }
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869 bits = exact_log2 (c & -c);
01870 if (bits > 0)
01871 for (; bits > 0; bits--)
01872 {
01873 new = c >> bits;
01874 temp = alpha_emit_set_const (subtarget, mode, new, i, no_output);
01875 if (!temp && c < 0)
01876 {
01877 new = (unsigned HOST_WIDE_INT)c >> bits;
01878 temp = alpha_emit_set_const (subtarget, mode, new,
01879 i, no_output);
01880 }
01881 if (temp)
01882 {
01883 if (no_output)
01884 return temp;
01885 return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
01886 target, 0, OPTAB_WIDEN);
01887 }
01888 }
01889
01890
01891
01892
01893
01894
01895
01896 bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
01897 - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64));
01898 if (bits > 0)
01899 for (; bits > 0; bits--)
01900 {
01901 new = c << bits;
01902 temp = alpha_emit_set_const (subtarget, mode, new, i, no_output);
01903 if (!temp)
01904 {
01905 new = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1);
01906 temp = alpha_emit_set_const (subtarget, mode, new,
01907 i, no_output);
01908 }
01909 if (temp)
01910 {
01911 if (no_output)
01912 return temp;
01913 return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
01914 target, 1, OPTAB_WIDEN);
01915 }
01916 }
01917
01918
01919
01920
01921
01922 bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
01923 - floor_log2 (~ c) - 2);
01924 if (bits > 0)
01925 for (; bits > 0; bits--)
01926 {
01927 new = c << bits;
01928 temp = alpha_emit_set_const (subtarget, mode, new, i, no_output);
01929 if (!temp)
01930 {
01931 new = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1);
01932 temp = alpha_emit_set_const (subtarget, mode, new,
01933 i, no_output);
01934 }
01935 if (temp)
01936 {
01937 if (no_output)
01938 return temp;
01939 return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
01940 target, 0, OPTAB_WIDEN);
01941 }
01942 }
01943 }
01944
01945 #if HOST_BITS_PER_WIDE_INT == 64
01946
01947
01948
01949
01950 new = c;
01951 for (i = 0; i < 64; i += 8)
01952 if ((new & ((HOST_WIDE_INT) 0xff << i)) == 0)
01953 new |= (HOST_WIDE_INT) 0xff << i;
01954
01955
01956
01957
01958 if (mode == SImode)
01959 new = ((new & 0xffffffff) ^ 0x80000000) - 0x80000000;
01960
01961 if (new != c)
01962 {
01963 temp = alpha_emit_set_const (subtarget, mode, new, n - 1, no_output);
01964 if (temp)
01965 {
01966 if (no_output)
01967 return temp;
01968 return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
01969 target, 0, OPTAB_WIDEN);
01970 }
01971 }
01972 #endif
01973
01974 return 0;
01975 }
01976
01977
01978
01979
01980
01981
01982
01983 static rtx
01984 alpha_emit_set_const (rtx target, enum machine_mode mode,
01985 HOST_WIDE_INT c, int n, bool no_output)
01986 {
01987 enum machine_mode orig_mode = mode;
01988 rtx orig_target = target;
01989 rtx result = 0;
01990 int i;
01991
01992
01993
01994 if (no_new_pseudos && mode == SImode
01995 && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
01996 {
01997 result = alpha_emit_set_const_1 (target, mode, c, 1, no_output);
01998 if (result)
01999 return result;
02000
02001 target = no_output ? NULL : gen_lowpart (DImode, target);
02002 mode = DImode;
02003 }
02004 else if (mode == V8QImode || mode == V4HImode || mode == V2SImode)
02005 {
02006 target = no_output ? NULL : gen_lowpart (DImode, target);
02007 mode = DImode;
02008 }
02009
02010
02011 for (i = 1; i <= n; i++)
02012 {
02013 result = alpha_emit_set_const_1 (target, mode, c, i, no_output);
02014 if (result)
02015 {
02016 rtx insn, set;
02017
02018 if (no_output)
02019 return result;
02020
02021 insn = get_last_insn ();
02022 set = single_set (insn);
02023 if (! CONSTANT_P (SET_SRC (set)))
02024 set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c));
02025 break;
02026 }
02027 }
02028
02029
02030 if (result)
02031 {
02032 if (result == target)
02033 result = orig_target;
02034 else if (mode != orig_mode)
02035 result = gen_lowpart (orig_mode, result);
02036 }
02037
02038 return result;
02039 }
02040
02041
02042
02043
02044
02045
02046 static rtx
02047 alpha_emit_set_long_const (rtx target, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
02048 {
02049 HOST_WIDE_INT d1, d2, d3, d4;
02050
02051
02052 #if HOST_BITS_PER_WIDE_INT >= 64
02053 gcc_assert (c2 == -(c1 < 0));
02054 d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02055 c1 -= d1;
02056 d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02057 c1 = (c1 - d2) >> 32;
02058 d3 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02059 c1 -= d3;
02060 d4 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02061 gcc_assert (c1 == d4);
02062 #else
02063 d1 = ((c1 & 0xffff) ^ 0x8000) - 0x8000;
02064 c1 -= d1;
02065 d2 = ((c1 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02066 gcc_assert (c1 == d2);
02067 c2 += (d2 < 0);
02068 d3 = ((c2 & 0xffff) ^ 0x8000) - 0x8000;
02069 c2 -= d3;
02070 d4 = ((c2 & 0xffffffff) ^ 0x80000000) - 0x80000000;
02071 gcc_assert (c2 == d4);
02072 #endif
02073
02074
02075 if (d4)
02076 {
02077 emit_move_insn (target, GEN_INT (d4));
02078 if (d3)
02079 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d3)));
02080 }
02081 else
02082 emit_move_insn (target, GEN_INT (d3));
02083
02084
02085 emit_move_insn (target, gen_rtx_ASHIFT (DImode, target, GEN_INT (32)));
02086
02087
02088 if (d2)
02089 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d2)));
02090 if (d1)
02091 emit_move_insn (target, gen_rtx_PLUS (DImode, target, GEN_INT (d1)));
02092
02093 return target;
02094 }
02095
02096
02097
02098
02099 static void
02100 alpha_extract_integer (rtx x, HOST_WIDE_INT *p0, HOST_WIDE_INT *p1)
02101 {
02102 HOST_WIDE_INT i0, i1;
02103
02104 if (GET_CODE (x) == CONST_VECTOR)
02105 x = simplify_subreg (DImode, x, GET_MODE (x), 0);
02106
02107
02108 if (GET_CODE (x) == CONST_INT)
02109 {
02110 i0 = INTVAL (x);
02111 i1 = -(i0 < 0);
02112 }
02113 else if (HOST_BITS_PER_WIDE_INT >= 64)
02114 {
02115 i0 = CONST_DOUBLE_LOW (x);
02116 i1 = -(i0 < 0);
02117 }
02118 else
02119 {
02120 i0 = CONST_DOUBLE_LOW (x);
02121 i1 = CONST_DOUBLE_HIGH (x);
02122 }
02123
02124 *p0 = i0;
02125 *p1 = i1;
02126 }
02127
02128
02129
02130
02131
02132
02133 bool
02134 alpha_legitimate_constant_p (rtx x)
02135 {
02136 enum machine_mode mode = GET_MODE (x);
02137 HOST_WIDE_INT i0, i1;
02138
02139 switch (GET_CODE (x))
02140 {
02141 case CONST:
02142 case LABEL_REF:
02143 case HIGH:
02144 return true;
02145
02146 case SYMBOL_REF:
02147
02148 return SYMBOL_REF_TLS_MODEL (x) == 0;
02149
02150 case CONST_DOUBLE:
02151 if (x == CONST0_RTX (mode))
02152 return true;
02153 if (FLOAT_MODE_P (mode))
02154 return false;
02155 goto do_integer;
02156
02157 case CONST_VECTOR:
02158 if (x == CONST0_RTX (mode))
02159 return true;
02160 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
02161 return false;
02162 if (GET_MODE_SIZE (mode) != 8)
02163 return false;
02164 goto do_integer;
02165
02166 case CONST_INT:
02167 do_integer:
02168 if (TARGET_BUILD_CONSTANTS)
02169 return true;
02170 alpha_extract_integer (x, &i0, &i1);
02171 if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == (-i0 < 0))
02172 return alpha_emit_set_const_1 (x, mode, i0, 3, true) != NULL;
02173 return false;
02174
02175 default:
02176 return false;
02177 }
02178 }
02179
02180
02181
02182
02183 bool
02184 alpha_split_const_mov (enum machine_mode mode, rtx *operands)
02185 {
02186 HOST_WIDE_INT i0, i1;
02187 rtx temp = NULL_RTX;
02188
02189 alpha_extract_integer (operands[1], &i0, &i1);
02190
02191 if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0))
02192 temp = alpha_emit_set_const (operands[0], mode, i0, 3, false);
02193
02194 if (!temp && TARGET_BUILD_CONSTANTS)
02195 temp = alpha_emit_set_long_const (operands[0], i0, i1);
02196
02197 if (temp)
02198 {
02199 if (!rtx_equal_p (operands[0], temp))
02200 emit_move_insn (operands[0], temp);
02201 return true;
02202 }
02203
02204 return false;
02205 }
02206
02207
02208
02209
02210 bool
02211 alpha_expand_mov (enum machine_mode mode, rtx *operands)
02212 {
02213
02214 if (GET_CODE (operands[0]) == MEM
02215 && ! reg_or_0_operand (operands[1], mode))
02216 operands[1] = force_reg (mode, operands[1]);
02217
02218
02219 if (mode == Pmode && symbolic_operand (operands[1], mode))
02220 {
02221 rtx tmp;
02222
02223 tmp = alpha_legitimize_address (operands[1], operands[0], mode);
02224 if (tmp)
02225 {
02226 if (tmp == operands[0])
02227 return true;
02228 operands[1] = tmp;
02229 return false;
02230 }
02231 }
02232
02233
02234 if (! CONSTANT_P (operands[1]) || input_operand (operands[1], mode))
02235 return false;
02236
02237
02238 if (GET_CODE (operands[1]) == CONST_INT
02239 || GET_CODE (operands[1]) == CONST_DOUBLE
02240 || GET_CODE (operands[1]) == CONST_VECTOR)
02241 {
02242 if (alpha_split_const_mov (mode, operands))
02243 return true;
02244 }
02245
02246
02247 operands[1] = force_const_mem (mode, operands[1]);
02248 if (reload_in_progress)
02249 {
02250 emit_move_insn (operands[0], XEXP (operands[1], 0));
02251 operands[1] = copy_rtx (operands[1]);
02252 XEXP (operands[1], 0) = operands[0];
02253 }
02254 else
02255 operands[1] = validize_mem (operands[1]);
02256 return false;
02257 }
02258
02259
02260
02261
02262 bool
02263 alpha_expand_mov_nobwx (enum machine_mode mode, rtx *operands)
02264 {
02265
02266 if (GET_CODE (operands[0]) == MEM)
02267 operands[1] = force_reg (mode, operands[1]);
02268
02269
02270
02271
02272
02273 if (GET_CODE (operands[1]) == MEM
02274 || (GET_CODE (operands[1]) == SUBREG
02275 && GET_CODE (SUBREG_REG (operands[1])) == MEM)
02276 || (reload_in_progress && GET_CODE (operands[1]) == REG
02277 && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
02278 || (reload_in_progress && GET_CODE (operands[1]) == SUBREG
02279 && GET_CODE (SUBREG_REG (operands[1])) == REG
02280 && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
02281 {
02282 if (aligned_memory_operand (operands[1], mode))
02283 {
02284 if (reload_in_progress)
02285 {
02286 emit_insn ((mode == QImode
02287 ? gen_reload_inqi_help
02288 : gen_reload_inhi_help)
02289 (operands[0], operands[1],
02290 gen_rtx_REG (SImode, REGNO (operands[0]))));
02291 }
02292 else
02293 {
02294 rtx aligned_mem, bitnum;
02295 rtx scratch = gen_reg_rtx (SImode);
02296 rtx subtarget;
02297 bool copyout;
02298
02299 get_aligned_mem (operands[1], &aligned_mem, &bitnum);
02300
02301 subtarget = operands[0];
02302 if (GET_CODE (subtarget) == REG)
02303 subtarget = gen_lowpart (DImode, subtarget), copyout = false;
02304 else
02305 subtarget = gen_reg_rtx (DImode), copyout = true;
02306
02307 emit_insn ((mode == QImode
02308 ? gen_aligned_loadqi
02309 : gen_aligned_loadhi)
02310 (subtarget, aligned_mem, bitnum, scratch));
02311
02312 if (copyout)
02313 emit_move_insn (operands[0], gen_lowpart (mode, subtarget));
02314 }
02315 }
02316 else
02317 {
02318
02319
02320
02321
02322 rtx temp1, temp2, seq, subtarget;
02323 bool copyout;
02324
02325 temp1 = gen_reg_rtx (DImode);
02326 temp2 = gen_reg_rtx (DImode);
02327
02328 subtarget = operands[0];
02329 if (GET_CODE (subtarget) == REG)
02330 subtarget = gen_lowpart (DImode, subtarget), copyout = false;
02331 else
02332 subtarget = gen_reg_rtx (DImode), copyout = true;
02333
02334 seq = ((mode == QImode
02335 ? gen_unaligned_loadqi
02336 : gen_unaligned_loadhi)
02337 (subtarget, get_unaligned_address (operands[1]),
02338 temp1, temp2));
02339 alpha_set_memflags (seq, operands[1]);
02340 emit_insn (seq);
02341
02342 if (copyout)
02343 emit_move_insn (operands[0], gen_lowpart (mode, subtarget));
02344 }
02345 return true;
02346 }
02347
02348 if (GET_CODE (operands[0]) == MEM
02349 || (GET_CODE (operands[0]) == SUBREG
02350 && GET_CODE (SUBREG_REG (operands[0])) == MEM)
02351 || (reload_in_progress && GET_CODE (operands[0]) == REG
02352 && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
02353 || (reload_in_progress && GET_CODE (operands[0]) == SUBREG
02354 && GET_CODE (SUBREG_REG (operands[0])) == REG
02355 && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
02356 {
02357 if (aligned_memory_operand (operands[0], mode))
02358 {
02359 rtx aligned_mem, bitnum;
02360 rtx temp1 = gen_reg_rtx (SImode);
02361 rtx temp2 = gen_reg_rtx (SImode);
02362
02363 get_aligned_mem (operands[0], &aligned_mem, &bitnum);
02364
02365 emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
02366 temp1, temp2));
02367 }
02368 else
02369 {
02370 rtx temp1 = gen_reg_rtx (DImode);
02371 rtx temp2 = gen_reg_rtx (DImode);
02372 rtx temp3 = gen_reg_rtx (DImode);
02373 rtx seq = ((mode == QImode
02374 ? gen_unaligned_storeqi
02375 : gen_unaligned_storehi)
02376 (get_unaligned_address (operands[0]),
02377 operands[1], temp1, temp2, temp3));
02378
02379 alpha_set_memflags (seq, operands[0]);
02380 emit_insn (seq);
02381 }
02382 return true;
02383 }
02384
02385 return false;
02386 }
02387
02388
02389
02390
02391 void
02392 alpha_expand_movmisalign (enum machine_mode mode, rtx *operands)
02393 {
02394
02395 if (MEM_P (operands[1]))
02396 {
02397 rtx tmp;
02398
02399 if (register_operand (operands[0], mode))
02400 tmp = operands[0];
02401 else
02402 tmp = gen_reg_rtx (mode);
02403
02404 alpha_expand_unaligned_load (tmp, operands[1], 8, 0, 0);
02405 if (tmp != operands[0])
02406 emit_move_insn (operands[0], tmp);
02407 }
02408 else if (MEM_P (operands[0]))
02409 {
02410 if (!reg_or_0_operand (operands[1], mode))
02411 operands[1] = force_reg (mode, operands[1]);
02412 alpha_expand_unaligned_store (operands[0], operands[1], 8, 0);
02413 }
02414 else
02415 gcc_unreachable ();
02416 }
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468 void
02469 alpha_emit_floatuns (rtx operands[2])
02470 {
02471 rtx neglab, donelab, i0, i1, f0, in, out;
02472 enum machine_mode mode;
02473
02474 out = operands[0];
02475 in = force_reg (DImode, operands[1]);
02476 mode = GET_MODE (out);
02477 neglab = gen_label_rtx ();
02478 donelab = gen_label_rtx ();
02479 i0 = gen_reg_rtx (DImode);
02480 i1 = gen_reg_rtx (DImode);
02481 f0 = gen_reg_rtx (mode);
02482
02483 emit_cmp_and_jump_insns (in, const0_rtx, LT, const0_rtx, DImode, 0, neglab);
02484
02485 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_FLOAT (mode, in)));
02486 emit_jump_insn (gen_jump (donelab));
02487 emit_barrier ();
02488
02489 emit_label (neglab);
02490
02491 emit_insn (gen_lshrdi3 (i0, in, const1_rtx));
02492 emit_insn (gen_anddi3 (i1, in, const1_rtx));
02493 emit_insn (gen_iordi3 (i0, i0, i1));
02494 emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_FLOAT (mode, i0)));
02495 emit_insn (gen_rtx_SET (VOIDmode, out, gen_rtx_PLUS (mode, f0, f0)));
02496
02497 emit_label (donelab);
02498 }
02499
02500
02501
02502 rtx
02503 alpha_emit_conditional_branch (enum rtx_code code)
02504 {
02505 enum rtx_code cmp_code, branch_code;
02506 enum machine_mode cmp_mode, branch_mode = VOIDmode;
02507 rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
02508 rtx tem;
02509
02510 if (alpha_compare.fp_p && GET_MODE (op0) == TFmode)
02511 {
02512 op0 = alpha_emit_xfloating_compare (&code, op0, op1);
02513 op1 = const0_rtx;
02514 alpha_compare.fp_p = 0;
02515 }
02516
02517
02518
02519 switch (code)
02520 {
02521 case EQ: case LE: case LT: case LEU: case LTU:
02522 case UNORDERED:
02523
02524 cmp_code = code, branch_code = NE;
02525 break;
02526
02527 case NE:
02528 case ORDERED:
02529
02530 cmp_code = reverse_condition (code), branch_code = EQ;
02531 break;
02532
02533 case GE: case GT: case GEU: case GTU:
02534
02535 if (alpha_compare.fp_p)
02536 {
02537 cmp_code = swap_condition (code);
02538 branch_code = NE;
02539 tem = op0, op0 = op1, op1 = tem;
02540 }
02541 else
02542 {
02543 cmp_code = reverse_condition (code);
02544 branch_code = EQ;
02545 }
02546 break;
02547
02548 default:
02549 gcc_unreachable ();
02550 }
02551
02552 if (alpha_compare.fp_p)
02553 {
02554 cmp_mode = DFmode;
02555 if (flag_unsafe_math_optimizations)
02556 {
02557
02558
02559 if (op1 == CONST0_RTX (DFmode))
02560 cmp_code = UNKNOWN, branch_code = code;
02561 else if (op0 == CONST0_RTX (DFmode))
02562 {
02563
02564 tem = op0, op0 = op1, op1 = tem;
02565 branch_code = swap_condition (cmp_code);
02566 cmp_code = UNKNOWN;
02567 }
02568 }
02569 else
02570 {
02571
02572
02573
02574 branch_mode = CCmode;
02575 }
02576 }
02577 else
02578 {
02579 cmp_mode = DImode;
02580
02581
02582 if (code != LEU && code != LTU && code != GEU && code != GTU)
02583 {
02584
02585 if (op1 == const0_rtx)
02586 cmp_code = UNKNOWN, branch_code = code;
02587
02588
02589
02590
02591
02592
02593
02594 else if (GET_CODE (op1) == CONST_INT
02595 && (code == EQ || code == NE)
02596 && !(symbolic_operand (op0, VOIDmode)
02597 || (GET_CODE (op0) == REG && REG_POINTER (op0))))
02598 {
02599 HOST_WIDE_INT v = INTVAL (op1), n = -v;
02600
02601 if (! CONST_OK_FOR_LETTER_P (v, 'I')
02602 && (CONST_OK_FOR_LETTER_P (n, 'K')
02603 || CONST_OK_FOR_LETTER_P (n, 'L')))
02604 {
02605 cmp_code = PLUS, branch_code = code;
02606 op1 = GEN_INT (n);
02607 }
02608 }
02609 }
02610
02611 if (!reg_or_0_operand (op0, DImode))
02612 op0 = force_reg (DImode, op0);
02613 if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
02614 op1 = force_reg (DImode, op1);
02615 }
02616
02617
02618 tem = op0;
02619 if (cmp_code != UNKNOWN)
02620 {
02621 tem = gen_reg_rtx (cmp_mode);
02622 emit_move_insn (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode, op0, op1));
02623 }
02624
02625
02626 memset (&alpha_compare, 0, sizeof (alpha_compare));
02627
02628
02629 return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
02630 }
02631
02632
02633
02634
02635 rtx
02636 alpha_emit_setcc (enum rtx_code code)
02637 {
02638 enum rtx_code cmp_code;
02639 rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
02640 int fp_p = alpha_compare.fp_p;
02641 rtx tmp;
02642
02643
02644 memset (&alpha_compare, 0, sizeof (alpha_compare));
02645
02646 if (fp_p && GET_MODE (op0) == TFmode)
02647 {
02648 op0 = alpha_emit_xfloating_compare (&code, op0, op1);
02649 op1 = const0_rtx;
02650 fp_p = 0;
02651 }
02652
02653 if (fp_p && !TARGET_FIX)
02654 return NULL_RTX;
02655
02656
02657
02658
02659 cmp_code = UNKNOWN;
02660 switch (code)
02661 {
02662 case EQ: case LE: case LT: case LEU: case LTU:
02663 case UNORDERED:
02664
02665 if (fp_p)
02666 cmp_code = code, code = NE;
02667 break;
02668
02669 case NE:
02670 if (!fp_p && op1 == const0_rtx)
02671 break;
02672
02673
02674 case ORDERED:
02675 cmp_code = reverse_condition (code);
02676 code = EQ;
02677 break;
02678
02679 case GE: case GT: case GEU: case GTU:
02680
02681
02682 if (!fp_p && op1 == const0_rtx)
02683 break;
02684 code = swap_condition (code);
02685 if (fp_p)
02686 cmp_code = code, code = NE;
02687 tmp = op0, op0 = op1, op1 = tmp;
02688 break;
02689
02690 default:
02691 gcc_unreachable ();
02692 }
02693
02694 if (!fp_p)
02695 {
02696 if (!register_operand (op0, DImode))
02697 op0 = force_reg (DImode, op0);
02698 if (!reg_or_8bit_operand (op1, DImode))
02699 op1 = force_reg (DImode, op1);
02700 }
02701
02702
02703 if (cmp_code != UNKNOWN)
02704 {
02705 enum machine_mode mode = fp_p ? DFmode : DImode;
02706
02707 tmp = gen_reg_rtx (mode);
02708 emit_insn (gen_rtx_SET (VOIDmode, tmp,
02709 gen_rtx_fmt_ee (cmp_code, mode, op0, op1)));
02710
02711 op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp;
02712 op1 = const0_rtx;
02713 }
02714
02715
02716 return gen_rtx_fmt_ee (code, DImode, op0, op1);
02717 }
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727 rtx
02728 alpha_emit_conditional_move (rtx cmp, enum machine_mode mode)
02729 {
02730 enum rtx_code code = GET_CODE (cmp);
02731 enum rtx_code cmov_code = NE;
02732 rtx op0 = alpha_compare.op0;
02733 rtx op1 = alpha_compare.op1;
02734 int fp_p = alpha_compare.fp_p;
02735 enum machine_mode cmp_mode
02736 = (GET_MODE (op0) == VOIDmode ? DImode : GET_MODE (op0));
02737 enum machine_mode cmp_op_mode = fp_p ? DFmode : DImode;
02738 enum machine_mode cmov_mode = VOIDmode;
02739 int local_fast_math = flag_unsafe_math_optimizations;
02740 rtx tem;
02741
02742
02743 memset (&alpha_compare, 0, sizeof (alpha_compare));
02744
02745 if (fp_p != FLOAT_MODE_P (mode))
02746 {
02747 enum rtx_code cmp_code;
02748
02749 if (! TARGET_FIX)
02750 return 0;
02751
02752
02753
02754
02755
02756
02757 switch (code)
02758 {
02759 case EQ: case LE: case LT: case LEU: case LTU:
02760
02761 cmp_code = code, code = NE;
02762 break;
02763
02764 case NE:
02765
02766 cmp_code = EQ, code = EQ;
02767 break;
02768
02769 case GE: case GT: case GEU: case GTU:
02770
02771
02772 if (!fp_p && op1 == const0_rtx)
02773 cmp_code = code, code = NE;
02774 else
02775 {
02776 cmp_code = swap_condition (code);
02777 code = NE;
02778 tem = op0, op0 = op1, op1 = tem;
02779 }
02780 break;
02781
02782 default:
02783 gcc_unreachable ();
02784 }
02785
02786 tem = gen_reg_rtx (cmp_op_mode);
02787 emit_insn (gen_rtx_SET (VOIDmode, tem,
02788 gen_rtx_fmt_ee (cmp_code, cmp_op_mode,
02789 op0, op1)));
02790
02791 cmp_mode = cmp_op_mode = fp_p ? DImode : DFmode;
02792 op0 = gen_lowpart (cmp_op_mode, tem);
02793 op1 = CONST0_RTX (cmp_op_mode);
02794 fp_p = !fp_p;
02795 local_fast_math = 1;
02796 }
02797
02798
02799
02800 if (signed_comparison_operator (cmp, VOIDmode)
02801 && (!fp_p || local_fast_math)
02802 && (op0 == CONST0_RTX (cmp_mode) || op1 == CONST0_RTX (cmp_mode)))
02803 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
02804
02805
02806
02807
02808
02809
02810 if (no_new_pseudos)
02811 return NULL_RTX;
02812
02813 switch (code)
02814 {
02815 case EQ: case LE: case LT: case LEU: case LTU:
02816
02817 break;
02818
02819 case NE:
02820
02821 code = reverse_condition (code);
02822 cmov_code = EQ;
02823 break;
02824
02825 case GE: case GT: case GEU: case GTU:
02826
02827 if (op1 != CONST0_RTX (cmp_mode))
02828 {
02829 code = swap_condition (code);
02830 tem = op0, op0 = op1, op1 = tem;
02831 }
02832 break;
02833
02834 default:
02835 gcc_unreachable ();
02836 }
02837
02838 if (!fp_p)
02839 {
02840 if (!reg_or_0_operand (op0, DImode))
02841 op0 = force_reg (DImode, op0);
02842 if (!reg_or_8bit_operand (op1, DImode))
02843 op1 = force_reg (DImode, op1);
02844 }
02845
02846
02847
02848
02849 if (fp_p && !local_fast_math)
02850 cmov_mode = CCmode;
02851
02852 tem = gen_reg_rtx (cmp_op_mode);
02853 emit_move_insn (tem, gen_rtx_fmt_ee (code, cmp_op_mode, op0, op1));
02854 return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
02855 }
02856
02857
02858
02859
02860
02861
02862 int
02863 alpha_split_conditional_move (enum rtx_code code, rtx dest, rtx cond,
02864 rtx t_rtx, rtx f_rtx)
02865 {
02866 HOST_WIDE_INT t, f, diff;
02867 enum machine_mode mode;
02868 rtx target, subtarget, tmp;
02869
02870 mode = GET_MODE (dest);
02871 t = INTVAL (t_rtx);
02872 f = INTVAL (f_rtx);
02873 diff = t - f;
02874
02875 if (((code == NE || code == EQ) && diff < 0)
02876 || (code == GE || code == GT))
02877 {
02878 code = reverse_condition (code);
02879 diff = t, t = f, f = diff;
02880 diff = t - f;
02881 }
02882
02883 subtarget = target = dest;
02884 if (mode != DImode)
02885 {
02886 target = gen_lowpart (DImode, dest);
02887 if (! no_new_pseudos)
02888 subtarget = gen_reg_rtx (DImode);
02889 else
02890 subtarget = target;
02891 }
02892
02893
02894
02895
02896 if (f == 0 && exact_log2 (diff) > 0
02897
02898
02899
02900 && (diff <= 8 || alpha_tune == PROCESSOR_EV6))
02901 {
02902 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
02903 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
02904
02905 tmp = gen_rtx_ASHIFT (DImode, copy_rtx (subtarget),
02906 GEN_INT (exact_log2 (t)));
02907 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
02908 }
02909 else if (f == 0 && t == -1)
02910 {
02911 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
02912 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
02913
02914 emit_insn (gen_negdi2 (target, copy_rtx (subtarget)));
02915 }
02916 else if (diff == 1 || diff == 4 || diff == 8)
02917 {
02918 rtx add_op;
02919
02920 tmp = gen_rtx_fmt_ee (code, DImode, cond, const0_rtx);
02921 emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (subtarget), tmp));
02922
02923 if (diff == 1)
02924 emit_insn (gen_adddi3 (target, copy_rtx (subtarget), GEN_INT (f)));
02925 else
02926 {
02927 add_op = GEN_INT (f);
02928 if (sext_add_operand (add_op, mode))
02929 {
02930 tmp = gen_rtx_MULT (DImode, copy_rtx (subtarget),
02931 GEN_INT (diff));
02932 tmp = gen_rtx_PLUS (DImode, tmp, add_op);
02933 emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
02934 }
02935 else
02936 return 0;
02937 }
02938 }
02939 else
02940 return 0;
02941
02942 return 1;
02943 }
02944
02945
02946
02947
02948 struct xfloating_op GTY(())
02949 {
02950 const enum rtx_code code;
02951 const char *const GTY((skip)) osf_func;
02952 const char *const GTY((skip)) vms_func;
02953 rtx libcall;
02954 };
02955
02956 static GTY(()) struct xfloating_op xfloating_ops[] =
02957 {
02958 { PLUS, "_OtsAddX", "OTS$ADD_X", 0 },
02959 { MINUS, "_OtsSubX", "OTS$SUB_X", 0 },
02960 { MULT, "_OtsMulX", "OTS$MUL_X", 0 },
02961 { DIV, "_OtsDivX", "OTS$DIV_X", 0 },
02962 { EQ, "_OtsEqlX", "OTS$EQL_X", 0 },
02963 { NE, "_OtsNeqX", "OTS$NEQ_X", 0 },
02964 { LT, "_OtsLssX", "OTS$LSS_X", 0 },
02965 { LE, "_OtsLeqX", "OTS$LEQ_X", 0 },
02966 { GT, "_OtsGtrX", "OTS$GTR_X", 0 },
02967 { GE, "_OtsGeqX", "OTS$GEQ_X", 0 },
02968 { FIX, "_OtsCvtXQ", "OTS$CVTXQ", 0 },
02969 { FLOAT, "_OtsCvtQX", "OTS$CVTQX", 0 },
02970 { UNSIGNED_FLOAT, "_OtsCvtQUX", "OTS$CVTQUX", 0 },
02971 { FLOAT_EXTEND, "_OtsConvertFloatTX", "OTS$CVT_FLOAT_T_X", 0 },
02972 { FLOAT_TRUNCATE, "_OtsConvertFloatXT", "OTS$CVT_FLOAT_X_T", 0 }
02973 };
02974
02975 static GTY(()) struct xfloating_op vax_cvt_ops[] =
02976 {
02977 { FLOAT_EXTEND, "_OtsConvertFloatGX", "OTS$CVT_FLOAT_G_X", 0 },
02978 { FLOAT_TRUNCATE, "_OtsConvertFloatXG", "OTS$CVT_FLOAT_X_G", 0 }
02979 };
02980
02981 static rtx
02982 alpha_lookup_xfloating_lib_func (enum rtx_code code)
02983 {
02984 struct xfloating_op *ops = xfloating_ops;
02985 long n = ARRAY_SIZE (xfloating_ops);
02986 long i;
02987
02988 gcc_assert (TARGET_HAS_XFLOATING_LIBS);
02989
02990
02991 if (TARGET_FLOAT_VAX && (code == FLOAT_EXTEND || code == FLOAT_TRUNCATE))
02992 {
02993 ops = vax_cvt_ops;
02994 n = ARRAY_SIZE (vax_cvt_ops);
02995 }
02996
02997 for (i = 0; i < n; ++i, ++ops)
02998 if (ops->code == code)
02999 {
03000 rtx func = ops->libcall;
03001 if (!func)
03002 {
03003 func = init_one_libfunc (TARGET_ABI_OPEN_VMS
03004 ? ops->vms_func : ops->osf_func);
03005 ops->libcall = func;
03006 }
03007 return func;
03008 }
03009
03010 gcc_unreachable ();
03011 }
03012
03013
03014
03015
03016 static int
03017 alpha_compute_xfloating_mode_arg (enum rtx_code code,
03018 enum alpha_fp_rounding_mode round)
03019 {
03020 int mode;
03021
03022 switch (round)
03023 {
03024 case ALPHA_FPRM_NORM:
03025 mode = 2;
03026 break;
03027 case ALPHA_FPRM_MINF:
03028 mode = 1;
03029 break;
03030 case ALPHA_FPRM_CHOP:
03031 mode = 0;
03032 break;
03033 case ALPHA_FPRM_DYN:
03034 mode = 4;
03035 break;
03036 default:
03037 gcc_unreachable ();
03038
03039
03040 }
03041
03042 if (code == FLOAT_TRUNCATE && alpha_fptm == ALPHA_FPTM_N)
03043 mode |= 0x10000;
03044
03045 return mode;
03046 }
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061 static void
03062 alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
03063 int noperands, rtx equiv)
03064 {
03065 rtx usage = NULL_RTX, tmp, reg;
03066 int regno = 16, i;
03067
03068 start_sequence ();
03069
03070 for (i = 0; i < noperands; ++i)
03071 {
03072 switch (GET_MODE (operands[i]))
03073 {
03074 case TFmode:
03075 reg = gen_rtx_REG (TFmode, regno);
03076 regno += 2;
03077 break;
03078
03079 case DFmode:
03080 reg = gen_rtx_REG (DFmode, regno + 32);
03081 regno += 1;
03082 break;
03083
03084 case VOIDmode:
03085 gcc_assert (GET_CODE (operands[i]) == CONST_INT);
03086
03087 case DImode:
03088 reg = gen_rtx_REG (DImode, regno);
03089 regno += 1;
03090 break;
03091
03092 default:
03093 gcc_unreachable ();
03094 }
03095
03096 emit_move_insn (reg, operands[i]);
03097 usage = alloc_EXPR_LIST (0, gen_rtx_USE (VOIDmode, reg), usage);
03098 }
03099
03100 switch (GET_MODE (target))
03101 {
03102 case TFmode:
03103 reg = gen_rtx_REG (TFmode, 16);
03104 break;
03105 case DFmode:
03106 reg = gen_rtx_REG (DFmode, 32);
03107 break;
03108 case DImode:
03109 reg = gen_rtx_REG (DImode, 0);
03110 break;
03111 default:
03112 gcc_unreachable ();
03113 }
03114
03115 tmp = gen_rtx_MEM (QImode, func);
03116 tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
03117 const0_rtx, const0_rtx));
03118 CALL_INSN_FUNCTION_USAGE (tmp) = usage;
03119 CONST_OR_PURE_CALL_P (tmp) = 1;
03120
03121 tmp = get_insns ();
03122 end_sequence ();
03123
03124 emit_libcall_block (tmp, target, reg, equiv);
03125 }
03126
03127
03128
03129 void
03130 alpha_emit_xfloating_arith (enum rtx_code code, rtx operands[])
03131 {
03132 rtx func;
03133 int mode;
03134 rtx out_operands[3];
03135
03136 func = alpha_lookup_xfloating_lib_func (code);
03137 mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
03138
03139 out_operands[0] = operands[1];
03140 out_operands[1] = operands[2];
03141 out_operands[2] = GEN_INT (mode);
03142 alpha_emit_xfloating_libcall (func, operands[0], out_operands, 3,
03143 gen_rtx_fmt_ee (code, TFmode, operands[1],
03144 operands[2]));
03145 }
03146
03147
03148
03149 static rtx
03150 alpha_emit_xfloating_compare (enum rtx_code *pcode, rtx op0, rtx op1)
03151 {
03152 enum rtx_code cmp_code, res_code;
03153 rtx func, out, operands[2];
03154
03155
03156
03157
03158
03159
03160
03161 cmp_code = *pcode;
03162 switch (cmp_code)
03163 {
03164 case UNORDERED:
03165 cmp_code = EQ;
03166 res_code = LT;
03167 break;
03168 case ORDERED:
03169 cmp_code = EQ;
03170 res_code = GE;
03171 break;
03172 case NE:
03173 res_code = NE;
03174 break;
03175 case EQ:
03176 case LT:
03177 case GT:
03178 case LE:
03179 case GE:
03180 res_code = GT;
03181 break;
03182 default:
03183 gcc_unreachable ();
03184 }
03185 *pcode = res_code;
03186
03187 func = alpha_lookup_xfloating_lib_func (cmp_code);
03188
03189 operands[0] = op0;
03190 operands[1] = op1;
03191 out = gen_reg_rtx (DImode);
03192
03193
03194
03195 alpha_emit_xfloating_libcall (func, out, operands, 2,
03196 gen_rtx_fmt_ee (cmp_code, CCmode, op0, op1));
03197
03198 return out;
03199 }
03200
03201
03202
03203 void
03204 alpha_emit_xfloating_cvt (enum rtx_code orig_code, rtx operands[])
03205 {
03206 int noperands = 1, mode;
03207 rtx out_operands[2];
03208 rtx func;
03209 enum rtx_code code = orig_code;
03210
03211 if (code == UNSIGNED_FIX)
03212 code = FIX;
03213
03214 func = alpha_lookup_xfloating_lib_func (code);
03215
03216 out_operands[0] = operands[1];
03217
03218 switch (code)
03219 {
03220 case FIX:
03221 mode = alpha_compute_xfloating_mode_arg (code, ALPHA_FPRM_CHOP);
03222 out_operands[1] = GEN_INT (mode);
03223 noperands = 2;
03224 break;
03225 case FLOAT_TRUNCATE:
03226 mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
03227 out_operands[1] = GEN_INT (mode);
03228 noperands = 2;
03229 break;
03230 default:
03231 break;
03232 }
03233
03234 alpha_emit_xfloating_libcall (func, operands[0], out_operands, noperands,
03235 gen_rtx_fmt_e (orig_code,
03236 GET_MODE (operands[0]),
03237 operands[1]));
03238 }
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248 void
03249 alpha_split_tmode_pair (rtx operands[4], enum machine_mode mode,
03250 bool fixup_overlap)
03251 {
03252 switch (GET_CODE (operands[1]))
03253 {
03254 case REG:
03255 operands[3] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
03256 operands[2] = gen_rtx_REG (DImode, REGNO (operands[1]));
03257 break;
03258
03259 case MEM:
03260 operands[3] = adjust_address (operands[1], DImode, 8);
03261 operands[2] = adjust_address (operands[1], DImode, 0);
03262 break;
03263
03264 case CONST_INT:
03265 case CONST_DOUBLE:
03266 gcc_assert (operands[1] == CONST0_RTX (mode));
03267 operands[2] = operands[3] = const0_rtx;
03268 break;
03269
03270 default:
03271 gcc_unreachable ();
03272 }
03273
03274 switch (GET_CODE (operands[0]))
03275 {
03276 case REG:
03277 operands[1] = gen_rtx_REG (DImode, REGNO (operands[0]) + 1);
03278 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
03279 break;
03280
03281 case MEM:
03282 operands[1] = adjust_address (operands[0], DImode, 8);
03283 operands[0] = adjust_address (operands[0], DImode, 0);
03284 break;
03285
03286 default:
03287 gcc_unreachable ();
03288 }
03289
03290 if (fixup_overlap && reg_overlap_mentioned_p (operands[0], operands[3]))
03291 {
03292 rtx tmp;
03293 tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
03294 tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
03295 }
03296 }
03297
03298
03299
03300
03301
03302 void
03303 alpha_split_tfmode_frobsign (rtx operands[3], rtx (*operation) (rtx, rtx, rtx))
03304 {
03305 rtx high_bit = operands[2];
03306 rtx scratch;
03307 int move;
03308
03309 alpha_split_tmode_pair (operands, TFmode, false);
03310
03311
03312 move = 1;
03313 if (rtx_equal_p (operands[0], operands[2]))
03314 move = 0;
03315 else if (rtx_equal_p (operands[1], operands[2]))
03316 {
03317 if (rtx_equal_p (operands[0], high_bit))
03318 move = 2;
03319 else
03320 move = -1;
03321 }
03322
03323 if (move < 0)
03324 emit_move_insn (operands[0], operands[2]);
03325
03326
03327
03328
03329
03330 scratch = operands[move < 2 ? 1 : 3];
03331
03332 emit_insn ((*operation) (scratch, high_bit, operands[3]));
03333
03334 if (move > 0)
03335 {
03336 emit_move_insn (operands[0], operands[2]);
03337 if (move > 1)
03338 emit_move_insn (operands[1], scratch);
03339 }
03340 }
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369 void
03370 alpha_expand_unaligned_load (rtx tgt, rtx mem, HOST_WIDE_INT size,
03371 HOST_WIDE_INT ofs, int sign)
03372 {
03373 rtx meml, memh, addr, extl, exth, tmp, mema;
03374 enum machine_mode mode;
03375
03376 if (TARGET_BWX && size == 2)
03377 {
03378 meml = adjust_address (mem, QImode, ofs);
03379 memh = adjust_address (mem, QImode, ofs+1);
03380 if (BYTES_BIG_ENDIAN)
03381 tmp = meml, meml = memh, memh = tmp;
03382 extl = gen_reg_rtx (DImode);
03383 exth = gen_reg_rtx (DImode);
03384 emit_insn (gen_zero_extendqidi2 (extl, meml));
03385 emit_insn (gen_zero_extendqidi2 (exth, memh));
03386 exth = expand_simple_binop (DImode, ASHIFT, exth, GEN_INT (8),
03387 NULL, 1, OPTAB_LIB_WIDEN);
03388 addr = expand_simple_binop (DImode, IOR, extl, exth,
03389 NULL, 1, OPTAB_LIB_WIDEN);
03390
03391 if (sign && GET_MODE (tgt) != HImode)
03392 {
03393 addr = gen_lowpart (HImode, addr);
03394 emit_insn (gen_extend_insn (tgt, addr, GET_MODE (tgt), HImode, 0));
03395 }
03396 else
03397 {
03398 if (GET_MODE (tgt) != DImode)
03399 addr = gen_lowpart (GET_MODE (tgt), addr);
03400 emit_move_insn (tgt, addr);
03401 }
03402 return;
03403 }
03404
03405 meml = gen_reg_rtx (DImode);
03406 memh = gen_reg_rtx (DImode);
03407 addr = gen_reg_rtx (DImode);
03408 extl = gen_reg_rtx (DImode);
03409 exth = gen_reg_rtx (DImode);
03410
03411 mema = XEXP (mem, 0);
03412 if (GET_CODE (mema) == LO_SUM)
03413 mema = force_reg (Pmode, mema);
03414
03415
03416
03417
03418
03419 tmp = change_address (mem, DImode,
03420 gen_rtx_AND (DImode,
03421 plus_constant (mema, ofs),
03422 GEN_INT (-8)));
03423 set_mem_alias_set (tmp, 0);
03424 emit_move_insn (meml, tmp);
03425
03426 tmp = change_address (mem, DImode,
03427 gen_rtx_AND (DImode,
03428 plus_constant (mema, ofs + size - 1),
03429 GEN_INT (-8)));
03430 set_mem_alias_set (tmp, 0);
03431 emit_move_insn (memh, tmp);
03432
03433 if (WORDS_BIG_ENDIAN && sign && (size == 2 || size == 4))
03434 {
03435 emit_move_insn (addr, plus_constant (mema, -1));
03436
03437 emit_insn (gen_extqh_be (extl, meml, addr));
03438 emit_insn (gen_extxl_be (exth, memh, GEN_INT (64), addr));
03439
03440 addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
03441 addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (64 - size*8),
03442 addr, 1, OPTAB_WIDEN);
03443 }
03444 else if (sign && size == 2)
03445 {
03446 emit_move_insn (addr, plus_constant (mema, ofs+2));
03447
03448 emit_insn (gen_extxl_le (extl, meml, GEN_INT (64), addr));
03449 emit_insn (gen_extqh_le (exth, memh, addr));
03450
03451
03452
03453
03454 addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
03455 addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (48),
03456 addr, 1, OPTAB_WIDEN);
03457 }
03458 else
03459 {
03460 if (WORDS_BIG_ENDIAN)
03461 {
03462 emit_move_insn (addr, plus_constant (mema, ofs+size-1));
03463 switch ((int) size)
03464 {
03465 case 2:
03466 emit_insn (gen_extwh_be (extl, meml, addr));
03467 mode = HImode;
03468 break;
03469
03470 case 4:
03471 emit_insn (gen_extlh_be (extl, meml, addr));
03472 mode = SImode;
03473 break;
03474
03475 case 8:
03476 emit_insn (gen_extqh_be (extl, meml, addr));
03477 mode = DImode;
03478 break;
03479
03480 default:
03481 gcc_unreachable ();
03482 }
03483 emit_insn (gen_extxl_be (exth, memh, GEN_INT (size*8), addr));
03484 }
03485 else
03486 {
03487 emit_move_insn (addr, plus_constant (mema, ofs));
03488 emit_insn (gen_extxl_le (extl, meml, GEN_INT (size*8), addr));
03489 switch ((int) size)
03490 {
03491 case 2:
03492 emit_insn (gen_extwh_le (exth, memh, addr));
03493 mode = HImode;
03494 break;
03495
03496 case 4:
03497 emit_insn (gen_extlh_le (exth, memh, addr));
03498 mode = SImode;
03499 break;
03500
03501 case 8:
03502 emit_insn (gen_extqh_le (exth, memh, addr));
03503 mode = DImode;
03504 break;
03505
03506 default:
03507 gcc_unreachable ();
03508 }
03509 }
03510
03511 addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
03512 gen_lowpart (mode, exth), gen_lowpart (mode, tgt),
03513 sign, OPTAB_WIDEN);
03514 }
03515
03516 if (addr != tgt)
03517 emit_move_insn (tgt, gen_lowpart (GET_MODE (tgt), addr));
03518 }
03519
03520
03521
03522 void
03523 alpha_expand_unaligned_store (rtx dst, rtx src,
03524 HOST_WIDE_INT size, HOST_WIDE_INT ofs)
03525 {
03526 rtx dstl, dsth, addr, insl, insh, meml, memh, dsta;
03527
03528 if (TARGET_BWX && size == 2)
03529 {
03530 if (src != const0_rtx)
03531 {
03532 dstl = gen_lowpart (QImode, src);
03533 dsth = expand_simple_binop (DImode, LSHIFTRT, src, GEN_INT (8),
03534 NULL, 1, OPTAB_LIB_WIDEN);
03535 dsth = gen_lowpart (QImode, dsth);
03536 }
03537 else
03538 dstl = dsth = const0_rtx;
03539
03540 meml = adjust_address (dst, QImode, ofs);
03541 memh = adjust_address (dst, QImode, ofs+1);
03542 if (BYTES_BIG_ENDIAN)
03543 addr = meml, meml = memh, memh = addr;
03544
03545 emit_move_insn (meml, dstl);
03546 emit_move_insn (memh, dsth);
03547 return;
03548 }
03549
03550 dstl = gen_reg_rtx (DImode);
03551 dsth = gen_reg_rtx (DImode);
03552 insl = gen_reg_rtx (DImode);
03553 insh = gen_reg_rtx (DImode);
03554
03555 dsta = XEXP (dst, 0);
03556 if (GET_CODE (dsta) == LO_SUM)
03557 dsta = force_reg (Pmode, dsta);
03558
03559
03560
03561
03562
03563 meml = change_address (dst, DImode,
03564 gen_rtx_AND (DImode,
03565 plus_constant (dsta, ofs),
03566 GEN_INT (-8)));
03567 set_mem_alias_set (meml, 0);
03568
03569 memh = change_address (dst, DImode,
03570 gen_rtx_AND (DImode,
03571 plus_constant (dsta, ofs + size - 1),
03572 GEN_INT (-8)));
03573 set_mem_alias_set (memh, 0);
03574
03575 emit_move_insn (dsth, memh);
03576 emit_move_insn (dstl, meml);
03577 if (WORDS_BIG_ENDIAN)
03578 {
03579 addr = copy_addr_to_reg (plus_constant (dsta, ofs+size-1));
03580
03581 if (src != const0_rtx)
03582 {
03583 switch ((int) size)
03584 {
03585 case 2:
03586 emit_insn (gen_inswl_be (insh, gen_lowpart (HImode,src), addr));
03587 break;
03588 case 4:
03589 emit_insn (gen_insll_be (insh, gen_lowpart (SImode,src), addr));
03590 break;
03591 case 8:
03592 emit_insn (gen_insql_be (insh, gen_lowpart (DImode,src), addr));
03593 break;
03594 }
03595 emit_insn (gen_insxh (insl, gen_lowpart (DImode, src),
03596 GEN_INT (size*8), addr));
03597 }
03598
03599 switch ((int) size)
03600 {
03601 case 2:
03602 emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
03603 break;
03604 case 4:
03605 {
03606 rtx msk = immed_double_const (0xffffffff, 0, DImode);
03607 emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
03608 break;
03609 }
03610 case 8:
03611 emit_insn (gen_mskxl_be (dsth, dsth, constm1_rtx, addr));
03612 break;
03613 }
03614
03615 emit_insn (gen_mskxh (dstl, dstl, GEN_INT (size*8), addr));
03616 }
03617 else
03618 {
03619 addr = copy_addr_to_reg (plus_constant (dsta, ofs));
03620
03621 if (src != CONST0_RTX (GET_MODE (src)))
03622 {
03623 emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
03624 GEN_INT (size*8), addr));
03625
03626 switch ((int) size)
03627 {
03628 case 2:
03629 emit_insn (gen_inswl_le (insl, gen_lowpart (HImode, src), addr));
03630 break;
03631 case 4:
03632 emit_insn (gen_insll_le (insl, gen_lowpart (SImode, src), addr));
03633 break;
03634 case 8:
03635 emit_insn (gen_insql_le (insl, src, addr));
03636 break;
03637 }
03638 }
03639
03640 emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
03641
03642 switch ((int) size)
03643 {
03644 case 2:
03645 emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
03646 break;
03647 case 4:
03648 {
03649 rtx msk = immed_double_const (0xffffffff, 0, DImode);
03650 emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
03651 break;
03652 }
03653 case 8:
03654 emit_insn (gen_mskxl_le (dstl, dstl, constm1_rtx, addr));
03655 break;
03656 }
03657 }
03658
03659 if (src != CONST0_RTX (GET_MODE (src)))
03660 {
03661 dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
03662 dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
03663 }
03664
03665 if (WORDS_BIG_ENDIAN)
03666 {
03667 emit_move_insn (meml, dstl);
03668 emit_move_insn (memh, dsth);
03669 }
03670 else
03671 {
03672
03673 emit_move_insn (memh, dsth);
03674 emit_move_insn (meml, dstl);
03675 }
03676 }
03677
03678
03679
03680
03681
03682
03683
03684 #define MAX_MOVE_WORDS 8
03685
03686
03687
03688 static void
03689 alpha_expand_unaligned_load_words (rtx *out_regs, rtx smem,
03690 HOST_WIDE_INT words, HOST_WIDE_INT ofs)
03691 {
03692 rtx const im8 = GEN_INT (-8);
03693 rtx const i64 = GEN_INT (64);
03694 rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1];
03695 rtx sreg, areg, tmp, smema;
03696 HOST_WIDE_INT i;
03697
03698 smema = XEXP (smem, 0);
03699 if (GET_CODE (smema) == LO_SUM)
03700 smema = force_reg (Pmode, smema);
03701
03702
03703 for (i = 0; i < words; ++i)
03704 {
03705 data_regs[i] = out_regs[i];
03706 ext_tmps[i] = gen_reg_rtx (DImode);
03707 }
03708 data_regs[words] = gen_reg_rtx (DImode);
03709
03710 if (ofs != 0)
03711 smem = adjust_address (smem, GET_MODE (smem), ofs);
03712
03713
03714 for (i = 0; i < words; ++i)
03715 {
03716 tmp = change_address (smem, DImode,
03717 gen_rtx_AND (DImode,
03718 plus_constant (smema, 8*i),
03719 im8));
03720 set_mem_alias_set (tmp, 0);
03721 emit_move_insn (data_regs[i], tmp);
03722 }
03723
03724 tmp = change_address (smem, DImode,
03725 gen_rtx_AND (DImode,
03726 plus_constant (smema, 8*words - 1),
03727 im8));
03728 set_mem_alias_set (tmp, 0);
03729 emit_move_insn (data_regs[words], tmp);
03730
03731
03732
03733
03734
03735 sreg = copy_addr_to_reg (smema);
03736 areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL,
03737 1, OPTAB_WIDEN);
03738 if (WORDS_BIG_ENDIAN)
03739 emit_move_insn (sreg, plus_constant (sreg, 7));
03740 for (i = 0; i < words; ++i)
03741 {
03742 if (WORDS_BIG_ENDIAN)
03743 {
03744 emit_insn (gen_extqh_be (data_regs[i], data_regs[i], sreg));
03745 emit_insn (gen_extxl_be (ext_tmps[i], data_regs[i+1], i64, sreg));
03746 }
03747 else
03748 {
03749 emit_insn (gen_extxl_le (data_regs[i], data_regs[i], i64, sreg));
03750 emit_insn (gen_extqh_le (ext_tmps[i], data_regs[i+1], sreg));
03751 }
03752 emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
03753 gen_rtx_IF_THEN_ELSE (DImode,
03754 gen_rtx_EQ (DImode, areg,
03755 const0_rtx),
03756 const0_rtx, ext_tmps[i])));
03757 }
03758
03759
03760 for (i = 0; i < words; ++i)
03761 {
03762 out_regs[i] = expand_binop (DImode, ior_optab, data_regs[i],
03763 ext_tmps[i], data_regs[i], 1, OPTAB_WIDEN);
03764 }
03765 }
03766
03767
03768
03769
03770 static void
03771 alpha_expand_unaligned_store_words (rtx *data_regs, rtx dmem,
03772 HOST_WIDE_INT words, HOST_WIDE_INT ofs)
03773 {
03774 rtx const im8 = GEN_INT (-8);
03775 rtx const i64 = GEN_INT (64);
03776 rtx ins_tmps[MAX_MOVE_WORDS];
03777 rtx st_tmp_1, st_tmp_2, dreg;
03778 rtx st_addr_1, st_addr_2, dmema;
03779 HOST_WIDE_INT i;
03780
03781 dmema = XEXP (dmem, 0);
03782 if (GET_CODE (dmema) == LO_SUM)
03783 dmema = force_reg (Pmode, dmema);
03784
03785
03786 if (data_regs != NULL)
03787 for (i = 0; i < words; ++i)
03788 ins_tmps[i] = gen_reg_rtx(DImode);
03789 st_tmp_1 = gen_reg_rtx(DImode);
03790 st_tmp_2 = gen_reg_rtx(DImode);
03791
03792 if (ofs != 0)
03793 dmem = adjust_address (dmem, GET_MODE (dmem), ofs);
03794
03795 st_addr_2 = change_address (dmem, DImode,
03796 gen_rtx_AND (DImode,
03797 plus_constant (dmema, words*8 - 1),
03798 im8));
03799 set_mem_alias_set (st_addr_2, 0);
03800
03801 st_addr_1 = change_address (dmem, DImode,
03802 gen_rtx_AND (DImode, dmema, im8));
03803 set_mem_alias_set (st_addr_1, 0);
03804
03805
03806 emit_move_insn (st_tmp_2, st_addr_2);
03807 emit_move_insn (st_tmp_1, st_addr_1);
03808
03809
03810 dreg = copy_addr_to_reg (dmema);
03811 if (WORDS_BIG_ENDIAN)
03812 emit_move_insn (dreg, plus_constant (dreg, 7));
03813 if (data_regs != NULL)
03814 {
03815 for (i = words-1; i >= 0; --i)
03816 {
03817 if (WORDS_BIG_ENDIAN)
03818 {
03819 emit_insn (gen_insql_be (ins_tmps[i], data_regs[i], dreg));
03820 emit_insn (gen_insxh (data_regs[i], data_regs[i], i64, dreg));
03821 }
03822 else
03823 {
03824 emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
03825 emit_insn (gen_insql_le (data_regs[i], data_regs[i], dreg));
03826 }
03827 }
03828 for (i = words-1; i > 0; --i)
03829 {
03830 ins_tmps[i-1] = expand_binop (DImode, ior_optab, data_regs[i],
03831 ins_tmps[i-1], ins_tmps[i-1], 1,
03832 OPTAB_WIDEN);
03833 }
03834 }
03835
03836
03837 if (WORDS_BIG_ENDIAN)
03838 {
03839 emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, constm1_rtx, dreg));
03840 emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
03841 }
03842 else
03843 {
03844 emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
03845 emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, constm1_rtx, dreg));
03846 }
03847
03848 if (data_regs != NULL)
03849 {
03850 st_tmp_2 = expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1],
03851 st_tmp_2, 1, OPTAB_WIDEN);
03852 st_tmp_1 = expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0],
03853 st_tmp_1, 1, OPTAB_WIDEN);
03854 }
03855
03856
03857 if (WORDS_BIG_ENDIAN)
03858 emit_move_insn (st_addr_1, st_tmp_1);
03859 else
03860 emit_move_insn (st_addr_2, st_tmp_2);
03861 for (i = words-1; i > 0; --i)
03862 {
03863 rtx tmp = change_address (dmem, DImode,
03864 gen_rtx_AND (DImode,
03865 plus_constant(dmema,
03866 WORDS_BIG_ENDIAN ? i*8-1 : i*8),
03867 im8));
03868 set_mem_alias_set (tmp, 0);
03869 emit_move_insn (tmp, data_regs ? ins_tmps[i-1] : const0_rtx);
03870 }
03871 if (WORDS_BIG_ENDIAN)
03872 emit_move_insn (st_addr_2, st_tmp_2);
03873 else
03874 emit_move_insn (st_addr_1, st_tmp_1);
03875 }
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885 int
03886 alpha_expand_block_move (rtx operands[])
03887 {
03888 rtx bytes_rtx = operands[2];
03889 rtx align_rtx = operands[3];
03890 HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
03891 HOST_WIDE_INT bytes = orig_bytes;
03892 HOST_WIDE_INT src_align = INTVAL (align_rtx) * BITS_PER_UNIT;
03893 HOST_WIDE_INT dst_align = src_align;
03894 rtx orig_src = operands[1];
03895 rtx orig_dst = operands[0];
03896 rtx data_regs[2 * MAX_MOVE_WORDS + 16];
03897 rtx tmp;
03898 unsigned int i, words, ofs, nregs = 0;
03899
03900 if (orig_bytes <= 0)
03901 return 1;
03902 else if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
03903 return 0;
03904
03905
03906
03907 tmp = XEXP (orig_src, 0);
03908 if (GET_CODE (tmp) == REG)
03909 src_align = MAX (src_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
03910 else if (GET_CODE (tmp) == PLUS
03911 && GET_CODE (XEXP (tmp, 0)) == REG
03912 && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
03913 {
03914 unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
03915 unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
03916
03917 if (a > src_align)
03918 {
03919 if (a >= 64 && c % 8 == 0)
03920 src_align = 64;
03921 else if (a >= 32 && c % 4 == 0)
03922 src_align = 32;
03923 else if (a >= 16 && c % 2 == 0)
03924 src_align = 16;
03925 }
03926 }
03927
03928 tmp = XEXP (orig_dst, 0);
03929 if (GET_CODE (tmp) == REG)
03930 dst_align = MAX (dst_align, REGNO_POINTER_ALIGN (REGNO (tmp)));
03931 else if (GET_CODE (tmp) == PLUS
03932 && GET_CODE (XEXP (tmp, 0)) == REG
03933 && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
03934 {
03935 unsigned HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
03936 unsigned int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
03937
03938 if (a > dst_align)
03939 {
03940 if (a >= 64 && c % 8 == 0)
03941 dst_align = 64;
03942 else if (a >= 32 && c % 4 == 0)
03943 dst_align = 32;
03944 else if (a >= 16 && c % 2 == 0)
03945 dst_align = 16;
03946 }
03947 }
03948
03949 ofs = 0;
03950 if (src_align >= 64 && bytes >= 8)
03951 {
03952 words = bytes / 8;
03953
03954 for (i = 0; i < words; ++i)
03955 data_regs[nregs + i] = gen_reg_rtx (DImode);
03956
03957 for (i = 0; i < words; ++i)
03958 emit_move_insn (data_regs[nregs + i],
03959 adjust_address (orig_src, DImode, ofs + i * 8));
03960
03961 nregs += words;
03962 bytes -= words * 8;
03963 ofs += words * 8;
03964 }
03965
03966 if (src_align >= 32 && bytes >= 4)
03967 {
03968 words = bytes / 4;
03969
03970 for (i = 0; i < words; ++i)
03971 data_regs[nregs + i] = gen_reg_rtx (SImode);
03972
03973 for (i = 0; i < words; ++i)
03974 emit_move_insn (data_regs[nregs + i],
03975 adjust_address (orig_src, SImode, ofs + i * 4));
03976
03977 nregs += words;
03978 bytes -= words * 4;
03979 ofs += words * 4;
03980 }
03981
03982 if (bytes >= 8)
03983 {
03984 words = bytes / 8;
03985
03986 for (i = 0; i < words+1; ++i)
03987 data_regs[nregs + i] = gen_reg_rtx (DImode);
03988
03989 alpha_expand_unaligned_load_words (data_regs + nregs, orig_src,
03990 words, ofs);
03991
03992 nregs += words;
03993 bytes -= words * 8;
03994 ofs += words * 8;
03995 }
03996
03997 if (! TARGET_BWX && bytes >= 4)
03998 {
03999 data_regs[nregs++] = tmp = gen_reg_rtx (SImode);
04000 alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
04001 bytes -= 4;
04002 ofs += 4;
04003 }
04004
04005 if (bytes >= 2)
04006 {
04007 if (src_align >= 16)
04008 {
04009 do {
04010 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
04011 emit_move_insn (tmp, adjust_address (orig_src, HImode, ofs));
04012 bytes -= 2;
04013 ofs += 2;
04014 } while (bytes >= 2);
04015 }
04016 else if (! TARGET_BWX)
04017 {
04018 data_regs[nregs++] = tmp = gen_reg_rtx (HImode);
04019 alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
04020 bytes -= 2;
04021 ofs += 2;
04022 }
04023 }
04024
04025 while (bytes > 0)
04026 {
04027 data_regs[nregs++] = tmp = gen_reg_rtx (QImode);
04028 emit_move_insn (tmp, adjust_address (orig_src, QImode, ofs));
04029 bytes -= 1;
04030 ofs += 1;
04031 }
04032
04033 gcc_assert (nregs <= ARRAY_SIZE (data_regs));
04034
04035
04036
04037 i = 0, ofs = 0;
04038
04039
04040 if (dst_align >= 64)
04041 {
04042 while (i < nregs && GET_MODE (data_regs[i]) == DImode)
04043 {
04044 emit_move_insn (adjust_address (orig_dst, DImode, ofs),
04045 data_regs[i]);
04046 ofs += 8;
04047 i++;
04048 }
04049 }
04050
04051 if (dst_align >= 32)
04052 {
04053
04054
04055 while (i < nregs && GET_MODE (data_regs[i]) == DImode)
04056 {
04057 tmp = expand_binop (DImode, lshr_optab, data_regs[i], GEN_INT (32),
04058 NULL_RTX, 1, OPTAB_WIDEN);
04059
04060 emit_move_insn (adjust_address (orig_dst, SImode, ofs),
04061 gen_lowpart (SImode, data_regs[i]));
04062 emit_move_insn (adjust_address (orig_dst, SImode, ofs + 4),
04063 gen_lowpart (SImode, tmp));
04064 ofs += 8;
04065 i++;
04066 }
04067
04068 while (i < nregs && GET_MODE (data_regs[i]) == SImode)
04069 {
04070 emit_move_insn (adjust_address (orig_dst, SImode, ofs),
04071 data_regs[i]);
04072 ofs += 4;
04073 i++;
04074 }
04075 }
04076
04077 if (i < nregs && GET_MODE (data_regs[i]) == DImode)
04078 {
04079
04080
04081 for (words = 1; i + words < nregs; words++)
04082 if (GET_MODE (data_regs[i + words]) != DImode)
04083 break;
04084
04085 if (words == 1)
04086 alpha_expand_unaligned_store (orig_dst, data_regs[i], 8, ofs);
04087 else
04088 alpha_expand_unaligned_store_words (data_regs + i, orig_dst,
04089 words, ofs);
04090
04091 i += words;
04092 ofs += words * 8;
04093 }
04094
04095
04096
04097
04098 while (i < nregs && GET_MODE (data_regs[i]) == SImode)
04099 {
04100 alpha_expand_unaligned_store (orig_dst, data_regs[i], 4, ofs);
04101 ofs += 4;
04102 i++;
04103 }
04104
04105 if (dst_align >= 16)
04106 while (i < nregs && GET_MODE (data_regs[i]) == HImode)
04107 {
04108 emit_move_insn (adjust_address (orig_dst, HImode, ofs), data_regs[i]);
04109 i++;
04110 ofs += 2;
04111 }
04112 else
04113 while (i < nregs && GET_MODE (data_regs[i]) == HImode)
04114 {
04115 alpha_expand_unaligned_store (orig_dst, data_regs[i], 2, ofs);
04116 i++;
04117 ofs += 2;
04118 }
04119
04120
04121 while (i < nregs)
04122 {
04123 gcc_assert (GET_MODE (data_regs[i]) == QImode);
04124 emit_move_insn (adjust_address (orig_dst, QImode, ofs), data_regs[i]);
04125 i++;
04126 ofs += 1;
04127 }
04128
04129 return 1;
04130 }
04131
04132 int
04133 alpha_expand_block_clear (rtx operands[])
04134 {
04135 rtx bytes_rtx = operands[1];
04136 rtx align_rtx = operands[3];
04137 HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
04138 HOST_WIDE_INT bytes = orig_bytes;
04139 HOST_WIDE_INT align = INTVAL (align_rtx) * BITS_PER_UNIT;
04140 HOST_WIDE_INT alignofs = 0;
04141 rtx orig_dst = operands[0];
04142 rtx tmp;
04143 int i, words, ofs = 0;
04144
04145 if (orig_bytes <= 0)
04146 return 1;
04147 if (orig_bytes > MAX_MOVE_WORDS * UNITS_PER_WORD)
04148 return 0;
04149
04150
04151 tmp = XEXP (orig_dst, 0);
04152 if (GET_CODE (tmp) == REG)
04153 align = MAX (align, REGNO_POINTER_ALIGN (REGNO (tmp)));
04154 else if (GET_CODE (tmp) == PLUS
04155 && GET_CODE (XEXP (tmp, 0)) == REG
04156 && GET_CODE (XEXP (tmp, 1)) == CONST_INT)
04157 {
04158 HOST_WIDE_INT c = INTVAL (XEXP (tmp, 1));
04159 int a = REGNO_POINTER_ALIGN (REGNO (XEXP (tmp, 0)));
04160
04161 if (a > align)
04162 {
04163 if (a >= 64)
04164 align = a, alignofs = 8 - c % 8;
04165 else if (a >= 32)
04166 align = a, alignofs = 4 - c % 4;
04167 else if (a >= 16)
04168 align = a, alignofs = 2 - c % 2;
04169 }
04170 }
04171
04172
04173
04174 if (alignofs > 0)
04175 {
04176 #if HOST_BITS_PER_WIDE_INT >= 64
04177
04178
04179
04180 if ((!TARGET_BWX || alignofs == 7)
04181 && align >= 32
04182 && !(alignofs == 4 && bytes >= 4))
04183 {
04184 enum machine_mode mode = (align >= 64 ? DImode : SImode);
04185 int inv_alignofs = (align >= 64 ? 8 : 4) - alignofs;
04186 rtx mem, tmp;
04187 HOST_WIDE_INT mask;
04188
04189 mem = adjust_address (orig_dst, mode, ofs - inv_alignofs);
04190 set_mem_alias_set (mem, 0);
04191
04192 mask = ~(~(HOST_WIDE_INT)0 << (inv_alignofs * 8));
04193 if (bytes < alignofs)
04194 {
04195 mask |= ~(HOST_WIDE_INT)0 << ((inv_alignofs + bytes) * 8);
04196 ofs += bytes;
04197 bytes = 0;
04198 }
04199 else
04200 {
04201 bytes -= alignofs;
04202 ofs += alignofs;
04203 }
04204 alignofs = 0;
04205
04206 tmp = expand_binop (mode, and_optab, mem, GEN_INT (mask),
04207 NULL_RTX, 1, OPTAB_WIDEN);
04208
04209 emit_move_insn (mem, tmp);
04210 }
04211 #endif
04212
04213 if (TARGET_BWX && (alignofs & 1) && bytes >= 1)
04214 {
04215 emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
04216 bytes -= 1;
04217 ofs += 1;
04218 alignofs -= 1;
04219 }
04220 if (TARGET_BWX && align >= 16 && (alignofs & 3) == 2 && bytes >= 2)
04221 {
04222 emit_move_insn (adjust_address (orig_dst, HImode, ofs), const0_rtx);
04223 bytes -= 2;
04224 ofs += 2;
04225 alignofs -= 2;
04226 }
04227 if (alignofs == 4 && bytes >= 4)
04228 {
04229 emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
04230 bytes -= 4;
04231 ofs += 4;
04232 alignofs = 0;
04233 }
04234
04235
04236
04237 if (alignofs > 0)
04238 {
04239 alignofs = alignofs & -alignofs;
04240 align = MIN (align, alignofs * BITS_PER_UNIT);
04241 }
04242 }
04243
04244
04245
04246 if (align >= 64 && bytes >= 8)
04247 {
04248 words = bytes / 8;
04249
04250 for (i = 0; i < words; ++i)
04251 emit_move_insn (adjust_address (orig_dst, DImode, ofs + i * 8),
04252 const0_rtx);
04253
04254 bytes -= words * 8;
04255 ofs += words * 8;
04256 }
04257
04258
04259
04260
04261 if (align >= 32 && bytes > 16)
04262 {
04263 rtx orig_dsta;
04264
04265 emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx);
04266 bytes -= 4;
04267 ofs += 4;
04268
04269 orig_dsta = XEXP (orig_dst, 0);
04270 if (GET_CODE (orig_dsta) == LO_SUM)
04271 orig_dsta = force_reg (Pmode, orig_dsta);
04272
04273 words = bytes / 8;
04274 for (i = 0; i < words; ++i)
04275 {
04276 rtx mem
04277 = change_address (orig_dst, DImode,
04278 gen_rtx_AND (DImode,
04279 plus_constant (orig_dsta, ofs + i*8),
04280 GEN_INT (-8)));
04281 set_mem_alias_set (mem, 0);
04282 emit_move_insn (mem, const0_rtx);
04283 }
04284
04285
04286
04287
04288
04289 bytes -= words * 8 - 4;
04290 ofs += words * 8 - 4;
04291 }
04292
04293
04294
04295 if ((align >= 64 && bytes == 4)
04296 || (align == 32 && bytes >= 4))
04297 {
04298 words = bytes / 4;
04299
04300 for (i = 0; i < words; ++i)
04301 emit_move_insn (adjust_address (orig_dst, SImode, ofs + i * 4),
04302 const0_rtx);
04303
04304 bytes -= words * 4;
04305 ofs += words * 4;
04306 }
04307
04308
04309
04310 if (bytes >= 8)
04311 {
04312 words = bytes / 8;
04313
04314 alpha_expand_unaligned_store_words (NULL, orig_dst, words, ofs);
04315
04316 bytes -= words * 8;
04317 ofs += words * 8;
04318 }
04319
04320
04321
04322 #if HOST_BITS_PER_WIDE_INT >= 64
04323
04324
04325 words = 0;
04326 for (i = (TARGET_BWX ? 1 : 4); i * BITS_PER_UNIT <= align ; i <<= 1)
04327 if (bytes & i)
04328 words += 1;
04329
04330
04331
04332 if (TARGET_BWX ? words > 2 : bytes > 0)
04333 {
04334 if (align >= 64)
04335 {
04336 rtx mem, tmp;
04337 HOST_WIDE_INT mask;
04338
04339 mem = adjust_address (orig_dst, DImode, ofs);
04340 set_mem_alias_set (mem, 0);
04341
04342 mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
04343
04344 tmp = expand_binop (DImode, and_optab, mem, GEN_INT (mask),
04345 NULL_RTX, 1, OPTAB_WIDEN);
04346
04347 emit_move_insn (mem, tmp);
04348 return 1;
04349 }
04350 else if (align >= 32 && bytes < 4)
04351 {
04352 rtx mem, tmp;
04353 HOST_WIDE_INT mask;
04354
04355 mem = adjust_address (orig_dst, SImode, ofs);
04356 set_mem_alias_set (mem, 0);
04357
04358 mask = ~(HOST_WIDE_INT)0 << (bytes * 8);
04359
04360 tmp = expand_binop (SImode, and_optab, mem, GEN_INT (mask),
04361 NULL_RTX, 1, OPTAB_WIDEN);
04362
04363 emit_move_insn (mem, tmp);
04364 return 1;
04365 }
04366 }
04367 #endif
04368
04369 if (!TARGET_BWX && bytes >= 4)
04370 {
04371 alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs);
04372 bytes -= 4;
04373 ofs += 4;
04374 }
04375
04376 if (bytes >= 2)
04377 {
04378 if (align >= 16)
04379 {
04380 do {
04381 emit_move_insn (adjust_address (orig_dst, HImode, ofs),
04382 const0_rtx);
04383 bytes -= 2;
04384 ofs += 2;
04385 } while (bytes >= 2);
04386 }
04387 else if (! TARGET_BWX)
04388 {
04389 alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs);
04390 bytes -= 2;
04391 ofs += 2;
04392 }
04393 }
04394
04395 while (bytes > 0)
04396 {
04397 emit_move_insn (adjust_address (orig_dst, QImode, ofs), const0_rtx);
04398 bytes -= 1;
04399 ofs += 1;
04400 }
04401
04402 return 1;
04403 }
04404
04405
04406
04407 rtx
04408 alpha_expand_zap_mask (HOST_WIDE_INT value)
04409 {
04410 rtx result;
04411 int i;
04412
04413 if (HOST_BITS_PER_WIDE_INT >= 64)
04414 {
04415 HOST_WIDE_INT mask = 0;
04416
04417 for (i = 7; i >= 0; --i)
04418 {
04419 mask <<= 8;
04420 if (!((value >> i) & 1))
04421 mask |= 0xff;
04422 }
04423
04424 result = gen_int_mode (mask, DImode);
04425 }
04426 else
04427 {
04428 HOST_WIDE_INT mask_lo = 0, mask_hi = 0;
04429
04430 gcc_assert (HOST_BITS_PER_WIDE_INT == 32);
04431
04432 for (i = 7; i >= 4; --i)
04433 {
04434 mask_hi <<= 8;
04435 if (!((value >> i) & 1))
04436 mask_hi |= 0xff;
04437 }
04438
04439 for (i = 3; i >= 0; --i)
04440 {
04441 mask_lo <<= 8;
04442 if (!((value >> i) & 1))
04443 mask_lo |= 0xff;
04444 }
04445
04446 result = immed_double_const (mask_lo, mask_hi, DImode);
04447 }
04448
04449 return result;
04450 }
04451
04452 void
04453 alpha_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
04454 enum machine_mode mode,
04455 rtx op0, rtx op1, rtx op2)
04456 {
04457 op0 = gen_lowpart (mode, op0);
04458
04459 if (op1 == const0_rtx)
04460 op1 = CONST0_RTX (mode);
04461 else
04462 op1 = gen_lowpart (mode, op1);
04463
04464 if (op2 == const0_rtx)
04465 op2 = CONST0_RTX (mode);
04466 else
04467 op2 = gen_lowpart (mode, op2);
04468
04469 emit_insn ((*gen) (op0, op1, op2));
04470 }
04471
04472
04473
04474
04475 static void
04476 emit_unlikely_jump (rtx cond, rtx label)
04477 {
04478 rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
04479 rtx x;
04480
04481 x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
04482 x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
04483 REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
04484 }
04485
04486
04487
04488
04489 static void
04490 emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
04491 {
04492 rtx (*fn) (rtx, rtx) = NULL;
04493 if (mode == SImode)
04494 fn = gen_load_locked_si;
04495 else if (mode == DImode)
04496 fn = gen_load_locked_di;
04497 emit_insn (fn (reg, mem));
04498 }
04499
04500
04501
04502
04503 static void
04504 emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
04505 {
04506 rtx (*fn) (rtx, rtx, rtx) = NULL;
04507 if (mode == SImode)
04508 fn = gen_store_conditional_si;
04509 else if (mode == DImode)
04510 fn = gen_store_conditional_di;
04511 emit_insn (fn (res, mem, val));
04512 }
04513
04514
04515
04516
04517 static rtx
04518 emit_insxl (enum machine_mode mode, rtx op1, rtx op2)
04519 {
04520 rtx ret = gen_reg_rtx (DImode);
04521 rtx (*fn) (rtx, rtx, rtx);
04522
04523 if (WORDS_BIG_ENDIAN)
04524 {
04525 if (mode == QImode)
04526 fn = gen_insbl_be;
04527 else
04528 fn = gen_inswl_be;
04529 }
04530 else
04531 {
04532 if (mode == QImode)
04533 fn = gen_insbl_le;
04534 else
04535 fn = gen_inswl_le;
04536 }
04537 emit_insn (fn (ret, op1, op2));
04538
04539 return ret;
04540 }
04541
04542
04543
04544
04545
04546
04547
04548 void
04549 alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
04550 rtx before, rtx after, rtx scratch)
04551 {
04552 enum machine_mode mode = GET_MODE (mem);
04553 rtx label, x, cond = gen_rtx_REG (DImode, REGNO (scratch));
04554
04555 emit_insn (gen_memory_barrier ());
04556
04557 label = gen_label_rtx ();
04558 emit_label (label);
04559 label = gen_rtx_LABEL_REF (DImode, label);
04560
04561 if (before == NULL)
04562 before = scratch;
04563 emit_load_locked (mode, before, mem);
04564
04565 if (code == NOT)
04566 x = gen_rtx_AND (mode, gen_rtx_NOT (mode, before), val);
04567 else
04568 x = gen_rtx_fmt_ee (code, mode, before, val);
04569 if (after)
04570 emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
04571 emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
04572
04573 emit_store_conditional (mode, cond, mem, scratch);
04574
04575 x = gen_rtx_EQ (DImode, cond, const0_rtx);
04576 emit_unlikely_jump (x, label);
04577
04578 emit_insn (gen_memory_barrier ());
04579 }
04580
04581
04582
04583 void
04584 alpha_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
04585 rtx scratch)
04586 {
04587 enum machine_mode mode = GET_MODE (mem);
04588 rtx label1, label2, x, cond = gen_lowpart (DImode, scratch);
04589
04590 emit_insn (gen_memory_barrier ());
04591
04592 label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
04593 label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
04594 emit_label (XEXP (label1, 0));
04595
04596 emit_load_locked (mode, retval, mem);
04597
04598 x = gen_lowpart (DImode, retval);
04599 if (oldval == const0_rtx)
04600 x = gen_rtx_NE (DImode, x, const0_rtx);
04601 else
04602 {
04603 x = gen_rtx_EQ (DImode, x, oldval);
04604 emit_insn (gen_rtx_SET (VOIDmode, cond, x));
04605 x = gen_rtx_EQ (DImode, cond, const0_rtx);
04606 }
04607 emit_unlikely_jump (x, label2);
04608
04609 emit_move_insn (scratch, newval);
04610 emit_store_conditional (mode, cond, mem, scratch);
04611
04612 x = gen_rtx_EQ (DImode, cond, const0_rtx);
04613 emit_unlikely_jump (x, label1);
04614
04615 emit_insn (gen_memory_barrier ());
04616 emit_label (XEXP (label2, 0));
04617 }
04618
04619 void
04620 alpha_expand_compare_and_swap_12 (rtx dst, rtx mem, rtx oldval, rtx newval)
04621 {
04622 enum machine_mode mode = GET_MODE (mem);
04623 rtx addr, align, wdst;
04624 rtx (*fn5) (rtx, rtx, rtx, rtx, rtx);
04625
04626 addr = force_reg (DImode, XEXP (mem, 0));
04627 align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
04628 NULL_RTX, 1, OPTAB_DIRECT);
04629
04630 oldval = convert_modes (DImode, mode, oldval, 1);
04631 newval = emit_insxl (mode, newval, addr);
04632
04633 wdst = gen_reg_rtx (DImode);
04634 if (mode == QImode)
04635 fn5 = gen_sync_compare_and_swapqi_1;
04636 else
04637 fn5 = gen_sync_compare_and_swaphi_1;
04638 emit_insn (fn5 (wdst, addr, oldval, newval, align));
04639
04640 emit_move_insn (dst, gen_lowpart (mode, wdst));
04641 }
04642
04643 void
04644 alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
04645 rtx oldval, rtx newval, rtx align,
04646 rtx scratch, rtx cond)
04647 {
04648 rtx label1, label2, mem, width, mask, x;
04649
04650 mem = gen_rtx_MEM (DImode, align);
04651 MEM_VOLATILE_P (mem) = 1;
04652
04653 emit_insn (gen_memory_barrier ());
04654 label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
04655 label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
04656 emit_label (XEXP (label1, 0));
04657
04658 emit_load_locked (DImode, scratch, mem);
04659
04660 width = GEN_INT (GET_MODE_BITSIZE (mode));
04661 mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
04662 if (WORDS_BIG_ENDIAN)
04663 emit_insn (gen_extxl_be (dest, scratch, width, addr));
04664 else
04665 emit_insn (gen_extxl_le (dest, scratch, width, addr));
04666
04667 if (oldval == const0_rtx)
04668 x = gen_rtx_NE (DImode, dest, const0_rtx);
04669 else
04670 {
04671 x = gen_rtx_EQ (DImode, dest, oldval);
04672 emit_insn (gen_rtx_SET (VOIDmode, cond, x));
04673 x = gen_rtx_EQ (DImode, cond, const0_rtx);
04674 }
04675 emit_unlikely_jump (x, label2);
04676
04677 if (WORDS_BIG_ENDIAN)
04678 emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
04679 else
04680 emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
04681 emit_insn (gen_iordi3 (scratch, scratch, newval));
04682
04683 emit_store_conditional (DImode, scratch, mem, scratch);
04684
04685 x = gen_rtx_EQ (DImode, scratch, const0_rtx);
04686 emit_unlikely_jump (x, label1);
04687
04688 emit_insn (gen_memory_barrier ());
04689 emit_label (XEXP (label2, 0));
04690 }
04691
04692
04693
04694 void
04695 alpha_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
04696 {
04697 enum machine_mode mode = GET_MODE (mem);
04698 rtx label, x, cond = gen_lowpart (DImode, scratch);
04699
04700 emit_insn (gen_memory_barrier ());
04701
04702 label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
04703 emit_label (XEXP (label, 0));
04704
04705 emit_load_locked (mode, retval, mem);
04706 emit_move_insn (scratch, val);
04707 emit_store_conditional (mode, cond, mem, scratch);
04708
04709 x = gen_rtx_EQ (DImode, cond, const0_rtx);
04710 emit_unlikely_jump (x, label);
04711 }
04712
04713 void
04714 alpha_expand_lock_test_and_set_12 (rtx dst, rtx mem, rtx val)
04715 {
04716 enum machine_mode mode = GET_MODE (mem);
04717 rtx addr, align, wdst;
04718 rtx (*fn4) (rtx, rtx, rtx, rtx);
04719
04720
04721 addr = force_reg (DImode, XEXP (mem, 0));
04722
04723
04724 align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
04725 NULL_RTX, 1, OPTAB_DIRECT);
04726
04727
04728 val = emit_insxl (mode, val, addr);
04729
04730 wdst = gen_reg_rtx (DImode);
04731 if (mode == QImode)
04732 fn4 = gen_sync_lock_test_and_setqi_1;
04733 else
04734 fn4 = gen_sync_lock_test_and_sethi_1;
04735 emit_insn (fn4 (wdst, addr, val, align));
04736
04737 emit_move_insn (dst, gen_lowpart (mode, wdst));
04738 }
04739
04740 void
04741 alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
04742 rtx val, rtx align, rtx scratch)
04743 {
04744 rtx label, mem, width, mask, x;
04745
04746 mem = gen_rtx_MEM (DImode, align);
04747 MEM_VOLATILE_P (mem) = 1;
04748
04749 emit_insn (gen_memory_barrier ());
04750 label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
04751 emit_label (XEXP (label, 0));
04752
04753 emit_load_locked (DImode, scratch, mem);
04754
04755 width = GEN_INT (GET_MODE_BITSIZE (mode));
04756 mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
04757 if (WORDS_BIG_ENDIAN)
04758 {
04759 emit_insn (gen_extxl_be (dest, scratch, width, addr));
04760 emit_insn (gen_mskxl_be (scratch, scratch, mask, addr));
04761 }
04762 else
04763 {
04764 emit_insn (gen_extxl_le (dest, scratch, width, addr));
04765 emit_insn (gen_mskxl_le (scratch, scratch, mask, addr));
04766 }
04767 emit_insn (gen_iordi3 (scratch, scratch, val));
04768
04769 emit_store_conditional (DImode, scratch, mem, scratch);
04770
04771 x = gen_rtx_EQ (DImode, scratch, const0_rtx);
04772 emit_unlikely_jump (x, label);
04773 }
04774
04775
04776
04777
04778 static int
04779 alpha_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
04780 {
04781 enum attr_type insn_type, dep_insn_type;
04782
04783
04784
04785
04786 if (REG_NOTE_KIND (link) != 0)
04787 return cost;
04788
04789
04790 if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
04791 return cost;
04792
04793 insn_type = get_attr_type (insn);
04794 dep_insn_type = get_attr_type (dep_insn);
04795
04796
04797 if (dep_insn_type == TYPE_ILD
04798 || dep_insn_type == TYPE_FLD
04799 || dep_insn_type == TYPE_LDSYM)
04800 cost += alpha_memory_latency-1;
04801
04802
04803
04804 return cost;
04805 }
04806
04807
04808
04809 static int
04810 alpha_issue_rate (void)
04811 {
04812 return (alpha_tune == PROCESSOR_EV4 ? 2 : 4);
04813 }
04814
04815
04816
04817
04818
04819
04820
04821
04822
04823 static int
04824 alpha_multipass_dfa_lookahead (void)
04825 {
04826 return (alpha_tune == PROCESSOR_EV6 ? 4 : 2);
04827 }
04828
04829
04830
04831 struct machine_function GTY(())
04832 {
04833
04834
04835 struct rtx_def *first_ciw;
04836 struct rtx_def *last_ciw;
04837 int ciw_count;
04838
04839
04840 struct rtx_def *addr_list;
04841
04842
04843 const char *some_ld_name;
04844
04845
04846 struct rtx_def *gp_save_rtx;
04847 };
04848
04849
04850
04851 static struct machine_function *
04852 alpha_init_machine_status (void)
04853 {
04854 return ((struct machine_function *)
04855 ggc_alloc_cleared (sizeof (struct machine_function)));
04856 }
04857
04858
04859
04860
04861
04862 rtx
04863 alpha_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
04864 {
04865 if (count != 0)
04866 return const0_rtx;
04867
04868 return get_hard_reg_initial_val (Pmode, REG_RA);
04869 }
04870
04871
04872
04873
04874 rtx
04875 alpha_gp_save_rtx (void)
04876 {
04877 rtx seq, m = cfun->machine->gp_save_rtx;
04878
04879 if (m == NULL)
04880 {
04881 start_sequence ();
04882
04883 m = assign_stack_local (DImode, UNITS_PER_WORD, BITS_PER_WORD);
04884 m = validize_mem (m);
04885 emit_move_insn (m, pic_offset_table_rtx);
04886
04887 seq = get_insns ();
04888 end_sequence ();
04889 emit_insn_at_entry (seq);
04890
04891 cfun->machine->gp_save_rtx = m;
04892 }
04893
04894 return m;
04895 }
04896
04897 static int
04898 alpha_ra_ever_killed (void)
04899 {
04900 rtx top;
04901
04902 if (!has_hard_reg_initial_val (Pmode, REG_RA))
04903 return regs_ever_live[REG_RA];
04904
04905 push_topmost_sequence ();
04906 top = get_insns ();
04907 pop_topmost_sequence ();
04908
04909 return reg_set_between_p (gen_rtx_REG (Pmode, REG_RA), top, NULL_RTX);
04910 }
04911
04912
04913
04914
04915
04916 static const char *
04917 get_trap_mode_suffix (void)
04918 {
04919 enum attr_trap_suffix s = get_attr_trap_suffix (current_output_insn);
04920
04921 switch (s)
04922 {
04923 case TRAP_SUFFIX_NONE:
04924 return NULL;
04925
04926 case TRAP_SUFFIX_SU:
04927 if (alpha_fptm >= ALPHA_FPTM_SU)
04928 return "su";
04929 return NULL;
04930
04931 case TRAP_SUFFIX_SUI:
04932 if (alpha_fptm >= ALPHA_FPTM_SUI)
04933 return "sui";
04934 return NULL;
04935
04936 case TRAP_SUFFIX_V_SV:
04937 switch (alpha_fptm)
04938 {
04939 case ALPHA_FPTM_N:
04940 return NULL;
04941 case ALPHA_FPTM_U:
04942 return "v";
04943 case ALPHA_FPTM_SU:
04944 case ALPHA_FPTM_SUI:
04945 return "sv";
04946 default:
04947 gcc_unreachable ();
04948 }
04949
04950 case TRAP_SUFFIX_V_SV_SVI:
04951 switch (alpha_fptm)
04952 {
04953 case ALPHA_FPTM_N:
04954 return NULL;
04955 case ALPHA_FPTM_U:
04956 return "v";
04957 case ALPHA_FPTM_SU:
04958 return "sv";
04959 case ALPHA_FPTM_SUI:
04960 return "svi";
04961 default:
04962 gcc_unreachable ();
04963 }
04964 break;
04965
04966 case TRAP_SUFFIX_U_SU_SUI:
04967 switch (alpha_fptm)
04968 {
04969 case ALPHA_FPTM_N:
04970 return NULL;
04971 case ALPHA_FPTM_U:
04972 return "u";
04973 case ALPHA_FPTM_SU:
04974 return "su";
04975 case ALPHA_FPTM_SUI:
04976 return "sui";
04977 default:
04978 gcc_unreachable ();
04979 }
04980 break;
04981
04982 default:
04983 gcc_unreachable ();
04984 }
04985 gcc_unreachable ();
04986 }
04987
04988
04989
04990
04991 static const char *
04992 get_round_mode_suffix (void)
04993 {
04994 enum attr_round_suffix s = get_attr_round_suffix (current_output_insn);
04995
04996 switch (s)
04997 {
04998 case ROUND_SUFFIX_NONE:
04999 return NULL;
05000 case ROUND_SUFFIX_NORMAL:
05001 switch (alpha_fprm)
05002 {
05003 case ALPHA_FPRM_NORM:
05004 return NULL;
05005 case ALPHA_FPRM_MINF:
05006 return "m";
05007 case ALPHA_FPRM_CHOP:
05008 return "c";
05009 case ALPHA_FPRM_DYN:
05010 return "d";
05011 default:
05012 gcc_unreachable ();
05013 }
05014 break;
05015
05016 case ROUND_SUFFIX_C:
05017 return "c";
05018
05019 default:
05020 gcc_unreachable ();
05021 }
05022 gcc_unreachable ();
05023 }
05024
05025
05026
05027
05028 static int
05029 get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
05030 {
05031 rtx x = *px;
05032
05033 if (GET_CODE (x) == SYMBOL_REF
05034 && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
05035 {
05036 cfun->machine->some_ld_name = XSTR (x, 0);
05037 return 1;
05038 }
05039
05040 return 0;
05041 }
05042
05043 static const char *
05044 get_some_local_dynamic_name (void)
05045 {
05046 rtx insn;
05047
05048 if (cfun->machine->some_ld_name)
05049 return cfun->machine->some_ld_name;
05050
05051 for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
05052 if (INSN_P (insn)
05053 && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
05054 return cfun->machine->some_ld_name;
05055
05056 gcc_unreachable ();
05057 }
05058
05059
05060
05061 void
05062 print_operand (FILE *file, rtx x, int code)
05063 {
05064 int i;
05065
05066 switch (code)
05067 {
05068 case '~':
05069
05070 assemble_name (file, alpha_fnname);
05071 break;
05072
05073 case '&':
05074 assemble_name (file, get_some_local_dynamic_name ());
05075 break;
05076
05077 case '/':
05078 {
05079 const char *trap = get_trap_mode_suffix ();
05080 const char *round = get_round_mode_suffix ();
05081
05082 if (trap || round)
05083 fprintf (file, (TARGET_AS_SLASH_BEFORE_SUFFIX ? "/%s%s" : "%s%s"),
05084 (trap ? trap : ""), (round ? round : ""));
05085 break;
05086 }
05087
05088 case ',':
05089
05090 fputc ((TARGET_FLOAT_VAX ? 'f' : 's'), file);
05091 break;
05092
05093 case '-':
05094
05095 fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file);
05096 break;
05097
05098 case '+':
05099
05100
05101 if (next_real_insn (current_output_insn) == 0)
05102 fprintf (file, "\n\tnop");
05103 break;
05104
05105 case '#':
05106 if (alpha_this_literal_sequence_number == 0)
05107 alpha_this_literal_sequence_number = alpha_next_sequence_number++;
05108 fprintf (file, "%d", alpha_this_literal_sequence_number);
05109 break;
05110
05111 case '*':
05112 if (alpha_this_gpdisp_sequence_number == 0)
05113 alpha_this_gpdisp_sequence_number = alpha_next_sequence_number++;
05114 fprintf (file, "%d", alpha_this_gpdisp_sequence_number);
05115 break;
05116
05117 case 'H':
05118 if (GET_CODE (x) == HIGH)
05119 output_addr_const (file, XEXP (x, 0));
05120 else
05121 output_operand_lossage ("invalid %%H value");
05122 break;
05123
05124 case 'J':
05125 {
05126 const char *lituse;
05127
05128 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD_CALL)
05129 {
05130 x = XVECEXP (x, 0, 0);
05131 lituse = "lituse_tlsgd";
05132 }
05133 else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM_CALL)
05134 {
05135 x = XVECEXP (x, 0, 0);
05136 lituse = "lituse_tlsldm";
05137 }
05138 else if (GET_CODE (x) == CONST_INT)
05139 lituse = "lituse_jsr";
05140 else
05141 {
05142 output_operand_lossage ("invalid %%J value");
05143 break;
05144 }
05145
05146 if (x != const0_rtx)
05147 fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x));
05148 }
05149 break;
05150
05151 case 'j':
05152 {
05153 const char *lituse;
05154
05155 #ifdef HAVE_AS_JSRDIRECT_RELOCS
05156 lituse = "lituse_jsrdirect";
05157 #else
05158 lituse = "lituse_jsr";
05159 #endif
05160
05161 gcc_assert (INTVAL (x) != 0);
05162 fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x));
05163 }
05164 break;
05165 case 'r':
05166
05167 if (GET_CODE (x) == REG)
05168 fprintf (file, "%s", reg_names[REGNO (x)]);
05169 else if (x == CONST0_RTX (GET_MODE (x)))
05170 fprintf (file, "$31");
05171 else
05172 output_operand_lossage ("invalid %%r value");
05173 break;
05174
05175 case 'R':
05176
05177 if (GET_CODE (x) == REG)
05178 fprintf (file, "%s", reg_names[REGNO (x)]);
05179 else if (x == CONST0_RTX (GET_MODE (x)))
05180 fprintf (file, "$f31");
05181 else
05182 output_operand_lossage ("invalid %%R value");
05183 break;
05184
05185 case 'N':
05186
05187 if (GET_CODE (x) != CONST_INT)
05188 output_operand_lossage ("invalid %%N value");
05189
05190 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x));
05191 break;
05192
05193 case 'P':
05194
05195 if (GET_CODE (x) != CONST_INT)
05196 output_operand_lossage ("invalid %%P value");
05197
05198 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) 1 << INTVAL (x));
05199 break;
05200
05201 case 'h':
05202
05203 if (GET_CODE (x) != CONST_INT)
05204 output_operand_lossage ("invalid %%h value");
05205
05206 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) >> 16);
05207 break;
05208
05209 case 'L':
05210
05211 if (GET_CODE (x) != CONST_INT)
05212 output_operand_lossage ("invalid %%L value");
05213
05214 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
05215 (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000));
05216 break;
05217
05218 case 'm':
05219
05220 if (GET_CODE (x) == CONST_DOUBLE)
05221 {
05222 HOST_WIDE_INT mask = 0;
05223 HOST_WIDE_INT value;
05224
05225 value = CONST_DOUBLE_LOW (x);
05226 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
05227 i++, value >>= 8)
05228 if (value & 0xff)
05229 mask |= (1 << i);
05230
05231 value = CONST_DOUBLE_HIGH (x);
05232 for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
05233 i++, value >>= 8)
05234 if (value & 0xff)
05235 mask |= (1 << (i + sizeof (int)));
05236
05237 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff);
05238 }
05239
05240 else if (GET_CODE (x) == CONST_INT)
05241 {
05242 HOST_WIDE_INT mask = 0, value = INTVAL (x);
05243
05244 for (i = 0; i < 8; i++, value >>= 8)
05245 if (value & 0xff)
05246 mask |= (1 << i);
05247
05248 fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask);
05249 }
05250 else
05251 output_operand_lossage ("invalid %%m value");
05252 break;
05253
05254 case 'M':
05255
05256 if (GET_CODE (x) != CONST_INT
05257 || (INTVAL (x) != 8 && INTVAL (x) != 16
05258 && INTVAL (x) != 32 && INTVAL (x) != 64))
05259 output_operand_lossage ("invalid %%M value");
05260
05261 fprintf (file, "%s",
05262 (INTVAL (x) == 8 ? "b"
05263 : INTVAL (x) == 16 ? "w"
05264 : INTVAL (x) == 32 ? "l"
05265 : "q"));
05266 break;
05267
05268 case 'U':
05269
05270 if (GET_CODE (x) == CONST_INT)
05271 {
05272 HOST_WIDE_INT value = INTVAL (x);
05273
05274 if (value == 0xff)
05275 {
05276 fputc ('b', file);
05277 break;
05278 }
05279 if (value == 0xffff)
05280 {
05281 fputc ('w', file);
05282 break;
05283 }
05284 if (value == 0xffffffff)
05285 {
05286 fputc ('l', file);
05287 break;
05288 }
05289 if (value == -1)
05290 {
05291 fputc ('q', file);
05292 break;
05293 }
05294 }
05295 else if (HOST_BITS_PER_WIDE_INT == 32
05296 && GET_CODE (x) == CONST_DOUBLE
05297 && CONST_DOUBLE_LOW (x) == 0xffffffff
05298 && CONST_DOUBLE_HIGH (x) == 0)
05299 {
05300 fputc ('l', file);
05301 break;
05302 }
05303 output_operand_lossage ("invalid %%U value");
05304 break;
05305
05306 case 's':
05307
05308
05309
05310 if (GET_CODE (x) != CONST_INT
05311 || (unsigned HOST_WIDE_INT) INTVAL (x) >= (WORDS_BIG_ENDIAN
05312 ? 56
05313 : 64)
05314 || (INTVAL (x) & 7) != 0)
05315 output_operand_lossage ("invalid %%s value");
05316
05317 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
05318 WORDS_BIG_ENDIAN
05319 ? (56 - INTVAL (x)) / 8
05320 : INTVAL (x) / 8);
05321 break;
05322
05323 case 'S':
05324
05325
05326 if (GET_CODE (x) != CONST_INT
05327 && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
05328 && (INTVAL (x) & 7) != 8)
05329 output_operand_lossage ("invalid %%s value");
05330
05331 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);
05332 break;
05333
05334 case 't':
05335 {
05336
05337
05338 int dex = unicosmk_need_dex (x);
05339 if (dex)
05340 fprintf (file, "DEX(%d)", dex);
05341 else
05342 output_addr_const (file, x);
05343 }
05344 break;
05345
05346 case 'C': case 'D': case 'c': case 'd':
05347
05348 {
05349 enum rtx_code c = GET_CODE (x);
05350
05351 if (!COMPARISON_P (x))
05352 output_operand_lossage ("invalid %%C value");
05353
05354 else if (code == 'D')
05355 c = reverse_condition (c);
05356 else if (code == 'c')
05357 c = swap_condition (c);
05358 else if (code == 'd')
05359 c = swap_condition (reverse_condition (c));
05360
05361 if (c == LEU)
05362 fprintf (file, "ule");
05363 else if (c == LTU)
05364 fprintf (file, "ult");
05365 else if (c == UNORDERED)
05366 fprintf (file, "un");
05367 else
05368 fprintf (file, "%s", GET_RTX_NAME (c));
05369 }
05370 break;
05371
05372 case 'E':
05373
05374 switch (GET_CODE (x))
05375 {
05376 case DIV:
05377 fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");
05378 break;
05379 case UDIV:
05380 fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");
05381 break;
05382 case MOD:
05383 fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");
05384 break;
05385 case UMOD:
05386 fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");
05387 break;
05388 default:
05389 output_operand_lossage ("invalid %%E value");
05390 break;
05391 }
05392 break;
05393
05394 case 'A':
05395
05396 if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)
05397 fprintf (file, "_u");
05398 break;
05399
05400 case 0:
05401 if (GET_CODE (x) == REG)
05402 fprintf (file, "%s", reg_names[REGNO (x)]);
05403 else if (GET_CODE (x) == MEM)
05404 output_address (XEXP (x, 0));
05405 else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
05406 {
05407 switch (XINT (XEXP (x, 0), 1))
05408 {
05409 case UNSPEC_DTPREL:
05410 case UNSPEC_TPREL:
05411 output_addr_const (file, XVECEXP (XEXP (x, 0), 0, 0));
05412 break;
05413 default:
05414 output_operand_lossage ("unknown relocation unspec");
05415 break;
05416 }
05417 }
05418 else
05419 output_addr_const (file, x);
05420 break;
05421
05422 default:
05423 output_operand_lossage ("invalid %%xn code");
05424 }
05425 }
05426
05427 void
05428 print_operand_address (FILE *file, rtx addr)
05429 {
05430 int basereg = 31;
05431 HOST_WIDE_INT offset = 0;
05432
05433 if (GET_CODE (addr) == AND)
05434 addr = XEXP (addr, 0);
05435
05436 if (GET_CODE (addr) == PLUS
05437 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
05438 {
05439 offset = INTVAL (XEXP (addr, 1));
05440 addr = XEXP (addr, 0);
05441 }
05442
05443 if (GET_CODE (addr) == LO_SUM)
05444 {
05445 const char *reloc16, *reloclo;
05446 rtx op1 = XEXP (addr, 1);
05447
05448 if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1, 0)) == UNSPEC)
05449 {
05450 op1 = XEXP (op1, 0);
05451 switch (XINT (op1, 1))
05452 {
05453 case UNSPEC_DTPREL:
05454 reloc16 = NULL;
05455 reloclo = (alpha_tls_size == 16 ? "dtprel" : "dtprello");
05456 break;
05457 case UNSPEC_TPREL:
05458 reloc16 = NULL;
05459 reloclo = (alpha_tls_size == 16 ? "tprel" : "tprello");
05460 break;
05461 default:
05462 output_operand_lossage ("unknown relocation unspec");
05463 return;
05464 }
05465
05466 output_addr_const (file, XVECEXP (op1, 0, 0));
05467 }
05468 else
05469 {
05470 reloc16 = "gprel";
05471 reloclo = "gprellow";
05472 output_addr_const (file, op1);
05473 }
05474
05475 if (offset)
05476 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset);
05477
05478 addr = XEXP (addr, 0);
05479 switch (GET_CODE (addr))
05480 {
05481 case REG:
05482 basereg = REGNO (addr);
05483 break;
05484
05485 case SUBREG:
05486 basereg = subreg_regno (addr);
05487 break;
05488
05489 default:
05490 gcc_unreachable ();
05491 }
05492
05493 fprintf (file, "($%d)\t\t!%s", basereg,
05494 (basereg == 29 ? reloc16 : reloclo));
05495 return;
05496 }
05497
05498 switch (GET_CODE (addr))
05499 {
05500 case REG:
05501 basereg = REGNO (addr);
05502 break;
05503
05504 case SUBREG:
05505 basereg = subreg_regno (addr);
05506 break;
05507
05508 case CONST_INT:
05509 offset = INTVAL (addr);
05510 break;
05511
05512 #if TARGET_ABI_OPEN_VMS
05513 case SYMBOL_REF:
05514 fprintf (file, "%s", XSTR (addr, 0));
05515 return;
05516
05517 case CONST:
05518 gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS
05519 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF);
05520 fprintf (file, "%s+" HOST_WIDE_INT_PRINT_DEC,
05521 XSTR (XEXP (XEXP (addr, 0), 0), 0),
05522 INTVAL (XEXP (XEXP (addr, 0), 1)));
05523 return;
05524
05525 #endif
05526 default:
05527 gcc_unreachable ();
05528 }
05529
05530 fprintf (file, HOST_WIDE_INT_PRINT_DEC "($%d)", offset, basereg);
05531 }
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546 void
05547 alpha_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt,
05548 int fnofs, int cxtofs, int jmpofs)
05549 {
05550 rtx temp, temp1, addr;
05551
05552 enum machine_mode mode = TARGET_ABI_OPEN_VMS ? Pmode : ptr_mode;
05553
05554 #ifdef POINTERS_EXTEND_UNSIGNED
05555 fnaddr = convert_memory_address (mode, fnaddr);
05556 cxt = convert_memory_address (mode, cxt);
05557 #endif
05558
05559
05560 addr = memory_address (mode, plus_constant (tramp, fnofs));
05561 emit_move_insn (gen_rtx_MEM (mode, addr), fnaddr);
05562 addr = memory_address (mode, plus_constant (tramp, cxtofs));
05563 emit_move_insn (gen_rtx_MEM (mode, addr), cxt);
05564
05565
05566
05567 if (0 && jmpofs >= 0)
05568 {
05569
05570 temp = force_operand (plus_constant (tramp, jmpofs+4), NULL_RTX);
05571 temp = expand_binop (DImode, sub_optab, fnaddr, temp, temp, 1,
05572 OPTAB_WIDEN);
05573 temp = expand_shift (RSHIFT_EXPR, Pmode, temp,
05574 build_int_cst (NULL_TREE, 2), NULL_RTX, 1);
05575 temp = expand_and (SImode, gen_lowpart (SImode, temp),
05576 GEN_INT (0x3fff), 0);
05577
05578
05579 addr = memory_address (SImode, plus_constant (tramp, jmpofs));
05580 temp1 = force_reg (SImode, gen_rtx_MEM (SImode, addr));
05581 temp1 = expand_and (SImode, temp1, GEN_INT (0xffffc000), NULL_RTX);
05582 temp1 = expand_binop (SImode, ior_optab, temp1, temp, temp1, 1,
05583 OPTAB_WIDEN);
05584 emit_move_insn (gen_rtx_MEM (SImode, addr), temp1);
05585 }
05586
05587 #ifdef ENABLE_EXECUTE_STACK
05588 emit_library_call (init_one_libfunc ("__enable_execute_stack"),
05589 0, VOIDmode, 1, tramp, Pmode);
05590 #endif
05591
05592 if (jmpofs >= 0)
05593 emit_insn (gen_imb ());
05594 }
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612 rtx
05613 function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type,
05614 int named ATTRIBUTE_UNUSED)
05615 {
05616 int basereg;
05617 int num_args;
05618
05619
05620 if (type && AGGREGATE_TYPE_P (type))
05621 basereg = 16;
05622 else
05623 {
05624 #ifdef ENABLE_CHECKING
05625
05626
05627 gcc_assert (!COMPLEX_MODE_P (mode));
05628 #endif
05629
05630
05631
05632 if (TARGET_FPREGS && GET_MODE_CLASS (mode) == MODE_FLOAT)
05633 basereg = 32 + 16;
05634 else
05635 basereg = 16;
05636 }
05637
05638
05639
05640 #if TARGET_ABI_OPEN_VMS
05641 {
05642 if (mode == VOIDmode)
05643 return alpha_arg_info_reg_val (cum);
05644
05645 num_args = cum.num_args;
05646 if (num_args >= 6
05647 || targetm.calls.must_pass_in_stack (mode, type))
05648 return NULL_RTX;
05649 }
05650 #elif TARGET_ABI_UNICOSMK
05651 {
05652 int size;
05653
05654
05655
05656
05657 if (mode == VOIDmode)
05658 {
05659 int i;
05660 HOST_WIDE_INT lo;
05661 HOST_WIDE_INT hi;
05662 rtx ciw;
05663
05664 lo = 0;
05665
05666 for (i = 0; i < cum.num_reg_words && i < 5; i++)
05667 if (cum.reg_args_type[i])
05668 lo |= (1 << (7 - i));
05669
05670 if (cum.num_reg_words == 6 && cum.reg_args_type[5])
05671 lo |= 7;
05672 else
05673 lo |= cum.num_reg_words;
05674
05675 #if HOST_BITS_PER_WIDE_INT == 32
05676 hi = (cum.num_args << 20) | cum.num_arg_words;
05677 #else
05678 lo = lo | ((HOST_WIDE_INT) cum.num_args << 52)
05679 | ((HOST_WIDE_INT) cum.num_arg_words << 32);
05680 hi = 0;
05681 #endif
05682 ciw = immed_double_const (lo, hi, DImode);
05683
05684 return gen_rtx_UNSPEC (DImode, gen_rtvec (1, ciw),
05685 UNSPEC_UMK_LOAD_CIW);
05686 }
05687
05688 size = ALPHA_ARG_SIZE (mode, type, named);
05689 num_args = cum.num_reg_words;
05690 if (cum.force_stack
05691 || cum.num_reg_words + size > 6
05692 || targetm.calls.must_pass_in_stack (mode, type))
05693 return NULL_RTX;
05694 else if (type && TYPE_MODE (type) == BLKmode)
05695 {
05696 rtx reg1, reg2;
05697
05698 reg1 = gen_rtx_REG (DImode, num_args + 16);
05699 reg1 = gen_rtx_EXPR_LIST (DImode, reg1, const0_rtx);
05700
05701
05702
05703 if (size == 0)
05704 return NULL_RTX;
05705 else if (size == 1)
05706 return gen_rtx_PARALLEL (mode, gen_rtvec (1, reg1));
05707 else
05708 {
05709 reg2 = gen_rtx_REG (DImode, num_args + 17);
05710 reg2 = gen_rtx_EXPR_LIST (DImode, reg2, GEN_INT (8));
05711 return gen_rtx_PARALLEL (mode, gen_rtvec (2, reg1, reg2));
05712 }
05713 }
05714 }
05715 #elif TARGET_ABI_OSF
05716 {
05717 if (cum >= 6)
05718 return NULL_RTX;
05719 num_args = cum;
05720
05721
05722 if (type == void_type_node)
05723 basereg = 16;
05724 else if (targetm.calls.must_pass_in_stack (mode, type))
05725 return NULL_RTX;
05726 }
05727 #else
05728 #error Unhandled ABI
05729 #endif
05730
05731 return gen_rtx_REG (mode, num_args + basereg);
05732 }
05733
05734 static int
05735 alpha_arg_partial_bytes (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
05736 enum machine_mode mode ATTRIBUTE_UNUSED,
05737 tree type ATTRIBUTE_UNUSED,
05738 bool named ATTRIBUTE_UNUSED)
05739 {
05740 int words = 0;
05741
05742 #if TARGET_ABI_OPEN_VMS
05743 if (cum->num_args < 6
05744 && 6 < cum->num_args + ALPHA_ARG_SIZE (mode, type, named))
05745 words = 6 - cum->num_args;
05746 #elif TARGET_ABI_UNICOSMK
05747
05748 #elif TARGET_ABI_OSF
05749 if (*cum < 6 && 6 < *cum + ALPHA_ARG_SIZE (mode, type, named))
05750 words = 6 - *cum;
05751 #else
05752 #error Unhandled ABI
05753 #endif
05754
05755 return words * UNITS_PER_WORD;
05756 }
05757
05758
05759
05760
05761 static bool
05762 alpha_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
05763 {
05764 enum machine_mode mode = VOIDmode;
05765 int size;
05766
05767 if (type)
05768 {
05769 mode = TYPE_MODE (type);
05770
05771
05772 if (AGGREGATE_TYPE_P (type))
05773 return true;
05774 }
05775
05776 size = GET_MODE_SIZE (mode);
05777 switch (GET_MODE_CLASS (mode))
05778 {
05779 case MODE_VECTOR_FLOAT:
05780
05781 return true;
05782
05783 case MODE_COMPLEX_FLOAT:
05784
05785
05786 size = GET_MODE_UNIT_SIZE (mode);
05787 break;
05788
05789 case MODE_INT:
05790 case MODE_FLOAT:
05791 case MODE_COMPLEX_INT:
05792 case MODE_VECTOR_INT:
05793 break;
05794
05795 default:
05796
05797
05798
05799
05800 return true;
05801 }
05802
05803
05804 return size > UNITS_PER_WORD;
05805 }
05806
05807
05808
05809 static bool
05810 alpha_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
05811 enum machine_mode mode,
05812 tree type ATTRIBUTE_UNUSED,
05813 bool named ATTRIBUTE_UNUSED)
05814 {
05815 return mode == TFmode || mode == TCmode;
05816 }
05817
05818
05819
05820
05821
05822
05823
05824
05825
05826 rtx
05827 function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
05828 enum machine_mode mode)
05829 {
05830 unsigned int regnum, dummy;
05831 enum mode_class class;
05832
05833 gcc_assert (!valtype || !alpha_return_in_memory (valtype, func));
05834
05835 if (valtype)
05836 mode = TYPE_MODE (valtype);
05837
05838 class = GET_MODE_CLASS (mode);
05839 switch (class)
05840 {
05841 case MODE_INT:
05842 PROMOTE_MODE (mode, dummy, valtype);
05843
05844
05845 case MODE_COMPLEX_INT:
05846 case MODE_VECTOR_INT:
05847 regnum = 0;
05848 break;
05849
05850 case MODE_FLOAT:
05851 regnum = 32;
05852 break;
05853
05854 case MODE_COMPLEX_FLOAT:
05855 {
05856 enum machine_mode cmode = GET_MODE_INNER (mode);
05857
05858 return gen_rtx_PARALLEL
05859 (VOIDmode,
05860 gen_rtvec (2,
05861 gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 32),
05862 const0_rtx),
05863 gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 33),
05864 GEN_INT (GET_MODE_SIZE (cmode)))));
05865 }
05866
05867 default:
05868 gcc_unreachable ();
05869 }
05870
05871 return gen_rtx_REG (mode, regnum);
05872 }
05873
05874
05875
05876
05877 static bool
05878 alpha_split_complex_arg (tree type)
05879 {
05880 return TYPE_MODE (type) != TCmode;
05881 }
05882
05883 static tree
05884 alpha_build_builtin_va_list (void)
05885 {
05886 tree base, ofs, space, record, type_decl;
05887
05888 if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
05889 return ptr_type_node;
05890
05891 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
05892 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
05893 TREE_CHAIN (record) = type_decl;
05894 TYPE_NAME (record) = type_decl;
05895
05896
05897
05898
05899 space = build_decl (FIELD_DECL, NULL_TREE, integer_type_node);
05900 DECL_FIELD_CONTEXT (space) = record;
05901 DECL_ARTIFICIAL (space) = 1;
05902 DECL_IGNORED_P (space) = 1;
05903
05904 ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
05905 integer_type_node);
05906 DECL_FIELD_CONTEXT (ofs) = record;
05907 TREE_CHAIN (ofs) = space;
05908
05909 base = build_decl (FIELD_DECL, get_identifier ("__base"),
05910 ptr_type_node);
05911 DECL_FIELD_CONTEXT (base) = record;
05912 TREE_CHAIN (base) = ofs;
05913
05914 TYPE_FIELDS (record) = base;
05915 layout_type (record);
05916
05917 va_list_gpr_counter_field = ofs;
05918 return record;
05919 }
05920
05921 #if TARGET_ABI_OSF
05922
05923
05924
05925 static tree
05926 va_list_skip_additions (tree lhs)
05927 {
05928 tree rhs, stmt;
05929
05930 if (TREE_CODE (lhs) != SSA_NAME)
05931 return lhs;
05932
05933 for (;;)
05934 {
05935 stmt = SSA_NAME_DEF_STMT (lhs);
05936
05937 if (TREE_CODE (stmt) == PHI_NODE)
05938 return stmt;
05939
05940 if (TREE_CODE (stmt) != MODIFY_EXPR
05941 || TREE_OPERAND (stmt, 0) != lhs)
05942 return lhs;
05943
05944 rhs = TREE_OPERAND (stmt, 1);
05945 if (TREE_CODE (rhs) == WITH_SIZE_EXPR)
05946 rhs = TREE_OPERAND (rhs, 0);
05947
05948 if ((TREE_CODE (rhs) != NOP_EXPR
05949 && TREE_CODE (rhs) != CONVERT_EXPR
05950 && (TREE_CODE (rhs) != PLUS_EXPR
05951 || TREE_CODE (TREE_OPERAND (rhs, 1)) != INTEGER_CST
05952 || !host_integerp (TREE_OPERAND (rhs, 1), 1)))
05953 || TREE_CODE (TREE_OPERAND (rhs, 0)) != SSA_NAME)
05954 return rhs;
05955
05956 lhs = TREE_OPERAND (rhs, 0);
05957 }
05958 }
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974 static bool
05975 alpha_stdarg_optimize_hook (struct stdarg_info *si, tree lhs, tree rhs)
05976 {
05977 tree base, offset, arg1, arg2;
05978 int offset_arg = 1;
05979
05980 if (TREE_CODE (rhs) != INDIRECT_REF
05981 || TREE_CODE (TREE_OPERAND (rhs, 0)) != SSA_NAME)
05982 return false;
05983
05984 lhs = va_list_skip_additions (TREE_OPERAND (rhs, 0));
05985 if (lhs == NULL_TREE
05986 || TREE_CODE (lhs) != PLUS_EXPR)
05987 return false;
05988
05989 base = TREE_OPERAND (lhs, 0);
05990 if (TREE_CODE (base) == SSA_NAME)
05991 base = va_list_skip_additions (base);
05992
05993 if (TREE_CODE (base) != COMPONENT_REF
05994 || TREE_OPERAND (base, 1) != TYPE_FIELDS (va_list_type_node))
05995 {
05996 base = TREE_OPERAND (lhs, 0);
05997 if (TREE_CODE (base) == SSA_NAME)
05998 base = va_list_skip_additions (base);
05999
06000 if (TREE_CODE (base) != COMPONENT_REF
06001 || TREE_OPERAND (base, 1) != TYPE_FIELDS (va_list_type_node))
06002 return false;
06003
06004 offset_arg = 0;
06005 }
06006
06007 base = get_base_address (base);
06008 if (TREE_CODE (base) != VAR_DECL
06009 || !bitmap_bit_p (si->va_list_vars, DECL_UID (base)))
06010 return false;
06011
06012 offset = TREE_OPERAND (lhs, offset_arg);
06013 if (TREE_CODE (offset) == SSA_NAME)
06014 offset = va_list_skip_additions (offset);
06015
06016 if (TREE_CODE (offset) == PHI_NODE)
06017 {
06018 HOST_WIDE_INT sub;
06019
06020 if (PHI_NUM_ARGS (offset) != 2)
06021 goto escapes;
06022
06023 arg1 = va_list_skip_additions (PHI_ARG_DEF (offset, 0));
06024 arg2 = va_list_skip_additions (PHI_ARG_DEF (offset, 1));
06025 if (TREE_CODE (arg2) != MINUS_EXPR && TREE_CODE (arg2) != PLUS_EXPR)
06026 {
06027 tree tem = arg1;
06028 arg1 = arg2;
06029 arg2 = tem;
06030
06031 if (TREE_CODE (arg2) != MINUS_EXPR && TREE_CODE (arg2) != PLUS_EXPR)
06032 goto escapes;
06033 }
06034 if (!host_integerp (TREE_OPERAND (arg2, 1), 0))
06035 goto escapes;
06036
06037 sub = tree_low_cst (TREE_OPERAND (arg2, 1), 0);
06038 if (TREE_CODE (arg2) == MINUS_EXPR)
06039 sub = -sub;
06040 if (sub < -48 || sub > -32)
06041 goto escapes;
06042
06043 arg2 = va_list_skip_additions (TREE_OPERAND (arg2, 0));
06044 if (arg1 != arg2)
06045 goto escapes;
06046
06047 if (TREE_CODE (arg1) == SSA_NAME)
06048 arg1 = va_list_skip_additions (arg1);
06049
06050 if (TREE_CODE (arg1) != COMPONENT_REF
06051 || TREE_OPERAND (arg1, 1) != va_list_gpr_counter_field
06052 || get_base_address (arg1) != base)
06053 goto escapes;
06054
06055
06056 cfun->va_list_fpr_size |= 2;
06057 }
06058 else if (TREE_CODE (offset) != COMPONENT_REF
06059 || TREE_OPERAND (offset, 1) != va_list_gpr_counter_field
06060 || get_base_address (offset) != base)
06061 goto escapes;
06062 else
06063
06064 cfun->va_list_fpr_size |= 1;
06065 return false;
06066
06067 escapes:
06068 si->va_list_escapes = true;
06069 return false;
06070 }
06071 #endif
06072
06073
06074
06075
06076 static void
06077 alpha_setup_incoming_varargs (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
06078 tree type, int *pretend_size, int no_rtl)
06079 {
06080 CUMULATIVE_ARGS cum = *pcum;
06081
06082
06083 FUNCTION_ARG_ADVANCE (cum, mode, type, 1);
06084
06085 #if TARGET_ABI_UNICOSMK
06086
06087
06088
06089
06090 if (cum.num_reg_words < 6)
06091 {
06092 if (!no_rtl)
06093 {
06094 emit_insn (gen_umk_mismatch_args (GEN_INT (cum.num_reg_words)));
06095 emit_insn (gen_arg_home_umk ());
06096 }
06097 *pretend_size = 0;
06098 }
06099 #elif TARGET_ABI_OPEN_VMS
06100
06101
06102
06103
06104
06105
06106 if (cum.num_args < 6)
06107 {
06108 if (!no_rtl)
06109 {
06110 emit_move_insn (gen_rtx_REG (DImode, 1), virtual_incoming_args_rtx);
06111 emit_insn (gen_arg_home ());
06112 }
06113 *pretend_size = 7 * UNITS_PER_WORD;
06114 }
06115 #else
06116
06117
06118
06119
06120
06121
06122
06123
06124
06125
06126
06127 if (cum >= 6)
06128 return;
06129
06130 if (!no_rtl)
06131 {
06132 int count, set = get_varargs_alias_set ();
06133 rtx tmp;
06134
06135 count = cfun->va_list_gpr_size / UNITS_PER_WORD;
06136 if (count > 6 - cum)
06137 count = 6 - cum;
06138
06139
06140
06141
06142
06143
06144 gcc_assert ((VA_LIST_MAX_FPR_SIZE & 3) == 3);
06145
06146 if (cfun->va_list_fpr_size & 1)
06147 {
06148 tmp = gen_rtx_MEM (BLKmode,
06149 plus_constant (virtual_incoming_args_rtx,
06150 (cum + 6) * UNITS_PER_WORD));
06151 MEM_NOTRAP_P (tmp) = 1;
06152 set_mem_alias_set (tmp, set);
06153 move_block_from_reg (16 + cum, tmp, count);
06154 }
06155
06156 if (cfun->va_list_fpr_size & 2)
06157 {
06158 tmp = gen_rtx_MEM (BLKmode,
06159 plus_constant (virtual_incoming_args_rtx,
06160 cum * UNITS_PER_WORD));
06161 MEM_NOTRAP_P (tmp) = 1;
06162 set_mem_alias_set (tmp, set);
06163 move_block_from_reg (16 + cum + TARGET_FPREGS*32, tmp, count);
06164 }
06165 }
06166 *pretend_size = 12 * UNITS_PER_WORD;
06167 #endif
06168 }
06169
06170 void
06171 alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
06172 {
06173 HOST_WIDE_INT offset;
06174 tree t, offset_field, base_field;
06175
06176 if (TREE_CODE (TREE_TYPE (valist)) == ERROR_MARK)
06177 return;
06178
06179 if (TARGET_ABI_UNICOSMK)
06180 std_expand_builtin_va_start (valist, nextarg);
06181
06182
06183
06184
06185
06186
06187
06188
06189
06190
06191
06192
06193
06194 if (NUM_ARGS < 6)
06195 offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
06196 else
06197 offset = -6 * UNITS_PER_WORD + current_function_pretend_args_size;
06198
06199 if (TARGET_ABI_OPEN_VMS)
06200 {
06201 nextarg = plus_constant (nextarg, offset);
06202 nextarg = plus_constant (nextarg, NUM_ARGS * UNITS_PER_WORD);
06203 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
06204 make_tree (ptr_type_node, nextarg));
06205 TREE_SIDE_EFFECTS (t) = 1;
06206
06207 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06208 }
06209 else
06210 {
06211 base_field = TYPE_FIELDS (TREE_TYPE (valist));
06212 offset_field = TREE_CHAIN (base_field);
06213
06214 base_field = build3 (COMPONENT_REF, TREE_TYPE (base_field),
06215 valist, base_field, NULL_TREE);
06216 offset_field = build3 (COMPONENT_REF, TREE_TYPE (offset_field),
06217 valist, offset_field, NULL_TREE);
06218
06219 t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
06220 t = build2 (PLUS_EXPR, ptr_type_node, t,
06221 build_int_cst (NULL_TREE, offset));
06222 t = build2 (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
06223 TREE_SIDE_EFFECTS (t) = 1;
06224 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06225
06226 t = build_int_cst (NULL_TREE, NUM_ARGS * UNITS_PER_WORD);
06227 t = build2 (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
06228 TREE_SIDE_EFFECTS (t) = 1;
06229 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
06230 }
06231 }
06232
06233 static tree
06234 alpha_gimplify_va_arg_1 (tree type, tree base, tree offset, tree *pre_p)
06235 {
06236 tree type_size, ptr_type, addend, t, addr, internal_post;
06237
06238
06239
06240 if (targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
06241 {
06242 t = build_int_cst (TREE_TYPE (offset), 6*8);
06243 t = build2 (MODIFY_EXPR, TREE_TYPE (offset), offset,
06244 build2 (MAX_EXPR, TREE_TYPE (offset), offset, t));
06245 gimplify_and_add (t, pre_p);
06246 }
06247
06248 addend = offset;
06249 ptr_type = build_pointer_type (type);
06250
06251 if (TREE_CODE (type) == COMPLEX_TYPE)
06252 {
06253 tree real_part, imag_part, real_temp;
06254
06255 real_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base,
06256 offset, pre_p);
06257
06258
06259
06260 real_temp = get_initialized_tmp_var (real_part, pre_p, NULL);
06261
06262 imag_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base,
06263 offset, pre_p);
06264
06265 return build2 (COMPLEX_EXPR, type, real_temp, imag_part);
06266 }
06267 else if (TREE_CODE (type) == REAL_TYPE)
06268 {
06269 tree fpaddend, cond, fourtyeight;
06270
06271 fourtyeight = build_int_cst (TREE_TYPE (addend), 6*8);
06272 fpaddend = fold_build2 (MINUS_EXPR, TREE_TYPE (addend),
06273 addend, fourtyeight);
06274 cond = fold_build2 (LT_EXPR, boolean_type_node, addend, fourtyeight);
06275 addend = fold_build3 (COND_EXPR, TREE_TYPE (addend), cond,
06276 fpaddend, addend);
06277 }
06278
06279
06280 addr = build2 (PLUS_EXPR, ptr_type, fold_convert (ptr_type, base),
06281 fold_convert (ptr_type, addend));
06282 internal_post = NULL;
06283 gimplify_expr (&addr, pre_p, &internal_post, is_gimple_val, fb_rvalue);
06284 append_to_statement_list (internal_post, pre_p);
06285
06286
06287 type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));
06288 if (type_size == NULL || TREE_OVERFLOW (type_size))
06289 t = size_zero_node;
06290 else
06291 {
06292 t = size_binop (PLUS_EXPR, type_size, size_int (7));
06293 t = size_binop (TRUNC_DIV_EXPR, t, size_int (8));
06294 t = size_binop (MULT_EXPR, t, size_int (8));
06295 }
06296 t = fold_convert (TREE_TYPE (offset), t);
06297 t = build2 (MODIFY_EXPR, void_type_node, offset,
06298 build2 (PLUS_EXPR, TREE_TYPE (offset), offset, t));
06299 gimplify_and_add (t, pre_p);
06300
06301 return build_va_arg_indirect_ref (addr);
06302 }
06303
06304 static tree
06305 alpha_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
06306 {
06307 tree offset_field, base_field, offset, base, t, r;
06308 bool indirect;
06309
06310 if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
06311 return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
06312
06313 base_field = TYPE_FIELDS (va_list_type_node);
06314 offset_field = TREE_CHAIN (base_field);
06315 base_field = build3 (COMPONENT_REF, TREE_TYPE (base_field),
06316 valist, base_field, NULL_TREE);
06317 offset_field = build3 (COMPONENT_REF, TREE_TYPE (offset_field),
06318 valist, offset_field, NULL_TREE);
06319
06320
06321
06322
06323 base = get_formal_tmp_var (base_field, pre_p);
06324
06325 t = fold_convert (lang_hooks.types.type_for_size (64, 0), offset_field);
06326 offset = get_initialized_tmp_var (t, pre_p, NULL);
06327
06328 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
06329 if (indirect)
06330 type = build_pointer_type (type);
06331
06332
06333
06334 r = alpha_gimplify_va_arg_1 (type, base, offset, pre_p);
06335
06336
06337 t = build2 (MODIFY_EXPR, void_type_node, offset_field,
06338 fold_convert (TREE_TYPE (offset_field), offset));
06339 gimplify_and_add (t, pre_p);
06340
06341 if (indirect)
06342 r = build_va_arg_indirect_ref (r);
06343
06344 return r;
06345 }
06346
06347
06348
06349 enum alpha_builtin
06350 {
06351 ALPHA_BUILTIN_CMPBGE,
06352 ALPHA_BUILTIN_EXTBL,
06353 ALPHA_BUILTIN_EXTWL,
06354 ALPHA_BUILTIN_EXTLL,
06355 ALPHA_BUILTIN_EXTQL,
06356 ALPHA_BUILTIN_EXTWH,
06357 ALPHA_BUILTIN_EXTLH,
06358 ALPHA_BUILTIN_EXTQH,
06359 ALPHA_BUILTIN_INSBL,
06360 ALPHA_BUILTIN_INSWL,
06361 ALPHA_BUILTIN_INSLL,
06362 ALPHA_BUILTIN_INSQL,
06363 ALPHA_BUILTIN_INSWH,
06364 ALPHA_BUILTIN_INSLH,
06365 ALPHA_BUILTIN_INSQH,
06366 ALPHA_BUILTIN_MSKBL,
06367 ALPHA_BUILTIN_MSKWL,
06368 ALPHA_BUILTIN_MSKLL,
06369 ALPHA_BUILTIN_MSKQL,
06370 ALPHA_BUILTIN_MSKWH,
06371 ALPHA_BUILTIN_MSKLH,
06372 ALPHA_BUILTIN_MSKQH,
06373 ALPHA_BUILTIN_UMULH,
06374 ALPHA_BUILTIN_ZAP,
06375 ALPHA_BUILTIN_ZAPNOT,
06376 ALPHA_BUILTIN_AMASK,
06377 ALPHA_BUILTIN_IMPLVER,
06378 ALPHA_BUILTIN_RPCC,
06379 ALPHA_BUILTIN_THREAD_POINTER,
06380 ALPHA_BUILTIN_SET_THREAD_POINTER,
06381
06382
06383 ALPHA_BUILTIN_MINUB8,
06384 ALPHA_BUILTIN_MINSB8,
06385 ALPHA_BUILTIN_MINUW4,
06386 ALPHA_BUILTIN_MINSW4,
06387 ALPHA_BUILTIN_MAXUB8,
06388 ALPHA_BUILTIN_MAXSB8,
06389 ALPHA_BUILTIN_MAXUW4,
06390 ALPHA_BUILTIN_MAXSW4,
06391 ALPHA_BUILTIN_PERR,
06392 ALPHA_BUILTIN_PKLB,
06393 ALPHA_BUILTIN_PKWB,
06394 ALPHA_BUILTIN_UNPKBL,
06395 ALPHA_BUILTIN_UNPKBW,
06396
06397
06398 ALPHA_BUILTIN_CTTZ,
06399 ALPHA_BUILTIN_CTLZ,
06400 ALPHA_BUILTIN_CTPOP,
06401
06402 ALPHA_BUILTIN_max
06403 };
06404
06405 static unsigned int const code_for_builtin[ALPHA_BUILTIN_max] = {
06406 CODE_FOR_builtin_cmpbge,
06407 CODE_FOR_builtin_extbl,
06408 CODE_FOR_builtin_extwl,
06409 CODE_FOR_builtin_extll,
06410 CODE_FOR_builtin_extql,
06411 CODE_FOR_builtin_extwh,
06412 CODE_FOR_builtin_extlh,
06413 CODE_FOR_builtin_extqh,
06414 CODE_FOR_builtin_insbl,
06415 CODE_FOR_builtin_inswl,
06416 CODE_FOR_builtin_insll,
06417 CODE_FOR_builtin_insql,
06418 CODE_FOR_builtin_inswh,
06419 CODE_FOR_builtin_inslh,
06420 CODE_FOR_builtin_insqh,
06421 CODE_FOR_builtin_mskbl,
06422 CODE_FOR_builtin_mskwl,
06423 CODE_FOR_builtin_mskll,
06424 CODE_FOR_builtin_mskql,
06425 CODE_FOR_builtin_mskwh,
06426 CODE_FOR_builtin_msklh,
06427 CODE_FOR_builtin_mskqh,
06428 CODE_FOR_umuldi3_highpart,
06429 CODE_FOR_builtin_zap,
06430 CODE_FOR_builtin_zapnot,
06431 CODE_FOR_builtin_amask,
06432 CODE_FOR_builtin_implver,
06433 CODE_FOR_builtin_rpcc,
06434 CODE_FOR_load_tp,
06435 CODE_FOR_set_tp,
06436
06437
06438 CODE_FOR_builtin_minub8,
06439 CODE_FOR_builtin_minsb8,
06440 CODE_FOR_builtin_minuw4,
06441 CODE_FOR_builtin_minsw4,
06442 CODE_FOR_builtin_maxub8,
06443 CODE_FOR_builtin_maxsb8,
06444 CODE_FOR_builtin_maxuw4,
06445 CODE_FOR_builtin_maxsw4,
06446 CODE_FOR_builtin_perr,
06447 CODE_FOR_builtin_pklb,
06448 CODE_FOR_builtin_pkwb,
06449 CODE_FOR_builtin_unpkbl,
06450 CODE_FOR_builtin_unpkbw,
06451
06452
06453 CODE_FOR_ctzdi2,
06454 CODE_FOR_clzdi2,
06455 CODE_FOR_popcountdi2
06456 };
06457
06458 struct alpha_builtin_def
06459 {
06460 const char *name;
06461 enum alpha_builtin code;
06462 unsigned int target_mask;
06463 bool is_const;
06464 };
06465
06466 static struct alpha_builtin_def const zero_arg_builtins[] = {
06467 { "__builtin_alpha_implver", ALPHA_BUILTIN_IMPLVER, 0, true },
06468 { "__builtin_alpha_rpcc", ALPHA_BUILTIN_RPCC, 0, false }
06469 };
06470
06471 static struct alpha_builtin_def const one_arg_builtins[] = {
06472 { "__builtin_alpha_amask", ALPHA_BUILTIN_AMASK, 0, true },
06473 { "__builtin_alpha_pklb", ALPHA_BUILTIN_PKLB, MASK_MAX, true },
06474 { "__builtin_alpha_pkwb", ALPHA_BUILTIN_PKWB, MASK_MAX, true },
06475 { "__builtin_alpha_unpkbl", ALPHA_BUILTIN_UNPKBL, MASK_MAX, true },
06476 { "__builtin_alpha_unpkbw", ALPHA_BUILTIN_UNPKBW, MASK_MAX, true },
06477 { "__builtin_alpha_cttz", ALPHA_BUILTIN_CTTZ, MASK_CIX, true },
06478 { "__builtin_alpha_ctlz", ALPHA_BUILTIN_CTLZ, MASK_CIX, true },
06479 { "__builtin_alpha_ctpop", ALPHA_BUILTIN_CTPOP, MASK_CIX, true }
06480 };
06481
06482 static struct alpha_builtin_def const two_arg_builtins[] = {
06483 { "__builtin_alpha_cmpbge", ALPHA_BUILTIN_CMPBGE, 0, true },
06484 { "__builtin_alpha_extbl", ALPHA_BUILTIN_EXTBL, 0, true },
06485 { "__builtin_alpha_extwl", ALPHA_BUILTIN_EXTWL, 0, true },
06486 { "__builtin_alpha_extll", ALPHA_BUILTIN_EXTLL, 0, true },
06487 { "__builtin_alpha_extql", ALPHA_BUILTIN_EXTQL, 0, true },
06488 { "__builtin_alpha_extwh", ALPHA_BUILTIN_EXTWH, 0, true },
06489 { "__builtin_alpha_extlh", ALPHA_BUILTIN_EXTLH, 0, true },
06490 { "__builtin_alpha_extqh", ALPHA_BUILTIN_EXTQH, 0, true },
06491 { "__builtin_alpha_insbl", ALPHA_BUILTIN_INSBL, 0, true },
06492 { "__builtin_alpha_inswl", ALPHA_BUILTIN_INSWL, 0, true },
06493 { "__builtin_alpha_insll", ALPHA_BUILTIN_INSLL, 0, true },
06494 { "__builtin_alpha_insql", ALPHA_BUILTIN_INSQL, 0, true },
06495 { "__builtin_alpha_inswh", ALPHA_BUILTIN_INSWH, 0, true },
06496 { "__builtin_alpha_inslh", ALPHA_BUILTIN_INSLH, 0, true },
06497 { "__builtin_alpha_insqh", ALPHA_BUILTIN_INSQH, 0, true },
06498 { "__builtin_alpha_mskbl", ALPHA_BUILTIN_MSKBL, 0, true },
06499 { "__builtin_alpha_mskwl", ALPHA_BUILTIN_MSKWL, 0, true },
06500 { "__builtin_alpha_mskll", ALPHA_BUILTIN_MSKLL, 0, true },
06501 { "__builtin_alpha_mskql", ALPHA_BUILTIN_MSKQL, 0, true },
06502 { "__builtin_alpha_mskwh", ALPHA_BUILTIN_MSKWH, 0, true },
06503 { "__builtin_alpha_msklh", ALPHA_BUILTIN_MSKLH, 0, true },
06504 { "__builtin_alpha_mskqh", ALPHA_BUILTIN_MSKQH, 0, true },
06505 { "__builtin_alpha_umulh", ALPHA_BUILTIN_UMULH, 0, true },
06506 { "__builtin_alpha_zap", ALPHA_BUILTIN_ZAP, 0, true },
06507 { "__builtin_alpha_zapnot", ALPHA_BUILTIN_ZAPNOT, 0, true },
06508 { "__builtin_alpha_minub8", ALPHA_BUILTIN_MINUB8, MASK_MAX, true },
06509 { "__builtin_alpha_minsb8", ALPHA_BUILTIN_MINSB8, MASK_MAX, true },
06510 { "__builtin_alpha_minuw4", ALPHA_BUILTIN_MINUW4, MASK_MAX, true },
06511 { "__builtin_alpha_minsw4", ALPHA_BUILTIN_MINSW4, MASK_MAX, true },
06512 { "__builtin_alpha_maxub8", ALPHA_BUILTIN_MAXUB8, MASK_MAX, true },
06513 { "__builtin_alpha_maxsb8", ALPHA_BUILTIN_MAXSB8, MASK_MAX, true },
06514 { "__builtin_alpha_maxuw4", ALPHA_BUILTIN_MAXUW4, MASK_MAX, true },
06515 { "__builtin_alpha_maxsw4", ALPHA_BUILTIN_MAXSW4, MASK_MAX, true },
06516 { "__builtin_alpha_perr", ALPHA_BUILTIN_PERR, MASK_MAX, true }
06517 };
06518
06519 static GTY(()) tree alpha_v8qi_u;
06520 static GTY(()) tree alpha_v8qi_s;
06521 static GTY(()) tree alpha_v4hi_u;
06522 static GTY(()) tree alpha_v4hi_s;
06523
06524 static void
06525 alpha_init_builtins (void)
06526 {
06527 const struct alpha_builtin_def *p;
06528 tree dimode_integer_type_node;
06529 tree ftype, attrs[2];
06530 size_t i;
06531
06532 dimode_integer_type_node = lang_hooks.types.type_for_mode (DImode, 0);
06533
06534 attrs[0] = tree_cons (get_identifier ("nothrow"), NULL, NULL);
06535 attrs[1] = tree_cons (get_identifier ("const"), NULL, attrs[0]);
06536
06537 ftype = build_function_type (dimode_integer_type_node, void_list_node);
06538
06539 p = zero_arg_builtins;
06540 for (i = 0; i < ARRAY_SIZE (zero_arg_builtins); ++i, ++p)
06541 if ((target_flags & p->target_mask) == p->target_mask)
06542 lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
06543 NULL, attrs[p->is_const]);
06544
06545 ftype = build_function_type_list (dimode_integer_type_node,
06546 dimode_integer_type_node, NULL_TREE);
06547
06548 p = one_arg_builtins;
06549 for (i = 0; i < ARRAY_SIZE (one_arg_builtins); ++i, ++p)
06550 if ((target_flags & p->target_mask) == p->target_mask)
06551 lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
06552 NULL, attrs[p->is_const]);
06553
06554 ftype = build_function_type_list (dimode_integer_type_node,
06555 dimode_integer_type_node,
06556 dimode_integer_type_node, NULL_TREE);
06557
06558 p = two_arg_builtins;
06559 for (i = 0; i < ARRAY_SIZE (two_arg_builtins); ++i, ++p)
06560 if ((target_flags & p->target_mask) == p->target_mask)
06561 lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
06562 NULL, attrs[p->is_const]);
06563
06564 ftype = build_function_type (ptr_type_node, void_list_node);
06565 lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
06566 ALPHA_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
06567 NULL, attrs[0]);
06568
06569 ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
06570 lang_hooks.builtin_function ("__builtin_set_thread_pointer", ftype,
06571 ALPHA_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
06572 NULL, attrs[0]);
06573
06574 alpha_v8qi_u = build_vector_type (unsigned_intQI_type_node, 8);
06575 alpha_v8qi_s = build_vector_type (intQI_type_node, 8);
06576 alpha_v4hi_u = build_vector_type (unsigned_intHI_type_node, 4);
06577 alpha_v4hi_s = build_vector_type (intHI_type_node, 4);
06578 }
06579
06580
06581
06582
06583
06584
06585
06586 static rtx
06587 alpha_expand_builtin (tree exp, rtx target,
06588 rtx subtarget ATTRIBUTE_UNUSED,
06589 enum machine_mode mode ATTRIBUTE_UNUSED,
06590 int ignore ATTRIBUTE_UNUSED)
06591 {
06592 #define MAX_ARGS 2
06593
06594 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
06595 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
06596 tree arglist = TREE_OPERAND (exp, 1);
06597 enum insn_code icode;
06598 rtx op[MAX_ARGS], pat;
06599 int arity;
06600 bool nonvoid;
06601
06602 if (fcode >= ALPHA_BUILTIN_max)
06603 internal_error ("bad builtin fcode");
06604 icode = code_for_builtin[fcode];
06605 if (icode == 0)
06606 internal_error ("bad builtin fcode");
06607
06608 nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
06609
06610 for (arglist = TREE_OPERAND (exp, 1), arity = 0;
06611 arglist;
06612 arglist = TREE_CHAIN (arglist), arity++)
06613 {
06614 const struct insn_operand_data *insn_op;
06615
06616 tree arg = TREE_VALUE (arglist);
06617 if (arg == error_mark_node)
06618 return NULL_RTX;
06619 if (arity > MAX_ARGS)
06620 return NULL_RTX;
06621
06622 insn_op = &insn_data[icode].operand[arity + nonvoid];
06623
06624 op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, 0);
06625
06626 if (!(*insn_op->predicate) (op[arity], insn_op->mode))
06627 op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
06628 }
06629
06630 if (nonvoid)
06631 {
06632 enum machine_mode tmode = insn_data[icode].operand[0].mode;
06633 if (!target
06634 || GET_MODE (target) != tmode
06635 || !(*insn_data[icode].operand[0].predicate) (target, tmode))
06636 target = gen_reg_rtx (tmode);
06637 }
06638
06639 switch (arity)
06640 {
06641 case 0:
06642 pat = GEN_FCN (icode) (target);
06643 break;
06644 case 1:
06645 if (nonvoid)
06646 pat = GEN_FCN (icode) (target, op[0]);
06647 else
06648 pat = GEN_FCN (icode) (op[0]);
06649 break;
06650 case 2:
06651 pat = GEN_FCN (icode) (target, op[0], op[1]);
06652 break;
06653 default:
06654 gcc_unreachable ();
06655 }
06656 if (!pat)
06657 return NULL_RTX;
06658 emit_insn (pat);
06659
06660 if (nonvoid)
06661 return target;
06662 else
06663 return const0_rtx;
06664 }
06665
06666
06667
06668
06669 #if HOST_BITS_PER_WIDE_INT < 64
06670 # error "HOST_WIDE_INT too small"
06671 #endif
06672
06673
06674
06675
06676
06677 static tree
06678 alpha_fold_builtin_cmpbge (unsigned HOST_WIDE_INT opint[], long op_const)
06679 {
06680 if (op_const == 3)
06681 {
06682 int i, val;
06683 for (i = 0, val = 0; i < 8; ++i)
06684 {
06685 unsigned HOST_WIDE_INT c0 = (opint[0] >> (i * 8)) & 0xff;
06686 unsigned HOST_WIDE_INT c1 = (opint[1] >> (i * 8)) & 0xff;
06687 if (c0 >= c1)
06688 val |= 1 << i;
06689 }
06690 return build_int_cst (long_integer_type_node, val);
06691 }
06692 else if (op_const == 2 && opint[1] == 0)
06693 return build_int_cst (long_integer_type_node, 0xff);
06694 return NULL;
06695 }
06696
06697
06698
06699
06700
06701
06702
06703
06704
06705
06706 static tree
06707 alpha_fold_builtin_zapnot (tree *op, unsigned HOST_WIDE_INT opint[],
06708 long op_const)
06709 {
06710 if (op_const & 2)
06711 {
06712 unsigned HOST_WIDE_INT mask = 0;
06713 int i;
06714
06715 for (i = 0; i < 8; ++i)
06716 if ((opint[1] >> i) & 1)
06717 mask |= (unsigned HOST_WIDE_INT)0xff << (i * 8);
06718
06719 if (op_const & 1)
06720 return build_int_cst (long_integer_type_node, opint[0] & mask);
06721
06722 if (op)
06723 return fold (build2 (BIT_AND_EXPR, long_integer_type_node, op[0],
06724 build_int_cst (long_integer_type_node, mask)));
06725 }
06726 else if ((op_const & 1) && opint[0] == 0)
06727 return build_int_cst (long_integer_type_node, 0);
06728 return NULL;
06729 }
06730
06731
06732
06733 static tree
06734 alpha_fold_builtin_extxx (tree op[], unsigned HOST_WIDE_INT opint[],
06735 long op_const, unsigned HOST_WIDE_INT bytemask,
06736 bool is_high)
06737 {
06738 long zap_const = 2;
06739 tree *zap_op = NULL;
06740
06741 if (op_const & 2)
06742 {
06743 unsigned HOST_WIDE_INT loc;
06744
06745 loc = opint[1] & 7;
06746 if (BYTES_BIG_ENDIAN)
06747 loc ^= 7;
06748 loc *= 8;
06749
06750 if (loc != 0)
06751 {
06752 if (op_const & 1)
06753 {
06754 unsigned HOST_WIDE_INT temp = opint[0];
06755 if (is_high)
06756 temp <<= loc;
06757 else
06758 temp >>= loc;
06759 opint[0] = temp;
06760 zap_const = 3;
06761 }
06762 }
06763 else
06764 zap_op = op;
06765 }
06766
06767 opint[1] = bytemask;
06768 return alpha_fold_builtin_zapnot (zap_op, opint, zap_const);
06769 }
06770
06771
06772
06773 static tree
06774 alpha_fold_builtin_insxx (tree op[], unsigned HOST_WIDE_INT opint[],
06775 long op_const, unsigned HOST_WIDE_INT bytemask,
06776 bool is_high)
06777 {
06778 if ((op_const & 1) && opint[0] == 0)
06779 return build_int_cst (long_integer_type_node, 0);
06780
06781 if (op_const & 2)
06782 {
06783 unsigned HOST_WIDE_INT temp, loc, byteloc;
06784 tree *zap_op = NULL;
06785
06786 loc = opint[1] & 7;
06787 if (BYTES_BIG_ENDIAN)
06788 loc ^= 7;
06789 bytemask <<= loc;
06790
06791 temp = opint[0];
06792 if (is_high)
06793 {
06794 byteloc = (64 - (loc * 8)) & 0x3f;
06795 if (byteloc == 0)
06796 zap_op = op;
06797 else
06798 temp >>= byteloc;
06799 bytemask >>= 8;
06800 }
06801 else
06802 {
06803 byteloc = loc * 8;
06804 if (byteloc == 0)
06805 zap_op = op;
06806 else
06807 temp <<= byteloc;
06808 }
06809
06810 opint[0] = temp;
06811 opint[1] = bytemask;
06812 return alpha_fold_builtin_zapnot (zap_op, opint, op_const);
06813 }
06814
06815 return NULL;
06816 }
06817
06818 static tree
06819 alpha_fold_builtin_mskxx (tree op[], unsigned HOST_WIDE_INT opint[],
06820 long op_const, unsigned HOST_WIDE_INT bytemask,
06821 bool is_high)
06822 {
06823 if (op_const & 2)
06824 {
06825 unsigned HOST_WIDE_INT loc;
06826
06827 loc = opint[1] & 7;
06828 if (BYTES_BIG_ENDIAN)
06829 loc ^= 7;
06830 bytemask <<= loc;
06831
06832 if (is_high)
06833 bytemask >>= 8;
06834
06835 opint[1] = bytemask ^ 0xff;
06836 }
06837
06838 return alpha_fold_builtin_zapnot (op, opint, op_const);
06839 }
06840
06841 static tree
06842 alpha_fold_builtin_umulh (unsigned HOST_WIDE_INT opint[], long op_const)
06843 {
06844 switch (op_const)
06845 {
06846 case 3:
06847 {
06848 unsigned HOST_WIDE_INT l;
06849 HOST_WIDE_INT h;
06850
06851 mul_double (opint[0], 0, opint[1], 0, &l, &h);
06852
06853 #if HOST_BITS_PER_WIDE_INT > 64
06854 # error fixme
06855 #endif
06856
06857 return build_int_cst (long_integer_type_node, h);
06858 }
06859
06860 case 1:
06861 opint[1] = opint[0];
06862
06863 case 2:
06864
06865 if (opint[1] == 0 || opint[1] == 1)
06866 return build_int_cst (long_integer_type_node, 0);
06867 break;
06868 }
06869 return NULL;
06870 }
06871
06872 static tree
06873 alpha_fold_vector_minmax (enum tree_code code, tree op[], tree vtype)
06874 {
06875 tree op0 = fold_convert (vtype, op[0]);
06876 tree op1 = fold_convert (vtype, op[1]);
06877 tree val = fold (build2 (code, vtype, op0, op1));
06878 return fold_convert (long_integer_type_node, val);
06879 }
06880
06881 static tree
06882 alpha_fold_builtin_perr (unsigned HOST_WIDE_INT opint[], long op_const)
06883 {
06884 unsigned HOST_WIDE_INT temp = 0;
06885 int i;
06886
06887 if (op_const != 3)
06888 return NULL;
06889
06890 for (i = 0; i < 8; ++i)
06891 {
06892 unsigned HOST_WIDE_INT a = (opint[0] >> (i * 8)) & 0xff;
06893 unsigned HOST_WIDE_INT b = (opint[1] >> (i * 8)) & 0xff;
06894 if (a >= b)
06895 temp += a - b;
06896 else
06897 temp += b - a;
06898 }
06899
06900 return build_int_cst (long_integer_type_node, temp);
06901 }
06902
06903 static tree
06904 alpha_fold_builtin_pklb (unsigned HOST_WIDE_INT opint[], long op_const)
06905 {
06906 unsigned HOST_WIDE_INT temp;
06907
06908 if (op_const == 0)
06909 return NULL;
06910
06911 temp = opint[0] & 0xff;
06912 temp |= (opint[0] >> 24) & 0xff00;
06913
06914 return build_int_cst (long_integer_type_node, temp);
06915 }
06916
06917 static tree
06918 alpha_fold_builtin_pkwb (unsigned HOST_WIDE_INT opint[], long op_const)
06919 {
06920 unsigned HOST_WIDE_INT temp;
06921
06922 if (op_const == 0)
06923 return NULL;
06924
06925 temp = opint[0] & 0xff;
06926 temp |= (opint[0] >> 8) & 0xff00;
06927 temp |= (opint[0] >> 16) & 0xff0000;
06928 temp |= (opint[0] >> 24) & 0xff000000;
06929
06930 return build_int_cst (long_integer_type_node, temp);
06931 }
06932
06933 static tree
06934 alpha_fold_builtin_unpkbl (unsigned HOST_WIDE_INT opint[], long op_const)
06935 {
06936 unsigned HOST_WIDE_INT temp;
06937
06938 if (op_const == 0)
06939 return NULL;
06940
06941 temp = opint[0] & 0xff;
06942 temp |= (opint[0] & 0xff00) << 24;
06943
06944 return build_int_cst (long_integer_type_node, temp);
06945 }
06946
06947 static tree
06948 alpha_fold_builtin_unpkbw (unsigned HOST_WIDE_INT opint[], long op_const)
06949 {
06950 unsigned HOST_WIDE_INT temp;
06951
06952 if (op_const == 0)
06953 return NULL;
06954
06955 temp = opint[0] & 0xff;
06956 temp |= (opint[0] & 0x0000ff00) << 8;
06957 temp |= (opint[0] & 0x00ff0000) << 16;
06958 temp |= (opint[0] & 0xff000000) << 24;
06959
06960 return build_int_cst (long_integer_type_node, temp);
06961 }
06962
06963 static tree
06964 alpha_fold_builtin_cttz (unsigned HOST_WIDE_INT opint[], long op_const)
06965 {
06966 unsigned HOST_WIDE_INT temp;
06967
06968 if (op_const == 0)
06969 return NULL;
06970
06971 if (opint[0] == 0)
06972 temp = 64;
06973 else
06974 temp = exact_log2 (opint[0] & -opint[0]);
06975
06976 return build_int_cst (long_integer_type_node, temp);
06977 }
06978
06979 static tree
06980 alpha_fold_builtin_ctlz (unsigned HOST_WIDE_INT opint[], long op_const)
06981 {
06982 unsigned HOST_WIDE_INT temp;
06983
06984 if (op_const == 0)
06985 return NULL;
06986
06987 if (opint[0] == 0)
06988 temp = 64;
06989 else
06990 temp = 64 - floor_log2 (opint[0]) - 1;
06991
06992 return build_int_cst (long_integer_type_node, temp);
06993 }
06994
06995 static tree
06996 alpha_fold_builtin_ctpop (unsigned HOST_WIDE_INT opint[], long op_const)
06997 {
06998 unsigned HOST_WIDE_INT temp, op;
06999
07000 if (op_const == 0)
07001 return NULL;
07002
07003 op = opint[0];
07004 temp = 0;
07005 while (op)
07006 temp++, op &= op - 1;
07007
07008 return build_int_cst (long_integer_type_node, temp);
07009 }
07010
07011
07012
07013 static tree
07014 alpha_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
07015 {
07016 tree op[MAX_ARGS], t;
07017 unsigned HOST_WIDE_INT opint[MAX_ARGS];
07018 long op_const = 0, arity = 0;
07019
07020 for (t = arglist; t ; t = TREE_CHAIN (t), ++arity)
07021 {
07022 tree arg = TREE_VALUE (t);
07023 if (arg == error_mark_node)
07024 return NULL;
07025 if (arity >= MAX_ARGS)
07026 return NULL;
07027
07028 op[arity] = arg;
07029 opint[arity] = 0;
07030 if (TREE_CODE (arg) == INTEGER_CST)
07031 {
07032 op_const |= 1L << arity;
07033 opint[arity] = int_cst_value (arg);
07034 }
07035 }
07036
07037 switch (DECL_FUNCTION_CODE (fndecl))
07038 {
07039 case ALPHA_BUILTIN_CMPBGE:
07040 return alpha_fold_builtin_cmpbge (opint, op_const);
07041
07042 case ALPHA_BUILTIN_EXTBL:
07043 return alpha_fold_builtin_extxx (op, opint, op_const, 0x01, false);
07044 case ALPHA_BUILTIN_EXTWL:
07045 return alpha_fold_builtin_extxx (op, opint, op_const, 0x03, false);
07046 case ALPHA_BUILTIN_EXTLL:
07047 return alpha_fold_builtin_extxx (op, opint, op_const, 0x0f, false);
07048 case ALPHA_BUILTIN_EXTQL:
07049 return alpha_fold_builtin_extxx (op, opint, op_const, 0xff, false);
07050 case ALPHA_BUILTIN_EXTWH:
07051 return alpha_fold_builtin_extxx (op, opint, op_const, 0x03, true);
07052 case ALPHA_BUILTIN_EXTLH:
07053 return alpha_fold_builtin_extxx (op, opint, op_const, 0x0f, true);
07054 case ALPHA_BUILTIN_EXTQH:
07055 return alpha_fold_builtin_extxx (op, opint, op_const, 0xff, true);
07056
07057 case ALPHA_BUILTIN_INSBL:
07058 return alpha_fold_builtin_insxx (op, opint, op_const, 0x01, false);
07059 case ALPHA_BUILTIN_INSWL:
07060 return alpha_fold_builtin_insxx (op, opint, op_const, 0x03, false);
07061 case ALPHA_BUILTIN_INSLL:
07062 return alpha_fold_builtin_insxx (op, opint, op_const, 0x0f, false);
07063 case ALPHA_BUILTIN_INSQL:
07064 return alpha_fold_builtin_insxx (op, opint, op_const, 0xff, false);
07065 case ALPHA_BUILTIN_INSWH:
07066 return alpha_fold_builtin_insxx (op, opint, op_const, 0x03, true);
07067 case ALPHA_BUILTIN_INSLH:
07068 return alpha_fold_builtin_insxx (op, opint, op_const, 0x0f, true);
07069 case ALPHA_BUILTIN_INSQH:
07070 return alpha_fold_builtin_insxx (op, opint, op_const, 0xff, true);
07071
07072 case ALPHA_BUILTIN_MSKBL:
07073 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x01, false);
07074 case ALPHA_BUILTIN_MSKWL:
07075 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x03, false);
07076 case ALPHA_BUILTIN_MSKLL:
07077 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x0f, false);
07078 case ALPHA_BUILTIN_MSKQL:
07079 return alpha_fold_builtin_mskxx (op, opint, op_const, 0xff, false);
07080 case ALPHA_BUILTIN_MSKWH:
07081 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x03, true);
07082 case ALPHA_BUILTIN_MSKLH:
07083 return alpha_fold_builtin_mskxx (op, opint, op_const, 0x0f, true);
07084 case ALPHA_BUILTIN_MSKQH:
07085 return alpha_fold_builtin_mskxx (op, opint, op_const, 0xff, true);
07086
07087 case ALPHA_BUILTIN_UMULH:
07088 return alpha_fold_builtin_umulh (opint, op_const);
07089
07090 case ALPHA_BUILTIN_ZAP:
07091 opint[1] ^= 0xff;
07092
07093 case ALPHA_BUILTIN_ZAPNOT:
07094 return alpha_fold_builtin_zapnot (op, opint, op_const);
07095
07096 case ALPHA_BUILTIN_MINUB8:
07097 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v8qi_u);
07098 case ALPHA_BUILTIN_MINSB8:
07099 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v8qi_s);
07100 case ALPHA_BUILTIN_MINUW4:
07101 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v4hi_u);
07102 case ALPHA_BUILTIN_MINSW4:
07103 return alpha_fold_vector_minmax (MIN_EXPR, op, alpha_v4hi_s);
07104 case ALPHA_BUILTIN_MAXUB8:
07105 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v8qi_u);
07106 case ALPHA_BUILTIN_MAXSB8:
07107 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v8qi_s);
07108 case ALPHA_BUILTIN_MAXUW4:
07109 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v4hi_u);
07110 case ALPHA_BUILTIN_MAXSW4:
07111 return alpha_fold_vector_minmax (MAX_EXPR, op, alpha_v4hi_s);
07112
07113 case ALPHA_BUILTIN_PERR:
07114 return alpha_fold_builtin_perr (opint, op_const);
07115 case ALPHA_BUILTIN_PKLB:
07116 return alpha_fold_builtin_pklb (opint, op_const);
07117 case ALPHA_BUILTIN_PKWB:
07118 return alpha_fold_builtin_pkwb (opint, op_const);
07119 case ALPHA_BUILTIN_UNPKBL:
07120 return alpha_fold_builtin_unpkbl (opint, op_const);
07121 case ALPHA_BUILTIN_UNPKBW:
07122 return alpha_fold_builtin_unpkbw (opint, op_const);
07123
07124 case ALPHA_BUILTIN_CTTZ:
07125 return alpha_fold_builtin_cttz (opint, op_const);
07126 case ALPHA_BUILTIN_CTLZ:
07127 return alpha_fold_builtin_ctlz (opint, op_const);
07128 case ALPHA_BUILTIN_CTPOP:
07129 return alpha_fold_builtin_ctpop (opint, op_const);
07130
07131 case ALPHA_BUILTIN_AMASK:
07132 case ALPHA_BUILTIN_IMPLVER:
07133 case ALPHA_BUILTIN_RPCC:
07134 case ALPHA_BUILTIN_THREAD_POINTER:
07135 case ALPHA_BUILTIN_SET_THREAD_POINTER:
07136
07137 default:
07138 return NULL;
07139 }
07140 }
07141
07142
07143
07144
07145
07146
07147
07148
07149
07150
07151
07152
07153 enum alpha_procedure_types {PT_NULL = 0, PT_REGISTER = 1, PT_STACK = 2};
07154 static enum alpha_procedure_types alpha_procedure_type;
07155
07156
07157 static int vms_unwind_regno;
07158
07159
07160
07161
07162 static int vms_save_fp_regno;
07163
07164
07165 static int vms_base_regno;
07166
07167
07168
07169 static void
07170 alpha_sa_mask (unsigned long *imaskP, unsigned long *fmaskP)
07171 {
07172 unsigned long imask = 0;
07173 unsigned long fmask = 0;
07174 unsigned int i;
07175
07176
07177
07178
07179 if (current_function_is_thunk)
07180 {
07181 *imaskP = 0;
07182 *fmaskP = 0;
07183 return;
07184 }
07185
07186 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
07187 imask |= (1UL << HARD_FRAME_POINTER_REGNUM);
07188
07189
07190 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
07191 if (! fixed_regs[i] && ! call_used_regs[i]
07192 && regs_ever_live[i] && i != REG_RA
07193 && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
07194 {
07195 if (i < 32)
07196 imask |= (1UL << i);
07197 else
07198 fmask |= (1UL << (i - 32));
07199 }
07200
07201
07202 if (current_function_calls_eh_return)
07203 {
07204 for (i = 0; ; ++i)
07205 {
07206 unsigned regno = EH_RETURN_DATA_REGNO (i);
07207 if (regno == INVALID_REGNUM)
07208 break;
07209 imask |= 1UL << regno;
07210 }
07211 }
07212
07213
07214
07215
07216 if (imask || fmask || alpha_ra_ever_killed ())
07217 imask |= (1UL << REG_RA);
07218
07219 *imaskP = imask;
07220 *fmaskP = fmask;
07221 }
07222
07223 int
07224 alpha_sa_size (void)
07225 {
07226 unsigned long mask[2];
07227 int sa_size = 0;
07228 int i, j;
07229
07230 alpha_sa_mask (&mask[0], &mask[1]);
07231
07232 if (TARGET_ABI_UNICOSMK)
07233 {
07234 if (mask[0] || mask[1])
07235 sa_size = 14;
07236 }
07237 else
07238 {
07239 for (j = 0; j < 2; ++j)
07240 for (i = 0; i < 32; ++i)
07241 if ((mask[j] >> i) & 1)
07242 sa_size++;
07243 }
07244
07245 if (TARGET_ABI_UNICOSMK)
07246 {
07247
07248
07249
07250
07251
07252
07253 alpha_procedure_type
07254 = (sa_size || get_frame_size() != 0
07255 || current_function_outgoing_args_size
07256 || current_function_stdarg || current_function_calls_alloca
07257 || frame_pointer_needed)
07258 ? PT_STACK : PT_REGISTER;
07259
07260
07261
07262 if (alpha_procedure_type == PT_STACK)
07263 sa_size = 14;
07264 }
07265 else if (TARGET_ABI_OPEN_VMS)
07266 {
07267
07268
07269
07270 if ((mask[0] >> REG_RA) & 1)
07271 alpha_procedure_type = PT_STACK;
07272 else if (get_frame_size() != 0)
07273 alpha_procedure_type = PT_REGISTER;
07274 else
07275 alpha_procedure_type = PT_NULL;
07276
07277
07278
07279 if (alpha_procedure_type == PT_STACK)
07280 sa_size -= 2;
07281
07282
07283
07284
07285
07286
07287 vms_base_regno
07288 = (frame_pointer_needed
07289 || current_function_has_nonlocal_label
07290 || alpha_procedure_type == PT_STACK
07291 || current_function_outgoing_args_size)
07292 ? REG_PV : HARD_FRAME_POINTER_REGNUM;
07293
07294
07295
07296
07297 vms_save_fp_regno = -1;
07298 if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
07299 for (i = 0; i < 32; i++)
07300 if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i])
07301 vms_save_fp_regno = i;
07302
07303 if (vms_save_fp_regno == -1 && alpha_procedure_type == PT_REGISTER)
07304 vms_base_regno = REG_PV, alpha_procedure_type = PT_STACK;
07305 else if (alpha_procedure_type == PT_NULL)
07306 vms_base_regno = REG_PV;
07307
07308
07309 vms_unwind_regno = (vms_base_regno == REG_PV
07310 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
07311
07312
07313 if (alpha_procedure_type == PT_STACK)
07314 sa_size += 2;
07315 }
07316 else
07317 {
07318
07319 if (sa_size & 1)
07320 sa_size++;
07321 }
07322
07323 return sa_size * 8;
07324 }
07325
07326
07327
07328
07329 HOST_WIDE_INT
07330 alpha_initial_elimination_offset (unsigned int from,
07331 unsigned int to ATTRIBUTE_UNUSED)
07332 {
07333 HOST_WIDE_INT ret;
07334
07335 ret = alpha_sa_size ();
07336 ret += ALPHA_ROUND (current_function_outgoing_args_size);
07337
07338 switch (from)
07339 {
07340 case FRAME_POINTER_REGNUM:
07341 break;
07342
07343 case ARG_POINTER_REGNUM:
07344 ret += (ALPHA_ROUND (get_frame_size ()
07345 + current_function_pretend_args_size)
07346 - current_function_pretend_args_size);
07347 break;
07348
07349 default:
07350 gcc_unreachable ();
07351 }
07352
07353 return ret;
07354 }
07355
07356 int
07357 alpha_pv_save_size (void)
07358 {
07359 alpha_sa_size ();
07360 return alpha_procedure_type == PT_STACK ? 8 : 0;
07361 }
07362
07363 int
07364 alpha_using_fp (void)
07365 {
07366 alpha_sa_size ();
07367 return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM;
07368 }
07369
07370 #if TARGET_ABI_OPEN_VMS
07371
07372 const struct attribute_spec vms_attribute_table[] =
07373 {
07374
07375 { "overlaid", 0, 0, true, false, false, NULL },
07376 { "global", 0, 0, true, false, false, NULL },
07377 { "initialize", 0, 0, true, false, false, NULL },
07378 { NULL, 0, 0, false, false, false, NULL }
07379 };
07380
07381 #endif
07382
07383 static int
07384 find_lo_sum_using_gp (rtx *px, void *data ATTRIBUTE_UNUSED)
07385 {
07386 return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx;
07387 }
07388
07389 int
07390 alpha_find_lo_sum_using_gp (rtx insn)
07391 {
07392 return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0;
07393 }
07394
07395 static int
07396 alpha_does_function_need_gp (void)
07397 {
07398 rtx insn;
07399
07400
07401 if (! TARGET_ABI_OSF)
07402 return 0;
07403
07404
07405 if (TARGET_PROFILING_NEEDS_GP && current_function_profile)
07406 return 1;
07407
07408
07409 if (current_function_is_thunk)
07410 return 1;
07411
07412
07413
07414
07415
07416 if (current_function_has_nonlocal_goto)
07417 return 1;
07418
07419
07420
07421
07422
07423 push_topmost_sequence ();
07424 insn = get_insns ();
07425 pop_topmost_sequence ();
07426
07427 for (; insn; insn = NEXT_INSN (insn))
07428 if (INSN_P (insn)
07429 && ! JUMP_TABLE_DATA_P (insn)
07430 && GET_CODE (PATTERN (insn)) != USE
07431 && GET_CODE (PATTERN (insn)) != CLOBBER
07432 && get_attr_usegp (insn))
07433 return 1;
07434
07435 return 0;
07436 }
07437
07438
07439
07440
07441
07442 static rtx
07443 set_frame_related_p (void)
07444 {
07445 rtx seq = get_insns ();
07446 rtx insn;
07447
07448 end_sequence ();
07449
07450 if (!seq)
07451 return NULL_RTX;
07452
07453 if (INSN_P (seq))
07454 {
07455 insn = seq;
07456 while (insn != NULL_RTX)
07457 {
07458 RTX_FRAME_RELATED_P (insn) = 1;
07459 insn = NEXT_INSN (insn);
07460 }
07461 seq = emit_insn (seq);
07462 }
07463 else
07464 {
07465 seq = emit_insn (seq);
07466 RTX_FRAME_RELATED_P (seq) = 1;
07467 }
07468 return seq;
07469 }
07470
07471 #define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
07472
07473
07474
07475
07476
07477
07478
07479 static void
07480 emit_frame_store_1 (rtx value, rtx base_reg, HOST_WIDE_INT frame_bias,
07481 HOST_WIDE_INT base_ofs, rtx frame_reg)
07482 {
07483 rtx addr, mem, insn;
07484
07485 addr = plus_constant (base_reg, base_ofs);
07486 mem = gen_rtx_MEM (DImode, addr);
07487 set_mem_alias_set (mem, alpha_sr_alias_set);
07488
07489 insn = emit_move_insn (mem, value);
07490 RTX_FRAME_RELATED_P (insn) = 1;
07491
07492 if (frame_bias || value != frame_reg)
07493 {
07494 if (frame_bias)
07495 {
07496 addr = plus_constant (stack_pointer_rtx, frame_bias + base_ofs);
07497 mem = gen_rtx_MEM (DImode, addr);
07498 }
07499
07500 REG_NOTES (insn)
07501 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
07502 gen_rtx_SET (VOIDmode, mem, frame_reg),
07503 REG_NOTES (insn));
07504 }
07505 }
07506
07507 static void
07508 emit_frame_store (unsigned int regno, rtx base_reg,
07509 HOST_WIDE_INT frame_bias, HOST_WIDE_INT base_ofs)
07510 {
07511 rtx reg = gen_rtx_REG (DImode, regno);
07512 emit_frame_store_1 (reg, base_reg, frame_bias, base_ofs, reg);
07513 }
07514
07515
07516
07517
07518
07519
07520
07521
07522
07523
07524
07525
07526
07527
07528
07529
07530
07531
07532 void
07533 alpha_expand_prologue (void)
07534 {
07535
07536 unsigned long imask = 0;
07537 unsigned long fmask = 0;
07538
07539 HOST_WIDE_INT sa_size;
07540
07541 HOST_WIDE_INT frame_size;
07542
07543 HOST_WIDE_INT reg_offset;
07544 rtx sa_reg;
07545 int i;
07546
07547 sa_size = alpha_sa_size ();
07548
07549 frame_size = get_frame_size ();
07550 if (TARGET_ABI_OPEN_VMS)
07551 frame_size = ALPHA_ROUND (sa_size
07552 + (alpha_procedure_type == PT_STACK ? 8 : 0)
07553 + frame_size
07554 + current_function_pretend_args_size);
07555 else if (TARGET_ABI_UNICOSMK)
07556
07557 frame_size = ALPHA_ROUND (sa_size
07558 + (alpha_procedure_type == PT_STACK ? 48 : 0))
07559 + ALPHA_ROUND (frame_size
07560 + current_function_outgoing_args_size);
07561 else
07562 frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
07563 + sa_size
07564 + ALPHA_ROUND (frame_size
07565 + current_function_pretend_args_size));
07566
07567 if (TARGET_ABI_OPEN_VMS)
07568 reg_offset = 8;
07569 else
07570 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
07571
07572 alpha_sa_mask (&imask, &fmask);
07573
07574
07575 if (TARGET_ABI_OSF)
07576 {
07577 alpha_function_needs_gp = alpha_does_function_need_gp ();
07578 if (alpha_function_needs_gp)
07579 emit_insn (gen_prologue_ldgp ());
07580 }
07581
07582
07583
07584
07585
07586 if (TARGET_PROFILING_NEEDS_GP && current_function_profile)
07587 emit_insn (gen_prologue_mcount ());
07588
07589 if (TARGET_ABI_UNICOSMK)
07590 unicosmk_gen_dsib (&imask);
07591
07592
07593
07594
07595
07596
07597
07598
07599
07600
07601 if (frame_size <= 32768)
07602 {
07603 if (frame_size > 4096)
07604 {
07605 int probed;
07606
07607 for (probed = 4096; probed < frame_size; probed += 8192)
07608 emit_insn (gen_probe_stack (GEN_INT (TARGET_ABI_UNICOSMK
07609 ? -probed + 64
07610 : -probed)));
07611
07612
07613 if (sa_size == 0 && frame_size > probed - 4096)
07614 emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
07615 }
07616
07617 if (frame_size != 0)
07618 FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
07619 GEN_INT (TARGET_ABI_UNICOSMK
07620 ? -frame_size + 64
07621 : -frame_size))));
07622 }
07623 else
07624 {
07625
07626
07627
07628
07629
07630
07631 HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
07632 HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
07633 rtx ptr = gen_rtx_REG (DImode, 22);
07634 rtx count = gen_rtx_REG (DImode, 23);
07635 rtx seq;
07636
07637 emit_move_insn (count, GEN_INT (blocks));
07638 emit_insn (gen_adddi3 (ptr, stack_pointer_rtx,
07639 GEN_INT (TARGET_ABI_UNICOSMK ? 4096 - 64 : 4096)));
07640
07641
07642
07643 emit_insn (gen_prologue_stack_probe_loop (count, ptr));
07644
07645 if (leftover > 4096 && sa_size == 0)
07646 {
07647 rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover));
07648 MEM_VOLATILE_P (last) = 1;
07649 emit_move_insn (last, const0_rtx);
07650 }
07651
07652 if (TARGET_ABI_WINDOWS_NT)
07653 {
07654
07655
07656
07657
07658
07659
07660
07661
07662 HOST_WIDE_INT lo, hi;
07663 lo = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
07664 hi = frame_size - lo;
07665
07666 emit_move_insn (ptr, GEN_INT (hi));
07667 emit_insn (gen_adddi3 (ptr, ptr, GEN_INT (lo)));
07668 seq = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
07669 ptr));
07670 }
07671 else
07672 {
07673 seq = emit_insn (gen_adddi3 (stack_pointer_rtx, ptr,
07674 GEN_INT (-leftover)));
07675 }
07676
07677
07678
07679
07680 RTX_FRAME_RELATED_P (seq) = 1;
07681 REG_NOTES (seq)
07682 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
07683 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
07684 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
07685 GEN_INT (TARGET_ABI_UNICOSMK
07686 ? -frame_size + 64
07687 : -frame_size))),
07688 REG_NOTES (seq));
07689 }
07690
07691 if (!TARGET_ABI_UNICOSMK)
07692 {
07693 HOST_WIDE_INT sa_bias = 0;
07694
07695
07696 sa_reg = stack_pointer_rtx;
07697 if (reg_offset + sa_size > 0x8000)
07698 {
07699 int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
07700 rtx sa_bias_rtx;
07701
07702 if (low + sa_size <= 0x8000)
07703 sa_bias = reg_offset - low, reg_offset = low;
07704 else
07705 sa_bias = reg_offset, reg_offset = 0;
07706
07707 sa_reg = gen_rtx_REG (DImode, 24);
07708 sa_bias_rtx = GEN_INT (sa_bias);
07709
07710 if (add_operand (sa_bias_rtx, DImode))
07711 emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, sa_bias_rtx));
07712 else
07713 {
07714 emit_move_insn (sa_reg, sa_bias_rtx);
07715 emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, sa_reg));
07716 }
07717 }
07718
07719
07720 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
07721 emit_frame_store (REG_PV, stack_pointer_rtx, 0, 0);
07722
07723
07724 if (imask & (1UL << REG_RA))
07725 {
07726 emit_frame_store (REG_RA, sa_reg, sa_bias, reg_offset);
07727 imask &= ~(1UL << REG_RA);
07728 reg_offset += 8;
07729 }
07730
07731
07732 for (i = 0; i < 31; i++)
07733 if (imask & (1UL << i))
07734 {
07735 emit_frame_store (i, sa_reg, sa_bias, reg_offset);
07736 reg_offset += 8;
07737 }
07738
07739 for (i = 0; i < 31; i++)
07740 if (fmask & (1UL << i))
07741 {
07742 emit_frame_store (i+32, sa_reg, sa_bias, reg_offset);
07743 reg_offset += 8;
07744 }
07745 }
07746 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
07747 {
07748
07749
07750
07751
07752 reg_offset = -56;
07753 for (i = 9; i < 15; i++)
07754 if (imask & (1UL << i))
07755 {
07756 emit_frame_store (i, hard_frame_pointer_rtx, 0, reg_offset);
07757 reg_offset -= 8;
07758 }
07759 for (i = 2; i < 10; i++)
07760 if (fmask & (1UL << i))
07761 {
07762 emit_frame_store (i+32, hard_frame_pointer_rtx, 0, reg_offset);
07763 reg_offset -= 8;
07764 }
07765 }
07766
07767 if (TARGET_ABI_OPEN_VMS)
07768 {
07769 if (alpha_procedure_type == PT_REGISTER)
07770
07771
07772 emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
07773 hard_frame_pointer_rtx);
07774
07775 if (alpha_procedure_type != PT_NULL && vms_base_regno != REG_PV)
07776 emit_insn (gen_force_movdi (gen_rtx_REG (DImode, vms_base_regno),
07777 gen_rtx_REG (DImode, REG_PV)));
07778
07779 if (alpha_procedure_type != PT_NULL
07780 && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
07781 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
07782
07783
07784 if (current_function_outgoing_args_size != 0)
07785 {
07786 rtx seq
07787 = emit_move_insn (stack_pointer_rtx,
07788 plus_constant
07789 (hard_frame_pointer_rtx,
07790 - (ALPHA_ROUND
07791 (current_function_outgoing_args_size))));
07792
07793
07794
07795
07796
07797
07798
07799
07800
07801
07802
07803
07804
07805
07806
07807
07808 RTX_FRAME_RELATED_P (seq) = ! frame_pointer_needed;
07809 }
07810 }
07811 else if (!TARGET_ABI_UNICOSMK)
07812 {
07813
07814 if (frame_pointer_needed)
07815 {
07816 if (TARGET_CAN_FAULT_IN_PROLOGUE)
07817 FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
07818 else
07819
07820
07821 FRP (emit_insn (gen_init_fp (hard_frame_pointer_rtx,
07822 stack_pointer_rtx, sa_reg)));
07823 }
07824 }
07825
07826
07827
07828
07829
07830
07831
07832
07833
07834
07835
07836 if (! TARGET_CAN_FAULT_IN_PROLOGUE)
07837 emit_insn (gen_blockage ());
07838 }
07839
07840
07841 int num_source_filenames = 0;
07842
07843
07844
07845 void
07846 alpha_start_function (FILE *file, const char *fnname,
07847 tree decl ATTRIBUTE_UNUSED)
07848 {
07849 unsigned long imask = 0;
07850 unsigned long fmask = 0;
07851
07852 HOST_WIDE_INT sa_size;
07853
07854 unsigned HOST_WIDE_INT frame_size;
07855
07856 unsigned HOST_WIDE_INT max_frame_size = TARGET_ABI_OSF && !TARGET_GAS
07857 ? 524288
07858 : 1UL << 31;
07859
07860 HOST_WIDE_INT reg_offset;
07861 char *entry_label = (char *) alloca (strlen (fnname) + 6);
07862 int i;
07863
07864
07865 if (TARGET_ABI_UNICOSMK)
07866 {
07867 tree name_tree;
07868 name_tree = get_identifier (fnname);
07869 TREE_ASM_WRITTEN (name_tree) = 1;
07870 }
07871
07872 alpha_fnname = fnname;
07873 sa_size = alpha_sa_size ();
07874
07875 frame_size = get_frame_size ();
07876 if (TARGET_ABI_OPEN_VMS)
07877 frame_size = ALPHA_ROUND (sa_size
07878 + (alpha_procedure_type == PT_STACK ? 8 : 0)
07879 + frame_size
07880 + current_function_pretend_args_size);
07881 else if (TARGET_ABI_UNICOSMK)
07882 frame_size = ALPHA_ROUND (sa_size
07883 + (alpha_procedure_type == PT_STACK ? 48 : 0))
07884 + ALPHA_ROUND (frame_size
07885 + current_function_outgoing_args_size);
07886 else
07887 frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
07888 + sa_size
07889 + ALPHA_ROUND (frame_size
07890 + current_function_pretend_args_size));
07891
07892 if (TARGET_ABI_OPEN_VMS)
07893 reg_offset = 8;
07894 else
07895 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
07896
07897 alpha_sa_mask (&imask, &fmask);
07898
07899
07900
07901
07902
07903
07904
07905
07906
07907 if (write_symbols == SDB_DEBUG)
07908 {
07909 #ifdef ASM_OUTPUT_SOURCE_FILENAME
07910 ASM_OUTPUT_SOURCE_FILENAME (file,
07911 DECL_SOURCE_FILE (current_function_decl));
07912 #endif
07913 #ifdef SDB_OUTPUT_SOURCE_LINE
07914 if (debug_info_level != DINFO_LEVEL_TERSE)
07915 SDB_OUTPUT_SOURCE_LINE (file,
07916 DECL_SOURCE_LINE (current_function_decl));
07917 #endif
07918 }
07919
07920
07921 if (TARGET_ABI_OPEN_VMS
07922 || (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive))
07923 {
07924 fputs ("\t.ent ", file);
07925 assemble_name (file, fnname);
07926 putc ('\n', file);
07927
07928
07929
07930 if (TARGET_ABI_OSF
07931 && ! alpha_function_needs_gp
07932 && ! current_function_is_thunk)
07933 {
07934 putc ('$', file);
07935 assemble_name (file, fnname);
07936 fputs ("..ng:\n", file);
07937 }
07938 }
07939
07940 strcpy (entry_label, fnname);
07941 if (TARGET_ABI_OPEN_VMS)
07942 strcat (entry_label, "..en");
07943
07944
07945
07946 if (TARGET_ABI_UNICOSMK && TREE_PUBLIC (decl))
07947 strcat (entry_label, ":");
07948
07949 ASM_OUTPUT_LABEL (file, entry_label);
07950 inside_function = TRUE;
07951
07952 if (TARGET_ABI_OPEN_VMS)
07953 fprintf (file, "\t.base $%d\n", vms_base_regno);
07954
07955 if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK && TARGET_IEEE_CONFORMANT
07956 && !flag_inhibit_size_directive)
07957 {
07958
07959
07960
07961 fputs ("\t.eflag 48\n", file);
07962 }
07963
07964
07965 alpha_auto_offset = -frame_size + current_function_pretend_args_size;
07966 alpha_arg_offset = -frame_size + 48;
07967
07968
07969
07970
07971 if (TARGET_ABI_UNICOSMK)
07972 ;
07973 else if (TARGET_ABI_OPEN_VMS)
07974 fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,"
07975 HOST_WIDE_INT_PRINT_DEC "\n",
07976 vms_unwind_regno,
07977 frame_size >= (1UL << 31) ? 0 : frame_size,
07978 reg_offset);
07979 else if (!flag_inhibit_size_directive)
07980 fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,%d\n",
07981 (frame_pointer_needed
07982 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM),
07983 frame_size >= max_frame_size ? 0 : frame_size,
07984 current_function_pretend_args_size);
07985
07986
07987 if (TARGET_ABI_UNICOSMK)
07988 ;
07989 else if (TARGET_ABI_OPEN_VMS)
07990 {
07991 if (imask)
07992
07993
07994 fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1UL << REG_RA));
07995 if (fmask)
07996 fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
07997 if (alpha_procedure_type == PT_REGISTER)
07998 fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno);
07999 }
08000 else if (!flag_inhibit_size_directive)
08001 {
08002 if (imask)
08003 {
08004 fprintf (file, "\t.mask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", imask,
08005 frame_size >= max_frame_size ? 0 : reg_offset - frame_size);
08006
08007 for (i = 0; i < 32; ++i)
08008 if (imask & (1UL << i))
08009 reg_offset += 8;
08010 }
08011
08012 if (fmask)
08013 fprintf (file, "\t.fmask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", fmask,
08014 frame_size >= max_frame_size ? 0 : reg_offset - frame_size);
08015 }
08016
08017 #if TARGET_ABI_OPEN_VMS
08018
08019 switch_to_section (readonly_data_section);
08020 fprintf (file, "\t.align 3\n");
08021 assemble_name (file, fnname); fputs ("..na:\n", file);
08022 fputs ("\t.ascii \"", file);
08023 assemble_name (file, fnname);
08024 fputs ("\\0\"\n", file);
08025 alpha_need_linkage (fnname, 1);
08026 switch_to_section (text_section);
08027 #endif
08028 }
08029
08030
08031
08032 static void
08033 alpha_output_function_end_prologue (FILE *file)
08034 {
08035 if (TARGET_ABI_UNICOSMK)
08036 ;
08037 else if (TARGET_ABI_OPEN_VMS)
08038 fputs ("\t.prologue\n", file);
08039 else if (TARGET_ABI_WINDOWS_NT)
08040 fputs ("\t.prologue 0\n", file);
08041 else if (!flag_inhibit_size_directive)
08042 fprintf (file, "\t.prologue %d\n",
08043 alpha_function_needs_gp || current_function_is_thunk);
08044 }
08045
08046
08047
08048
08049
08050
08051 #undef FRP
08052 #define FRP(exp) exp
08053
08054 void
08055 alpha_expand_epilogue (void)
08056 {
08057
08058 unsigned long imask = 0;
08059 unsigned long fmask = 0;
08060
08061 HOST_WIDE_INT sa_size;
08062
08063 HOST_WIDE_INT frame_size;
08064
08065 HOST_WIDE_INT reg_offset;
08066 int fp_is_frame_pointer, fp_offset;
08067 rtx sa_reg, sa_reg_exp = NULL;
08068 rtx sp_adj1, sp_adj2, mem;
08069 rtx eh_ofs;
08070 int i;
08071
08072 sa_size = alpha_sa_size ();
08073
08074 frame_size = get_frame_size ();
08075 if (TARGET_ABI_OPEN_VMS)
08076 frame_size = ALPHA_ROUND (sa_size
08077 + (alpha_procedure_type == PT_STACK ? 8 : 0)
08078 + frame_size
08079 + current_function_pretend_args_size);
08080 else if (TARGET_ABI_UNICOSMK)
08081 frame_size = ALPHA_ROUND (sa_size
08082 + (alpha_procedure_type == PT_STACK ? 48 : 0))
08083 + ALPHA_ROUND (frame_size
08084 + current_function_outgoing_args_size);
08085 else
08086 frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
08087 + sa_size
08088 + ALPHA_ROUND (frame_size
08089 + current_function_pretend_args_size));
08090
08091 if (TARGET_ABI_OPEN_VMS)
08092 {
08093 if (alpha_procedure_type == PT_STACK)
08094 reg_offset = 8;
08095 else
08096 reg_offset = 0;
08097 }
08098 else
08099 reg_offset = ALPHA_ROUND (current_function_outgoing_args_size);
08100
08101 alpha_sa_mask (&imask, &fmask);
08102
08103 fp_is_frame_pointer
08104 = ((TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
08105 || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed));
08106 fp_offset = 0;
08107 sa_reg = stack_pointer_rtx;
08108
08109 if (current_function_calls_eh_return)
08110 eh_ofs = EH_RETURN_STACKADJ_RTX;
08111 else
08112 eh_ofs = NULL_RTX;
08113
08114 if (!TARGET_ABI_UNICOSMK && sa_size)
08115 {
08116
08117 if ((TARGET_ABI_OPEN_VMS
08118 && vms_unwind_regno == HARD_FRAME_POINTER_REGNUM)
08119 || (!TARGET_ABI_OPEN_VMS && frame_pointer_needed))
08120 FRP (emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx));
08121
08122
08123 if (reg_offset + sa_size > 0x8000)
08124 {
08125 int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
08126 HOST_WIDE_INT bias;
08127
08128 if (low + sa_size <= 0x8000)
08129 bias = reg_offset - low, reg_offset = low;
08130 else
08131 bias = reg_offset, reg_offset = 0;
08132
08133 sa_reg = gen_rtx_REG (DImode, 22);
08134 sa_reg_exp = plus_constant (stack_pointer_rtx, bias);
08135
08136 FRP (emit_move_insn (sa_reg, sa_reg_exp));
08137 }
08138
08139
08140
08141 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
08142 if (! eh_ofs)
08143 set_mem_alias_set (mem, alpha_sr_alias_set);
08144 FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
08145
08146 reg_offset += 8;
08147 imask &= ~(1UL << REG_RA);
08148
08149 for (i = 0; i < 31; ++i)
08150 if (imask & (1UL << i))
08151 {
08152 if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
08153 fp_offset = reg_offset;
08154 else
08155 {
08156 mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
08157 set_mem_alias_set (mem, alpha_sr_alias_set);
08158 FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
08159 }
08160 reg_offset += 8;
08161 }
08162
08163 for (i = 0; i < 31; ++i)
08164 if (fmask & (1UL << i))
08165 {
08166 mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset));
08167 set_mem_alias_set (mem, alpha_sr_alias_set);
08168 FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
08169 reg_offset += 8;
08170 }
08171 }
08172 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type == PT_STACK)
08173 {
08174
08175
08176 reg_offset = -56;
08177
08178 for (i = 9; i < 15; i++)
08179 if (imask & (1UL << i))
08180 {
08181 mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
08182 reg_offset));
08183 set_mem_alias_set (mem, alpha_sr_alias_set);
08184 FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
08185 reg_offset -= 8;
08186 }
08187
08188 for (i = 2; i < 10; i++)
08189 if (fmask & (1UL << i))
08190 {
08191 mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
08192 reg_offset));
08193 set_mem_alias_set (mem, alpha_sr_alias_set);
08194 FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
08195 reg_offset -= 8;
08196 }
08197
08198
08199
08200 mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx, -8));
08201 set_mem_alias_set (mem, alpha_sr_alias_set);
08202 FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
08203 }
08204
08205 if (frame_size || eh_ofs)
08206 {
08207 sp_adj1 = stack_pointer_rtx;
08208
08209 if (eh_ofs)
08210 {
08211 sp_adj1 = gen_rtx_REG (DImode, 23);
08212 emit_move_insn (sp_adj1,
08213 gen_rtx_PLUS (Pmode, stack_pointer_rtx, eh_ofs));
08214 }
08215
08216
08217
08218
08219 if (frame_size < 32768
08220 && ! (TARGET_ABI_UNICOSMK && current_function_calls_alloca))
08221 sp_adj2 = GEN_INT (frame_size);
08222 else if (TARGET_ABI_UNICOSMK)
08223 {
08224 sp_adj1 = gen_rtx_REG (DImode, 23);
08225 FRP (emit_move_insn (sp_adj1, hard_frame_pointer_rtx));
08226 sp_adj2 = const0_rtx;
08227 }
08228 else if (frame_size < 0x40007fffL)
08229 {
08230 int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
08231
08232 sp_adj2 = plus_constant (sp_adj1, frame_size - low);
08233 if (sa_reg_exp && rtx_equal_p (sa_reg_exp, sp_adj2))
08234 sp_adj1 = sa_reg;
08235 else
08236 {
08237 sp_adj1 = gen_rtx_REG (DImode, 23);
08238 FRP (emit_move_insn (sp_adj1, sp_adj2));
08239 }
08240 sp_adj2 = GEN_INT (low);
08241 }
08242 else
08243 {
08244 rtx tmp = gen_rtx_REG (DImode, 23);
08245 FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size,
08246 3, false));
08247 if (!sp_adj2)
08248 {
08249
08250
08251 FRP (sp_adj2 = alpha_emit_set_long_const (tmp, frame_size,
08252 -(frame_size < 0)));
08253 gcc_assert (sp_adj2);
08254 }
08255 }
08256
08257
08258
08259
08260 if (TARGET_ABI_UNICOSMK)
08261 {
08262 emit_insn (gen_blockage ());
08263 mem = gen_rtx_MEM (DImode,
08264 plus_constant (hard_frame_pointer_rtx, -16));
08265 set_mem_alias_set (mem, alpha_sr_alias_set);
08266 FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
08267 }
08268 else if (fp_is_frame_pointer)
08269 {
08270 emit_insn (gen_blockage ());
08271 mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, fp_offset));
08272 set_mem_alias_set (mem, alpha_sr_alias_set);
08273 FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
08274 }
08275 else if (TARGET_ABI_OPEN_VMS)
08276 {
08277 emit_insn (gen_blockage ());
08278 FRP (emit_move_insn (hard_frame_pointer_rtx,
08279 gen_rtx_REG (DImode, vms_save_fp_regno)));
08280 }
08281
08282
08283 emit_insn (gen_blockage ());
08284 if (sp_adj2 == const0_rtx)
08285 FRP (emit_move_insn (stack_pointer_rtx, sp_adj1));
08286 else
08287 FRP (emit_move_insn (stack_pointer_rtx,
08288 gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
08289 }
08290 else
08291 {
08292 if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_REGISTER)
08293 {
08294 emit_insn (gen_blockage ());
08295 FRP (emit_move_insn (hard_frame_pointer_rtx,
08296 gen_rtx_REG (DImode, vms_save_fp_regno)));
08297 }
08298 else if (TARGET_ABI_UNICOSMK && alpha_procedure_type != PT_STACK)
08299 {
08300
08301
08302
08303 emit_insn (gen_blockage ());
08304 FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
08305 hard_frame_pointer_rtx, constm1_rtx)));
08306 }
08307 }
08308 }
08309
08310
08311
08312 void
08313 alpha_end_function (FILE *file, const char *fnname, tree decl ATTRIBUTE_UNUSED)
08314 {
08315 #if TARGET_ABI_OPEN_VMS
08316 alpha_write_linkage (file, fnname, decl);
08317 #endif
08318
08319
08320 if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive)
08321 {
08322 fputs ("\t.end ", file);
08323 assemble_name (file, fnname);
08324 putc ('\n', file);
08325 }
08326 inside_function = FALSE;
08327
08328
08329 if (TARGET_ABI_UNICOSMK)
08330 {
08331 unicosmk_output_ssib (file, fnname);
08332 unicosmk_output_deferred_case_vectors (file);
08333 }
08334 }
08335
08336 #if TARGET_ABI_OSF
08337
08338
08339
08340
08341
08342
08343
08344
08345
08346 static void
08347 alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
08348 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
08349 tree function)
08350 {
08351 HOST_WIDE_INT hi, lo;
08352 rtx this, insn, funexp;
08353
08354 reset_block_changes ();
08355
08356
08357 emit_insn (gen_prologue_ldgp ());
08358 emit_note (NOTE_INSN_PROLOGUE_END);
08359
08360
08361
08362 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
08363 this = gen_rtx_REG (Pmode, 17);
08364 else
08365 this = gen_rtx_REG (Pmode, 16);
08366
08367
08368
08369 lo = ((delta & 0xffff) ^ 0x8000) - 0x8000;
08370 hi = (((delta - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
08371 if (hi + lo == delta)
08372 {
08373 if (hi)
08374 emit_insn (gen_adddi3 (this, this, GEN_INT (hi)));
08375 if (lo)
08376 emit_insn (gen_adddi3 (this, this, GEN_INT (lo)));
08377 }
08378 else
08379 {
08380 rtx tmp = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 0),
08381 delta, -(delta < 0));
08382 emit_insn (gen_adddi3 (this, this, tmp));
08383 }
08384
08385
08386 if (vcall_offset)
08387 {
08388 rtx tmp, tmp2;
08389
08390 tmp = gen_rtx_REG (Pmode, 0);
08391 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
08392
08393 lo = ((vcall_offset & 0xffff) ^ 0x8000) - 0x8000;
08394 hi = (((vcall_offset - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
08395 if (hi + lo == vcall_offset)
08396 {
08397 if (hi)
08398 emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (hi)));
08399 }
08400 else
08401 {
08402 tmp2 = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 1),
08403 vcall_offset, -(vcall_offset < 0));
08404 emit_insn (gen_adddi3 (tmp, tmp, tmp2));
08405 lo = 0;
08406 }
08407 if (lo)
08408 tmp2 = gen_rtx_PLUS (Pmode, tmp, GEN_INT (lo));
08409 else
08410 tmp2 = tmp;
08411 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp2));
08412
08413 emit_insn (gen_adddi3 (this, this, tmp));
08414 }
08415
08416
08417 if (! TREE_USED (function))
08418 {
08419 assemble_external (function);
08420 TREE_USED (function) = 1;
08421 }
08422 funexp = XEXP (DECL_RTL (function), 0);
08423 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
08424 insn = emit_call_insn (gen_sibcall (funexp, const0_rtx));
08425 SIBLING_CALL_P (insn) = 1;
08426
08427
08428
08429
08430
08431 insn = get_insns ();
08432 insn_locators_initialize ();
08433 shorten_branches (insn);
08434 final_start_function (insn, file, 1);
08435 final (insn, file, 1);
08436 final_end_function ();
08437 }
08438 #endif
08439
08440
08441
08442 #include "gstab.h"
08443
08444
08445
08446
08447 int sdb_label_count = 0;
08448
08449
08450
08451 static const char *current_function_file = "";
08452
08453
08454
08455 long alpha_arg_offset;
08456 long alpha_auto_offset;
08457
08458
08459
08460 void
08461 alpha_output_filename (FILE *stream, const char *name)
08462 {
08463 static int first_time = TRUE;
08464
08465 if (first_time)
08466 {
08467 first_time = FALSE;
08468 ++num_source_filenames;
08469 current_function_file = name;
08470 fprintf (stream, "\t.file\t%d ", num_source_filenames);
08471 output_quoted_string (stream, name);
08472 fprintf (stream, "\n");
08473 if (!TARGET_GAS && write_symbols == DBX_DEBUG)
08474 fprintf (stream, "\t#@stabs\n");
08475 }
08476
08477 else if (write_symbols == DBX_DEBUG)
08478
08479 return;
08480
08481 else if (name != current_function_file
08482 && strcmp (name, current_function_file) != 0)
08483 {
08484 if (inside_function && ! TARGET_GAS)
08485 fprintf (stream, "\t#.file\t%d ", num_source_filenames);
08486 else
08487 {
08488 ++num_source_filenames;
08489 current_function_file = name;
08490 fprintf (stream, "\t.file\t%d ", num_source_filenames);
08491 }
08492
08493 output_quoted_string (stream, name);
08494 fprintf (stream, "\n");
08495 }
08496 }
08497
08498
08499
08500 struct shadow_summary
08501 {
08502 struct {
08503 unsigned int i : 31;
08504 unsigned int fp : 31;
08505 unsigned int mem : 1;
08506 } used, defd;
08507 };
08508
08509
08510
08511
08512
08513 static void
08514 summarize_insn (rtx x, struct shadow_summary *sum, int set)
08515 {
08516 const char *format_ptr;
08517 int i, j;
08518
08519 if (x == 0)
08520 return;
08521
08522 switch (GET_CODE (x))
08523 {
08524
08525
08526 case SET:
08527 summarize_insn (SET_SRC (x), sum, 0);
08528 summarize_insn (SET_DEST (x), sum, 1);
08529 break;
08530
08531 case CLOBBER:
08532 summarize_insn (XEXP (x, 0), sum, 1);
08533 break;
08534
08535 case USE:
08536 summarize_insn (XEXP (x, 0), sum, 0);
08537 break;
08538
08539 case ASM_OPERANDS:
08540 for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
08541 summarize_insn (ASM_OPERANDS_INPUT (x, i), sum, 0);
08542 break;
08543
08544 case PARALLEL:
08545 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
08546 summarize_insn (XVECEXP (x, 0, i), sum, 0);
08547 break;
08548
08549 case SUBREG:
08550 summarize_insn (SUBREG_REG (x), sum, 0);
08551 break;
08552
08553 case REG:
08554 {
08555 int regno = REGNO (x);
08556 unsigned long mask = ((unsigned long) 1) << (regno % 32);
08557
08558 if (regno == 31 || regno == 63)
08559 break;
08560
08561 if (set)
08562 {
08563 if (regno < 32)
08564 sum->defd.i |= mask;
08565 else
08566 sum->defd.fp |= mask;
08567 }
08568 else
08569 {
08570 if (regno < 32)
08571 sum->used.i |= mask;
08572 else
08573 sum->used.fp |= mask;
08574 }
08575 }
08576 break;
08577
08578 case MEM:
08579 if (set)
08580 sum->defd.mem = 1;
08581 else
08582 sum->used.mem = 1;
08583
08584
08585 summarize_insn (XEXP (x, 0), sum, 0);
08586 break;
08587
08588 case CONST_INT: case CONST_DOUBLE:
08589 case SYMBOL_REF: case LABEL_REF: case CONST:
08590 case SCRATCH: case ASM_INPUT:
08591 break;
08592
08593
08594 case COMPARE: case PLUS: case MINUS: case MULT: case DIV:
08595 case MOD: case UDIV: case UMOD: case AND: case IOR:
08596 case XOR: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT:
08597 case ROTATERT: case SMIN: case SMAX: case UMIN: case UMAX:
08598 case NE: case EQ: case GE: case GT: case LE:
08599 case LT: case GEU: case GTU: case LEU: case LTU:
08600 summarize_insn (XEXP (x, 0), sum, 0);
08601 summarize_insn (XEXP (x, 1), sum, 0);
08602 break;
08603
08604 case NEG: case NOT: case SIGN_EXTEND: case ZERO_EXTEND:
08605 case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT:
08606 case FIX: case UNSIGNED_FLOAT: case UNSIGNED_FIX: case ABS:
08607 case SQRT: case FFS:
08608 summarize_insn (XEXP (x, 0), sum, 0);
08609 break;
08610
08611 default:
08612 format_ptr = GET_RTX_FORMAT (GET_CODE (x));
08613 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
08614 switch (format_ptr[i])
08615 {
08616 case 'e':
08617 summarize_insn (XEXP (x, i), sum, 0);
08618 break;
08619
08620 case 'E':
08621 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
08622 summarize_insn (XVECEXP (x, i, j), sum, 0);
08623 break;
08624
08625 case 'i':
08626 break;
08627
08628 default:
08629 gcc_unreachable ();
08630 }
08631 }
08632 }
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642
08643
08644
08645
08646
08647
08648
08649
08650
08651
08652
08653
08654
08655
08656
08657
08658
08659
08660
08661
08662
08663
08664
08665
08666
08667 static void
08668 alpha_handle_trap_shadows (void)
08669 {
08670 struct shadow_summary shadow;
08671 int trap_pending, exception_nesting;
08672 rtx i, n;
08673
08674 trap_pending = 0;
08675 exception_nesting = 0;
08676 shadow.used.i = 0;
08677 shadow.used.fp = 0;
08678 shadow.used.mem = 0;
08679 shadow.defd = shadow.used;
08680
08681 for (i = get_insns (); i ; i = NEXT_INSN (i))
08682 {
08683 if (GET_CODE (i) == NOTE)
08684 {
08685 switch (NOTE_LINE_NUMBER (i))
08686 {
08687 case NOTE_INSN_EH_REGION_BEG:
08688 exception_nesting++;
08689 if (trap_pending)
08690 goto close_shadow;
08691 break;
08692
08693 case NOTE_INSN_EH_REGION_END:
08694 exception_nesting--;
08695 if (trap_pending)
08696 goto close_shadow;
08697 break;
08698
08699 case NOTE_INSN_EPILOGUE_BEG:
08700 if (trap_pending && alpha_tp >= ALPHA_TP_FUNC)
08701 goto close_shadow;
08702 break;
08703 }
08704 }
08705 else if (trap_pending)
08706 {
08707 if (alpha_tp == ALPHA_TP_FUNC)
08708 {
08709 if (GET_CODE (i) == JUMP_INSN
08710 && GET_CODE (PATTERN (i)) == RETURN)
08711 goto close_shadow;
08712 }
08713 else if (alpha_tp == ALPHA_TP_INSN)
08714 {
08715 if (optimize > 0)
08716 {
08717 struct shadow_summary sum;
08718
08719 sum.used.i = 0;
08720 sum.used.fp = 0;
08721 sum.used.mem = 0;
08722 sum.defd = sum.used;
08723
08724 switch (GET_CODE (i))
08725 {
08726 case INSN:
08727
08728 if (GET_CODE (PATTERN (i)) == USE
08729 || GET_CODE (PATTERN (i)) == CLOBBER)
08730 break;
08731
08732 summarize_insn (PATTERN (i), &sum, 0);
08733
08734 if ((sum.defd.i & shadow.defd.i)
08735 || (sum.defd.fp & shadow.defd.fp))
08736 {
08737
08738 goto close_shadow;
08739 }
08740
08741
08742 shadow.used.i |= sum.used.i;
08743 shadow.used.fp |= sum.used.fp;
08744 shadow.used.mem |= sum.used.mem;
08745 shadow.defd.i |= sum.defd.i;
08746 shadow.defd.fp |= sum.defd.fp;
08747 shadow.defd.mem |= sum.defd.mem;
08748
08749 if ((sum.defd.i & shadow.used.i)
08750 || (sum.defd.fp & shadow.used.fp)
08751 || (sum.defd.mem & shadow.used.mem))
08752 {
08753
08754 gcc_assert (get_attr_trap (i) != TRAP_YES
08755 || (!(sum.defd.i & sum.used.i)
08756 && !(sum.defd.fp & sum.used.fp)));
08757
08758 goto close_shadow;
08759 }
08760 break;
08761
08762 case JUMP_INSN:
08763 case CALL_INSN:
08764 case CODE_LABEL:
08765 goto close_shadow;
08766
08767 default:
08768 gcc_unreachable ();
08769 }
08770 }
08771 else
08772 {
08773 close_shadow:
08774 n = emit_insn_before (gen_trapb (), i);
08775 PUT_MODE (n, TImode);
08776 PUT_MODE (i, TImode);
08777 trap_pending = 0;
08778 shadow.used.i = 0;
08779 shadow.used.fp = 0;
08780 shadow.used.mem = 0;
08781 shadow.defd = shadow.used;
08782 }
08783 }
08784 }
08785
08786 if ((exception_nesting > 0 || alpha_tp >= ALPHA_TP_FUNC)
08787 && GET_CODE (i) == INSN
08788 && GET_CODE (PATTERN (i)) != USE
08789 && GET_CODE (PATTERN (i)) != CLOBBER
08790 && get_attr_trap (i) == TRAP_YES)
08791 {
08792 if (optimize && !trap_pending)
08793 summarize_insn (PATTERN (i), &shadow, 0);
08794 trap_pending = 1;
08795 }
08796 }
08797 }
08798
08799
08800
08801
08802
08803
08804
08805
08806
08807 enum alphaev4_pipe {
08808 EV4_STOP = 0,
08809 EV4_IB0 = 1,
08810 EV4_IB1 = 2,
08811 EV4_IBX = 4
08812 };
08813
08814 enum alphaev5_pipe {
08815 EV5_STOP = 0,
08816 EV5_NONE = 1,
08817 EV5_E01 = 2,
08818 EV5_E0 = 4,
08819 EV5_E1 = 8,
08820 EV5_FAM = 16,
08821 EV5_FA = 32,
08822 EV5_FM = 64
08823 };
08824
08825 static enum alphaev4_pipe
08826 alphaev4_insn_pipe (rtx insn)
08827 {
08828 if (recog_memoized (insn) < 0)
08829 return EV4_STOP;
08830 if (get_attr_length (insn) != 4)
08831 return EV4_STOP;
08832
08833 switch (get_attr_type (insn))
08834 {
08835 case TYPE_ILD:
08836 case TYPE_LDSYM:
08837 case TYPE_FLD:
08838 case TYPE_LD_L:
08839 return EV4_IBX;
08840
08841 case TYPE_IADD:
08842 case TYPE_ILOG:
08843 case TYPE_ICMOV:
08844 case TYPE_ICMP:
08845 case TYPE_FST:
08846 case TYPE_SHIFT:
08847 case TYPE_IMUL:
08848 case TYPE_FBR:
08849 case TYPE_MVI:
08850 return EV4_IB0;
08851
08852 case TYPE_IST:
08853 case TYPE_MISC:
08854 case TYPE_IBR:
08855 case TYPE_JSR:
08856 case TYPE_CALLPAL:
08857 case TYPE_FCPYS:
08858 case TYPE_FCMOV:
08859 case TYPE_FADD:
08860 case TYPE_FDIV:
08861 case TYPE_FMUL:
08862 case TYPE_ST_C:
08863 case TYPE_MB:
08864 case TYPE_FSQRT:
08865 case TYPE_FTOI:
08866 case TYPE_ITOF:
08867 return EV4_IB1;
08868
08869 default:
08870 gcc_unreachable ();
08871 }
08872 }
08873
08874 static enum alphaev5_pipe
08875 alphaev5_insn_pipe (rtx insn)
08876 {
08877 if (recog_memoized (insn) < 0)
08878 return EV5_STOP;
08879 if (get_attr_length (insn) != 4)
08880 return EV5_STOP;
08881
08882 switch (get_attr_type (insn))
08883 {
08884 case TYPE_ILD:
08885 case TYPE_FLD:
08886 case TYPE_LDSYM:
08887 case TYPE_IADD:
08888 case TYPE_ILOG:
08889 case TYPE_ICMOV:
08890 case TYPE_ICMP:
08891 return EV5_E01;
08892
08893 case TYPE_IST:
08894 case TYPE_FST:
08895 case TYPE_SHIFT:
08896 case TYPE_IMUL:
08897 case TYPE_MISC:
08898 case TYPE_MVI:
08899 case TYPE_LD_L:
08900 case TYPE_ST_C:
08901 case TYPE_MB:
08902 case TYPE_FTOI:
08903 case TYPE_ITOF:
08904 return EV5_E0;
08905
08906 case TYPE_IBR:
08907 case TYPE_JSR:
08908 case TYPE_CALLPAL:
08909 return EV5_E1;
08910
08911 case TYPE_FCPYS:
08912 return EV5_FAM;
08913
08914 case TYPE_FBR:
08915 case TYPE_FCMOV:
08916 case TYPE_FADD:
08917 case TYPE_FDIV:
08918 case TYPE_FSQRT:
08919 return EV5_FA;
08920
08921 case TYPE_FMUL:
08922 return EV5_FM;
08923
08924 default:
08925 gcc_unreachable ();
08926 }
08927 }
08928
08929
08930
08931
08932
08933
08934
08935 static rtx
08936 alphaev4_next_group (rtx insn, int *pin_use, int *plen)
08937 {
08938 int len, in_use;
08939
08940 len = in_use = 0;
08941
08942 if (! INSN_P (insn)
08943 || GET_CODE (PATTERN (insn)) == CLOBBER
08944 || GET_CODE (PATTERN (insn)) == USE)
08945 goto next_and_done;
08946
08947 while (1)
08948 {
08949 enum alphaev4_pipe pipe;
08950
08951 pipe = alphaev4_insn_pipe (insn);
08952 switch (pipe)
08953 {
08954 case EV4_STOP:
08955
08956 if (in_use)
08957 goto done;
08958
08959
08960
08961
08962 if (recog_memoized (insn) < 0)
08963 len = -1;
08964 else
08965 len = get_attr_length (insn);
08966 goto next_and_done;
08967
08968 case EV4_IBX:
08969 if (in_use & EV4_IB0)
08970 {
08971 if (in_use & EV4_IB1)
08972 goto done;
08973 in_use |= EV4_IB1;
08974 }
08975 else
08976 in_use |= EV4_IB0 | EV4_IBX;
08977 break;
08978
08979 case EV4_IB0:
08980 if (in_use & EV4_IB0)
08981 {
08982 if (!(in_use & EV4_IBX) || (in_use & EV4_IB1))
08983 goto done;
08984 in_use |= EV4_IB1;
08985 }
08986 in_use |= EV4_IB0;
08987 break;
08988
08989 case EV4_IB1:
08990 if (in_use & EV4_IB1)
08991 goto done;
08992 in_use |= EV4_IB1;
08993 break;
08994
08995 default:
08996 gcc_unreachable ();
08997 }
08998 len += 4;
08999
09000
09001 if (GET_CODE (insn) == JUMP_INSN)
09002 goto next_and_done;
09003
09004 next:
09005 insn = next_nonnote_insn (insn);
09006
09007 if (!insn || ! INSN_P (insn))
09008 goto done;
09009
09010
09011 if (GET_MODE (insn) == TImode)
09012 goto done;
09013
09014 if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
09015 goto next;
09016 }
09017
09018 next_and_done:
09019 insn = next_nonnote_insn (insn);
09020
09021 done:
09022 *plen = len;
09023 *pin_use = in_use;
09024 return insn;
09025 }
09026
09027
09028
09029
09030
09031
09032
09033 static rtx
09034 alphaev5_next_group (rtx insn, int *pin_use, int *plen)
09035 {
09036 int len, in_use;
09037
09038 len = in_use = 0;
09039
09040 if (! INSN_P (insn)
09041 || GET_CODE (PATTERN (insn)) == CLOBBER
09042 || GET_CODE (PATTERN (insn)) == USE)
09043 goto next_and_done;
09044
09045 while (1)
09046 {
09047 enum alphaev5_pipe pipe;
09048
09049 pipe = alphaev5_insn_pipe (insn);
09050 switch (pipe)
09051 {
09052 case EV5_STOP:
09053
09054 if (in_use)
09055 goto done;
09056
09057
09058
09059
09060 if (recog_memoized (insn) < 0)
09061 len = -1;
09062 else
09063 len = get_attr_length (insn);
09064 goto next_and_done;
09065
09066
09067
09068
09069
09070
09071 case EV5_E01:
09072 if (in_use & EV5_E0)
09073 {
09074 if (in_use & EV5_E1)
09075 goto done;
09076 in_use |= EV5_E1;
09077 }
09078 else
09079 in_use |= EV5_E0 | EV5_E01;
09080 break;
09081
09082 case EV5_E0:
09083 if (in_use & EV5_E0)
09084 {
09085 if (!(in_use & EV5_E01) || (in_use & EV5_E1))
09086 goto done;
09087 in_use |= EV5_E1;
09088 }
09089 in_use |= EV5_E0;
09090 break;
09091
09092 case EV5_E1:
09093 if (in_use & EV5_E1)
09094 goto done;
09095 in_use |= EV5_E1;
09096 break;
09097
09098 case EV5_FAM:
09099 if (in_use & EV5_FA)
09100 {
09101 if (in_use & EV5_FM)
09102 goto done;
09103 in_use |= EV5_FM;
09104 }
09105 else
09106 in_use |= EV5_FA | EV5_FAM;
09107 break;
09108
09109 case EV5_FA:
09110 if (in_use & EV5_FA)
09111 goto done;
09112 in_use |= EV5_FA;
09113 break;
09114
09115 case EV5_FM:
09116 if (in_use & EV5_FM)
09117 goto done;
09118 in_use |= EV5_FM;
09119 break;
09120
09121 case EV5_NONE:
09122 break;
09123
09124 default:
09125 gcc_unreachable ();
09126 }
09127 len += 4;
09128
09129
09130
09131
09132 if (GET_CODE (insn) == JUMP_INSN)
09133 goto next_and_done;
09134
09135 next:
09136 insn = next_nonnote_insn (insn);
09137
09138 if (!insn || ! INSN_P (insn))
09139 goto done;
09140
09141
09142 if (GET_MODE (insn) == TImode)
09143 goto done;
09144
09145 if (GET_CODE (insn) == CLOBBER || GET_CODE (insn) == USE)
09146 goto next;
09147 }
09148
09149 next_and_done:
09150 insn = next_nonnote_insn (insn);
09151
09152 done:
09153 *plen = len;
09154 *pin_use = in_use;
09155 return insn;
09156 }
09157
09158 static rtx
09159 alphaev4_next_nop (int *pin_use)
09160 {
09161 int in_use = *pin_use;
09162 rtx nop;
09163
09164 if (!(in_use & EV4_IB0))
09165 {
09166 in_use |= EV4_IB0;
09167 nop = gen_nop ();
09168 }
09169 else if ((in_use & (EV4_IBX|EV4_IB1)) == EV4_IBX)
09170 {
09171 in_use |= EV4_IB1;
09172 nop = gen_nop ();
09173 }
09174 else if (TARGET_FP && !(in_use & EV4_IB1))
09175 {
09176 in_use |= EV4_IB1;
09177 nop = gen_fnop ();
09178 }
09179 else
09180 nop = gen_unop ();
09181
09182 *pin_use = in_use;
09183 return nop;
09184 }
09185
09186 static rtx
09187 alphaev5_next_nop (int *pin_use)
09188 {
09189 int in_use = *pin_use;
09190 rtx nop;
09191
09192 if (!(in_use & EV5_E1))
09193 {
09194 in_use |= EV5_E1;
09195 nop = gen_nop ();
09196 }
09197 else if (TARGET_FP && !(in_use & EV5_FA))
09198 {
09199 in_use |= EV5_FA;
09200 nop = gen_fnop ();
09201 }
09202 else if (TARGET_FP && !(in_use & EV5_FM))
09203 {
09204 in_use |= EV5_FM;
09205 nop = gen_fnop ();
09206 }
09207 else
09208 nop = gen_unop ();
09209
09210 *pin_use = in_use;
09211 return nop;
09212 }
09213
09214
09215
09216 static void
09217 alpha_align_insns (unsigned int max_align,
09218 rtx (*next_group) (rtx, int *, int *),
09219 rtx (*next_nop) (int *))
09220 {
09221
09222 unsigned int align;
09223
09224 int ofs;
09225 int prev_in_use, in_use, len, ldgp;
09226 rtx i, next;
09227
09228
09229 shorten_branches (get_insns ());
09230
09231 if (align_functions < 4)
09232 align = 4;
09233 else if ((unsigned int) align_functions < max_align)
09234 align = align_functions;
09235 else
09236 align = max_align;
09237
09238 ofs = prev_in_use = 0;
09239 i = get_insns ();
09240 if (GET_CODE (i) == NOTE)
09241 i = next_nonnote_insn (i);
09242
09243 ldgp = alpha_function_needs_gp ? 8 : 0;
09244
09245 while (i)
09246 {
09247 next = (*next_group) (i, &in_use, &len);
09248
09249
09250 if (GET_CODE (i) == CODE_LABEL)
09251 {
09252 unsigned int new_align = 1 << label_to_alignment (i);
09253
09254 if (new_align >= align)
09255 {
09256 align = new_align < max_align ? new_align : max_align;
09257 ofs = 0;
09258 }
09259
09260 else if (ofs & (new_align-1))
09261 ofs = (ofs | (new_align-1)) + 1;
09262 gcc_assert (!len);
09263 }
09264
09265
09266 else if (in_use == 0)
09267 {
09268
09269
09270
09271 if (len < 0)
09272 {
09273 ofs = 0;
09274 align = 4;
09275 len = 0;
09276 }
09277 }
09278
09279
09280
09281 else if ((int) align < len)
09282 {
09283 unsigned int new_log_align = len > 8 ? 4 : 3;
09284 rtx prev, where;
09285
09286 where = prev = prev_nonnote_insn (i);
09287 if (!where || GET_CODE (where) != CODE_LABEL)
09288 where = i;
09289
09290
09291 if (! (TARGET_EXPLICIT_RELOCS
09292 && prev && GET_CODE (prev) == CALL_INSN))
09293 {
09294 emit_insn_before (gen_realign (GEN_INT (new_log_align)), where);
09295 align = 1 << new_log_align;
09296 ofs = 0;
09297 }
09298 }
09299
09300
09301 else if (ldgp > 0)
09302 ldgp -= len;
09303
09304
09305
09306
09307
09308
09309
09310 else if (ofs + len > (int) align)
09311 {
09312 int nop_count = (align - ofs) / 4;
09313 rtx where;
09314
09315
09316
09317 where = prev_nonnote_insn (i);
09318 if (where)
09319 {
09320 if (GET_CODE (where) == CODE_LABEL)
09321 {
09322 rtx where2 = prev_nonnote_insn (where);
09323 if (where2 && GET_CODE (where2) == JUMP_INSN)
09324 where = where2;
09325 }
09326 else if (GET_CODE (where) == INSN)
09327 where = i;
09328 }
09329 else
09330 where = i;
09331
09332 do
09333 emit_insn_before ((*next_nop)(&prev_in_use), where);
09334 while (--nop_count);
09335 ofs = 0;
09336 }
09337
09338 ofs = (ofs + len) & (align - 1);
09339 prev_in_use = in_use;
09340 i = next;
09341 }
09342 }
09343
09344
09345
09346 static void
09347 alpha_reorg (void)
09348 {
09349 if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
09350 alpha_handle_trap_shadows ();
09351
09352
09353
09354
09355 if (optimize && !optimize_size
09356 && alpha_tp != ALPHA_TP_INSN
09357 && flag_schedule_insns_after_reload)
09358 {
09359 if (alpha_tune == PROCESSOR_EV4)
09360 alpha_align_insns (8, alphaev4_next_group, alphaev4_next_nop);
09361 else if (alpha_tune == PROCESSOR_EV5)
09362 alpha_align_insns (16, alphaev5_next_group, alphaev5_next_nop);
09363 }
09364 }
09365
09366 #if !TARGET_ABI_UNICOSMK
09367
09368 #ifdef HAVE_STAMP_H
09369 #include <stamp.h>
09370 #endif
09371
09372 static void
09373 alpha_file_start (void)
09374 {
09375 #ifdef OBJECT_FORMAT_ELF
09376
09377
09378
09379 targetm.file_start_file_directive = (write_symbols == DBX_DEBUG);
09380 #endif
09381
09382 default_file_start ();
09383 #ifdef MS_STAMP
09384 fprintf (asm_out_file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);
09385 #endif
09386
09387 fputs ("\t.set noreorder\n", asm_out_file);
09388 fputs ("\t.set volatile\n", asm_out_file);
09389 if (!TARGET_ABI_OPEN_VMS)
09390 fputs ("\t.set noat\n", asm_out_file);
09391 if (TARGET_EXPLICIT_RELOCS)
09392 fputs ("\t.set nomacro\n", asm_out_file);
09393 if (TARGET_SUPPORT_ARCH | TARGET_BWX | TARGET_MAX | TARGET_FIX | TARGET_CIX)
09394 {
09395 const char *arch;
09396
09397 if (alpha_cpu == PROCESSOR_EV6 || TARGET_FIX || TARGET_CIX)
09398 arch = "ev6";
09399 else if (TARGET_MAX)
09400 arch = "pca56";
09401 else if (TARGET_BWX)
09402 arch = "ev56";
09403 else if (alpha_cpu == PROCESSOR_EV5)
09404 arch = "ev5";
09405 else
09406 arch = "ev4";
09407
09408 fprintf (asm_out_file, "\t.arch %s\n", arch);
09409 }
09410 }
09411 #endif
09412
09413 #ifdef OBJECT_FORMAT_ELF
09414
09415
09416
09417 static int
09418 alpha_elf_reloc_rw_mask (void)
09419 {
09420 return flag_pic ? 3 : 2;
09421 }
09422
09423
09424
09425
09426 static section *
09427 alpha_elf_select_rtx_section (enum machine_mode mode, rtx x,
09428 unsigned HOST_WIDE_INT align)
09429 {
09430 if (TARGET_SMALL_DATA && GET_MODE_SIZE (mode) <= g_switch_value)
09431
09432 return sdata_section;
09433 else
09434 return default_elf_select_rtx_section (mode, x, align);
09435 }
09436
09437 static unsigned int
09438 alpha_elf_section_type_flags (tree decl, const char *name, int reloc)
09439 {
09440 unsigned int flags = 0;
09441
09442 if (strcmp (name, ".sdata") == 0
09443 || strncmp (name, ".sdata.", 7) == 0
09444 || strncmp (name, ".gnu.linkonce.s.", 16) == 0
09445 || strcmp (name, ".sbss") == 0
09446 || strncmp (name, ".sbss.", 6) == 0
09447 || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
09448 flags = SECTION_SMALL;
09449
09450 flags |= default_section_type_flags (decl, name, reloc);
09451 return flags;
09452 }
09453 #endif
09454
09455
09456
09457
09458 enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
09459 enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR};
09460
09461 struct alpha_links GTY(())
09462 {
09463 int num;
09464 rtx linkage;
09465 enum links_kind lkind;
09466 enum reloc_kind rkind;
09467 };
09468
09469 struct alpha_funcs GTY(())
09470 {
09471 int num;
09472 splay_tree GTY ((param1_is (char *), param2_is (struct alpha_links *)))
09473 links;
09474 };
09475
09476 static GTY ((param1_is (char *), param2_is (struct alpha_links *)))
09477 splay_tree alpha_links_tree;
09478 static GTY ((param1_is (tree), param2_is (struct alpha_funcs *)))
09479 splay_tree alpha_funcs_tree;
09480
09481 static GTY(()) int alpha_funcs_num;
09482
09483 #if TARGET_ABI_OPEN_VMS
09484
09485
09486
09487 enum avms_arg_type
09488 alpha_arg_type (enum machine_mode mode)
09489 {
09490 switch (mode)
09491 {
09492 case SFmode:
09493 return TARGET_FLOAT_VAX ? FF : FS;
09494 case DFmode:
09495 return TARGET_FLOAT_VAX ? FD : FT;
09496 default:
09497 return I64;
09498 }
09499 }
09500
09501
09502
09503
09504 rtx
09505 alpha_arg_info_reg_val (CUMULATIVE_ARGS cum)
09506 {
09507 unsigned HOST_WIDE_INT regval = cum.num_args;
09508 int i;
09509
09510 for (i = 0; i < 6; i++)
09511 regval |= ((int) cum.atypes[i]) << (i * 3 + 8);
09512
09513 return GEN_INT (regval);
09514 }
09515
09516
09517
09518
09519
09520
09521
09522 rtx
09523 alpha_need_linkage (const char *name, int is_local)
09524 {
09525 splay_tree_node node;
09526 struct alpha_links *al;
09527
09528 if (name[0] == '*')
09529 name++;
09530
09531 if (is_local)
09532 {
09533 struct alpha_funcs *cfaf;
09534
09535 if (!alpha_funcs_tree)
09536 alpha_funcs_tree = splay_tree_new_ggc ((splay_tree_compare_fn)
09537 splay_tree_compare_pointers);
09538
09539 cfaf = (struct alpha_funcs *) ggc_alloc (sizeof (struct alpha_funcs));
09540
09541 cfaf->links = 0;
09542 cfaf->num = ++alpha_funcs_num;
09543
09544 splay_tree_insert (alpha_funcs_tree,
09545 (splay_tree_key) current_function_decl,
09546 (splay_tree_value) cfaf);
09547 }
09548
09549 if (alpha_links_tree)
09550 {
09551
09552
09553 node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
09554 if (node)
09555 {
09556 al = (struct alpha_links *) node->value;
09557 if (is_local)
09558 {
09559
09560 if (al->lkind == KIND_EXTERN)
09561 al->lkind = KIND_LOCAL;
09562 }
09563 else
09564 {
09565
09566 if (al->lkind == KIND_UNUSED)
09567 al->lkind = KIND_LOCAL;
09568 }
09569 return al->linkage;
09570 }
09571 }
09572 else
09573 alpha_links_tree = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
09574
09575 al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
09576 name = ggc_strdup (name);
09577
09578
09579 al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN);
09580
09581
09582 get_identifier (name);
09583
09584
09585 {
09586 size_t name_len = strlen (name);
09587 char *linksym = alloca (name_len + 6);
09588 linksym[0] = '$';
09589 memcpy (linksym + 1, name, name_len);
09590 memcpy (linksym + 1 + name_len, "..lk", 5);
09591 al->linkage = gen_rtx_SYMBOL_REF (Pmode,
09592 ggc_alloc_string (linksym, name_len + 5));
09593 }
09594
09595 splay_tree_insert (alpha_links_tree, (splay_tree_key) name,
09596 (splay_tree_value) al);
09597
09598 return al->linkage;
09599 }
09600
09601 rtx
09602 alpha_use_linkage (rtx linkage, tree cfundecl, int lflag, int rflag)
09603 {
09604 splay_tree_node cfunnode;
09605 struct alpha_funcs *cfaf;
09606 struct alpha_links *al;
09607 const char *name = XSTR (linkage, 0);
09608
09609 cfaf = (struct alpha_funcs *) 0;
09610 al = (struct alpha_links *) 0;
09611
09612 cfunnode = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) cfundecl);
09613 cfaf = (struct alpha_funcs *) cfunnode->value;
09614
09615 if (cfaf->links)
09616 {
09617 splay_tree_node lnode;
09618
09619
09620
09621 lnode = splay_tree_lookup (cfaf->links, (splay_tree_key) name);
09622 if (lnode)
09623 al = (struct alpha_links *) lnode->value;
09624 }
09625 else
09626 cfaf->links = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp);
09627
09628 if (!al)
09629 {
09630 size_t name_len;
09631 size_t buflen;
09632 char buf [512];
09633 char *linksym;
09634 splay_tree_node node = 0;
09635 struct alpha_links *anl;
09636
09637 if (name[0] == '*')
09638 name++;
09639
09640 name_len = strlen (name);
09641
09642 al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links));
09643 al->num = cfaf->num;
09644
09645 node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
09646 if (node)
09647 {
09648 anl = (struct alpha_links *) node->value;
09649 al->lkind = anl->lkind;
09650 }
09651
09652 sprintf (buf, "$%d..%s..lk", cfaf->num, name);
09653 buflen = strlen (buf);
09654 linksym = alloca (buflen + 1);
09655 memcpy (linksym, buf, buflen + 1);
09656
09657 al->linkage = gen_rtx_SYMBOL_REF
09658 (Pmode, ggc_alloc_string (linksym, buflen + 1));
09659
09660 splay_tree_insert (cfaf->links, (splay_tree_key) name,
09661 (splay_tree_value) al);
09662 }
09663
09664 if (rflag)
09665 al->rkind = KIND_CODEADDR;
09666 else
09667 al->rkind = KIND_LINKAGE;
09668
09669 if (lflag)
09670 return gen_rtx_MEM (Pmode, plus_constant (al->linkage, 8));
09671 else
09672 return al->linkage;
09673 }
09674
09675 static int
09676 alpha_write_one_linkage (splay_tree_node node, void *data)
09677 {
09678 const char *const name = (const char *) node->key;
09679 struct alpha_links *link = (struct alpha_links *) node->value;
09680 FILE *stream = (FILE *) data;
09681
09682 fprintf (stream, "$%d..%s..lk:\n", link->num, name);
09683 if (link->rkind == KIND_CODEADDR)
09684 {
09685 if (link->lkind == KIND_LOCAL)
09686 {
09687
09688 fprintf (stream, "\t.quad %s..en\n", name);
09689 }
09690 else
09691 {
09692
09693 fprintf (stream, "\t.code_address %s\n", name);
09694 }
09695 }
09696 else
09697 {
09698 if (link->lkind == KIND_LOCAL)
09699 {
09700
09701 fprintf (stream, "\t.quad %s..en\n", name);
09702 fprintf (stream, "\t.quad %s\n", name);
09703 }
09704 else
09705 {
09706
09707 fprintf (stream, "\t.linkage %s\n", name);
09708 }
09709 }
09710
09711 return 0;
09712 }
09713
09714 static void
09715 alpha_write_linkage (FILE *stream, const char *funname, tree fundecl)
09716 {
09717 splay_tree_node node;
09718 struct alpha_funcs *func;
09719
09720 fprintf (stream, "\t.link\n");
09721 fprintf (stream, "\t.align 3\n");
09722 in_section = NULL;
09723
09724 node = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) fundecl);
09725 func = (struct alpha_funcs *) node->value;
09726
09727 fputs ("\t.name ", stream);
09728 assemble_name (stream, funname);
09729 fputs ("..na\n", stream);
09730 ASM_OUTPUT_LABEL (stream, funname);
09731 fprintf (stream, "\t.pdesc ");
09732 assemble_name (stream, funname);
09733 fprintf (stream, "..en,%s\n",
09734 alpha_procedure_type == PT_STACK ? "stack"
09735 : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
09736
09737 if (func->links)
09738 {
09739 splay_tree_foreach (func->links, alpha_write_one_linkage, stream);
09740
09741 }
09742 }
09743
09744
09745
09746
09747 #define SECTION_VMS_OVERLAY SECTION_FORGET
09748 #define SECTION_VMS_GLOBAL SECTION_MACH_DEP
09749 #define SECTION_VMS_INITIALIZE (SECTION_VMS_GLOBAL << 1)
09750
09751 static unsigned int
09752 vms_section_type_flags (tree decl, const char *name, int reloc)
09753 {
09754 unsigned int flags = default_section_type_flags (decl, name, reloc);
09755
09756 if (decl && DECL_ATTRIBUTES (decl)
09757 && lookup_attribute ("overlaid", DECL_ATTRIBUTES (decl)))
09758 flags |= SECTION_VMS_OVERLAY;
09759 if (decl && DECL_ATTRIBUTES (decl)
09760 && lookup_attribute ("global", DECL_ATTRIBUTES (decl)))
09761 flags |= SECTION_VMS_GLOBAL;
09762 if (decl && DECL_ATTRIBUTES (decl)
09763 && lookup_attribute ("initialize", DECL_ATTRIBUTES (decl)))
09764 flags |= SECTION_VMS_INITIALIZE;
09765
09766 return flags;
09767 }
09768
09769
09770
09771
09772
09773 static void
09774 vms_asm_named_section (const char *name, unsigned int flags,
09775 tree decl ATTRIBUTE_UNUSED)
09776 {
09777 fputc ('\n', asm_out_file);
09778 fprintf (asm_out_file, ".section\t%s", name);
09779
09780 if (flags & SECTION_VMS_OVERLAY)
09781 fprintf (asm_out_file, ",OVR");
09782 if (flags & SECTION_VMS_GLOBAL)
09783 fprintf (asm_out_file, ",GBL");
09784 if (flags & SECTION_VMS_INITIALIZE)
09785 fprintf (asm_out_file, ",NOMOD");
09786 if (flags & SECTION_DEBUG)
09787 fprintf (asm_out_file, ",NOWRT");
09788
09789 fputc ('\n', asm_out_file);
09790 }
09791
09792
09793
09794
09795
09796
09797
09798
09799
09800 static void
09801 vms_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
09802 {
09803 switch_to_section (ctors_section);
09804 assemble_align (BITS_PER_WORD);
09805 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
09806 }
09807
09808 static void
09809 vms_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
09810 {
09811 switch_to_section (dtors_section);
09812 assemble_align (BITS_PER_WORD);
09813 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
09814 }
09815 #else
09816
09817 rtx
09818 alpha_need_linkage (const char *name ATTRIBUTE_UNUSED,
09819 int is_local ATTRIBUTE_UNUSED)
09820 {
09821 return NULL_RTX;
09822 }
09823
09824 rtx
09825 alpha_use_linkage (rtx linkage ATTRIBUTE_UNUSED,
09826 tree cfundecl ATTRIBUTE_UNUSED,
09827 int lflag ATTRIBUTE_UNUSED,
09828 int rflag ATTRIBUTE_UNUSED)
09829 {
09830 return NULL_RTX;
09831 }
09832
09833 #endif
09834
09835 #if TARGET_ABI_UNICOSMK
09836
09837
09838
09839
09840
09841 static bool
09842 unicosmk_must_pass_in_stack (enum machine_mode mode, tree type)
09843 {
09844 if (type == NULL)
09845 return false;
09846
09847 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
09848 return true;
09849 if (TREE_ADDRESSABLE (type))
09850 return true;
09851
09852 return ALPHA_ARG_SIZE (mode, type, 0) > 2;
09853 }
09854
09855
09856
09857
09858 int
09859 unicosmk_initial_elimination_offset (int from, int to)
09860 {
09861 int fixed_size;
09862
09863 fixed_size = alpha_sa_size();
09864 if (fixed_size != 0)
09865 fixed_size += 48;
09866
09867 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
09868 return -fixed_size;
09869 else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
09870 return 0;
09871 else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
09872 return (ALPHA_ROUND (current_function_outgoing_args_size)
09873 + ALPHA_ROUND (get_frame_size()));
09874 else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
09875 return (ALPHA_ROUND (fixed_size)
09876 + ALPHA_ROUND (get_frame_size()
09877 + current_function_outgoing_args_size));
09878 else
09879 gcc_unreachable ();
09880 }
09881
09882
09883
09884
09885
09886 static void
09887 unicosmk_output_module_name (FILE *file)
09888 {
09889 const char *name = lbasename (main_input_filename);
09890 unsigned len = strlen (name);
09891 char *clean_name = alloca (len + 2);
09892 char *ptr = clean_name;
09893
09894
09895
09896
09897 if (!ISALPHA (*name))
09898 *ptr++ = '$';
09899 memcpy (ptr, name, len + 1);
09900 clean_symbol_name (clean_name);
09901 fputs (clean_name, file);
09902 }
09903
09904
09905
09906 void
09907 unicosmk_output_common (FILE *file, const char *name, int size, int align)
09908 {
09909 tree name_tree;
09910 printf ("T3E__: common %s\n", name);
09911
09912 in_section = NULL;
09913 fputs("\t.endp\n\n\t.psect ", file);
09914 assemble_name(file, name);
09915 fprintf(file, ",%d,common\n", floor_log2 (align / BITS_PER_UNIT));
09916 fprintf(file, "\t.byte\t0:%d\n", size);
09917
09918
09919 name_tree = get_identifier (name);
09920 TREE_ASM_WRITTEN (name_tree) = 1;
09921 }
09922
09923 #define SECTION_PUBLIC SECTION_MACH_DEP
09924 #define SECTION_MAIN (SECTION_PUBLIC << 1)
09925 static int current_section_align;
09926
09927
09928
09929 static void
09930 unicosmk_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
09931 {
09932 static int count = 0;
09933 fprintf (asm_out_file, "\t.endp\n\n\t.psect\tgcc@text___%d,code\n", count++);
09934 }
09935
09936
09937
09938 static void
09939 unicosmk_output_data_section_asm_op (const void *data ATTRIBUTE_UNUSED)
09940 {
09941 static int count = 1;
09942 fprintf (asm_out_file, "\t.endp\n\n\t.psect\tgcc@data___%d,data\n", count++);
09943 }
09944
09945
09946
09947
09948
09949
09950
09951
09952 static void
09953 unicosmk_init_sections (void)
09954 {
09955 text_section = get_unnamed_section (SECTION_CODE,
09956 unicosmk_output_text_section_asm_op,
09957 NULL);
09958 data_section = get_unnamed_section (SECTION_WRITE,
09959 unicosmk_output_data_section_asm_op,
09960 NULL);
09961 readonly_data_section = data_section;
09962 }
09963
09964 static unsigned int
09965 unicosmk_section_type_flags (tree decl, const char *name,
09966 int reloc ATTRIBUTE_UNUSED)
09967 {
09968 unsigned int flags = default_section_type_flags (decl, name, reloc);
09969
09970 if (!decl)
09971 return flags;
09972
09973 if (TREE_CODE (decl) == FUNCTION_DECL)
09974 {
09975 current_section_align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
09976 if (align_functions_log > current_section_align)
09977 current_section_align = align_functions_log;
09978
09979 if (! strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), "main"))
09980 flags |= SECTION_MAIN;
09981 }
09982 else
09983 current_section_align = floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT);
09984
09985 if (TREE_PUBLIC (decl))
09986 flags |= SECTION_PUBLIC;
09987
09988 return flags;
09989 }
09990
09991
09992
09993
09994 static void
09995 unicosmk_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
09996 {
09997 const char *name;
09998 int len;
09999
10000 gcc_assert (decl);
10001
10002 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
10003 name = default_strip_name_encoding (name);
10004 len = strlen (name);
10005
10006 if (TREE_CODE (decl) == FUNCTION_DECL)
10007 {
10008 char *string;
10009
10010
10011
10012
10013
10014 string = alloca (len + 6);
10015 sprintf (string, "code@%s", name);
10016 DECL_SECTION_NAME (decl) = build_string (len + 5, string);
10017 }
10018 else if (TREE_PUBLIC (decl))
10019 DECL_SECTION_NAME (decl) = build_string (len, name);
10020 else
10021 {
10022 char *string;
10023
10024 string = alloca (len + 6);
10025 sprintf (string, "data@%s", name);
10026 DECL_SECTION_NAME (decl) = build_string (len + 5, string);
10027 }
10028 }
10029
10030
10031
10032
10033
10034 static void
10035 unicosmk_asm_named_section (const char *name, unsigned int flags,
10036 tree decl ATTRIBUTE_UNUSED)
10037 {
10038 const char *kind;
10039
10040
10041
10042 fputs ("\t.endp\n\n", asm_out_file);
10043
10044
10045
10046 if (flags & SECTION_MAIN)
10047 fputs ("\t.start\tmain\n", asm_out_file);
10048
10049 if (flags & SECTION_CODE)
10050 kind = "code";
10051 else if (flags & SECTION_PUBLIC)
10052 kind = "common";
10053 else
10054 kind = "data";
10055
10056 if (current_section_align != 0)
10057 fprintf (asm_out_file, "\t.psect\t%s,%d,%s\n", name,
10058 current_section_align, kind);
10059 else
10060 fprintf (asm_out_file, "\t.psect\t%s,%s\n", name, kind);
10061 }
10062
10063 static void
10064 unicosmk_insert_attributes (tree decl, tree *attr_ptr ATTRIBUTE_UNUSED)
10065 {
10066 if (DECL_P (decl)
10067 && (TREE_PUBLIC (decl) || TREE_CODE (decl) == FUNCTION_DECL))
10068 unicosmk_unique_section (decl, 0);
10069 }
10070
10071
10072
10073
10074 void
10075 unicosmk_output_align (FILE *file, int align)
10076 {
10077 if (inside_function)
10078 fprintf (file, "\tgcc@code@align\t%d\n", align);
10079 else
10080 fprintf (file, "\t.align\t%d\n", align);
10081 }
10082
10083
10084
10085
10086
10087 void
10088 unicosmk_defer_case_vector (rtx lab, rtx vec)
10089 {
10090 struct machine_function *machine = cfun->machine;
10091
10092 vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
10093 machine->addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec,
10094 machine->addr_list);
10095 }
10096
10097
10098
10099 static void
10100 unicosmk_output_addr_vec (FILE *file, rtx vec)
10101 {
10102 rtx lab = XEXP (vec, 0);
10103 rtx body = XEXP (vec, 1);
10104 int vlen = XVECLEN (body, 0);
10105 int idx;
10106
10107 (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (lab));
10108
10109 for (idx = 0; idx < vlen; idx++)
10110 {
10111 ASM_OUTPUT_ADDR_VEC_ELT
10112 (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
10113 }
10114 }
10115
10116
10117
10118 static void
10119 unicosmk_output_deferred_case_vectors (FILE *file)
10120 {
10121 struct machine_function *machine = cfun->machine;
10122 rtx t;
10123
10124 if (machine->addr_list == NULL_RTX)
10125 return;
10126
10127 switch_to_section (data_section);
10128 for (t = machine->addr_list; t; t = XEXP (t, 1))
10129 unicosmk_output_addr_vec (file, XEXP (t, 0));
10130 }
10131
10132
10133
10134 #define SSIB_PREFIX "__SSIB_"
10135 #define SSIB_PREFIX_LEN 7
10136
10137 static const char *
10138 unicosmk_ssib_name (void)
10139 {
10140
10141
10142
10143 static char name[256];
10144
10145 rtx x;
10146 const char *fnname;
10147 int len;
10148
10149 x = DECL_RTL (cfun->decl);
10150 gcc_assert (GET_CODE (x) == MEM);
10151 x = XEXP (x, 0);
10152 gcc_assert (GET_CODE (x) == SYMBOL_REF);
10153 fnname = XSTR (x, 0);
10154
10155 len = strlen (fnname);
10156 if (len + SSIB_PREFIX_LEN > 255)
10157 len = 255 - SSIB_PREFIX_LEN;
10158
10159 strcpy (name, SSIB_PREFIX);
10160 strncpy (name + SSIB_PREFIX_LEN, fnname, len);
10161 name[len + SSIB_PREFIX_LEN] = 0;
10162
10163 return name;
10164 }
10165
10166
10167
10168
10169
10170 static void
10171 unicosmk_gen_dsib (unsigned long *imaskP)
10172 {
10173 if (alpha_procedure_type == PT_STACK)
10174 {
10175 const char *ssib_name;
10176 rtx mem;
10177
10178
10179
10180 FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
10181 GEN_INT (-64))));
10182 emit_insn (gen_blockage ());
10183
10184
10185
10186 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 56));
10187 set_mem_alias_set (mem, alpha_sr_alias_set);
10188 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
10189 (*imaskP) &= ~(1UL << REG_RA);
10190
10191
10192
10193 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 48));
10194 set_mem_alias_set (mem, alpha_sr_alias_set);
10195 FRP (emit_move_insn (mem, hard_frame_pointer_rtx));
10196 (*imaskP) &= ~(1UL << HARD_FRAME_POINTER_REGNUM);
10197
10198 emit_insn (gen_blockage ());
10199
10200
10201
10202 ssib_name = ggc_strdup (unicosmk_ssib_name ());
10203 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 32));
10204 set_mem_alias_set (mem, alpha_sr_alias_set);
10205
10206 FRP (emit_move_insn (gen_rtx_REG (DImode, 5),
10207 gen_rtx_SYMBOL_REF (Pmode, ssib_name)));
10208 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, 5)));
10209
10210
10211
10212 mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 24));
10213 set_mem_alias_set (mem, alpha_sr_alias_set);
10214 FRP (emit_move_insn (mem, gen_rtx_REG (DImode, 25)));
10215
10216 emit_insn (gen_blockage ());
10217
10218
10219
10220 FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
10221 stack_pointer_rtx, GEN_INT (64))));
10222
10223 }
10224 else
10225 {
10226
10227
10228
10229 FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
10230 hard_frame_pointer_rtx, const1_rtx)));
10231 }
10232 }
10233
10234
10235
10236
10237 static void
10238 unicosmk_output_ssib (FILE *file, const char *fnname)
10239 {
10240 int len;
10241 int i;
10242 rtx x;
10243 rtx ciw;
10244 struct machine_function *machine = cfun->machine;
10245
10246 in_section = NULL;
10247 fprintf (file, "\t.endp\n\n\t.psect\t%s%s,data\n", user_label_prefix,
10248 unicosmk_ssib_name ());
10249
10250
10251
10252 len = strlen (fnname);
10253 fprintf (file, "\t.quad\t^X20008%2.2X28\n", len);
10254
10255
10256
10257
10258 fputs ("\t.quad\t0\n", file);
10259
10260
10261
10262 fputs ("\t.quad\t", file);
10263 assemble_name (file, fnname);
10264 putc ('\n', file);
10265
10266 fputs ("\t.quad\t0\n", file);
10267 fputs ("\t.quad\t0\n", file);
10268
10269
10270
10271
10272
10273 for( i = 0; i < len; i++ )
10274 fprintf (file, "\t.byte\t%d\n", (int)(fnname[i]));
10275 if( (len % 8) == 0 )
10276 fputs ("\t.quad\t0\n", file);
10277 else
10278 fprintf (file, "\t.bits\t%d : 0\n", (8 - (len % 8))*8);
10279
10280
10281
10282 for (x = machine->first_ciw; x; x = XEXP (x, 1))
10283 {
10284 ciw = XEXP (x, 0);
10285 #if HOST_BITS_PER_WIDE_INT == 32
10286 fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_DOUBLE_HEX "\n",
10287 CONST_DOUBLE_HIGH (ciw), CONST_DOUBLE_LOW (ciw));
10288 #else
10289 fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n", INTVAL (ciw));
10290 #endif
10291 }
10292 }
10293
10294
10295
10296
10297
10298
10299 rtx
10300 unicosmk_add_call_info_word (rtx x)
10301 {
10302 rtx node;
10303 struct machine_function *machine = cfun->machine;
10304
10305 node = gen_rtx_EXPR_LIST (VOIDmode, x, NULL_RTX);
10306 if (machine->first_ciw == NULL_RTX)
10307 machine->first_ciw = node;
10308 else
10309 XEXP (machine->last_ciw, 1) = node;
10310
10311 machine->last_ciw = node;
10312 ++machine->ciw_count;
10313
10314 return GEN_INT (machine->ciw_count
10315 + strlen (current_function_name ())/8 + 5);
10316 }
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328 struct unicosmk_extern_list
10329 {
10330 struct unicosmk_extern_list *next;
10331 const char *name;
10332 };
10333
10334 static struct unicosmk_extern_list *unicosmk_extern_head = 0;
10335
10336
10337
10338 static void
10339 unicosmk_output_default_externs (FILE *file)
10340 {
10341 static const char *const externs[] =
10342 { "__T3E_MISMATCH" };
10343
10344 int i;
10345 int n;
10346
10347 n = ARRAY_SIZE (externs);
10348
10349 for (i = 0; i < n; i++)
10350 fprintf (file, "\t.extern\t%s\n", externs[i]);
10351 }
10352
10353
10354
10355
10356 static void
10357 unicosmk_output_externs (FILE *file)
10358 {
10359 struct unicosmk_extern_list *p;
10360 const char *real_name;
10361 int len;
10362 tree name_tree;
10363
10364 len = strlen (user_label_prefix);
10365 for (p = unicosmk_extern_head; p != 0; p = p->next)
10366 {
10367
10368
10369
10370 real_name = default_strip_name_encoding (p->name);
10371 if (len && p->name[0] == '*'
10372 && !memcmp (real_name, user_label_prefix, len))
10373 real_name += len;
10374
10375 name_tree = get_identifier (real_name);
10376 if (! TREE_ASM_WRITTEN (name_tree))
10377 {
10378 TREE_ASM_WRITTEN (name_tree) = 1;
10379 fputs ("\t.extern\t", file);
10380 assemble_name (file, p->name);
10381 putc ('\n', file);
10382 }
10383 }
10384 }
10385
10386
10387
10388 void
10389 unicosmk_add_extern (const char *name)
10390 {
10391 struct unicosmk_extern_list *p;
10392
10393 p = (struct unicosmk_extern_list *)
10394 xmalloc (sizeof (struct unicosmk_extern_list));
10395 p->next = unicosmk_extern_head;
10396 p->name = name;
10397 unicosmk_extern_head = p;
10398 }
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408 struct unicosmk_dex {
10409 struct unicosmk_dex *next;
10410 const char *name;
10411 };
10412
10413
10414
10415
10416 static struct unicosmk_dex *unicosmk_dex_list = NULL;
10417
10418
10419
10420 static int unicosmk_dex_count = 0;
10421
10422
10423
10424 static int
10425 unicosmk_special_name (const char *name)
10426 {
10427 if (name[0] == '*')
10428 ++name;
10429
10430 if (name[0] == '$')
10431 ++name;
10432
10433 if (name[0] != 'r' && name[0] != 'f' && name[0] != 'R' && name[0] != 'F')
10434 return 0;
10435
10436 switch (name[1])
10437 {
10438 case '1': case '2':
10439 return (name[2] == '\0' || (ISDIGIT (name[2]) && name[3] == '\0'));
10440
10441 case '3':
10442 return (name[2] == '\0'
10443 || ((name[2] == '0' || name[2] == '1') && name[3] == '\0'));
10444
10445 default:
10446 return (ISDIGIT (name[1]) && name[2] == '\0');
10447 }
10448 }
10449
10450
10451
10452
10453 static int
10454 unicosmk_need_dex (rtx x)
10455 {
10456 struct unicosmk_dex *dex;
10457 const char *name;
10458 int i;
10459
10460 if (GET_CODE (x) != SYMBOL_REF)
10461 return 0;
10462
10463 name = XSTR (x,0);
10464 if (! unicosmk_special_name (name))
10465 return 0;
10466
10467 i = unicosmk_dex_count;
10468 for (dex = unicosmk_dex_list; dex; dex = dex->next)
10469 {
10470 if (! strcmp (name, dex->name))
10471 return i;
10472 --i;
10473 }
10474
10475 dex = (struct unicosmk_dex *) xmalloc (sizeof (struct unicosmk_dex));
10476 dex->name = name;
10477 dex->next = unicosmk_dex_list;
10478 unicosmk_dex_list = dex;
10479
10480 ++unicosmk_dex_count;
10481 return unicosmk_dex_count;
10482 }
10483
10484
10485
10486 static void
10487 unicosmk_output_dex (FILE *file)
10488 {
10489 struct unicosmk_dex *dex;
10490 int i;
10491
10492 if (unicosmk_dex_list == NULL)
10493 return;
10494
10495 fprintf (file, "\t.dexstart\n");
10496
10497 i = unicosmk_dex_count;
10498 for (dex = unicosmk_dex_list; dex; dex = dex->next)
10499 {
10500 fprintf (file, "\tDEX (%d) = ", i);
10501 assemble_name (file, dex->name);
10502 putc ('\n', file);
10503 --i;
10504 }
10505
10506 fprintf (file, "\t.dexend\n");
10507 }
10508
10509
10510
10511 static void
10512 unicosmk_file_start (void)
10513 {
10514 int i;
10515
10516 fputs ("\t.ident\t", asm_out_file);
10517 unicosmk_output_module_name (asm_out_file);
10518 fputs ("\n\n", asm_out_file);
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528 for (i = 0; i < 32; ++i)
10529 fprintf (asm_out_file, "$%d <- r%d\n", i, i);
10530
10531 for (i = 0; i < 32; ++i)
10532 fprintf (asm_out_file, "$f%d <- f%d\n", i, i);
10533
10534 putc ('\n', asm_out_file);
10535
10536
10537
10538
10539
10540
10541
10542 fputs ("\t.macro gcc@code@align n\n", asm_out_file);
10543 fputs ("gcc@n@bytes = 1 << n\n", asm_out_file);
10544 fputs ("gcc@here = . % gcc@n@bytes\n", asm_out_file);
10545 fputs ("\t.if ne, gcc@here, 0\n", asm_out_file);
10546 fputs ("\t.repeat (gcc@n@bytes - gcc@here) / 4\n", asm_out_file);
10547 fputs ("\tbis r31,r31,r31\n", asm_out_file);
10548 fputs ("\t.endr\n", asm_out_file);
10549 fputs ("\t.endif\n", asm_out_file);
10550 fputs ("\t.endm gcc@code@align\n\n", asm_out_file);
10551
10552
10553 unicosmk_output_default_externs (asm_out_file);
10554
10555
10556
10557
10558
10559 fputs ("\n\t.psect\t$SG00000,data\n", asm_out_file);
10560 }
10561
10562
10563
10564
10565 static void
10566 unicosmk_file_end (void)
10567 {
10568 fputs ("\t.endp\n\n", asm_out_file);
10569
10570
10571
10572 unicosmk_output_externs (asm_out_file);
10573
10574
10575
10576
10577 unicosmk_output_dex (asm_out_file);
10578
10579 fputs ("\t.end\t", asm_out_file);
10580 unicosmk_output_module_name (asm_out_file);
10581 putc ('\n', asm_out_file);
10582 }
10583
10584 #else
10585
10586 static void
10587 unicosmk_output_deferred_case_vectors (FILE *file ATTRIBUTE_UNUSED)
10588 {}
10589
10590 static void
10591 unicosmk_gen_dsib (unsigned long *imaskP ATTRIBUTE_UNUSED)
10592 {}
10593
10594 static void
10595 unicosmk_output_ssib (FILE * file ATTRIBUTE_UNUSED,
10596 const char * fnname ATTRIBUTE_UNUSED)
10597 {}
10598
10599 rtx
10600 unicosmk_add_call_info_word (rtx x ATTRIBUTE_UNUSED)
10601 {
10602 return NULL_RTX;
10603 }
10604
10605 static int
10606 unicosmk_need_dex (rtx x ATTRIBUTE_UNUSED)
10607 {
10608 return 0;
10609 }
10610
10611 #endif
10612
10613 static void
10614 alpha_init_libfuncs (void)
10615 {
10616 if (TARGET_ABI_UNICOSMK)
10617 {
10618
10619 set_optab_libfunc (sdiv_optab, SImode, 0);
10620 set_optab_libfunc (udiv_optab, SImode, 0);
10621
10622
10623
10624 set_optab_libfunc (sdiv_optab, DImode, "$sldiv");
10625 set_optab_libfunc (udiv_optab, DImode, "$uldiv");
10626 }
10627 else if (TARGET_ABI_OPEN_VMS)
10628 {
10629
10630
10631 set_optab_libfunc (sdiv_optab, SImode, "OTS$DIV_I");
10632 set_optab_libfunc (sdiv_optab, DImode, "OTS$DIV_L");
10633 set_optab_libfunc (udiv_optab, SImode, "OTS$DIV_UI");
10634 set_optab_libfunc (udiv_optab, DImode, "OTS$DIV_UL");
10635 set_optab_libfunc (smod_optab, SImode, "OTS$REM_I");
10636 set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
10637 set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
10638 set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
10639 }
10640 }
10641
10642
10643
10644 #if TARGET_ABI_OPEN_VMS
10645 # undef TARGET_ATTRIBUTE_TABLE
10646 # define TARGET_ATTRIBUTE_TABLE vms_attribute_table
10647 # undef TARGET_SECTION_TYPE_FLAGS
10648 # define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
10649 #endif
10650
10651 #undef TARGET_IN_SMALL_DATA_P
10652 #define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p
10653
10654 #if TARGET_ABI_UNICOSMK
10655 # undef TARGET_INSERT_ATTRIBUTES
10656 # define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes
10657 # undef TARGET_SECTION_TYPE_FLAGS
10658 # define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
10659 # undef TARGET_ASM_UNIQUE_SECTION
10660 # define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section
10661 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
10662 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
10663 # undef TARGET_ASM_GLOBALIZE_LABEL
10664 # define TARGET_ASM_GLOBALIZE_LABEL hook_void_FILEptr_constcharptr
10665 # undef TARGET_MUST_PASS_IN_STACK
10666 # define TARGET_MUST_PASS_IN_STACK unicosmk_must_pass_in_stack
10667 #endif
10668
10669 #undef TARGET_ASM_ALIGNED_HI_OP
10670 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
10671 #undef TARGET_ASM_ALIGNED_DI_OP
10672 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
10673
10674
10675
10676 #ifndef OBJECT_FORMAT_ELF
10677 #undef TARGET_ASM_UNALIGNED_HI_OP
10678 #define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.word\t"
10679 #undef TARGET_ASM_UNALIGNED_SI_OP
10680 #define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.long\t"
10681 #undef TARGET_ASM_UNALIGNED_DI_OP
10682 #define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t"
10683 #endif
10684
10685 #ifdef OBJECT_FORMAT_ELF
10686 #undef TARGET_ASM_RELOC_RW_MASK
10687 #define TARGET_ASM_RELOC_RW_MASK alpha_elf_reloc_rw_mask
10688 #undef TARGET_ASM_SELECT_RTX_SECTION
10689 #define TARGET_ASM_SELECT_RTX_SECTION alpha_elf_select_rtx_section
10690 #undef TARGET_SECTION_TYPE_FLAGS
10691 #define TARGET_SECTION_TYPE_FLAGS alpha_elf_section_type_flags
10692 #endif
10693
10694 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
10695 #define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue
10696
10697 #undef TARGET_INIT_LIBFUNCS
10698 #define TARGET_INIT_LIBFUNCS alpha_init_libfuncs
10699
10700 #if TARGET_ABI_UNICOSMK
10701 #undef TARGET_ASM_FILE_START
10702 #define TARGET_ASM_FILE_START unicosmk_file_start
10703 #undef TARGET_ASM_FILE_END
10704 #define TARGET_ASM_FILE_END unicosmk_file_end
10705 #else
10706 #undef TARGET_ASM_FILE_START
10707 #define TARGET_ASM_FILE_START alpha_file_start
10708 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
10709 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
10710 #endif
10711
10712 #undef TARGET_SCHED_ADJUST_COST
10713 #define TARGET_SCHED_ADJUST_COST alpha_adjust_cost
10714 #undef TARGET_SCHED_ISSUE_RATE
10715 #define TARGET_SCHED_ISSUE_RATE alpha_issue_rate
10716 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
10717 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
10718 alpha_multipass_dfa_lookahead
10719
10720 #undef TARGET_HAVE_TLS
10721 #define TARGET_HAVE_TLS HAVE_AS_TLS
10722
10723 #undef TARGET_INIT_BUILTINS
10724 #define TARGET_INIT_BUILTINS alpha_init_builtins
10725 #undef TARGET_EXPAND_BUILTIN
10726 #define TARGET_EXPAND_BUILTIN alpha_expand_builtin
10727 #undef TARGET_FOLD_BUILTIN
10728 #define TARGET_FOLD_BUILTIN alpha_fold_builtin
10729
10730 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
10731 #define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall
10732 #undef TARGET_CANNOT_COPY_INSN_P
10733 #define TARGET_CANNOT_COPY_INSN_P alpha_cannot_copy_insn_p
10734 #undef TARGET_CANNOT_FORCE_CONST_MEM
10735 #define TARGET_CANNOT_FORCE_CONST_MEM alpha_cannot_force_const_mem
10736
10737 #if TARGET_ABI_OSF
10738 #undef TARGET_ASM_OUTPUT_MI_THUNK
10739 #define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf
10740 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
10741 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
10742 #undef TARGET_STDARG_OPTIMIZE_HOOK
10743 #define TARGET_STDARG_OPTIMIZE_HOOK alpha_stdarg_optimize_hook
10744 #endif
10745
10746 #undef TARGET_RTX_COSTS
10747 #define TARGET_RTX_COSTS alpha_rtx_costs
10748 #undef TARGET_ADDRESS_COST
10749 #define TARGET_ADDRESS_COST hook_int_rtx_0
10750
10751 #undef TARGET_MACHINE_DEPENDENT_REORG
10752 #define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg
10753
10754 #undef TARGET_PROMOTE_FUNCTION_ARGS
10755 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
10756 #undef TARGET_PROMOTE_FUNCTION_RETURN
10757 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
10758 #undef TARGET_PROMOTE_PROTOTYPES
10759 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false
10760 #undef TARGET_RETURN_IN_MEMORY
10761 #define TARGET_RETURN_IN_MEMORY alpha_return_in_memory
10762 #undef TARGET_PASS_BY_REFERENCE
10763 #define TARGET_PASS_BY_REFERENCE alpha_pass_by_reference
10764 #undef TARGET_SETUP_INCOMING_VARARGS
10765 #define TARGET_SETUP_INCOMING_VARARGS alpha_setup_incoming_varargs
10766 #undef TARGET_STRICT_ARGUMENT_NAMING
10767 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
10768 #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
10769 #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true
10770 #undef TARGET_SPLIT_COMPLEX_ARG
10771 #define TARGET_SPLIT_COMPLEX_ARG alpha_split_complex_arg
10772 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
10773 #define TARGET_GIMPLIFY_VA_ARG_EXPR alpha_gimplify_va_arg
10774 #undef TARGET_ARG_PARTIAL_BYTES
10775 #define TARGET_ARG_PARTIAL_BYTES alpha_arg_partial_bytes
10776
10777 #undef TARGET_SCALAR_MODE_SUPPORTED_P
10778 #define TARGET_SCALAR_MODE_SUPPORTED_P alpha_scalar_mode_supported_p
10779 #undef TARGET_VECTOR_MODE_SUPPORTED_P
10780 #define TARGET_VECTOR_MODE_SUPPORTED_P alpha_vector_mode_supported_p
10781
10782 #undef TARGET_BUILD_BUILTIN_VA_LIST
10783 #define TARGET_BUILD_BUILTIN_VA_LIST alpha_build_builtin_va_list
10784
10785
10786
10787
10788 #undef TARGET_RELAXED_ORDERING
10789 #define TARGET_RELAXED_ORDERING true
10790
10791 #undef TARGET_DEFAULT_TARGET_FLAGS
10792 #define TARGET_DEFAULT_TARGET_FLAGS \
10793 (TARGET_DEFAULT | TARGET_CPU_DEFAULT | TARGET_DEFAULT_EXPLICIT_RELOCS)
10794 #undef TARGET_HANDLE_OPTION
10795 #define TARGET_HANDLE_OPTION alpha_handle_option
10796
10797 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
10798 #undef TARGET_MANGLE_FUNDAMENTAL_TYPE
10799 #define TARGET_MANGLE_FUNDAMENTAL_TYPE alpha_mangle_fundamental_type
10800 #endif
10801
10802 struct gcc_target targetm = TARGET_INITIALIZER;
10803
10804
10805 #include "gt-alpha.h"