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