00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "rtl.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "insn-attr.h"
00034 #include "flags.h"
00035 #include "tree.h"
00036 #include "output.h"
00037 #include "except.h"
00038 #include "expr.h"
00039 #include "optabs.h"
00040 #include "reload.h"
00041 #include "integrate.h"
00042 #include "function.h"
00043 #include "toplev.h"
00044 #include "ggc.h"
00045 #include "recog.h"
00046 #include "predict.h"
00047 #include "tm_p.h"
00048 #include "target.h"
00049 #include "target-def.h"
00050
00051
00052
00053 int
00054 hppa_fpstore_bypass_p (rtx out_insn, rtx in_insn)
00055 {
00056 enum machine_mode store_mode;
00057 enum machine_mode other_mode;
00058 rtx set;
00059
00060 if (recog_memoized (in_insn) < 0
00061 || get_attr_type (in_insn) != TYPE_FPSTORE
00062 || recog_memoized (out_insn) < 0)
00063 return 0;
00064
00065 store_mode = GET_MODE (SET_SRC (PATTERN (in_insn)));
00066
00067 set = single_set (out_insn);
00068 if (!set)
00069 return 0;
00070
00071 other_mode = GET_MODE (SET_SRC (set));
00072
00073 return (GET_MODE_SIZE (store_mode) == GET_MODE_SIZE (other_mode));
00074 }
00075
00076
00077 #ifndef DO_FRAME_NOTES
00078 #ifdef INCOMING_RETURN_ADDR_RTX
00079 #define DO_FRAME_NOTES 1
00080 #else
00081 #define DO_FRAME_NOTES 0
00082 #endif
00083 #endif
00084
00085 static void copy_reg_pointer (rtx, rtx);
00086 static void fix_range (const char *);
00087 static bool pa_handle_option (size_t, const char *, int);
00088 static int hppa_address_cost (rtx);
00089 static bool hppa_rtx_costs (rtx, int, int, int *);
00090 static inline rtx force_mode (enum machine_mode, rtx);
00091 static void pa_reorg (void);
00092 static void pa_combine_instructions (void);
00093 static int pa_can_combine_p (rtx, rtx, rtx, int, rtx, rtx, rtx);
00094 static int forward_branch_p (rtx);
00095 static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *);
00096 static int compute_movmem_length (rtx);
00097 static int compute_clrmem_length (rtx);
00098 static bool pa_assemble_integer (rtx, unsigned int, int);
00099 static void remove_useless_addtr_insns (int);
00100 static void store_reg (int, HOST_WIDE_INT, int);
00101 static void store_reg_modify (int, int, HOST_WIDE_INT);
00102 static void load_reg (int, HOST_WIDE_INT, int);
00103 static void set_reg_plus_d (int, int, HOST_WIDE_INT, int);
00104 static void pa_output_function_prologue (FILE *, HOST_WIDE_INT);
00105 static void update_total_code_bytes (int);
00106 static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT);
00107 static int pa_adjust_cost (rtx, rtx, rtx, int);
00108 static int pa_adjust_priority (rtx, int);
00109 static int pa_issue_rate (void);
00110 static void pa_som_asm_init_sections (void) ATTRIBUTE_UNUSED;
00111 static section *pa_select_section (tree, int, unsigned HOST_WIDE_INT)
00112 ATTRIBUTE_UNUSED;
00113 static void pa_encode_section_info (tree, rtx, int);
00114 static const char *pa_strip_name_encoding (const char *);
00115 static bool pa_function_ok_for_sibcall (tree, tree);
00116 static void pa_globalize_label (FILE *, const char *)
00117 ATTRIBUTE_UNUSED;
00118 static void pa_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
00119 HOST_WIDE_INT, tree);
00120 #if !defined(USE_COLLECT2)
00121 static void pa_asm_out_constructor (rtx, int);
00122 static void pa_asm_out_destructor (rtx, int);
00123 #endif
00124 static void pa_init_builtins (void);
00125 static rtx hppa_builtin_saveregs (void);
00126 static tree hppa_gimplify_va_arg_expr (tree, tree, tree *, tree *);
00127 static bool pa_scalar_mode_supported_p (enum machine_mode);
00128 static bool pa_commutative_p (rtx x, int outer_code);
00129 static void copy_fp_args (rtx) ATTRIBUTE_UNUSED;
00130 static int length_fp_args (rtx) ATTRIBUTE_UNUSED;
00131 static inline void pa_file_start_level (void) ATTRIBUTE_UNUSED;
00132 static inline void pa_file_start_space (int) ATTRIBUTE_UNUSED;
00133 static inline void pa_file_start_file (int) ATTRIBUTE_UNUSED;
00134 static inline void pa_file_start_mcount (const char*) ATTRIBUTE_UNUSED;
00135 static void pa_elf_file_start (void) ATTRIBUTE_UNUSED;
00136 static void pa_som_file_start (void) ATTRIBUTE_UNUSED;
00137 static void pa_linux_file_start (void) ATTRIBUTE_UNUSED;
00138 static void pa_hpux64_gas_file_start (void) ATTRIBUTE_UNUSED;
00139 static void pa_hpux64_hpas_file_start (void) ATTRIBUTE_UNUSED;
00140 static void output_deferred_plabels (void);
00141 static void output_deferred_profile_counters (void) ATTRIBUTE_UNUSED;
00142 #ifdef ASM_OUTPUT_EXTERNAL_REAL
00143 static void pa_hpux_file_end (void);
00144 #endif
00145 #ifdef HPUX_LONG_DOUBLE_LIBRARY
00146 static void pa_hpux_init_libfuncs (void);
00147 #endif
00148 static rtx pa_struct_value_rtx (tree, int);
00149 static bool pa_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00150 tree, bool);
00151 static int pa_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00152 tree, bool);
00153 static struct machine_function * pa_init_machine_status (void);
00154 static enum reg_class pa_secondary_reload (bool, rtx, enum reg_class,
00155 enum machine_mode,
00156 secondary_reload_info *);
00157
00158
00159
00160 static GTY(()) section *som_readonly_data_section;
00161 static GTY(()) section *som_one_only_readonly_data_section;
00162 static GTY(()) section *som_one_only_data_section;
00163
00164
00165
00166 rtx hppa_compare_op0, hppa_compare_op1;
00167 enum cmp_type hppa_branch_type;
00168
00169
00170 enum processor_type pa_cpu = TARGET_SCHED_DEFAULT;
00171
00172
00173 int flag_pa_unix = TARGET_HPUX_11_11 ? 1998 : TARGET_HPUX_10_10 ? 1995 : 1993;
00174
00175
00176
00177 static int gr_saved, fr_saved;
00178
00179 static rtx find_addr_reg (rtx);
00180
00181
00182
00183 unsigned long total_code_bytes;
00184
00185
00186
00187
00188 static int last_address;
00189
00190
00191
00192 struct deferred_plabel GTY(())
00193 {
00194 rtx internal_label;
00195 rtx symbol;
00196 };
00197 static GTY((length ("n_deferred_plabels"))) struct deferred_plabel *
00198 deferred_plabels;
00199 static size_t n_deferred_plabels = 0;
00200
00201
00202
00203
00204 #undef TARGET_ASM_ALIGNED_HI_OP
00205 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
00206 #undef TARGET_ASM_ALIGNED_SI_OP
00207 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00208 #undef TARGET_ASM_ALIGNED_DI_OP
00209 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
00210 #undef TARGET_ASM_UNALIGNED_HI_OP
00211 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
00212 #undef TARGET_ASM_UNALIGNED_SI_OP
00213 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
00214 #undef TARGET_ASM_UNALIGNED_DI_OP
00215 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
00216 #undef TARGET_ASM_INTEGER
00217 #define TARGET_ASM_INTEGER pa_assemble_integer
00218
00219 #undef TARGET_ASM_FUNCTION_PROLOGUE
00220 #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue
00221 #undef TARGET_ASM_FUNCTION_EPILOGUE
00222 #define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue
00223
00224 #undef TARGET_SCHED_ADJUST_COST
00225 #define TARGET_SCHED_ADJUST_COST pa_adjust_cost
00226 #undef TARGET_SCHED_ADJUST_PRIORITY
00227 #define TARGET_SCHED_ADJUST_PRIORITY pa_adjust_priority
00228 #undef TARGET_SCHED_ISSUE_RATE
00229 #define TARGET_SCHED_ISSUE_RATE pa_issue_rate
00230
00231 #undef TARGET_ENCODE_SECTION_INFO
00232 #define TARGET_ENCODE_SECTION_INFO pa_encode_section_info
00233 #undef TARGET_STRIP_NAME_ENCODING
00234 #define TARGET_STRIP_NAME_ENCODING pa_strip_name_encoding
00235
00236 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
00237 #define TARGET_FUNCTION_OK_FOR_SIBCALL pa_function_ok_for_sibcall
00238
00239 #undef TARGET_COMMUTATIVE_P
00240 #define TARGET_COMMUTATIVE_P pa_commutative_p
00241
00242 #undef TARGET_ASM_OUTPUT_MI_THUNK
00243 #define TARGET_ASM_OUTPUT_MI_THUNK pa_asm_output_mi_thunk
00244 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00245 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
00246
00247 #undef TARGET_ASM_FILE_END
00248 #ifdef ASM_OUTPUT_EXTERNAL_REAL
00249 #define TARGET_ASM_FILE_END pa_hpux_file_end
00250 #else
00251 #define TARGET_ASM_FILE_END output_deferred_plabels
00252 #endif
00253
00254 #if !defined(USE_COLLECT2)
00255 #undef TARGET_ASM_CONSTRUCTOR
00256 #define TARGET_ASM_CONSTRUCTOR pa_asm_out_constructor
00257 #undef TARGET_ASM_DESTRUCTOR
00258 #define TARGET_ASM_DESTRUCTOR pa_asm_out_destructor
00259 #endif
00260
00261 #undef TARGET_DEFAULT_TARGET_FLAGS
00262 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | TARGET_CPU_DEFAULT)
00263 #undef TARGET_HANDLE_OPTION
00264 #define TARGET_HANDLE_OPTION pa_handle_option
00265
00266 #undef TARGET_INIT_BUILTINS
00267 #define TARGET_INIT_BUILTINS pa_init_builtins
00268
00269 #undef TARGET_RTX_COSTS
00270 #define TARGET_RTX_COSTS hppa_rtx_costs
00271 #undef TARGET_ADDRESS_COST
00272 #define TARGET_ADDRESS_COST hppa_address_cost
00273
00274 #undef TARGET_MACHINE_DEPENDENT_REORG
00275 #define TARGET_MACHINE_DEPENDENT_REORG pa_reorg
00276
00277 #ifdef HPUX_LONG_DOUBLE_LIBRARY
00278 #undef TARGET_INIT_LIBFUNCS
00279 #define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs
00280 #endif
00281
00282 #undef TARGET_PROMOTE_FUNCTION_RETURN
00283 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00284 #undef TARGET_PROMOTE_PROTOTYPES
00285 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00286
00287 #undef TARGET_STRUCT_VALUE_RTX
00288 #define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx
00289 #undef TARGET_RETURN_IN_MEMORY
00290 #define TARGET_RETURN_IN_MEMORY pa_return_in_memory
00291 #undef TARGET_MUST_PASS_IN_STACK
00292 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
00293 #undef TARGET_PASS_BY_REFERENCE
00294 #define TARGET_PASS_BY_REFERENCE pa_pass_by_reference
00295 #undef TARGET_CALLEE_COPIES
00296 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
00297 #undef TARGET_ARG_PARTIAL_BYTES
00298 #define TARGET_ARG_PARTIAL_BYTES pa_arg_partial_bytes
00299
00300 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
00301 #define TARGET_EXPAND_BUILTIN_SAVEREGS hppa_builtin_saveregs
00302 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
00303 #define TARGET_GIMPLIFY_VA_ARG_EXPR hppa_gimplify_va_arg_expr
00304
00305 #undef TARGET_SCALAR_MODE_SUPPORTED_P
00306 #define TARGET_SCALAR_MODE_SUPPORTED_P pa_scalar_mode_supported_p
00307
00308 #undef TARGET_CANNOT_FORCE_CONST_MEM
00309 #define TARGET_CANNOT_FORCE_CONST_MEM pa_tls_referenced_p
00310
00311 #undef TARGET_SECONDARY_RELOAD
00312 #define TARGET_SECONDARY_RELOAD pa_secondary_reload
00313
00314 struct gcc_target targetm = TARGET_INITIALIZER;
00315
00316
00317
00318 static void
00319 fix_range (const char *const_str)
00320 {
00321 int i, first, last;
00322 char *str, *dash, *comma;
00323
00324
00325
00326
00327
00328
00329
00330 i = strlen (const_str);
00331 str = (char *) alloca (i + 1);
00332 memcpy (str, const_str, i + 1);
00333
00334 while (1)
00335 {
00336 dash = strchr (str, '-');
00337 if (!dash)
00338 {
00339 warning (0, "value of -mfixed-range must have form REG1-REG2");
00340 return;
00341 }
00342 *dash = '\0';
00343
00344 comma = strchr (dash + 1, ',');
00345 if (comma)
00346 *comma = '\0';
00347
00348 first = decode_reg_name (str);
00349 if (first < 0)
00350 {
00351 warning (0, "unknown register name: %s", str);
00352 return;
00353 }
00354
00355 last = decode_reg_name (dash + 1);
00356 if (last < 0)
00357 {
00358 warning (0, "unknown register name: %s", dash + 1);
00359 return;
00360 }
00361
00362 *dash = '-';
00363
00364 if (first > last)
00365 {
00366 warning (0, "%s-%s is an empty range", str, dash + 1);
00367 return;
00368 }
00369
00370 for (i = first; i <= last; ++i)
00371 fixed_regs[i] = call_used_regs[i] = 1;
00372
00373 if (!comma)
00374 break;
00375
00376 *comma = ',';
00377 str = comma + 1;
00378 }
00379
00380
00381 for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
00382 if (!fixed_regs[i])
00383 break;
00384
00385 if (i > FP_REG_LAST)
00386 target_flags |= MASK_DISABLE_FPREGS;
00387 }
00388
00389
00390
00391 static bool
00392 pa_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
00393 {
00394 switch (code)
00395 {
00396 case OPT_mnosnake:
00397 case OPT_mpa_risc_1_0:
00398 case OPT_march_1_0:
00399 target_flags &= ~(MASK_PA_11 | MASK_PA_20);
00400 return true;
00401
00402 case OPT_msnake:
00403 case OPT_mpa_risc_1_1:
00404 case OPT_march_1_1:
00405 target_flags &= ~MASK_PA_20;
00406 target_flags |= MASK_PA_11;
00407 return true;
00408
00409 case OPT_mpa_risc_2_0:
00410 case OPT_march_2_0:
00411 target_flags |= MASK_PA_11 | MASK_PA_20;
00412 return true;
00413
00414 case OPT_mschedule_:
00415 if (strcmp (arg, "8000") == 0)
00416 pa_cpu = PROCESSOR_8000;
00417 else if (strcmp (arg, "7100") == 0)
00418 pa_cpu = PROCESSOR_7100;
00419 else if (strcmp (arg, "700") == 0)
00420 pa_cpu = PROCESSOR_700;
00421 else if (strcmp (arg, "7100LC") == 0)
00422 pa_cpu = PROCESSOR_7100LC;
00423 else if (strcmp (arg, "7200") == 0)
00424 pa_cpu = PROCESSOR_7200;
00425 else if (strcmp (arg, "7300") == 0)
00426 pa_cpu = PROCESSOR_7300;
00427 else
00428 return false;
00429 return true;
00430
00431 case OPT_mfixed_range_:
00432 fix_range (arg);
00433 return true;
00434
00435 #if TARGET_HPUX
00436 case OPT_munix_93:
00437 flag_pa_unix = 1993;
00438 return true;
00439 #endif
00440
00441 #if TARGET_HPUX_10_10
00442 case OPT_munix_95:
00443 flag_pa_unix = 1995;
00444 return true;
00445 #endif
00446
00447 #if TARGET_HPUX_11_11
00448 case OPT_munix_98:
00449 flag_pa_unix = 1998;
00450 return true;
00451 #endif
00452
00453 default:
00454 return true;
00455 }
00456 }
00457
00458 void
00459 override_options (void)
00460 {
00461
00462
00463
00464 if (pa_cpu >= PROCESSOR_8000
00465 || (! USING_SJLJ_EXCEPTIONS && flag_exceptions)
00466 || flag_unwind_tables)
00467 target_flags &= ~MASK_JUMP_IN_DELAY;
00468
00469 if (flag_pic && TARGET_PORTABLE_RUNTIME)
00470 {
00471 warning (0, "PIC code generation is not supported in the portable runtime model");
00472 }
00473
00474 if (flag_pic && TARGET_FAST_INDIRECT_CALLS)
00475 {
00476 warning (0, "PIC code generation is not compatible with fast indirect calls");
00477 }
00478
00479 if (! TARGET_GAS && write_symbols != NO_DEBUG)
00480 {
00481 warning (0, "-g is only supported when using GAS on this processor,");
00482 warning (0, "-g option disabled");
00483 write_symbols = NO_DEBUG;
00484 }
00485
00486
00487
00488 if (flag_pic == 1 || TARGET_64BIT)
00489 flag_pic = 2;
00490
00491
00492 if (UNITS_PER_WORD == 4)
00493 targetm.asm_out.aligned_op.di = NULL;
00494
00495
00496 if (!TARGET_GAS)
00497 {
00498 targetm.asm_out.unaligned_op.hi = NULL;
00499 targetm.asm_out.unaligned_op.si = NULL;
00500 targetm.asm_out.unaligned_op.di = NULL;
00501 }
00502
00503 init_machine_status = pa_init_machine_status;
00504 }
00505
00506 static void
00507 pa_init_builtins (void)
00508 {
00509 #ifdef DONT_HAVE_FPUTC_UNLOCKED
00510 built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED] =
00511 built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
00512 implicit_built_in_decls[(int) BUILT_IN_FPUTC_UNLOCKED]
00513 = implicit_built_in_decls[(int) BUILT_IN_PUTC_UNLOCKED];
00514 #endif
00515 }
00516
00517
00518
00519
00520
00521 static struct machine_function *
00522 pa_init_machine_status (void)
00523 {
00524 return ggc_alloc_cleared (sizeof (machine_function));
00525 }
00526
00527
00528
00529
00530 static void
00531 copy_reg_pointer (rtx to, rtx from)
00532 {
00533 if (REG_POINTER (from))
00534 mark_reg_pointer (to, REGNO_POINTER_ALIGN (REGNO (from)));
00535 }
00536
00537
00538
00539
00540 int
00541 symbolic_expression_p (rtx x)
00542 {
00543
00544
00545 if (GET_CODE (x) == HIGH)
00546 x = XEXP (x, 0);
00547
00548 return (symbolic_operand (x, VOIDmode));
00549 }
00550
00551
00552
00553 int
00554 cint_ok_for_move (HOST_WIDE_INT intval)
00555 {
00556
00557 return (CONST_OK_FOR_LETTER_P (intval, 'J')
00558 || CONST_OK_FOR_LETTER_P (intval, 'N')
00559 || CONST_OK_FOR_LETTER_P (intval, 'K'));
00560 }
00561
00562
00563
00564 int
00565 adddi3_operand (rtx op, enum machine_mode mode)
00566 {
00567 return (register_operand (op, mode)
00568 || (GET_CODE (op) == CONST_INT
00569 && (TARGET_64BIT ? INT_14_BITS (op) : INT_11_BITS (op))));
00570 }
00571
00572
00573
00574
00575 int
00576 zdepi_cint_p (unsigned HOST_WIDE_INT x)
00577 {
00578 unsigned HOST_WIDE_INT lsb_mask, t;
00579
00580
00581
00582 lsb_mask = x & -x;
00583 t = ((x >> 4) + lsb_mask) & ~(lsb_mask - 1);
00584
00585 return ((t & (t - 1)) == 0);
00586 }
00587
00588
00589
00590
00591
00592
00593 int
00594 and_mask_p (unsigned HOST_WIDE_INT mask)
00595 {
00596 mask = ~mask;
00597 mask += mask & -mask;
00598 return (mask & (mask - 1)) == 0;
00599 }
00600
00601
00602 int
00603 ior_mask_p (unsigned HOST_WIDE_INT mask)
00604 {
00605 mask += mask & -mask;
00606 return (mask & (mask - 1)) == 0;
00607 }
00608
00609
00610
00611
00612
00613
00614 rtx
00615 legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
00616 {
00617 rtx pic_ref = orig;
00618
00619 gcc_assert (!PA_SYMBOL_REF_TLS_P (orig));
00620
00621
00622 if (pic_label_operand (orig, mode))
00623 {
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 mark_reg_pointer (reg, BITS_PER_UNIT);
00634 emit_insn (gen_rtx_SET (VOIDmode, reg, orig));
00635 current_function_uses_pic_offset_table = 1;
00636 return reg;
00637 }
00638 if (GET_CODE (orig) == SYMBOL_REF)
00639 {
00640 rtx insn, tmp_reg;
00641
00642 gcc_assert (reg);
00643
00644
00645
00646
00647 tmp_reg = ((reload_in_progress || reload_completed)
00648 ? reg : gen_reg_rtx (Pmode));
00649
00650 emit_move_insn (tmp_reg,
00651 gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
00652 gen_rtx_HIGH (word_mode, orig)));
00653 pic_ref
00654 = gen_const_mem (Pmode,
00655 gen_rtx_LO_SUM (Pmode, tmp_reg,
00656 gen_rtx_UNSPEC (Pmode,
00657 gen_rtvec (1, orig),
00658 UNSPEC_DLTIND14R)));
00659
00660 current_function_uses_pic_offset_table = 1;
00661 mark_reg_pointer (reg, BITS_PER_UNIT);
00662 insn = emit_move_insn (reg, pic_ref);
00663
00664
00665 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, REG_NOTES (insn));
00666
00667 return reg;
00668 }
00669 else if (GET_CODE (orig) == CONST)
00670 {
00671 rtx base;
00672
00673 if (GET_CODE (XEXP (orig, 0)) == PLUS
00674 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
00675 return orig;
00676
00677 gcc_assert (reg);
00678 gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
00679
00680 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
00681 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
00682 base == reg ? 0 : reg);
00683
00684 if (GET_CODE (orig) == CONST_INT)
00685 {
00686 if (INT_14_BITS (orig))
00687 return plus_constant (base, INTVAL (orig));
00688 orig = force_reg (Pmode, orig);
00689 }
00690 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
00691
00692 }
00693
00694 return pic_ref;
00695 }
00696
00697 static GTY(()) rtx gen_tls_tga;
00698
00699 static rtx
00700 gen_tls_get_addr (void)
00701 {
00702 if (!gen_tls_tga)
00703 gen_tls_tga = init_one_libfunc ("__tls_get_addr");
00704 return gen_tls_tga;
00705 }
00706
00707 static rtx
00708 hppa_tls_call (rtx arg)
00709 {
00710 rtx ret;
00711
00712 ret = gen_reg_rtx (Pmode);
00713 emit_library_call_value (gen_tls_get_addr (), ret,
00714 LCT_CONST, Pmode, 1, arg, Pmode);
00715
00716 return ret;
00717 }
00718
00719 static rtx
00720 legitimize_tls_address (rtx addr)
00721 {
00722 rtx ret, insn, tmp, t1, t2, tp;
00723 enum tls_model model = SYMBOL_REF_TLS_MODEL (addr);
00724
00725 switch (model)
00726 {
00727 case TLS_MODEL_GLOBAL_DYNAMIC:
00728 tmp = gen_reg_rtx (Pmode);
00729 emit_insn (gen_tgd_load (tmp, addr));
00730 ret = hppa_tls_call (tmp);
00731 break;
00732
00733 case TLS_MODEL_LOCAL_DYNAMIC:
00734 ret = gen_reg_rtx (Pmode);
00735 tmp = gen_reg_rtx (Pmode);
00736 start_sequence ();
00737 emit_insn (gen_tld_load (tmp, addr));
00738 t1 = hppa_tls_call (tmp);
00739 insn = get_insns ();
00740 end_sequence ();
00741 t2 = gen_reg_rtx (Pmode);
00742 emit_libcall_block (insn, t2, t1,
00743 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
00744 UNSPEC_TLSLDBASE));
00745 emit_insn (gen_tld_offset_load (ret, addr, t2));
00746 break;
00747
00748 case TLS_MODEL_INITIAL_EXEC:
00749 tp = gen_reg_rtx (Pmode);
00750 tmp = gen_reg_rtx (Pmode);
00751 ret = gen_reg_rtx (Pmode);
00752 emit_insn (gen_tp_load (tp));
00753 emit_insn (gen_tie_load (tmp, addr));
00754 emit_move_insn (ret, gen_rtx_PLUS (Pmode, tp, tmp));
00755 break;
00756
00757 case TLS_MODEL_LOCAL_EXEC:
00758 tp = gen_reg_rtx (Pmode);
00759 ret = gen_reg_rtx (Pmode);
00760 emit_insn (gen_tp_load (tp));
00761 emit_insn (gen_tle_load (ret, addr, tp));
00762 break;
00763
00764 default:
00765 gcc_unreachable ();
00766 }
00767
00768 return ret;
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 rtx
00823 hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
00824 enum machine_mode mode)
00825 {
00826 rtx orig = x;
00827
00828
00829
00830
00831 if (!TARGET_NO_SPACE_REGS
00832 && GET_CODE (x) == PLUS
00833 && GET_MODE (x) == Pmode
00834 && REG_P (XEXP (x, 0))
00835 && REG_P (XEXP (x, 1))
00836 && REG_POINTER (XEXP (x, 0))
00837 && !REG_POINTER (XEXP (x, 1)))
00838 return gen_rtx_PLUS (Pmode, XEXP (x, 1), XEXP (x, 0));
00839
00840 if (PA_SYMBOL_REF_TLS_P (x))
00841 return legitimize_tls_address (x);
00842 else if (flag_pic)
00843 return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));
00844
00845
00846 if (GET_CODE (x) == CONST)
00847 x = XEXP (x, 0);
00848
00849
00850
00851 if (GET_CODE (x) == PLUS
00852 && GET_CODE (XEXP (x, 0)) == REG
00853 && GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
00854 {
00855 rtx reg = force_reg (Pmode, XEXP (x, 1));
00856 return force_reg (Pmode, gen_rtx_PLUS (Pmode, reg, XEXP (x, 0)));
00857 }
00858
00859
00860
00861 if (GET_CODE (x) == PLUS
00862 && GET_CODE (XEXP (x, 1)) == CONST_INT
00863 && ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF
00864 && !FUNCTION_NAME_P (XSTR (XEXP (x, 0), 0)))
00865 || GET_CODE (XEXP (x, 0)) == REG))
00866 {
00867 rtx int_part, ptr_reg;
00868 int newoffset;
00869 int offset = INTVAL (XEXP (x, 1));
00870 int mask;
00871
00872 mask = (GET_MODE_CLASS (mode) == MODE_FLOAT
00873 ? (TARGET_PA_20 ? 0x3fff : 0x1f) : 0x3fff);
00874
00875
00876
00877 if ((offset & mask) >= ((mask + 1) / 2))
00878 newoffset = (offset & ~ mask) + mask + 1;
00879 else
00880 newoffset = (offset & ~ mask);
00881
00882
00883
00884
00885
00886
00887
00888 if (! VAL_14_BITS_P (newoffset)
00889 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
00890 {
00891 rtx const_part = plus_constant (XEXP (x, 0), newoffset);
00892 rtx tmp_reg
00893 = force_reg (Pmode,
00894 gen_rtx_HIGH (Pmode, const_part));
00895 ptr_reg
00896 = force_reg (Pmode,
00897 gen_rtx_LO_SUM (Pmode,
00898 tmp_reg, const_part));
00899 }
00900 else
00901 {
00902 if (! VAL_14_BITS_P (newoffset))
00903 int_part = force_reg (Pmode, GEN_INT (newoffset));
00904 else
00905 int_part = GEN_INT (newoffset);
00906
00907 ptr_reg = force_reg (Pmode,
00908 gen_rtx_PLUS (Pmode,
00909 force_reg (Pmode, XEXP (x, 0)),
00910 int_part));
00911 }
00912 return plus_constant (ptr_reg, offset - newoffset);
00913 }
00914
00915
00916
00917 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
00918 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
00919 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
00920 && (OBJECT_P (XEXP (x, 1))
00921 || GET_CODE (XEXP (x, 1)) == SUBREG)
00922 && GET_CODE (XEXP (x, 1)) != CONST)
00923 {
00924 int val = INTVAL (XEXP (XEXP (x, 0), 1));
00925 rtx reg1, reg2;
00926
00927 reg1 = XEXP (x, 1);
00928 if (GET_CODE (reg1) != REG)
00929 reg1 = force_reg (Pmode, force_operand (reg1, 0));
00930
00931 reg2 = XEXP (XEXP (x, 0), 0);
00932 if (GET_CODE (reg2) != REG)
00933 reg2 = force_reg (Pmode, force_operand (reg2, 0));
00934
00935 return force_reg (Pmode, gen_rtx_PLUS (Pmode,
00936 gen_rtx_MULT (Pmode,
00937 reg2,
00938 GEN_INT (val)),
00939 reg1));
00940 }
00941
00942
00943
00944
00945
00946 if (GET_CODE (x) == PLUS
00947 && GET_CODE (XEXP (x, 0)) == PLUS
00948 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
00949 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
00950 && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
00951 && (mode == SFmode || mode == DFmode))
00952 {
00953
00954
00955 rtx reg1, reg2, base, idx, orig_base;
00956
00957 reg1 = XEXP (XEXP (x, 0), 1);
00958 reg2 = XEXP (x, 1);
00959 base = NULL_RTX;
00960 idx = NULL_RTX;
00961
00962
00963
00964
00965 if (GET_CODE (reg1) != REG)
00966 reg1 = force_reg (Pmode, force_operand (reg1, 0));
00967
00968 if (GET_CODE (reg2) != REG)
00969 reg2 = force_reg (Pmode, force_operand (reg2, 0));
00970
00971
00972
00973 if (GET_CODE (reg1) == REG
00974 && REG_POINTER (reg1))
00975 {
00976 base = reg1;
00977 orig_base = XEXP (XEXP (x, 0), 1);
00978 idx = gen_rtx_PLUS (Pmode,
00979 gen_rtx_MULT (Pmode,
00980 XEXP (XEXP (XEXP (x, 0), 0), 0),
00981 XEXP (XEXP (XEXP (x, 0), 0), 1)),
00982 XEXP (x, 1));
00983 }
00984 else if (GET_CODE (reg2) == REG
00985 && REG_POINTER (reg2))
00986 {
00987 base = reg2;
00988 orig_base = XEXP (x, 1);
00989 idx = XEXP (x, 0);
00990 }
00991
00992 if (base == 0)
00993 return orig;
00994
00995
00996
00997 if (GET_CODE (XEXP (idx, 1)) == CONST_INT
00998 && VAL_14_BITS_P (INTVAL (XEXP (idx, 1))
00999 / INTVAL (XEXP (XEXP (idx, 0), 1)))
01000 && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0)
01001 {
01002
01003 int val = INTVAL (XEXP (idx, 1));
01004
01005 val /= INTVAL (XEXP (XEXP (idx, 0), 1));
01006 reg1 = XEXP (XEXP (idx, 0), 0);
01007 if (GET_CODE (reg1) != REG)
01008 reg1 = force_reg (Pmode, force_operand (reg1, 0));
01009
01010 reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, reg1, GEN_INT (val)));
01011
01012
01013 return
01014 force_reg
01015 (Pmode, gen_rtx_PLUS (Pmode,
01016 gen_rtx_MULT (Pmode, reg1,
01017 XEXP (XEXP (idx, 0), 1)),
01018 base));
01019 }
01020
01021
01022 if (GET_CODE (XEXP (idx, 1)) == CONST_INT
01023 && INTVAL (XEXP (idx, 1)) <= 4096
01024 && INTVAL (XEXP (idx, 1)) >= -4096)
01025 {
01026 int val = INTVAL (XEXP (XEXP (idx, 0), 1));
01027 rtx reg1, reg2;
01028
01029 reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1)));
01030
01031 reg2 = XEXP (XEXP (idx, 0), 0);
01032 if (GET_CODE (reg2) != CONST_INT)
01033 reg2 = force_reg (Pmode, force_operand (reg2, 0));
01034
01035 return force_reg (Pmode, gen_rtx_PLUS (Pmode,
01036 gen_rtx_MULT (Pmode,
01037 reg2,
01038 GEN_INT (val)),
01039 reg1));
01040 }
01041
01042
01043
01044
01045
01046 reg1 = XEXP (XEXP (idx, 0), 0);
01047 if (GET_CODE (reg1) != REG)
01048 reg1 = force_reg (Pmode, force_operand (reg1, 0));
01049
01050
01051 reg2 = XEXP (idx, 1);
01052 if (GET_CODE (reg2) != REG)
01053 reg2 = force_reg (Pmode, force_operand (reg2, 0));
01054
01055 reg1 = force_reg (Pmode,
01056 gen_rtx_PLUS (Pmode,
01057 gen_rtx_MULT (Pmode, reg1,
01058 XEXP (XEXP (idx, 0), 1)),
01059 reg2));
01060
01061
01062 return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, reg1));
01063
01064 }
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 if (GET_CODE (x) == PLUS
01078 && symbolic_expression_p (XEXP (x, 1)))
01079 {
01080
01081
01082
01083
01084 rtx regx1, regx2, regy1, regy2, y;
01085
01086
01087 y = XEXP (x, 1);
01088 if (GET_CODE (y) == CONST)
01089 y = XEXP (y, 0);
01090
01091 if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
01092 {
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF
01103 && GET_CODE (XEXP (x, 0)) == MULT
01104 && GET_CODE (XEXP (y, 1)) == CONST_INT
01105 && INTVAL (XEXP (y, 1)) >= -4096
01106 && INTVAL (XEXP (y, 1)) <= 4095
01107 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01108 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
01109 {
01110 int val = INTVAL (XEXP (XEXP (x, 0), 1));
01111 rtx reg1, reg2;
01112
01113 reg1 = XEXP (x, 1);
01114 if (GET_CODE (reg1) != REG)
01115 reg1 = force_reg (Pmode, force_operand (reg1, 0));
01116
01117 reg2 = XEXP (XEXP (x, 0), 0);
01118 if (GET_CODE (reg2) != REG)
01119 reg2 = force_reg (Pmode, force_operand (reg2, 0));
01120
01121 return force_reg (Pmode,
01122 gen_rtx_PLUS (Pmode,
01123 gen_rtx_MULT (Pmode,
01124 reg2,
01125 GEN_INT (val)),
01126 reg1));
01127 }
01128 else if ((mode == DFmode || mode == SFmode)
01129 && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
01130 && GET_CODE (XEXP (x, 0)) == MULT
01131 && GET_CODE (XEXP (y, 1)) == CONST_INT
01132 && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0
01133 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01134 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
01135 {
01136 regx1
01137 = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
01138 / INTVAL (XEXP (XEXP (x, 0), 1))));
01139 regx2 = XEXP (XEXP (x, 0), 0);
01140 if (GET_CODE (regx2) != REG)
01141 regx2 = force_reg (Pmode, force_operand (regx2, 0));
01142 regx2 = force_reg (Pmode, gen_rtx_fmt_ee (GET_CODE (y), Pmode,
01143 regx2, regx1));
01144 return
01145 force_reg (Pmode,
01146 gen_rtx_PLUS (Pmode,
01147 gen_rtx_MULT (Pmode, regx2,
01148 XEXP (XEXP (x, 0), 1)),
01149 force_reg (Pmode, XEXP (y, 0))));
01150 }
01151 else if (GET_CODE (XEXP (y, 1)) == CONST_INT
01152 && INTVAL (XEXP (y, 1)) >= -4096
01153 && INTVAL (XEXP (y, 1)) <= 4095)
01154 {
01155
01156
01157
01158 return orig;
01159 }
01160 else
01161 {
01162
01163 regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
01164 regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
01165 regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
01166 regx1 = force_reg (Pmode,
01167 gen_rtx_fmt_ee (GET_CODE (y), Pmode,
01168 regx1, regy2));
01169 return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));
01170 }
01171 }
01172 }
01173
01174 return orig;
01175 }
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 static int
01186 hppa_address_cost (rtx X)
01187 {
01188 switch (GET_CODE (X))
01189 {
01190 case REG:
01191 case PLUS:
01192 case LO_SUM:
01193 return 1;
01194 case HIGH:
01195 return 2;
01196 default:
01197 return 4;
01198 }
01199 }
01200
01201
01202
01203
01204
01205 static bool
01206 hppa_rtx_costs (rtx x, int code, int outer_code, int *total)
01207 {
01208 switch (code)
01209 {
01210 case CONST_INT:
01211 if (INTVAL (x) == 0)
01212 *total = 0;
01213 else if (INT_14_BITS (x))
01214 *total = 1;
01215 else
01216 *total = 2;
01217 return true;
01218
01219 case HIGH:
01220 *total = 2;
01221 return true;
01222
01223 case CONST:
01224 case LABEL_REF:
01225 case SYMBOL_REF:
01226 *total = 4;
01227 return true;
01228
01229 case CONST_DOUBLE:
01230 if ((x == CONST0_RTX (DFmode) || x == CONST0_RTX (SFmode))
01231 && outer_code != SET)
01232 *total = 0;
01233 else
01234 *total = 8;
01235 return true;
01236
01237 case MULT:
01238 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
01239 *total = COSTS_N_INSNS (3);
01240 else if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT)
01241 *total = COSTS_N_INSNS (8);
01242 else
01243 *total = COSTS_N_INSNS (20);
01244 return true;
01245
01246 case DIV:
01247 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
01248 {
01249 *total = COSTS_N_INSNS (14);
01250 return true;
01251 }
01252
01253
01254 case UDIV:
01255 case MOD:
01256 case UMOD:
01257 *total = COSTS_N_INSNS (60);
01258 return true;
01259
01260 case PLUS:
01261 case MINUS:
01262 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
01263 *total = COSTS_N_INSNS (3);
01264 else
01265 *total = COSTS_N_INSNS (1);
01266 return true;
01267
01268 case ASHIFT:
01269 case ASHIFTRT:
01270 case LSHIFTRT:
01271 *total = COSTS_N_INSNS (1);
01272 return true;
01273
01274 default:
01275 return false;
01276 }
01277 }
01278
01279
01280
01281 static inline rtx
01282 force_mode (enum machine_mode mode, rtx orig)
01283 {
01284 if (mode == GET_MODE (orig))
01285 return orig;
01286
01287 gcc_assert (REGNO (orig) < FIRST_PSEUDO_REGISTER);
01288
01289 return gen_rtx_REG (mode, REGNO (orig));
01290 }
01291
01292
01293
01294 static int
01295 pa_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
01296 {
01297 return PA_SYMBOL_REF_TLS_P (*x);
01298 }
01299
01300
01301
01302 bool
01303 pa_tls_referenced_p (rtx x)
01304 {
01305 if (!TARGET_HAVE_TLS)
01306 return false;
01307
01308 return for_each_rtx (&x, &pa_tls_symbol_ref_1, 0);
01309 }
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321 int
01322 emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
01323 {
01324 register rtx operand0 = operands[0];
01325 register rtx operand1 = operands[1];
01326 register rtx tem;
01327
01328
01329
01330
01331 if (GET_CODE (operand0) == MEM && IS_INDEX_ADDR_P (XEXP (operand0, 0)))
01332 {
01333
01334 gcc_assert (!no_new_pseudos);
01335
01336 tem = copy_to_mode_reg (Pmode, XEXP (operand0, 0));
01337 operand0 = replace_equiv_address (operand0, tem);
01338 }
01339
01340
01341
01342
01343
01344
01345
01346
01347 if (!TARGET_NO_SPACE_REGS
01348 && !cse_not_expected
01349 && GET_CODE (operand1) == MEM
01350 && GET_CODE (XEXP (operand1, 0)) == PLUS
01351 && REG_P (XEXP (XEXP (operand1, 0), 0))
01352 && REG_P (XEXP (XEXP (operand1, 0), 1)))
01353 operand1
01354 = replace_equiv_address (operand1,
01355 copy_to_mode_reg (Pmode, XEXP (operand1, 0)));
01356
01357 if (scratch_reg
01358 && reload_in_progress && GET_CODE (operand0) == REG
01359 && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
01360 operand0 = reg_equiv_mem[REGNO (operand0)];
01361 else if (scratch_reg
01362 && reload_in_progress && GET_CODE (operand0) == SUBREG
01363 && GET_CODE (SUBREG_REG (operand0)) == REG
01364 && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
01365 {
01366
01367
01368 rtx temp = gen_rtx_SUBREG (GET_MODE (operand0),
01369 reg_equiv_mem [REGNO (SUBREG_REG (operand0))],
01370 SUBREG_BYTE (operand0));
01371 operand0 = alter_subreg (&temp);
01372 }
01373
01374 if (scratch_reg
01375 && reload_in_progress && GET_CODE (operand1) == REG
01376 && REGNO (operand1) >= FIRST_PSEUDO_REGISTER)
01377 operand1 = reg_equiv_mem[REGNO (operand1)];
01378 else if (scratch_reg
01379 && reload_in_progress && GET_CODE (operand1) == SUBREG
01380 && GET_CODE (SUBREG_REG (operand1)) == REG
01381 && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
01382 {
01383
01384
01385 rtx temp = gen_rtx_SUBREG (GET_MODE (operand1),
01386 reg_equiv_mem [REGNO (SUBREG_REG (operand1))],
01387 SUBREG_BYTE (operand1));
01388 operand1 = alter_subreg (&temp);
01389 }
01390
01391 if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
01392 && ((tem = find_replacement (&XEXP (operand0, 0)))
01393 != XEXP (operand0, 0)))
01394 operand0 = replace_equiv_address (operand0, tem);
01395
01396 if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
01397 && ((tem = find_replacement (&XEXP (operand1, 0)))
01398 != XEXP (operand1, 0)))
01399 operand1 = replace_equiv_address (operand1, tem);
01400
01401
01402
01403
01404 if (scratch_reg
01405 && fp_reg_operand (operand0, mode)
01406 && ((GET_CODE (operand1) == MEM
01407 && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode),
01408 XEXP (operand1, 0)))
01409 || ((GET_CODE (operand1) == SUBREG
01410 && GET_CODE (XEXP (operand1, 0)) == MEM
01411 && !memory_address_p ((GET_MODE_SIZE (mode) == 4
01412 ? SFmode : DFmode),
01413 XEXP (XEXP (operand1, 0), 0))))))
01414 {
01415 if (GET_CODE (operand1) == SUBREG)
01416 operand1 = XEXP (operand1, 0);
01417
01418
01419
01420
01421 scratch_reg = force_mode (word_mode, scratch_reg);
01422
01423
01424
01425 if (!memory_address_p (Pmode, XEXP (operand1, 0)))
01426 {
01427 emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
01428 emit_move_insn (scratch_reg,
01429 gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),
01430 Pmode,
01431 XEXP (XEXP (operand1, 0), 0),
01432 scratch_reg));
01433 }
01434 else
01435 emit_move_insn (scratch_reg, XEXP (operand1, 0));
01436 emit_insn (gen_rtx_SET (VOIDmode, operand0,
01437 replace_equiv_address (operand1, scratch_reg)));
01438 return 1;
01439 }
01440 else if (scratch_reg
01441 && fp_reg_operand (operand1, mode)
01442 && ((GET_CODE (operand0) == MEM
01443 && !memory_address_p ((GET_MODE_SIZE (mode) == 4
01444 ? SFmode : DFmode),
01445 XEXP (operand0, 0)))
01446 || ((GET_CODE (operand0) == SUBREG)
01447 && GET_CODE (XEXP (operand0, 0)) == MEM
01448 && !memory_address_p ((GET_MODE_SIZE (mode) == 4
01449 ? SFmode : DFmode),
01450 XEXP (XEXP (operand0, 0), 0)))))
01451 {
01452 if (GET_CODE (operand0) == SUBREG)
01453 operand0 = XEXP (operand0, 0);
01454
01455
01456
01457
01458 scratch_reg = force_mode (word_mode, scratch_reg);
01459
01460
01461
01462 if (!memory_address_p (Pmode, XEXP (operand0, 0)))
01463 {
01464 emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));
01465 emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0,
01466 0)),
01467 Pmode,
01468 XEXP (XEXP (operand0, 0),
01469 0),
01470 scratch_reg));
01471 }
01472 else
01473 emit_move_insn (scratch_reg, XEXP (operand0, 0));
01474 emit_insn (gen_rtx_SET (VOIDmode,
01475 replace_equiv_address (operand0, scratch_reg),
01476 operand1));
01477 return 1;
01478 }
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488 else if (scratch_reg
01489 && CONSTANT_P (operand1)
01490 && fp_reg_operand (operand0, mode))
01491 {
01492 rtx const_mem, xoperands[2];
01493
01494
01495
01496
01497 scratch_reg = force_mode (word_mode, scratch_reg);
01498
01499
01500
01501 const_mem = force_const_mem (mode, operand1);
01502 xoperands[0] = scratch_reg;
01503 xoperands[1] = XEXP (const_mem, 0);
01504 emit_move_sequence (xoperands, Pmode, 0);
01505
01506
01507 emit_insn (gen_rtx_SET (mode, operand0,
01508 replace_equiv_address (const_mem, scratch_reg)));
01509 return 1;
01510 }
01511
01512
01513 else if (scratch_reg
01514 && GET_CODE (operand0) == REG
01515 && REGNO (operand0) < FIRST_PSEUDO_REGISTER
01516 && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS
01517 && (GET_CODE (operand1) == MEM
01518 || GET_CODE (operand1) == CONST_INT
01519 || (GET_CODE (operand1) == REG
01520 && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1))))))
01521 {
01522
01523
01524 if (GET_CODE (operand1) == MEM
01525 && !memory_address_p (Pmode, XEXP (operand1, 0)))
01526 {
01527
01528
01529 scratch_reg = force_mode (word_mode, scratch_reg);
01530
01531 emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
01532 emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1,
01533 0)),
01534 Pmode,
01535 XEXP (XEXP (operand1, 0),
01536 0),
01537 scratch_reg));
01538
01539
01540
01541
01542
01543 scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);
01544
01545 emit_move_insn (scratch_reg,
01546 replace_equiv_address (operand1, scratch_reg));
01547 }
01548 else
01549 {
01550
01551
01552 scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);
01553
01554 emit_move_insn (scratch_reg, operand1);
01555 }
01556
01557
01558
01559
01560 emit_move_insn (operand0, scratch_reg);
01561 return 1;
01562 }
01563
01564 else if (register_operand (operand0, mode))
01565 {
01566 if (register_operand (operand1, mode)
01567 || (GET_CODE (operand1) == CONST_INT
01568 && cint_ok_for_move (INTVAL (operand1)))
01569 || (operand1 == CONST0_RTX (mode))
01570 || (GET_CODE (operand1) == HIGH
01571 && !symbolic_operand (XEXP (operand1, 0), VOIDmode))
01572
01573 || GET_CODE (operand1) == MEM)
01574 {
01575
01576
01577
01578
01579
01580
01581 if (REG_P (operand0) && REG_P (operand1))
01582 {
01583 if (REG_POINTER (operand1)
01584 && !REG_POINTER (operand0)
01585 && !HARD_REGISTER_P (operand0))
01586 copy_reg_pointer (operand0, operand1);
01587 else if (REG_POINTER (operand0)
01588 && !REG_POINTER (operand1)
01589 && !HARD_REGISTER_P (operand1))
01590 copy_reg_pointer (operand1, operand0);
01591 }
01592
01593
01594
01595
01596 if (REG_P (operand0)
01597 && GET_CODE (operand1) == MEM
01598 && !REG_POINTER (operand0))
01599 {
01600 tree decl = MEM_EXPR (operand1);
01601
01602
01603
01604
01605
01606 if (decl
01607 && !(flag_argument_noalias > 1
01608 && TREE_CODE (decl) == INDIRECT_REF
01609 && TREE_CODE (TREE_OPERAND (decl, 0)) == PARM_DECL))
01610 {
01611 tree type;
01612
01613
01614
01615 if (TREE_CODE (decl) == COMPONENT_REF)
01616 decl = TREE_OPERAND (decl, 1);
01617
01618 type = TREE_TYPE (decl);
01619 if (TREE_CODE (type) == ARRAY_TYPE)
01620 type = get_inner_array_type (type);
01621
01622 if (POINTER_TYPE_P (type))
01623 {
01624 int align;
01625
01626 type = TREE_TYPE (type);
01627
01628
01629 align = (TYPE_ALIGN_OK (type) ? TYPE_ALIGN (type)
01630 : BITS_PER_UNIT);
01631 mark_reg_pointer (operand0, align);
01632 }
01633 }
01634 }
01635
01636 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
01637 return 1;
01638 }
01639 }
01640 else if (GET_CODE (operand0) == MEM)
01641 {
01642 if (mode == DFmode && operand1 == CONST0_RTX (mode)
01643 && !(reload_in_progress || reload_completed))
01644 {
01645 rtx temp = gen_reg_rtx (DFmode);
01646
01647 emit_insn (gen_rtx_SET (VOIDmode, temp, operand1));
01648 emit_insn (gen_rtx_SET (VOIDmode, operand0, temp));
01649 return 1;
01650 }
01651 if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode))
01652 {
01653
01654 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
01655 return 1;
01656 }
01657 if (! (reload_in_progress || reload_completed))
01658 {
01659 operands[0] = validize_mem (operand0);
01660 operands[1] = operand1 = force_reg (mode, operand1);
01661 }
01662 }
01663
01664
01665
01666
01667
01668 if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
01669 || function_label_operand (operand1, mode)
01670 || (GET_CODE (operand1) == HIGH
01671 && symbolic_operand (XEXP (operand1, 0), mode)))
01672 {
01673 int ishighonly = 0;
01674
01675 if (GET_CODE (operand1) == HIGH)
01676 {
01677 ishighonly = 1;
01678 operand1 = XEXP (operand1, 0);
01679 }
01680 if (symbolic_operand (operand1, mode))
01681 {
01682
01683
01684
01685
01686
01687 if ((GET_CODE (operand1) == CONST
01688 && GET_CODE (XEXP (operand1, 0)) == PLUS
01689 && function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode))
01690 || function_label_operand (operand1, mode))
01691 {
01692 rtx temp, const_part;
01693
01694
01695 if (reload_in_progress || reload_completed)
01696 {
01697 scratch_reg = scratch_reg ? scratch_reg : operand0;
01698
01699
01700
01701 scratch_reg = force_mode (word_mode, scratch_reg);
01702 }
01703 else if (flag_pic)
01704 scratch_reg = gen_reg_rtx (Pmode);
01705
01706 if (GET_CODE (operand1) == CONST)
01707 {
01708
01709 const_part = XEXP (XEXP (operand1, 0), 1);
01710 gcc_assert (GET_CODE (const_part) == CONST_INT);
01711
01712
01713 temp = force_const_mem (mode, XEXP (XEXP (operand1, 0), 0));
01714 }
01715 else
01716 {
01717
01718 const_part = NULL_RTX;
01719
01720
01721 temp = force_const_mem (mode, operand1);
01722 }
01723
01724
01725
01726
01727 temp = XEXP (temp, 0);
01728 if (flag_pic)
01729 temp = legitimize_pic_address (temp, mode, scratch_reg);
01730
01731
01732
01733 operands[1] = temp;
01734 emit_move_sequence (operands, mode, scratch_reg);
01735
01736
01737
01738 operands[1] = gen_rtx_MEM (Pmode, operands[0]);
01739 emit_move_sequence (operands, mode, scratch_reg);
01740
01741
01742 if (const_part != NULL_RTX)
01743 expand_inc (operand0, const_part);
01744
01745 return 1;
01746 }
01747
01748 if (flag_pic)
01749 {
01750 rtx temp;
01751
01752 if (reload_in_progress || reload_completed)
01753 {
01754 temp = scratch_reg ? scratch_reg : operand0;
01755
01756
01757
01758 temp = force_mode (word_mode, temp);
01759 }
01760 else
01761 temp = gen_reg_rtx (Pmode);
01762
01763
01764
01765
01766 if (GET_CODE (operand1) == CONST
01767 && GET_CODE (XEXP (operand1, 0)) == PLUS
01768 && GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT
01769 && !INT_14_BITS (XEXP (XEXP (operand1, 0), 1))
01770 && (reload_completed || reload_in_progress)
01771 && flag_pic)
01772 {
01773 rtx const_mem = force_const_mem (mode, operand1);
01774 operands[1] = legitimize_pic_address (XEXP (const_mem, 0),
01775 mode, temp);
01776 operands[1] = replace_equiv_address (const_mem, operands[1]);
01777 emit_move_sequence (operands, mode, temp);
01778 }
01779 else
01780 {
01781 operands[1] = legitimize_pic_address (operand1, mode, temp);
01782 if (REG_P (operand0) && REG_P (operands[1]))
01783 copy_reg_pointer (operand0, operands[1]);
01784 emit_insn (gen_rtx_SET (VOIDmode, operand0, operands[1]));
01785 }
01786 }
01787
01788
01789
01790 else
01791 {
01792 rtx temp, set;
01793
01794 if (reload_in_progress || reload_completed)
01795 {
01796 temp = scratch_reg ? scratch_reg : operand0;
01797
01798
01799
01800 temp = force_mode (word_mode, temp);
01801 }
01802 else
01803 temp = gen_reg_rtx (mode);
01804
01805
01806
01807
01808
01809 if (GET_CODE (operand0) == REG
01810 && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
01811 mark_reg_pointer (operand0, BITS_PER_UNIT);
01812 if (REGNO (temp) >= FIRST_PSEUDO_REGISTER)
01813 mark_reg_pointer (temp, BITS_PER_UNIT);
01814
01815 if (ishighonly)
01816 set = gen_rtx_SET (mode, operand0, temp);
01817 else
01818 set = gen_rtx_SET (VOIDmode,
01819 operand0,
01820 gen_rtx_LO_SUM (mode, temp, operand1));
01821
01822 emit_insn (gen_rtx_SET (VOIDmode,
01823 temp,
01824 gen_rtx_HIGH (mode, operand1)));
01825 emit_insn (set);
01826
01827 }
01828 return 1;
01829 }
01830 else if (pa_tls_referenced_p (operand1))
01831 {
01832 rtx tmp = operand1;
01833 rtx addend = NULL;
01834
01835 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
01836 {
01837 addend = XEXP (XEXP (tmp, 0), 1);
01838 tmp = XEXP (XEXP (tmp, 0), 0);
01839 }
01840
01841 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
01842 tmp = legitimize_tls_address (tmp);
01843 if (addend)
01844 {
01845 tmp = gen_rtx_PLUS (mode, tmp, addend);
01846 tmp = force_operand (tmp, operands[0]);
01847 }
01848 operands[1] = tmp;
01849 }
01850 else if (GET_CODE (operand1) != CONST_INT
01851 || !cint_ok_for_move (INTVAL (operand1)))
01852 {
01853 rtx insn, temp;
01854 rtx op1 = operand1;
01855 HOST_WIDE_INT value = 0;
01856 HOST_WIDE_INT insv = 0;
01857 int insert = 0;
01858
01859 if (GET_CODE (operand1) == CONST_INT)
01860 value = INTVAL (operand1);
01861
01862 if (TARGET_64BIT
01863 && GET_CODE (operand1) == CONST_INT
01864 && HOST_BITS_PER_WIDE_INT > 32
01865 && GET_MODE_BITSIZE (GET_MODE (operand0)) > 32)
01866 {
01867 HOST_WIDE_INT nval;
01868
01869
01870
01871
01872
01873
01874 nval = ((value & (((HOST_WIDE_INT) 2 << 31) - 1))
01875 ^ ((HOST_WIDE_INT) 1 << 31)) - ((HOST_WIDE_INT) 1 << 31);
01876 if (value != nval)
01877 {
01878 #if HOST_BITS_PER_WIDE_INT > 32
01879 insv = value >= 0 ? value >> 32 : ~(~value >> 32);
01880 #endif
01881 insert = 1;
01882 value = nval;
01883 operand1 = GEN_INT (nval);
01884 }
01885 }
01886
01887 if (reload_in_progress || reload_completed)
01888 temp = scratch_reg ? scratch_reg : operand0;
01889 else
01890 temp = gen_reg_rtx (mode);
01891
01892
01893
01894
01895 if (GET_CODE (operand1) == CONST_INT
01896 && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD
01897 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
01898 && !insert)
01899 {
01900
01901
01902
01903
01904
01905
01906 HOST_WIDE_INT low = value & 0x3fff;
01907 HOST_WIDE_INT high = value & ~ 0x3fff;
01908
01909 if (low >= 0x2000)
01910 {
01911 if (high == 0x7fffc000 || (mode == HImode && high == 0x4000))
01912 high += 0x2000;
01913 else
01914 high += 0x4000;
01915 }
01916
01917 low = value - high;
01918
01919 emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (high)));
01920 operands[1] = gen_rtx_PLUS (mode, temp, GEN_INT (low));
01921 }
01922 else
01923 {
01924 emit_insn (gen_rtx_SET (VOIDmode, temp,
01925 gen_rtx_HIGH (mode, operand1)));
01926 operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
01927 }
01928
01929 insn = emit_move_insn (operands[0], operands[1]);
01930
01931
01932
01933
01934
01935
01936
01937
01938 if (insert)
01939 {
01940
01941
01942
01943 if (temp != operand0 && (insv >= 16384 || insv < -16384))
01944 {
01945 operand1 = GEN_INT (insv);
01946
01947 emit_insn (gen_rtx_SET (VOIDmode, temp,
01948 gen_rtx_HIGH (mode, operand1)));
01949 emit_move_insn (temp, gen_rtx_LO_SUM (mode, temp, operand1));
01950 emit_insn (gen_insv (operand0, GEN_INT (32),
01951 const0_rtx, temp));
01952 }
01953 else
01954 {
01955 int len = 5, pos = 27;
01956
01957
01958 while (pos >= 0)
01959 {
01960 HOST_WIDE_INT v5 = ((insv & 31) ^ 16) - 16;
01961 HOST_WIDE_INT sign = v5 < 0;
01962
01963
01964 insv = (insv >= 0 ? insv >> len : ~(~insv >> len));
01965 while (pos > 0 && (insv & 1) == sign)
01966 {
01967 insv = (insv >= 0 ? insv >> 1 : ~(~insv >> 1));
01968 len += 1;
01969 pos -= 1;
01970 }
01971
01972 emit_insn (gen_insv (operand0, GEN_INT (len),
01973 GEN_INT (pos), GEN_INT (v5)));
01974
01975 len = pos > 0 && pos < 5 ? pos : 5;
01976 pos -= len;
01977 }
01978 }
01979 }
01980
01981 REG_NOTES (insn)
01982 = gen_rtx_EXPR_LIST (REG_EQUAL, op1, REG_NOTES (insn));
01983
01984 return 1;
01985 }
01986 }
01987
01988 return 0;
01989 }
01990
01991
01992
01993
01994 int
01995 reloc_needed (tree exp)
01996 {
01997 int reloc = 0;
01998
01999 switch (TREE_CODE (exp))
02000 {
02001 case ADDR_EXPR:
02002 return 1;
02003
02004 case PLUS_EXPR:
02005 case MINUS_EXPR:
02006 reloc = reloc_needed (TREE_OPERAND (exp, 0));
02007 reloc |= reloc_needed (TREE_OPERAND (exp, 1));
02008 break;
02009
02010 case NOP_EXPR:
02011 case CONVERT_EXPR:
02012 case NON_LVALUE_EXPR:
02013 reloc = reloc_needed (TREE_OPERAND (exp, 0));
02014 break;
02015
02016 case CONSTRUCTOR:
02017 {
02018 tree value;
02019 unsigned HOST_WIDE_INT ix;
02020
02021 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), ix, value)
02022 if (value)
02023 reloc |= reloc_needed (value);
02024 }
02025 break;
02026
02027 case ERROR_MARK:
02028 break;
02029
02030 default:
02031 break;
02032 }
02033 return reloc;
02034 }
02035
02036
02037
02038
02039
02040 int
02041 read_only_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
02042 {
02043 if (GET_CODE (operand) == CONST)
02044 operand = XEXP (XEXP (operand, 0), 0);
02045 if (flag_pic)
02046 {
02047 if (GET_CODE (operand) == SYMBOL_REF)
02048 return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand);
02049 }
02050 else
02051 {
02052 if (GET_CODE (operand) == SYMBOL_REF)
02053 return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
02054 }
02055 return 1;
02056 }
02057
02058
02059
02060
02061 const char *
02062 singlemove_string (rtx *operands)
02063 {
02064 HOST_WIDE_INT intval;
02065
02066 if (GET_CODE (operands[0]) == MEM)
02067 return "stw %r1,%0";
02068 if (GET_CODE (operands[1]) == MEM)
02069 return "ldw %1,%0";
02070 if (GET_CODE (operands[1]) == CONST_DOUBLE)
02071 {
02072 long i;
02073 REAL_VALUE_TYPE d;
02074
02075 gcc_assert (GET_MODE (operands[1]) == SFmode);
02076
02077
02078
02079 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[1]);
02080 REAL_VALUE_TO_TARGET_SINGLE (d, i);
02081
02082 operands[1] = GEN_INT (i);
02083
02084 }
02085 if (GET_CODE (operands[1]) == CONST_INT)
02086 {
02087 intval = INTVAL (operands[1]);
02088
02089 if (VAL_14_BITS_P (intval))
02090 return "ldi %1,%0";
02091 else if ((intval & 0x7ff) == 0)
02092 return "ldil L'%1,%0";
02093 else if (zdepi_cint_p (intval))
02094 return "{zdepi %Z1,%0|depwi,z %Z1,%0}";
02095 else
02096 return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
02097 }
02098 return "copy %1,%0";
02099 }
02100
02101
02102
02103
02104
02105 static void
02106 compute_zdepwi_operands (unsigned HOST_WIDE_INT imm, unsigned *op)
02107 {
02108 int lsb, len;
02109
02110
02111 for (lsb = 0; lsb < 32; lsb++)
02112 {
02113 if ((imm & 1) != 0)
02114 break;
02115 imm >>= 1;
02116 }
02117
02118
02119 if ((imm & 0x10) == 0)
02120 len = (lsb <= 28) ? 4 : 32 - lsb;
02121 else
02122 {
02123
02124 for (len = 5; len < 32; len++)
02125 {
02126 if ((imm & (1 << len)) == 0)
02127 break;
02128 }
02129
02130
02131 imm = (imm & 0xf) - 0x10;
02132 }
02133
02134 op[0] = imm;
02135 op[1] = 31 - lsb;
02136 op[2] = len;
02137 }
02138
02139
02140
02141
02142 void
02143 compute_zdepdi_operands (unsigned HOST_WIDE_INT imm, unsigned *op)
02144 {
02145 HOST_WIDE_INT lsb, len;
02146
02147
02148 for (lsb = 0; lsb < HOST_BITS_PER_WIDE_INT; lsb++)
02149 {
02150 if ((imm & 1) != 0)
02151 break;
02152 imm >>= 1;
02153 }
02154
02155
02156 if ((imm & 0x10) == 0)
02157 len = ((lsb <= HOST_BITS_PER_WIDE_INT - 4)
02158 ? 4 : HOST_BITS_PER_WIDE_INT - lsb);
02159 else
02160 {
02161
02162 for (len = 5; len < HOST_BITS_PER_WIDE_INT; len++)
02163 {
02164 if ((imm & ((unsigned HOST_WIDE_INT) 1 << len)) == 0)
02165 break;
02166 }
02167
02168
02169 imm = (imm & 0xf) - 0x10;
02170 }
02171
02172 op[0] = imm;
02173 op[1] = 63 - lsb;
02174 op[2] = len;
02175 }
02176
02177
02178
02179
02180 const char *
02181 output_move_double (rtx *operands)
02182 {
02183 enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
02184 rtx latehalf[2];
02185 rtx addreg0 = 0, addreg1 = 0;
02186
02187
02188
02189 if (REG_P (operands[0]))
02190 optype0 = REGOP;
02191 else if (offsettable_memref_p (operands[0]))
02192 optype0 = OFFSOP;
02193 else if (GET_CODE (operands[0]) == MEM)
02194 optype0 = MEMOP;
02195 else
02196 optype0 = RNDOP;
02197
02198 if (REG_P (operands[1]))
02199 optype1 = REGOP;
02200 else if (CONSTANT_P (operands[1]))
02201 optype1 = CNSTOP;
02202 else if (offsettable_memref_p (operands[1]))
02203 optype1 = OFFSOP;
02204 else if (GET_CODE (operands[1]) == MEM)
02205 optype1 = MEMOP;
02206 else
02207 optype1 = RNDOP;
02208
02209
02210
02211 gcc_assert (optype0 == REGOP || optype1 == REGOP);
02212
02213
02214
02215 if (optype0 == REGOP && optype1 == REGOP
02216 && FP_REG_P (operands[0]) ^ FP_REG_P (operands[1]))
02217 {
02218 if (FP_REG_P (operands[0]))
02219 {
02220 output_asm_insn ("{stws|stw} %1,-16(%%sp)", operands);
02221 output_asm_insn ("{stws|stw} %R1,-12(%%sp)", operands);
02222 return "{fldds|fldd} -16(%%sp),%0";
02223 }
02224 else
02225 {
02226 output_asm_insn ("{fstds|fstd} %1,-16(%%sp)", operands);
02227 output_asm_insn ("{ldws|ldw} -16(%%sp),%0", operands);
02228 return "{ldws|ldw} -12(%%sp),%R0";
02229 }
02230 }
02231
02232
02233
02234
02235
02236
02237
02238 if (optype0 == MEMOP)
02239 {
02240
02241
02242
02243 rtx addr = XEXP (operands[0], 0);
02244 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
02245 {
02246 rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);
02247
02248 operands[0] = XEXP (addr, 0);
02249 gcc_assert (GET_CODE (operands[1]) == REG
02250 && GET_CODE (operands[0]) == REG);
02251
02252 gcc_assert (!reg_overlap_mentioned_p (high_reg, addr));
02253
02254
02255
02256
02257 if (GET_CODE (addr) == POST_INC)
02258 return "{stws|stw},ma %1,8(%0)\n\tstw %R1,-4(%0)";
02259 return "{stws|stw},ma %1,-8(%0)\n\tstw %R1,12(%0)";
02260 }
02261 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
02262 {
02263 rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);
02264
02265 operands[0] = XEXP (addr, 0);
02266 gcc_assert (GET_CODE (operands[1]) == REG
02267 && GET_CODE (operands[0]) == REG);
02268
02269 gcc_assert (!reg_overlap_mentioned_p (high_reg, addr));
02270
02271
02272
02273 if (GET_CODE (addr) == PRE_INC)
02274 return "{stws|stw},mb %1,8(%0)\n\tstw %R1,4(%0)";
02275 return "{stws|stw},mb %1,-8(%0)\n\tstw %R1,4(%0)";
02276 }
02277 }
02278 if (optype1 == MEMOP)
02279 {
02280
02281
02282
02283 rtx addr = XEXP (operands[1], 0);
02284 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
02285 {
02286 rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02287
02288 operands[1] = XEXP (addr, 0);
02289 gcc_assert (GET_CODE (operands[0]) == REG
02290 && GET_CODE (operands[1]) == REG);
02291
02292 if (!reg_overlap_mentioned_p (high_reg, addr))
02293 {
02294
02295
02296
02297 if (GET_CODE (addr) == POST_INC)
02298 return "{ldws|ldw},ma 8(%1),%0\n\tldw -4(%1),%R0";
02299 return "{ldws|ldw},ma -8(%1),%0\n\tldw 12(%1),%R0";
02300 }
02301 else
02302 {
02303
02304
02305
02306 if (GET_CODE (addr) == POST_INC)
02307 return "ldw 4(%1),%R0\n\t{ldws|ldw},ma 8(%1),%0";
02308 return "ldw 4(%1),%R0\n\t{ldws|ldw},ma -8(%1),%0";
02309 }
02310 }
02311 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
02312 {
02313 rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02314
02315 operands[1] = XEXP (addr, 0);
02316 gcc_assert (GET_CODE (operands[0]) == REG
02317 && GET_CODE (operands[1]) == REG);
02318
02319 if (!reg_overlap_mentioned_p (high_reg, addr))
02320 {
02321
02322
02323
02324 if (GET_CODE (addr) == PRE_INC)
02325 return "{ldws|ldw},mb 8(%1),%0\n\tldw 4(%1),%R0";
02326 return "{ldws|ldw},mb -8(%1),%0\n\tldw 4(%1),%R0";
02327 }
02328 else
02329 {
02330
02331
02332
02333 if (GET_CODE (addr) == PRE_INC)
02334 return "ldw 12(%1),%R0\n\t{ldws|ldw},mb 8(%1),%0";
02335 return "ldw -4(%1),%R0\n\t{ldws|ldw},mb -8(%1),%0";
02336 }
02337 }
02338 else if (GET_CODE (addr) == PLUS
02339 && GET_CODE (XEXP (addr, 0)) == MULT)
02340 {
02341 rtx xoperands[4];
02342 rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02343
02344 if (!reg_overlap_mentioned_p (high_reg, addr))
02345 {
02346 xoperands[0] = high_reg;
02347 xoperands[1] = XEXP (addr, 1);
02348 xoperands[2] = XEXP (XEXP (addr, 0), 0);
02349 xoperands[3] = XEXP (XEXP (addr, 0), 1);
02350 output_asm_insn ("{sh%O3addl %2,%1,%0|shladd,l %2,%O3,%1,%0}",
02351 xoperands);
02352 return "ldw 4(%0),%R0\n\tldw 0(%0),%0";
02353 }
02354 else
02355 {
02356 xoperands[0] = high_reg;
02357 xoperands[1] = XEXP (addr, 1);
02358 xoperands[2] = XEXP (XEXP (addr, 0), 0);
02359 xoperands[3] = XEXP (XEXP (addr, 0), 1);
02360 output_asm_insn ("{sh%O3addl %2,%1,%R0|shladd,l %2,%O3,%1,%R0}",
02361 xoperands);
02362 return "ldw 0(%R0),%0\n\tldw 4(%R0),%R0";
02363 }
02364 }
02365 }
02366
02367
02368
02369
02370 if (optype0 == MEMOP)
02371 addreg0 = find_addr_reg (XEXP (operands[0], 0));
02372
02373 if (optype1 == MEMOP)
02374 addreg1 = find_addr_reg (XEXP (operands[1], 0));
02375
02376
02377
02378
02379
02380
02381
02382
02383 if (optype0 == REGOP)
02384 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
02385 else if (optype0 == OFFSOP)
02386 latehalf[0] = adjust_address (operands[0], SImode, 4);
02387 else
02388 latehalf[0] = operands[0];
02389
02390 if (optype1 == REGOP)
02391 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
02392 else if (optype1 == OFFSOP)
02393 latehalf[1] = adjust_address (operands[1], SImode, 4);
02394 else if (optype1 == CNSTOP)
02395 split_double (operands[1], &operands[1], &latehalf[1]);
02396 else
02397 latehalf[1] = operands[1];
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415 if (optype0 == REGOP
02416 && (optype1 == MEMOP || optype1 == OFFSOP)
02417 && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
02418 operands[1], 0))
02419 {
02420
02421 if (addreg1)
02422 output_asm_insn ("ldo 4(%0),%0", &addreg1);
02423 output_asm_insn (singlemove_string (latehalf), latehalf);
02424
02425
02426 if (addreg1)
02427 output_asm_insn ("ldo -4(%0),%0", &addreg1);
02428 return singlemove_string (operands);
02429 }
02430
02431
02432 if (optype0 == REGOP && optype1 == REGOP
02433 && REGNO (operands[0]) == REGNO (operands[1]) + 1)
02434 {
02435 output_asm_insn (singlemove_string (latehalf), latehalf);
02436 return singlemove_string (operands);
02437 }
02438
02439
02440
02441 output_asm_insn (singlemove_string (operands), operands);
02442
02443
02444 if (addreg0)
02445 output_asm_insn ("ldo 4(%0),%0", &addreg0);
02446 if (addreg1)
02447 output_asm_insn ("ldo 4(%0),%0", &addreg1);
02448
02449
02450 output_asm_insn (singlemove_string (latehalf), latehalf);
02451
02452
02453 if (addreg0)
02454 output_asm_insn ("ldo -4(%0),%0", &addreg0);
02455 if (addreg1)
02456 output_asm_insn ("ldo -4(%0),%0", &addreg1);
02457
02458 return "";
02459 }
02460
02461 const char *
02462 output_fp_move_double (rtx *operands)
02463 {
02464 if (FP_REG_P (operands[0]))
02465 {
02466 if (FP_REG_P (operands[1])
02467 || operands[1] == CONST0_RTX (GET_MODE (operands[0])))
02468 output_asm_insn ("fcpy,dbl %f1,%0", operands);
02469 else
02470 output_asm_insn ("fldd%F1 %1,%0", operands);
02471 }
02472 else if (FP_REG_P (operands[1]))
02473 {
02474 output_asm_insn ("fstd%F0 %1,%0", operands);
02475 }
02476 else
02477 {
02478 rtx xoperands[2];
02479
02480 gcc_assert (operands[1] == CONST0_RTX (GET_MODE (operands[0])));
02481
02482
02483
02484
02485
02486 gcc_assert (GET_CODE (operands[0]) == REG);
02487
02488 xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
02489 xoperands[0] = operands[0];
02490 output_asm_insn ("copy %%r0,%0\n\tcopy %%r0,%1", xoperands);
02491 }
02492 return "";
02493 }
02494
02495
02496
02497
02498 static rtx
02499 find_addr_reg (rtx addr)
02500 {
02501 while (GET_CODE (addr) == PLUS)
02502 {
02503 if (GET_CODE (XEXP (addr, 0)) == REG)
02504 addr = XEXP (addr, 0);
02505 else if (GET_CODE (XEXP (addr, 1)) == REG)
02506 addr = XEXP (addr, 1);
02507 else if (CONSTANT_P (XEXP (addr, 0)))
02508 addr = XEXP (addr, 1);
02509 else if (CONSTANT_P (XEXP (addr, 1)))
02510 addr = XEXP (addr, 0);
02511 else
02512 gcc_unreachable ();
02513 }
02514 gcc_assert (GET_CODE (addr) == REG);
02515 return addr;
02516 }
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528 const char *
02529 output_block_move (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
02530 {
02531 int align = INTVAL (operands[5]);
02532 unsigned long n_bytes = INTVAL (operands[4]);
02533
02534
02535
02536 if (align > (TARGET_64BIT ? 8 : 4))
02537 align = (TARGET_64BIT ? 8 : 4);
02538
02539
02540
02541 switch (align)
02542 {
02543 case 8:
02544
02545 operands[4] = GEN_INT (n_bytes - 16);
02546 output_asm_insn ("ldi %4,%2", operands);
02547
02548
02549 output_asm_insn ("ldd,ma 8(%1),%3", operands);
02550 output_asm_insn ("ldd,ma 8(%1),%6", operands);
02551 output_asm_insn ("std,ma %3,8(%0)", operands);
02552 output_asm_insn ("addib,>= -16,%2,.-12", operands);
02553 output_asm_insn ("std,ma %6,8(%0)", operands);
02554
02555
02556
02557 if (n_bytes % 16 != 0)
02558 {
02559 operands[4] = GEN_INT (n_bytes % 8);
02560 if (n_bytes % 16 >= 8)
02561 output_asm_insn ("ldd,ma 8(%1),%3", operands);
02562 if (n_bytes % 8 != 0)
02563 output_asm_insn ("ldd 0(%1),%6", operands);
02564 if (n_bytes % 16 >= 8)
02565 output_asm_insn ("std,ma %3,8(%0)", operands);
02566 if (n_bytes % 8 != 0)
02567 output_asm_insn ("stdby,e %6,%4(%0)", operands);
02568 }
02569 return "";
02570
02571 case 4:
02572
02573 operands[4] = GEN_INT (n_bytes - 8);
02574 output_asm_insn ("ldi %4,%2", operands);
02575
02576
02577 output_asm_insn ("{ldws|ldw},ma 4(%1),%3", operands);
02578 output_asm_insn ("{ldws|ldw},ma 4(%1),%6", operands);
02579 output_asm_insn ("{stws|stw},ma %3,4(%0)", operands);
02580 output_asm_insn ("addib,>= -8,%2,.-12", operands);
02581 output_asm_insn ("{stws|stw},ma %6,4(%0)", operands);
02582
02583
02584
02585 if (n_bytes % 8 != 0)
02586 {
02587 operands[4] = GEN_INT (n_bytes % 4);
02588 if (n_bytes % 8 >= 4)
02589 output_asm_insn ("{ldws|ldw},ma 4(%1),%3", operands);
02590 if (n_bytes % 4 != 0)
02591 output_asm_insn ("ldw 0(%1),%6", operands);
02592 if (n_bytes % 8 >= 4)
02593 output_asm_insn ("{stws|stw},ma %3,4(%0)", operands);
02594 if (n_bytes % 4 != 0)
02595 output_asm_insn ("{stbys|stby},e %6,%4(%0)", operands);
02596 }
02597 return "";
02598
02599 case 2:
02600
02601 operands[4] = GEN_INT (n_bytes - 4);
02602 output_asm_insn ("ldi %4,%2", operands);
02603
02604
02605 output_asm_insn ("{ldhs|ldh},ma 2(%1),%3", operands);
02606 output_asm_insn ("{ldhs|ldh},ma 2(%1),%6", operands);
02607 output_asm_insn ("{sths|sth},ma %3,2(%0)", operands);
02608 output_asm_insn ("addib,>= -4,%2,.-12", operands);
02609 output_asm_insn ("{sths|sth},ma %6,2(%0)", operands);
02610
02611
02612 if (n_bytes % 4 != 0)
02613 {
02614 if (n_bytes % 4 >= 2)
02615 output_asm_insn ("{ldhs|ldh},ma 2(%1),%3", operands);
02616 if (n_bytes % 2 != 0)
02617 output_asm_insn ("ldb 0(%1),%6", operands);
02618 if (n_bytes % 4 >= 2)
02619 output_asm_insn ("{sths|sth},ma %3,2(%0)", operands);
02620 if (n_bytes % 2 != 0)
02621 output_asm_insn ("stb %6,0(%0)", operands);
02622 }
02623 return "";
02624
02625 case 1:
02626
02627 operands[4] = GEN_INT (n_bytes - 2);
02628 output_asm_insn ("ldi %4,%2", operands);
02629
02630
02631 output_asm_insn ("{ldbs|ldb},ma 1(%1),%3", operands);
02632 output_asm_insn ("{ldbs|ldb},ma 1(%1),%6", operands);
02633 output_asm_insn ("{stbs|stb},ma %3,1(%0)", operands);
02634 output_asm_insn ("addib,>= -2,%2,.-12", operands);
02635 output_asm_insn ("{stbs|stb},ma %6,1(%0)", operands);
02636
02637
02638 if (n_bytes % 2 != 0)
02639 {
02640 output_asm_insn ("ldb 0(%1),%3", operands);
02641 output_asm_insn ("stb %3,0(%0)", operands);
02642 }
02643 return "";
02644
02645 default:
02646 gcc_unreachable ();
02647 }
02648 }
02649
02650
02651
02652
02653
02654
02655 static int
02656 compute_movmem_length (rtx insn)
02657 {
02658 rtx pat = PATTERN (insn);
02659 unsigned int align = INTVAL (XEXP (XVECEXP (pat, 0, 7), 0));
02660 unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0));
02661 unsigned int n_insns = 0;
02662
02663
02664
02665 if (align > (TARGET_64BIT ? 8 : 4))
02666 align = (TARGET_64BIT ? 8 : 4);
02667
02668
02669 n_insns = 6;
02670
02671
02672 if (n_bytes % (2 * align) != 0)
02673 {
02674 if ((n_bytes % (2 * align)) >= align)
02675 n_insns += 2;
02676
02677 if ((n_bytes % align) != 0)
02678 n_insns += 2;
02679 }
02680
02681
02682 return n_insns * 4;
02683 }
02684
02685
02686
02687
02688
02689
02690
02691
02692 const char *
02693 output_block_clear (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
02694 {
02695 int align = INTVAL (operands[3]);
02696 unsigned long n_bytes = INTVAL (operands[2]);
02697
02698
02699
02700 if (align > (TARGET_64BIT ? 8 : 4))
02701 align = (TARGET_64BIT ? 8 : 4);
02702
02703
02704
02705 switch (align)
02706 {
02707 case 8:
02708
02709 operands[2] = GEN_INT (n_bytes - 16);
02710 output_asm_insn ("ldi %2,%1", operands);
02711
02712
02713 output_asm_insn ("std,ma %%r0,8(%0)", operands);
02714 output_asm_insn ("addib,>= -16,%1,.-4", operands);
02715 output_asm_insn ("std,ma %%r0,8(%0)", operands);
02716
02717
02718
02719 if (n_bytes % 16 != 0)
02720 {
02721 operands[2] = GEN_INT (n_bytes % 8);
02722 if (n_bytes % 16 >= 8)
02723 output_asm_insn ("std,ma %%r0,8(%0)", operands);
02724 if (n_bytes % 8 != 0)
02725 output_asm_insn ("stdby,e %%r0,%2(%0)", operands);
02726 }
02727 return "";
02728
02729 case 4:
02730
02731 operands[2] = GEN_INT (n_bytes - 8);
02732 output_asm_insn ("ldi %2,%1", operands);
02733
02734
02735 output_asm_insn ("{stws|stw},ma %%r0,4(%0)", operands);
02736 output_asm_insn ("addib,>= -8,%1,.-4", operands);
02737 output_asm_insn ("{stws|stw},ma %%r0,4(%0)", operands);
02738
02739
02740
02741 if (n_bytes % 8 != 0)
02742 {
02743 operands[2] = GEN_INT (n_bytes % 4);
02744 if (n_bytes % 8 >= 4)
02745 output_asm_insn ("{stws|stw},ma %%r0,4(%0)", operands);
02746 if (n_bytes % 4 != 0)
02747 output_asm_insn ("{stbys|stby},e %%r0,%2(%0)", operands);
02748 }
02749 return "";
02750
02751 case 2:
02752
02753 operands[2] = GEN_INT (n_bytes - 4);
02754 output_asm_insn ("ldi %2,%1", operands);
02755
02756
02757 output_asm_insn ("{sths|sth},ma %%r0,2(%0)", operands);
02758 output_asm_insn ("addib,>= -4,%1,.-4", operands);
02759 output_asm_insn ("{sths|sth},ma %%r0,2(%0)", operands);
02760
02761
02762 if (n_bytes % 4 != 0)
02763 {
02764 if (n_bytes % 4 >= 2)
02765 output_asm_insn ("{sths|sth},ma %%r0,2(%0)", operands);
02766 if (n_bytes % 2 != 0)
02767 output_asm_insn ("stb %%r0,0(%0)", operands);
02768 }
02769 return "";
02770
02771 case 1:
02772
02773 operands[2] = GEN_INT (n_bytes - 2);
02774 output_asm_insn ("ldi %2,%1", operands);
02775
02776
02777 output_asm_insn ("{stbs|stb},ma %%r0,1(%0)", operands);
02778 output_asm_insn ("addib,>= -2,%1,.-4", operands);
02779 output_asm_insn ("{stbs|stb},ma %%r0,1(%0)", operands);
02780
02781
02782 if (n_bytes % 2 != 0)
02783 output_asm_insn ("stb %%r0,0(%0)", operands);
02784
02785 return "";
02786
02787 default:
02788 gcc_unreachable ();
02789 }
02790 }
02791
02792
02793
02794
02795
02796
02797 static int
02798 compute_clrmem_length (rtx insn)
02799 {
02800 rtx pat = PATTERN (insn);
02801 unsigned int align = INTVAL (XEXP (XVECEXP (pat, 0, 4), 0));
02802 unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 3), 0));
02803 unsigned int n_insns = 0;
02804
02805
02806
02807 if (align > (TARGET_64BIT ? 8 : 4))
02808 align = (TARGET_64BIT ? 8 : 4);
02809
02810
02811 n_insns = 4;
02812
02813
02814 if (n_bytes % (2 * align) != 0)
02815 {
02816 if ((n_bytes % (2 * align)) >= align)
02817 n_insns++;
02818
02819 if ((n_bytes % align) != 0)
02820 n_insns++;
02821 }
02822
02823
02824 return n_insns * 4;
02825 }
02826
02827
02828 const char *
02829 output_and (rtx *operands)
02830 {
02831 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
02832 {
02833 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02834 int ls0, ls1, ms0, p, len;
02835
02836 for (ls0 = 0; ls0 < 32; ls0++)
02837 if ((mask & (1 << ls0)) == 0)
02838 break;
02839
02840 for (ls1 = ls0; ls1 < 32; ls1++)
02841 if ((mask & (1 << ls1)) != 0)
02842 break;
02843
02844 for (ms0 = ls1; ms0 < 32; ms0++)
02845 if ((mask & (1 << ms0)) == 0)
02846 break;
02847
02848 gcc_assert (ms0 == 32);
02849
02850 if (ls1 == 32)
02851 {
02852 len = ls0;
02853
02854 gcc_assert (len);
02855
02856 operands[2] = GEN_INT (len);
02857 return "{extru|extrw,u} %1,31,%2,%0";
02858 }
02859 else
02860 {
02861
02862
02863
02864 p = 31 - ls0;
02865 len = ls1 - ls0;
02866
02867 operands[2] = GEN_INT (p);
02868 operands[3] = GEN_INT (len);
02869 return "{depi|depwi} 0,%2,%3,%0";
02870 }
02871 }
02872 else
02873 return "and %1,%2,%0";
02874 }
02875
02876
02877
02878 const char *
02879 output_64bit_and (rtx *operands)
02880 {
02881 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
02882 {
02883 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02884 int ls0, ls1, ms0, p, len;
02885
02886 for (ls0 = 0; ls0 < HOST_BITS_PER_WIDE_INT; ls0++)
02887 if ((mask & ((unsigned HOST_WIDE_INT) 1 << ls0)) == 0)
02888 break;
02889
02890 for (ls1 = ls0; ls1 < HOST_BITS_PER_WIDE_INT; ls1++)
02891 if ((mask & ((unsigned HOST_WIDE_INT) 1 << ls1)) != 0)
02892 break;
02893
02894 for (ms0 = ls1; ms0 < HOST_BITS_PER_WIDE_INT; ms0++)
02895 if ((mask & ((unsigned HOST_WIDE_INT) 1 << ms0)) == 0)
02896 break;
02897
02898 gcc_assert (ms0 == HOST_BITS_PER_WIDE_INT);
02899
02900 if (ls1 == HOST_BITS_PER_WIDE_INT)
02901 {
02902 len = ls0;
02903
02904 gcc_assert (len);
02905
02906 operands[2] = GEN_INT (len);
02907 return "extrd,u %1,63,%2,%0";
02908 }
02909 else
02910 {
02911
02912
02913
02914 p = 63 - ls0;
02915 len = ls1 - ls0;
02916
02917 operands[2] = GEN_INT (p);
02918 operands[3] = GEN_INT (len);
02919 return "depdi 0,%2,%3,%0";
02920 }
02921 }
02922 else
02923 return "and %1,%2,%0";
02924 }
02925
02926 const char *
02927 output_ior (rtx *operands)
02928 {
02929 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02930 int bs0, bs1, p, len;
02931
02932 if (INTVAL (operands[2]) == 0)
02933 return "copy %1,%0";
02934
02935 for (bs0 = 0; bs0 < 32; bs0++)
02936 if ((mask & (1 << bs0)) != 0)
02937 break;
02938
02939 for (bs1 = bs0; bs1 < 32; bs1++)
02940 if ((mask & (1 << bs1)) == 0)
02941 break;
02942
02943 gcc_assert (bs1 == 32 || ((unsigned HOST_WIDE_INT) 1 << bs1) > mask);
02944
02945 p = 31 - bs0;
02946 len = bs1 - bs0;
02947
02948 operands[2] = GEN_INT (p);
02949 operands[3] = GEN_INT (len);
02950 return "{depi|depwi} -1,%2,%3,%0";
02951 }
02952
02953
02954
02955 const char *
02956 output_64bit_ior (rtx *operands)
02957 {
02958 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02959 int bs0, bs1, p, len;
02960
02961 if (INTVAL (operands[2]) == 0)
02962 return "copy %1,%0";
02963
02964 for (bs0 = 0; bs0 < HOST_BITS_PER_WIDE_INT; bs0++)
02965 if ((mask & ((unsigned HOST_WIDE_INT) 1 << bs0)) != 0)
02966 break;
02967
02968 for (bs1 = bs0; bs1 < HOST_BITS_PER_WIDE_INT; bs1++)
02969 if ((mask & ((unsigned HOST_WIDE_INT) 1 << bs1)) == 0)
02970 break;
02971
02972 gcc_assert (bs1 == HOST_BITS_PER_WIDE_INT
02973 || ((unsigned HOST_WIDE_INT) 1 << bs1) > mask);
02974
02975 p = 63 - bs0;
02976 len = bs1 - bs0;
02977
02978 operands[2] = GEN_INT (p);
02979 operands[3] = GEN_INT (len);
02980 return "depdi -1,%2,%3,%0";
02981 }
02982
02983
02984
02985
02986
02987 static bool
02988 pa_assemble_integer (rtx x, unsigned int size, int aligned_p)
02989 {
02990 if (size == UNITS_PER_WORD
02991 && aligned_p
02992 && function_label_operand (x, VOIDmode))
02993 {
02994 fputs (size == 8? "\t.dword\tP%" : "\t.word\tP%", asm_out_file);
02995 output_addr_const (asm_out_file, x);
02996 fputc ('\n', asm_out_file);
02997 return true;
02998 }
02999 return default_assemble_integer (x, size, aligned_p);
03000 }
03001
03002
03003 void
03004 output_ascii (FILE *file, const char *p, int size)
03005 {
03006 int i;
03007 int chars_output;
03008 unsigned char partial_output[16];
03009
03010
03011
03012
03013
03014
03015
03016 fputs ("\t.STRING \"", file);
03017
03018 chars_output = 0;
03019 for (i = 0; i < size; i += 4)
03020 {
03021 int co = 0;
03022 int io = 0;
03023 for (io = 0, co = 0; io < MIN (4, size - i); io++)
03024 {
03025 register unsigned int c = (unsigned char) p[i + io];
03026
03027 if (c == '\"' || c == '\\')
03028 partial_output[co++] = '\\';
03029 if (c >= ' ' && c < 0177)
03030 partial_output[co++] = c;
03031 else
03032 {
03033 unsigned int hexd;
03034 partial_output[co++] = '\\';
03035 partial_output[co++] = 'x';
03036 hexd = c / 16 - 0 + '0';
03037 if (hexd > '9')
03038 hexd -= '9' - 'a' + 1;
03039 partial_output[co++] = hexd;
03040 hexd = c % 16 - 0 + '0';
03041 if (hexd > '9')
03042 hexd -= '9' - 'a' + 1;
03043 partial_output[co++] = hexd;
03044 }
03045 }
03046 if (chars_output + co > 243)
03047 {
03048 fputs ("\"\n\t.STRING \"", file);
03049 chars_output = 0;
03050 }
03051 fwrite (partial_output, 1, (size_t) co, file);
03052 chars_output += co;
03053 co = 0;
03054 }
03055 fputs ("\"\n", file);
03056 }
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070 static void
03071 remove_useless_addtr_insns (int check_notes)
03072 {
03073 rtx insn;
03074 static int pass = 0;
03075
03076
03077 if (optimize > 0)
03078 {
03079 int fcmp_count = 0;
03080 int fbranch_count = 0;
03081
03082
03083
03084 for (insn = get_insns (); insn; insn = next_insn (insn))
03085 {
03086 rtx tmp;
03087
03088
03089 if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
03090 continue;
03091
03092 tmp = PATTERN (insn);
03093
03094
03095 if (GET_CODE (tmp) != SET)
03096 continue;
03097
03098
03099 tmp = SET_DEST (tmp);
03100 if (GET_CODE (tmp) == REG && REGNO (tmp) == 0)
03101 {
03102 fcmp_count++;
03103 continue;
03104 }
03105
03106 tmp = PATTERN (insn);
03107
03108 if (GET_CODE (tmp) == SET
03109 && SET_DEST (tmp) == pc_rtx
03110 && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
03111 && GET_CODE (XEXP (SET_SRC (tmp), 0)) == NE
03112 && GET_CODE (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == REG
03113 && REGNO (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == 0)
03114 {
03115 fbranch_count++;
03116 continue;
03117 }
03118 }
03119
03120
03121
03122
03123 for (insn = get_insns (); insn; insn = next_insn (insn))
03124 {
03125 rtx tmp, next;
03126
03127
03128 if (GET_CODE (insn) != INSN)
03129 continue;
03130
03131 tmp = PATTERN (insn);
03132
03133
03134 if (GET_CODE (tmp) != SET)
03135 continue;
03136
03137
03138 tmp = SET_DEST (tmp);
03139 if (GET_CODE (tmp) != REG || REGNO (tmp) != 0)
03140 continue;
03141
03142
03143
03144
03145
03146
03147 next = next_insn (insn);
03148 while (next)
03149 {
03150
03151 if (GET_CODE (next) == JUMP_INSN
03152 || GET_CODE (next) == CALL_INSN
03153 || GET_CODE (next) == CODE_LABEL)
03154 break;
03155
03156
03157 if (GET_CODE (next) == INSN
03158 && GET_CODE (PATTERN (next)) == SET
03159 && GET_CODE (SET_DEST (PATTERN (next))) == REG
03160 && REGNO (SET_DEST (PATTERN (next))) == 0)
03161 break;
03162
03163 next = next_insn (next);
03164 }
03165
03166
03167 if (next
03168 && GET_CODE (next) == JUMP_INSN)
03169 {
03170 rtx pattern = PATTERN (next);
03171
03172
03173
03174
03175 if (GET_CODE (pattern) == SET
03176 && SET_DEST (pattern) == pc_rtx
03177 && GET_CODE (SET_SRC (pattern)) == IF_THEN_ELSE
03178 && GET_CODE (XEXP (SET_SRC (pattern), 0)) == NE
03179 && GET_CODE (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == REG
03180 && REGNO (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == 0
03181 && GET_CODE (XEXP (SET_SRC (pattern), 1)) == PC
03182 && (fcmp_count == fbranch_count
03183 || (check_notes
03184 && find_regno_note (next, REG_DEAD, 0))))
03185 {
03186
03187 tmp = XEXP (SET_SRC (pattern), 1);
03188 XEXP (SET_SRC (pattern), 1) = XEXP (SET_SRC (pattern), 2);
03189 XEXP (SET_SRC (pattern), 2) = tmp;
03190 INSN_CODE (next) = -1;
03191
03192
03193 tmp = PATTERN (insn);
03194 PUT_CODE (XEXP (tmp, 1),
03195 (reverse_condition_maybe_unordered
03196 (GET_CODE (XEXP (tmp, 1)))));
03197 }
03198 }
03199 }
03200 }
03201
03202 pass = !pass;
03203
03204 }
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272 static HOST_WIDE_INT actual_fsize, local_fsize;
03273 static int save_fregs;
03274
03275
03276
03277
03278
03279
03280
03281 static void
03282 store_reg (int reg, HOST_WIDE_INT disp, int base)
03283 {
03284 rtx insn, dest, src, basereg;
03285
03286 src = gen_rtx_REG (word_mode, reg);
03287 basereg = gen_rtx_REG (Pmode, base);
03288 if (VAL_14_BITS_P (disp))
03289 {
03290 dest = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
03291 insn = emit_move_insn (dest, src);
03292 }
03293 else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
03294 {
03295 rtx delta = GEN_INT (disp);
03296 rtx tmpreg = gen_rtx_REG (Pmode, 1);
03297
03298 emit_move_insn (tmpreg, delta);
03299 insn = emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg));
03300 if (DO_FRAME_NOTES)
03301 {
03302 REG_NOTES (insn)
03303 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03304 gen_rtx_SET (VOIDmode, tmpreg,
03305 gen_rtx_PLUS (Pmode, basereg, delta)),
03306 REG_NOTES (insn));
03307 RTX_FRAME_RELATED_P (insn) = 1;
03308 }
03309 dest = gen_rtx_MEM (word_mode, tmpreg);
03310 insn = emit_move_insn (dest, src);
03311 }
03312 else
03313 {
03314 rtx delta = GEN_INT (disp);
03315 rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
03316 rtx tmpreg = gen_rtx_REG (Pmode, 1);
03317
03318 emit_move_insn (tmpreg, high);
03319 dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
03320 insn = emit_move_insn (dest, src);
03321 if (DO_FRAME_NOTES)
03322 {
03323 REG_NOTES (insn)
03324 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03325 gen_rtx_SET (VOIDmode,
03326 gen_rtx_MEM (word_mode,
03327 gen_rtx_PLUS (word_mode, basereg,
03328 delta)),
03329 src),
03330 REG_NOTES (insn));
03331 }
03332 }
03333
03334 if (DO_FRAME_NOTES)
03335 RTX_FRAME_RELATED_P (insn) = 1;
03336 }
03337
03338
03339
03340
03341 static void
03342 store_reg_modify (int base, int reg, HOST_WIDE_INT mod)
03343 {
03344 rtx insn, basereg, srcreg, delta;
03345
03346 gcc_assert (VAL_14_BITS_P (mod));
03347
03348 basereg = gen_rtx_REG (Pmode, base);
03349 srcreg = gen_rtx_REG (word_mode, reg);
03350 delta = GEN_INT (mod);
03351
03352 insn = emit_insn (gen_post_store (basereg, srcreg, delta));
03353 if (DO_FRAME_NOTES)
03354 {
03355 RTX_FRAME_RELATED_P (insn) = 1;
03356
03357
03358
03359 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 0)) = 1;
03360 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1;
03361 }
03362 }
03363
03364
03365
03366
03367
03368
03369
03370
03371 static void
03372 set_reg_plus_d (int reg, int base, HOST_WIDE_INT disp, int note)
03373 {
03374 rtx insn;
03375
03376 if (VAL_14_BITS_P (disp))
03377 {
03378 insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
03379 plus_constant (gen_rtx_REG (Pmode, base), disp));
03380 }
03381 else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
03382 {
03383 rtx basereg = gen_rtx_REG (Pmode, base);
03384 rtx delta = GEN_INT (disp);
03385 rtx tmpreg = gen_rtx_REG (Pmode, 1);
03386
03387 emit_move_insn (tmpreg, delta);
03388 insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
03389 gen_rtx_PLUS (Pmode, tmpreg, basereg));
03390 if (DO_FRAME_NOTES)
03391 REG_NOTES (insn)
03392 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03393 gen_rtx_SET (VOIDmode, tmpreg,
03394 gen_rtx_PLUS (Pmode, basereg, delta)),
03395 REG_NOTES (insn));
03396 }
03397 else
03398 {
03399 rtx basereg = gen_rtx_REG (Pmode, base);
03400 rtx delta = GEN_INT (disp);
03401 rtx tmpreg = gen_rtx_REG (Pmode, 1);
03402
03403 emit_move_insn (tmpreg,
03404 gen_rtx_PLUS (Pmode, basereg,
03405 gen_rtx_HIGH (Pmode, delta)));
03406 insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
03407 gen_rtx_LO_SUM (Pmode, tmpreg, delta));
03408 }
03409
03410 if (DO_FRAME_NOTES && note)
03411 RTX_FRAME_RELATED_P (insn) = 1;
03412 }
03413
03414 HOST_WIDE_INT
03415 compute_frame_size (HOST_WIDE_INT size, int *fregs_live)
03416 {
03417 int freg_saved = 0;
03418 int i, j;
03419
03420
03421
03422
03423
03424
03425
03426 size = (size + UNITS_PER_WORD - 1) & ~(UNITS_PER_WORD - 1);
03427
03428
03429
03430
03431
03432 if (size || frame_pointer_needed)
03433 size += STARTING_FRAME_OFFSET;
03434
03435
03436
03437
03438 if (DO_FRAME_NOTES && current_function_calls_eh_return)
03439 {
03440 unsigned int i;
03441
03442 for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
03443 continue;
03444 size += i * UNITS_PER_WORD;
03445 }
03446
03447
03448 for (i = 18, j = frame_pointer_needed ? 4 : 3; i >= j; i--)
03449 if (regs_ever_live[i])
03450 size += UNITS_PER_WORD;
03451
03452
03453 for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03454 if (regs_ever_live[i]
03455 || (!TARGET_64BIT && regs_ever_live[i + 1]))
03456 {
03457 freg_saved = 1;
03458
03459
03460
03461 size += 8;
03462 }
03463
03464
03465
03466 if (freg_saved)
03467 {
03468 size = (size + 7) & ~7;
03469 if (fregs_live)
03470 *fregs_live = 1;
03471 }
03472
03473
03474
03475
03476
03477 size += current_function_outgoing_args_size;
03478
03479
03480
03481
03482 if (!current_function_is_leaf || size)
03483 size += TARGET_64BIT ? 48 : 32;
03484
03485
03486 return ((size + PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1)
03487 & ~(PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1));
03488 }
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507 static void
03508 pa_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
03509 {
03510
03511
03512
03513 ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
03514 fputs ("\t.PROC\n", file);
03515
03516
03517
03518
03519 fprintf (file, "\t.CALLINFO FRAME=" HOST_WIDE_INT_PRINT_DEC, actual_fsize);
03520 if (regs_ever_live[2])
03521 fputs (",CALLS,SAVE_RP", file);
03522 else
03523 fputs (",NO_CALLS", file);
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534 if (frame_pointer_needed)
03535 fputs (",SAVE_SP", file);
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545 if (gr_saved)
03546 fprintf (file, ",ENTRY_GR=%d", gr_saved + 2);
03547
03548 if (fr_saved)
03549 fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);
03550
03551 fputs ("\n\t.ENTRY\n", file);
03552
03553 remove_useless_addtr_insns (0);
03554 }
03555
03556 void
03557 hppa_expand_prologue (void)
03558 {
03559 int merge_sp_adjust_with_store = 0;
03560 HOST_WIDE_INT size = get_frame_size ();
03561 HOST_WIDE_INT offset;
03562 int i;
03563 rtx insn, tmpreg;
03564
03565 gr_saved = 0;
03566 fr_saved = 0;
03567 save_fregs = 0;
03568
03569
03570
03571
03572 local_fsize = (size + UNITS_PER_WORD - 1) & ~(UNITS_PER_WORD - 1);
03573 if (local_fsize || frame_pointer_needed)
03574 local_fsize += STARTING_FRAME_OFFSET;
03575
03576 actual_fsize = compute_frame_size (size, &save_fregs);
03577
03578
03579 tmpreg = gen_rtx_REG (word_mode, 1);
03580
03581
03582
03583
03584 if (regs_ever_live[2] || current_function_calls_eh_return)
03585 store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
03586
03587
03588 if (actual_fsize != 0)
03589 {
03590 if (frame_pointer_needed)
03591 {
03592
03593
03594
03595
03596
03597
03598 insn = emit_move_insn (tmpreg, frame_pointer_rtx);
03599 if (DO_FRAME_NOTES)
03600 RTX_FRAME_RELATED_P (insn) = 1;
03601
03602 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
03603 if (DO_FRAME_NOTES)
03604 RTX_FRAME_RELATED_P (insn) = 1;
03605
03606 if (VAL_14_BITS_P (actual_fsize))
03607 store_reg_modify (STACK_POINTER_REGNUM, 1, actual_fsize);
03608 else
03609 {
03610
03611
03612
03613
03614
03615
03616 HOST_WIDE_INT adjust1 = 8192 - 64;
03617 HOST_WIDE_INT adjust2 = actual_fsize - adjust1;
03618
03619 store_reg_modify (STACK_POINTER_REGNUM, 1, adjust1);
03620 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03621 adjust2, 1);
03622 }
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640 if (TARGET_HPUX_UNWIND_LIBRARY)
03641 {
03642 rtx addr = gen_rtx_PLUS (word_mode, stack_pointer_rtx,
03643 GEN_INT (TARGET_64BIT ? -8 : -4));
03644
03645 emit_move_insn (gen_rtx_MEM (word_mode, addr),
03646 frame_pointer_rtx);
03647 }
03648 else
03649 emit_insn (gen_blockage ());
03650 }
03651
03652 else
03653 {
03654
03655
03656
03657
03658 if (VAL_14_BITS_P (actual_fsize) && local_fsize == 0)
03659 merge_sp_adjust_with_store = 1;
03660
03661
03662 else
03663 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03664 actual_fsize, 1);
03665 }
03666 }
03667
03668
03669
03670
03671
03672 if (frame_pointer_needed)
03673 {
03674 offset = local_fsize;
03675
03676
03677
03678
03679 if (DO_FRAME_NOTES && current_function_calls_eh_return)
03680 {
03681 unsigned int i, regno;
03682
03683 for (i = 0; ; ++i)
03684 {
03685 regno = EH_RETURN_DATA_REGNO (i);
03686 if (regno == INVALID_REGNUM)
03687 break;
03688
03689 store_reg (regno, offset, FRAME_POINTER_REGNUM);
03690 offset += UNITS_PER_WORD;
03691 }
03692 }
03693
03694 for (i = 18; i >= 4; i--)
03695 if (regs_ever_live[i] && ! call_used_regs[i])
03696 {
03697 store_reg (i, offset, FRAME_POINTER_REGNUM);
03698 offset += UNITS_PER_WORD;
03699 gr_saved++;
03700 }
03701
03702 gr_saved++;
03703 }
03704
03705 else
03706 {
03707 offset = local_fsize - actual_fsize;
03708
03709
03710
03711 if (DO_FRAME_NOTES && current_function_calls_eh_return)
03712 {
03713 unsigned int i, regno;
03714
03715 for (i = 0; ; ++i)
03716 {
03717 regno = EH_RETURN_DATA_REGNO (i);
03718 if (regno == INVALID_REGNUM)
03719 break;
03720
03721
03722
03723 if (merge_sp_adjust_with_store)
03724 {
03725 store_reg_modify (STACK_POINTER_REGNUM, regno, -offset);
03726 merge_sp_adjust_with_store = 0;
03727 }
03728 else
03729 store_reg (regno, offset, STACK_POINTER_REGNUM);
03730 offset += UNITS_PER_WORD;
03731 }
03732 }
03733
03734 for (i = 18; i >= 3; i--)
03735 if (regs_ever_live[i] && ! call_used_regs[i])
03736 {
03737
03738
03739 if (merge_sp_adjust_with_store)
03740 {
03741 store_reg_modify (STACK_POINTER_REGNUM, i, -offset);
03742 merge_sp_adjust_with_store = 0;
03743 }
03744 else
03745 store_reg (i, offset, STACK_POINTER_REGNUM);
03746 offset += UNITS_PER_WORD;
03747 gr_saved++;
03748 }
03749
03750
03751
03752 if (merge_sp_adjust_with_store)
03753 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03754 actual_fsize, 1);
03755 }
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766 if (flag_pic && actual_fsize != 0 && !TARGET_64BIT)
03767 {
03768 rtx addr = gen_rtx_PLUS (word_mode, stack_pointer_rtx, GEN_INT (-32));
03769
03770 emit_move_insn (gen_rtx_MEM (word_mode, addr), pic_offset_table_rtx);
03771
03772 }
03773
03774
03775 offset = (offset + 7) & ~7;
03776
03777
03778 if (save_fregs)
03779 {
03780 rtx base;
03781
03782
03783
03784 if (frame_pointer_needed)
03785 {
03786 set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset, 0);
03787 base = frame_pointer_rtx;
03788 }
03789 else
03790 {
03791 set_reg_plus_d (1, STACK_POINTER_REGNUM, offset, 0);
03792 base = stack_pointer_rtx;
03793 }
03794
03795
03796 for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03797 {
03798 if (regs_ever_live[i]
03799 || (! TARGET_64BIT && regs_ever_live[i + 1]))
03800 {
03801 rtx addr, insn, reg;
03802 addr = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
03803 reg = gen_rtx_REG (DFmode, i);
03804 insn = emit_move_insn (addr, reg);
03805 if (DO_FRAME_NOTES)
03806 {
03807 RTX_FRAME_RELATED_P (insn) = 1;
03808 if (TARGET_64BIT)
03809 {
03810 rtx mem = gen_rtx_MEM (DFmode,
03811 plus_constant (base, offset));
03812 REG_NOTES (insn)
03813 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03814 gen_rtx_SET (VOIDmode, mem, reg),
03815 REG_NOTES (insn));
03816 }
03817 else
03818 {
03819 rtx meml = gen_rtx_MEM (SFmode,
03820 plus_constant (base, offset));
03821 rtx memr = gen_rtx_MEM (SFmode,
03822 plus_constant (base, offset + 4));
03823 rtx regl = gen_rtx_REG (SFmode, i);
03824 rtx regr = gen_rtx_REG (SFmode, i + 1);
03825 rtx setl = gen_rtx_SET (VOIDmode, meml, regl);
03826 rtx setr = gen_rtx_SET (VOIDmode, memr, regr);
03827 rtvec vec;
03828
03829 RTX_FRAME_RELATED_P (setl) = 1;
03830 RTX_FRAME_RELATED_P (setr) = 1;
03831 vec = gen_rtvec (2, setl, setr);
03832 REG_NOTES (insn)
03833 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03834 gen_rtx_SEQUENCE (VOIDmode, vec),
03835 REG_NOTES (insn));
03836 }
03837 }
03838 offset += GET_MODE_SIZE (DFmode);
03839 fr_saved++;
03840 }
03841 }
03842 }
03843 }
03844
03845
03846
03847
03848 static void
03849 load_reg (int reg, HOST_WIDE_INT disp, int base)
03850 {
03851 rtx dest = gen_rtx_REG (word_mode, reg);
03852 rtx basereg = gen_rtx_REG (Pmode, base);
03853 rtx src;
03854
03855 if (VAL_14_BITS_P (disp))
03856 src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
03857 else if (TARGET_64BIT && !VAL_32_BITS_P (disp))
03858 {
03859 rtx delta = GEN_INT (disp);
03860 rtx tmpreg = gen_rtx_REG (Pmode, 1);
03861
03862 emit_move_insn (tmpreg, delta);
03863 if (TARGET_DISABLE_INDEXING)
03864 {
03865 emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg));
03866 src = gen_rtx_MEM (word_mode, tmpreg);
03867 }
03868 else
03869 src = gen_rtx_MEM (word_mode, gen_rtx_PLUS (Pmode, tmpreg, basereg));
03870 }
03871 else
03872 {
03873 rtx delta = GEN_INT (disp);
03874 rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
03875 rtx tmpreg = gen_rtx_REG (Pmode, 1);
03876
03877 emit_move_insn (tmpreg, high);
03878 src = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
03879 }
03880
03881 emit_move_insn (dest, src);
03882 }
03883
03884
03885
03886 static void
03887 update_total_code_bytes (int nbytes)
03888 {
03889 if ((TARGET_PORTABLE_RUNTIME || !TARGET_GAS || !TARGET_SOM)
03890 && !IN_NAMED_SECTION_P (cfun->decl))
03891 {
03892 if (INSN_ADDRESSES_SET_P ())
03893 {
03894 unsigned long old_total = total_code_bytes;
03895
03896 total_code_bytes += nbytes;
03897
03898
03899 if (old_total > total_code_bytes)
03900 total_code_bytes = -1;
03901 }
03902 else
03903 total_code_bytes = -1;
03904 }
03905 }
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915 static void
03916 pa_output_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
03917 {
03918 rtx insn = get_last_insn ();
03919
03920 last_address = 0;
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932 if (GET_CODE (insn) == NOTE)
03933 insn = prev_real_insn (insn);
03934
03935
03936 if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
03937 insn = XVECEXP (PATTERN (insn), 0, 0);
03938
03939
03940
03941 if (insn && GET_CODE (insn) == CALL_INSN)
03942 {
03943 fputs ("\tnop\n", file);
03944 last_address += 4;
03945 }
03946
03947 fputs ("\t.EXIT\n\t.PROCEND\n", file);
03948
03949 if (TARGET_SOM && TARGET_GAS)
03950 {
03951
03952
03953
03954 in_section = NULL;
03955 cfun->machine->in_nsubspa = 2;
03956 }
03957
03958 if (INSN_ADDRESSES_SET_P ())
03959 {
03960 insn = get_last_nonnote_insn ();
03961 last_address += INSN_ADDRESSES (INSN_UID (insn));
03962 if (INSN_P (insn))
03963 last_address += insn_default_length (insn);
03964 last_address = ((last_address + FUNCTION_BOUNDARY / BITS_PER_UNIT - 1)
03965 & ~(FUNCTION_BOUNDARY / BITS_PER_UNIT - 1));
03966 }
03967
03968
03969 update_total_code_bytes (last_address);
03970 }
03971
03972 void
03973 hppa_expand_epilogue (void)
03974 {
03975 rtx tmpreg;
03976 HOST_WIDE_INT offset;
03977 HOST_WIDE_INT ret_off = 0;
03978 int i;
03979 int merge_sp_adjust_with_load = 0;
03980
03981
03982 tmpreg = gen_rtx_REG (word_mode, 1);
03983
03984
03985
03986
03987 if (regs_ever_live [2] || current_function_calls_eh_return)
03988 {
03989 ret_off = TARGET_64BIT ? -16 : -20;
03990 if (frame_pointer_needed)
03991 {
03992 load_reg (2, ret_off, FRAME_POINTER_REGNUM);
03993 ret_off = 0;
03994 }
03995 else
03996 {
03997
03998 if (VAL_14_BITS_P (ret_off - actual_fsize))
03999 {
04000 load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM);
04001 ret_off = 0;
04002 }
04003 }
04004 }
04005
04006
04007 if (frame_pointer_needed)
04008 {
04009 offset = local_fsize;
04010
04011
04012
04013 if (DO_FRAME_NOTES && current_function_calls_eh_return)
04014 {
04015 unsigned int i, regno;
04016
04017 for (i = 0; ; ++i)
04018 {
04019 regno = EH_RETURN_DATA_REGNO (i);
04020 if (regno == INVALID_REGNUM)
04021 break;
04022
04023 load_reg (regno, offset, FRAME_POINTER_REGNUM);
04024 offset += UNITS_PER_WORD;
04025 }
04026 }
04027
04028 for (i = 18; i >= 4; i--)
04029 if (regs_ever_live[i] && ! call_used_regs[i])
04030 {
04031 load_reg (i, offset, FRAME_POINTER_REGNUM);
04032 offset += UNITS_PER_WORD;
04033 }
04034 }
04035 else
04036 {
04037 offset = local_fsize - actual_fsize;
04038
04039
04040
04041 if (DO_FRAME_NOTES && current_function_calls_eh_return)
04042 {
04043 unsigned int i, regno;
04044
04045 for (i = 0; ; ++i)
04046 {
04047 regno = EH_RETURN_DATA_REGNO (i);
04048 if (regno == INVALID_REGNUM)
04049 break;
04050
04051
04052
04053
04054 if (merge_sp_adjust_with_load == 0
04055 && local_fsize == 0
04056 && VAL_14_BITS_P (-actual_fsize))
04057 merge_sp_adjust_with_load = regno;
04058 else
04059 load_reg (regno, offset, STACK_POINTER_REGNUM);
04060 offset += UNITS_PER_WORD;
04061 }
04062 }
04063
04064 for (i = 18; i >= 3; i--)
04065 {
04066 if (regs_ever_live[i] && ! call_used_regs[i])
04067 {
04068
04069
04070
04071 if (merge_sp_adjust_with_load == 0
04072 && local_fsize == 0
04073 && VAL_14_BITS_P (-actual_fsize))
04074 merge_sp_adjust_with_load = i;
04075 else
04076 load_reg (i, offset, STACK_POINTER_REGNUM);
04077 offset += UNITS_PER_WORD;
04078 }
04079 }
04080 }
04081
04082
04083 offset = (offset + 7) & ~7;
04084
04085
04086 if (save_fregs)
04087 {
04088
04089 if (frame_pointer_needed)
04090 set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset, 0);
04091 else
04092 set_reg_plus_d (1, STACK_POINTER_REGNUM, offset, 0);
04093
04094
04095 for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
04096 if (regs_ever_live[i]
04097 || (! TARGET_64BIT && regs_ever_live[i + 1]))
04098 {
04099 rtx src = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
04100 rtx dest = gen_rtx_REG (DFmode, i);
04101 emit_move_insn (dest, src);
04102 }
04103 }
04104
04105
04106
04107
04108
04109
04110 emit_insn (gen_blockage ());
04111
04112
04113
04114 if (frame_pointer_needed)
04115 {
04116 rtx delta = GEN_INT (-64);
04117
04118 set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64, 0);
04119 emit_insn (gen_pre_load (frame_pointer_rtx, stack_pointer_rtx, delta));
04120 }
04121
04122 else if (merge_sp_adjust_with_load)
04123 {
04124 rtx delta = GEN_INT (-actual_fsize);
04125 rtx dest = gen_rtx_REG (word_mode, merge_sp_adjust_with_load);
04126
04127 emit_insn (gen_pre_load (dest, stack_pointer_rtx, delta));
04128 }
04129 else if (actual_fsize != 0)
04130 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
04131 - actual_fsize, 0);
04132
04133
04134
04135 if (ret_off != 0)
04136 load_reg (2, ret_off, STACK_POINTER_REGNUM);
04137
04138 if (DO_FRAME_NOTES && current_function_calls_eh_return)
04139 {
04140 rtx sa = EH_RETURN_STACKADJ_RTX;
04141
04142 emit_insn (gen_blockage ());
04143 emit_insn (TARGET_64BIT
04144 ? gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, sa)
04145 : gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, sa));
04146 }
04147 }
04148
04149 rtx
04150 hppa_pic_save_rtx (void)
04151 {
04152 return get_hard_reg_initial_val (word_mode, PIC_OFFSET_TABLE_REGNUM);
04153 }
04154
04155 #ifndef NO_DEFERRED_PROFILE_COUNTERS
04156 #define NO_DEFERRED_PROFILE_COUNTERS 0
04157 #endif
04158
04159
04160 DEF_VEC_I(int);
04161 DEF_VEC_ALLOC_I(int,heap);
04162
04163
04164 static VEC(int,heap) *funcdef_nos;
04165
04166
04167 static void
04168 output_deferred_profile_counters (void)
04169 {
04170 unsigned int i;
04171 int align, n;
04172
04173 if (VEC_empty (int, funcdef_nos))
04174 return;
04175
04176 switch_to_section (data_section);
04177 align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
04178 ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
04179
04180 for (i = 0; VEC_iterate (int, funcdef_nos, i, n); i++)
04181 {
04182 targetm.asm_out.internal_label (asm_out_file, "LP", n);
04183 assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
04184 }
04185
04186 VEC_free (int, heap, funcdef_nos);
04187 }
04188
04189 void
04190 hppa_profile_hook (int label_no)
04191 {
04192
04193
04194
04195 rtx reg = gen_reg_rtx (SImode);
04196 rtx label_rtx = gen_label_rtx ();
04197 rtx begin_label_rtx, call_insn;
04198 char begin_label_name[16];
04199
04200 ASM_GENERATE_INTERNAL_LABEL (begin_label_name, FUNC_BEGIN_PROLOG_LABEL,
04201 label_no);
04202 begin_label_rtx = gen_rtx_SYMBOL_REF (SImode, ggc_strdup (begin_label_name));
04203
04204 if (TARGET_64BIT)
04205 emit_move_insn (arg_pointer_rtx,
04206 gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
04207 GEN_INT (64)));
04208
04209 emit_move_insn (gen_rtx_REG (word_mode, 26), gen_rtx_REG (word_mode, 2));
04210
04211
04212
04213
04214
04215 if (TARGET_PA_20)
04216 emit_insn (gen_lcla2 (reg, label_rtx));
04217 else
04218 emit_insn (gen_lcla1 (reg, label_rtx));
04219
04220 emit_insn (gen_load_offset_label_address (gen_rtx_REG (SImode, 25),
04221 reg, begin_label_rtx, label_rtx));
04222
04223 #if !NO_DEFERRED_PROFILE_COUNTERS
04224 {
04225 rtx count_label_rtx, addr, r24;
04226 char count_label_name[16];
04227
04228 VEC_safe_push (int, heap, funcdef_nos, label_no);
04229 ASM_GENERATE_INTERNAL_LABEL (count_label_name, "LP", label_no);
04230 count_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (count_label_name));
04231
04232 addr = force_reg (Pmode, count_label_rtx);
04233 r24 = gen_rtx_REG (Pmode, 24);
04234 emit_move_insn (r24, addr);
04235
04236 call_insn =
04237 emit_call_insn (gen_call (gen_rtx_MEM (Pmode,
04238 gen_rtx_SYMBOL_REF (Pmode,
04239 "_mcount")),
04240 GEN_INT (TARGET_64BIT ? 24 : 12)));
04241
04242 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), r24);
04243 }
04244 #else
04245
04246 call_insn =
04247 emit_call_insn (gen_call (gen_rtx_MEM (Pmode,
04248 gen_rtx_SYMBOL_REF (Pmode,
04249 "_mcount")),
04250 GEN_INT (TARGET_64BIT ? 16 : 8)));
04251
04252 #endif
04253
04254 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 25));
04255 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 26));
04256
04257
04258
04259 REG_NOTES (call_insn)
04260 = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx, REG_NOTES (call_insn));
04261 }
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289 rtx
04290 return_addr_rtx (int count, rtx frameaddr)
04291 {
04292 rtx label;
04293 rtx rp;
04294 rtx saved_rp;
04295 rtx ins;
04296
04297 if (count != 0)
04298 return NULL_RTX;
04299
04300 rp = get_hard_reg_initial_val (Pmode, 2);
04301
04302 if (TARGET_64BIT || TARGET_NO_SPACE_REGS)
04303 return rp;
04304
04305 saved_rp = gen_reg_rtx (Pmode);
04306 emit_move_insn (saved_rp, rp);
04307
04308
04309
04310
04311
04312 ins = copy_to_reg (gen_rtx_AND (Pmode, rp, MASK_RETURN_ADDR));
04313 label = gen_label_rtx ();
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326 emit_cmp_insn (gen_rtx_MEM (SImode, ins), GEN_INT (0x4bc23fd1), NE,
04327 NULL_RTX, SImode, 1);
04328 emit_jump_insn (gen_bne (label));
04329
04330 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)),
04331 GEN_INT (0x004010a1), NE, NULL_RTX, SImode, 1);
04332 emit_jump_insn (gen_bne (label));
04333
04334 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)),
04335 GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1);
04336 emit_jump_insn (gen_bne (label));
04337
04338
04339
04340 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)),
04341 GEN_INT (-532676606), NE, NULL_RTX, SImode, 1);
04342
04343
04344
04345
04346 emit_jump_insn (gen_bne (label));
04347
04348
04349
04350
04351
04352
04353 emit_move_insn (saved_rp,
04354 gen_rtx_MEM (Pmode,
04355 memory_address (Pmode,
04356 plus_constant (frameaddr,
04357 -24))));
04358
04359 emit_label (label);
04360 return saved_rp;
04361 }
04362
04363
04364
04365
04366
04367
04368
04369
04370 int
04371 hppa_can_use_return_insn_p (void)
04372 {
04373 return (reload_completed
04374 && (compute_frame_size (get_frame_size (), 0) ? 0 : 1)
04375 && ! regs_ever_live[2]
04376 && ! frame_pointer_needed);
04377 }
04378
04379 void
04380 emit_bcond_fp (enum rtx_code code, rtx operand0)
04381 {
04382 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
04383 gen_rtx_IF_THEN_ELSE (VOIDmode,
04384 gen_rtx_fmt_ee (code,
04385 VOIDmode,
04386 gen_rtx_REG (CCFPmode, 0),
04387 const0_rtx),
04388 gen_rtx_LABEL_REF (VOIDmode, operand0),
04389 pc_rtx)));
04390
04391 }
04392
04393 rtx
04394 gen_cmp_fp (enum rtx_code code, rtx operand0, rtx operand1)
04395 {
04396 return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
04397 gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1));
04398 }
04399
04400
04401
04402
04403 static int
04404 pa_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
04405 {
04406 enum attr_type attr_type;
04407
04408
04409
04410 if (pa_cpu >= PROCESSOR_8000 || REG_NOTE_KIND (link) == 0)
04411 return cost;
04412
04413 if (! recog_memoized (insn))
04414 return 0;
04415
04416 attr_type = get_attr_type (insn);
04417
04418 switch (REG_NOTE_KIND (link))
04419 {
04420 case REG_DEP_ANTI:
04421
04422
04423
04424 if (attr_type == TYPE_FPLOAD)
04425 {
04426 rtx pat = PATTERN (insn);
04427 rtx dep_pat = PATTERN (dep_insn);
04428 if (GET_CODE (pat) == PARALLEL)
04429 {
04430
04431 pat = XVECEXP (pat, 0, 0);
04432 }
04433 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
04434
04435
04436 return 0;
04437
04438 if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
04439 {
04440 if (! recog_memoized (dep_insn))
04441 return 0;
04442 switch (get_attr_type (dep_insn))
04443 {
04444 case TYPE_FPALU:
04445 case TYPE_FPMULSGL:
04446 case TYPE_FPMULDBL:
04447 case TYPE_FPDIVSGL:
04448 case TYPE_FPDIVDBL:
04449 case TYPE_FPSQRTSGL:
04450 case TYPE_FPSQRTDBL:
04451
04452
04453
04454
04455 return insn_default_latency (dep_insn) - 1;
04456
04457 default:
04458 return 0;
04459 }
04460 }
04461 }
04462 else if (attr_type == TYPE_FPALU)
04463 {
04464 rtx pat = PATTERN (insn);
04465 rtx dep_pat = PATTERN (dep_insn);
04466 if (GET_CODE (pat) == PARALLEL)
04467 {
04468
04469 pat = XVECEXP (pat, 0, 0);
04470 }
04471 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
04472
04473
04474 return 0;
04475
04476 if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
04477 {
04478 if (! recog_memoized (dep_insn))
04479 return 0;
04480 switch (get_attr_type (dep_insn))
04481 {
04482 case TYPE_FPDIVSGL:
04483 case TYPE_FPDIVDBL:
04484 case TYPE_FPSQRTSGL:
04485 case TYPE_FPSQRTDBL:
04486
04487
04488
04489
04490 return insn_default_latency (dep_insn) - 2;
04491
04492 default:
04493 return 0;
04494 }
04495 }
04496 }
04497
04498
04499 return 0;
04500
04501 case REG_DEP_OUTPUT:
04502
04503
04504 if (attr_type == TYPE_FPLOAD)
04505 {
04506 rtx pat = PATTERN (insn);
04507 rtx dep_pat = PATTERN (dep_insn);
04508 if (GET_CODE (pat) == PARALLEL)
04509 {
04510
04511 pat = XVECEXP (pat, 0, 0);
04512 }
04513 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
04514
04515
04516 return 0;
04517
04518 if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
04519 {
04520 if (! recog_memoized (dep_insn))
04521 return 0;
04522 switch (get_attr_type (dep_insn))
04523 {
04524 case TYPE_FPALU:
04525 case TYPE_FPMULSGL:
04526 case TYPE_FPMULDBL:
04527 case TYPE_FPDIVSGL:
04528 case TYPE_FPDIVDBL:
04529 case TYPE_FPSQRTSGL:
04530 case TYPE_FPSQRTDBL:
04531
04532
04533
04534
04535
04536
04537
04538
04539 return insn_default_latency (dep_insn) - 1;
04540
04541 default:
04542 return 0;
04543 }
04544 }
04545 }
04546 else if (attr_type == TYPE_FPALU)
04547 {
04548 rtx pat = PATTERN (insn);
04549 rtx dep_pat = PATTERN (dep_insn);
04550 if (GET_CODE (pat) == PARALLEL)
04551 {
04552
04553 pat = XVECEXP (pat, 0, 0);
04554 }
04555 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
04556
04557
04558 return 0;
04559
04560 if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
04561 {
04562 if (! recog_memoized (dep_insn))
04563 return 0;
04564 switch (get_attr_type (dep_insn))
04565 {
04566 case TYPE_FPDIVSGL:
04567 case TYPE_FPDIVDBL:
04568 case TYPE_FPSQRTSGL:
04569 case TYPE_FPSQRTDBL:
04570
04571
04572
04573
04574 return insn_default_latency (dep_insn) - 2;
04575
04576 default:
04577 return 0;
04578 }
04579 }
04580 }
04581
04582
04583 return 0;
04584
04585 default:
04586 gcc_unreachable ();
04587 }
04588 }
04589
04590
04591
04592 static int
04593 pa_adjust_priority (rtx insn, int priority)
04594 {
04595 rtx set = single_set (insn);
04596 rtx src, dest;
04597 if (set)
04598 {
04599 src = SET_SRC (set);
04600 dest = SET_DEST (set);
04601 if (GET_CODE (src) == LO_SUM
04602 && symbolic_operand (XEXP (src, 1), VOIDmode)
04603 && ! read_only_operand (XEXP (src, 1), VOIDmode))
04604 priority >>= 3;
04605
04606 else if (GET_CODE (src) == MEM
04607 && GET_CODE (XEXP (src, 0)) == LO_SUM
04608 && symbolic_operand (XEXP (XEXP (src, 0), 1), VOIDmode)
04609 && ! read_only_operand (XEXP (XEXP (src, 0), 1), VOIDmode))
04610 priority >>= 1;
04611
04612 else if (GET_CODE (dest) == MEM
04613 && GET_CODE (XEXP (dest, 0)) == LO_SUM
04614 && symbolic_operand (XEXP (XEXP (dest, 0), 1), VOIDmode)
04615 && ! read_only_operand (XEXP (XEXP (dest, 0), 1), VOIDmode))
04616 priority >>= 3;
04617 }
04618 return priority;
04619 }
04620
04621
04622
04623
04624 static int
04625 pa_issue_rate (void)
04626 {
04627 switch (pa_cpu)
04628 {
04629 case PROCESSOR_700: return 1;
04630 case PROCESSOR_7100: return 2;
04631 case PROCESSOR_7100LC: return 2;
04632 case PROCESSOR_7200: return 2;
04633 case PROCESSOR_7300: return 2;
04634 case PROCESSOR_8000: return 4;
04635
04636 default:
04637 gcc_unreachable ();
04638 }
04639 }
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651
04652 int
04653 pa_adjust_insn_length (rtx insn, int length)
04654 {
04655 rtx pat = PATTERN (insn);
04656
04657
04658
04659 if (GET_CODE (insn) == JUMP_INSN
04660 && GET_CODE (pat) == PARALLEL
04661 && get_attr_type (insn) == TYPE_BTABLE_BRANCH)
04662 return 4;
04663
04664 else if (GET_CODE (insn) == INSN
04665 && GET_CODE (pat) != SEQUENCE
04666 && GET_CODE (pat) != USE
04667 && GET_CODE (pat) != CLOBBER
04668 && get_attr_type (insn) == TYPE_MILLI)
04669 return 4;
04670
04671 else if (GET_CODE (insn) == INSN
04672 && GET_CODE (pat) == PARALLEL
04673 && GET_CODE (XVECEXP (pat, 0, 0)) == SET
04674 && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
04675 && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
04676 && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
04677 && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode)
04678 return compute_movmem_length (insn) - 4;
04679
04680 else if (GET_CODE (insn) == INSN
04681 && GET_CODE (pat) == PARALLEL
04682 && GET_CODE (XVECEXP (pat, 0, 0)) == SET
04683 && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
04684 && XEXP (XVECEXP (pat, 0, 0), 1) == const0_rtx
04685 && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode)
04686 return compute_clrmem_length (insn) - 4;
04687
04688 else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn))
04689 {
04690
04691 if (GET_CODE (pat) == SET
04692 && length == 4
04693 && ! forward_branch_p (insn))
04694 return 4;
04695 else if (GET_CODE (pat) == PARALLEL
04696 && get_attr_type (insn) == TYPE_PARALLEL_BRANCH
04697 && length == 4)
04698 return 4;
04699
04700
04701
04702 else if (GET_CODE (pat) == PARALLEL
04703 && GET_CODE (XVECEXP (pat, 0, 1)) == SET
04704 && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG
04705 && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0))
04706 && length == 4
04707 && ! forward_branch_p (insn))
04708 return 4;
04709 else
04710 return 0;
04711 }
04712 return 0;
04713 }
04714
04715
04716
04717
04718
04719 void
04720 print_operand (FILE *file, rtx x, int code)
04721 {
04722 switch (code)
04723 {
04724 case '#':
04725
04726 if (dbr_sequence_length () == 0)
04727 fputs ("\n\tnop", file);
04728 return;
04729 case '*':
04730
04731
04732 if (dbr_sequence_length () == 0 ||
04733 (final_sequence &&
04734 INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))))
04735 fputs (",n", file);
04736 return;
04737 case 'R':
04738
04739
04740 fputs (reg_names[REGNO (x) + 1], file);
04741 return;
04742 case 'r':
04743
04744 if (x == const0_rtx
04745 || (x == CONST0_RTX (DFmode))
04746 || (x == CONST0_RTX (SFmode)))
04747 {
04748 fputs ("%r0", file);
04749 return;
04750 }
04751 else
04752 break;
04753 case 'f':
04754
04755 if (x == const0_rtx
04756 || (x == CONST0_RTX (DFmode))
04757 || (x == CONST0_RTX (SFmode)))
04758 {
04759 fputs ("%fr0", file);
04760 return;
04761 }
04762 else
04763 break;
04764 case 'A':
04765 {
04766 rtx xoperands[2];
04767
04768 xoperands[0] = XEXP (XEXP (x, 0), 0);
04769 xoperands[1] = XVECEXP (XEXP (XEXP (x, 0), 1), 0, 0);
04770 output_global_address (file, xoperands[1], 0);
04771 fprintf (file, "(%s)", reg_names [REGNO (xoperands[0])]);
04772 return;
04773 }
04774
04775 case 'C':
04776 case 'X':
04777 switch (GET_CODE (x))
04778 {
04779 case EQ:
04780 fputs ("=", file); break;
04781 case NE:
04782 fputs ("<>", file); break;
04783 case GT:
04784 fputs (">", file); break;
04785 case GE:
04786 fputs (">=", file); break;
04787 case GEU:
04788 fputs (">>=", file); break;
04789 case GTU:
04790 fputs (">>", file); break;
04791 case LT:
04792 fputs ("<", file); break;
04793 case LE:
04794 fputs ("<=", file); break;
04795 case LEU:
04796 fputs ("<<=", file); break;
04797 case LTU:
04798 fputs ("<<", file); break;
04799 default:
04800 gcc_unreachable ();
04801 }
04802 return;
04803 case 'N':
04804 switch (GET_CODE (x))
04805 {
04806 case EQ:
04807 fputs ("<>", file); break;
04808 case NE:
04809 fputs ("=", file); break;
04810 case GT:
04811 fputs ("<=", file); break;
04812 case GE:
04813 fputs ("<", file); break;
04814 case GEU:
04815 fputs ("<<", file); break;
04816 case GTU:
04817 fputs ("<<=", file); break;
04818 case LT:
04819 fputs (">=", file); break;
04820 case LE:
04821 fputs (">", file); break;
04822 case LEU:
04823 fputs (">>", file); break;
04824 case LTU:
04825 fputs (">>=", file); break;
04826 default:
04827 gcc_unreachable ();
04828 }
04829 return;
04830
04831
04832
04833
04834
04835 case 'Y':
04836 switch (GET_CODE (x))
04837 {
04838 case EQ:
04839 fputs ("!=", file); break;
04840 case NE:
04841 fputs ("=", file); break;
04842 case GT:
04843 fputs ("!>", file); break;
04844 case GE:
04845 fputs ("!>=", file); break;
04846 case LT:
04847 fputs ("!<", file); break;
04848 case LE:
04849 fputs ("!<=", file); break;
04850 case LTGT:
04851 fputs ("!<>", file); break;
04852 case UNLE:
04853 fputs ("!?<=", file); break;
04854 case UNLT:
04855 fputs ("!?<", file); break;
04856 case UNGE:
04857 fputs ("!?>=", file); break;
04858 case UNGT:
04859 fputs ("!?>", file); break;
04860 case UNEQ:
04861 fputs ("!?=", file); break;
04862 case UNORDERED:
04863 fputs ("!?", file); break;
04864 case ORDERED:
04865 fputs ("?", file); break;
04866 default:
04867 gcc_unreachable ();
04868 }
04869 return;
04870 case 'S':
04871 switch (GET_CODE (x))
04872 {
04873 case EQ:
04874 fputs ("=", file); break;
04875 case NE:
04876 fputs ("<>", file); break;
04877 case GT:
04878 fputs ("<", file); break;
04879 case GE:
04880 fputs ("<=", file); break;
04881 case GEU:
04882 fputs ("<<=", file); break;
04883 case GTU:
04884 fputs ("<<", file); break;
04885 case LT:
04886 fputs (">", file); break;
04887 case LE:
04888 fputs (">=", file); break;
04889 case LEU:
04890 fputs (">>=", file); break;
04891 case LTU:
04892 fputs (">>", file); break;
04893 default:
04894 gcc_unreachable ();
04895 }
04896 return;
04897 case 'B':
04898 switch (GET_CODE (x))
04899 {
04900 case EQ:
04901 fputs ("<>", file); break;
04902 case NE:
04903 fputs ("=", file); break;
04904 case GT:
04905 fputs (">=", file); break;
04906 case GE:
04907 fputs (">", file); break;
04908 case GEU:
04909 fputs (">>", file); break;
04910 case GTU:
04911 fputs (">>=", file); break;
04912 case LT:
04913 fputs ("<=", file); break;
04914 case LE:
04915 fputs ("<", file); break;
04916 case LEU:
04917 fputs ("<<", file); break;
04918 case LTU:
04919 fputs ("<<=", file); break;
04920 default:
04921 gcc_unreachable ();
04922 }
04923 return;
04924 case 'k':
04925 gcc_assert (GET_CODE (x) == CONST_INT);
04926 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~INTVAL (x));
04927 return;
04928 case 'Q':
04929 gcc_assert (GET_CODE (x) == CONST_INT);
04930 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 64 - (INTVAL (x) & 63));
04931 return;
04932 case 'L':
04933 gcc_assert (GET_CODE (x) == CONST_INT);
04934 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 32 - (INTVAL (x) & 31));
04935 return;
04936 case 'O':
04937 gcc_assert (GET_CODE (x) == CONST_INT && exact_log2 (INTVAL (x)) >= 0);
04938 fprintf (file, "%d", exact_log2 (INTVAL (x)));
04939 return;
04940 case 'p':
04941 gcc_assert (GET_CODE (x) == CONST_INT);
04942 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 63 - (INTVAL (x) & 63));
04943 return;
04944 case 'P':
04945 gcc_assert (GET_CODE (x) == CONST_INT);
04946 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 31 - (INTVAL (x) & 31));
04947 return;
04948 case 'I':
04949 if (GET_CODE (x) == CONST_INT)
04950 fputs ("i", file);
04951 return;
04952 case 'M':
04953 case 'F':
04954 switch (GET_CODE (XEXP (x, 0)))
04955 {
04956 case PRE_DEC:
04957 case PRE_INC:
04958 if (ASSEMBLER_DIALECT == 0)
04959 fputs ("s,mb", file);
04960 else
04961 fputs (",mb", file);
04962 break;
04963 case POST_DEC:
04964 case POST_INC:
04965 if (ASSEMBLER_DIALECT == 0)
04966 fputs ("s,ma", file);
04967 else
04968 fputs (",ma", file);
04969 break;
04970 case PLUS:
04971 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
04972 && GET_CODE (XEXP (XEXP (x, 0), 1)) == REG)
04973 {
04974 if (ASSEMBLER_DIALECT == 0)
04975 fputs ("x", file);
04976 }
04977 else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
04978 || GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
04979 {
04980 if (ASSEMBLER_DIALECT == 0)
04981 fputs ("x,s", file);
04982 else
04983 fputs (",s", file);
04984 }
04985 else if (code == 'F' && ASSEMBLER_DIALECT == 0)
04986 fputs ("s", file);
04987 break;
04988 default:
04989 if (code == 'F' && ASSEMBLER_DIALECT == 0)
04990 fputs ("s", file);
04991 break;
04992 }
04993 return;
04994 case 'G':
04995 output_global_address (file, x, 0);
04996 return;
04997 case 'H':
04998 output_global_address (file, x, 1);
04999 return;
05000 case 0:
05001 break;
05002 case 'Z':
05003 {
05004 unsigned op[3];
05005 compute_zdepwi_operands (INTVAL (x), op);
05006 fprintf (file, "%d,%d,%d", op[0], op[1], op[2]);
05007 return;
05008 }
05009 case 'z':
05010 {
05011 unsigned op[3];
05012 compute_zdepdi_operands (INTVAL (x), op);
05013 fprintf (file, "%d,%d,%d", op[0], op[1], op[2]);
05014 return;
05015 }
05016 case 'c':
05017
05018
05019
05020 break;
05021 default:
05022 gcc_unreachable ();
05023 }
05024 if (GET_CODE (x) == REG)
05025 {
05026 fputs (reg_names [REGNO (x)], file);
05027 if (TARGET_64BIT && FP_REG_P (x) && GET_MODE_SIZE (GET_MODE (x)) <= 4)
05028 {
05029 fputs ("R", file);
05030 return;
05031 }
05032 if (FP_REG_P (x)
05033 && GET_MODE_SIZE (GET_MODE (x)) <= 4
05034 && (REGNO (x) & 1) == 0)
05035 fputs ("L", file);
05036 }
05037 else if (GET_CODE (x) == MEM)
05038 {
05039 int size = GET_MODE_SIZE (GET_MODE (x));
05040 rtx base = NULL_RTX;
05041 switch (GET_CODE (XEXP (x, 0)))
05042 {
05043 case PRE_DEC:
05044 case POST_DEC:
05045 base = XEXP (XEXP (x, 0), 0);
05046 fprintf (file, "-%d(%s)", size, reg_names [REGNO (base)]);
05047 break;
05048 case PRE_INC:
05049 case POST_INC:
05050 base = XEXP (XEXP (x, 0), 0);
05051 fprintf (file, "%d(%s)", size, reg_names [REGNO (base)]);
05052 break;
05053 case PLUS:
05054 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
05055 fprintf (file, "%s(%s)",
05056 reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0))],
05057 reg_names [REGNO (XEXP (XEXP (x, 0), 1))]);
05058 else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
05059 fprintf (file, "%s(%s)",
05060 reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 1), 0))],
05061 reg_names [REGNO (XEXP (XEXP (x, 0), 0))]);
05062 else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
05063 && GET_CODE (XEXP (XEXP (x, 0), 1)) == REG)
05064 {
05065
05066
05067
05068 rtx base = XEXP (XEXP (x, 0), 1);
05069 rtx index = XEXP (XEXP (x, 0), 0);
05070
05071 fprintf (file, "%s(%s)",
05072 reg_names [REGNO (index)], reg_names [REGNO (base)]);
05073 }
05074 else
05075 output_address (XEXP (x, 0));
05076 break;
05077 default:
05078 output_address (XEXP (x, 0));
05079 break;
05080 }
05081 }
05082 else
05083 output_addr_const (file, x);
05084 }
05085
05086
05087
05088 void
05089 output_global_address (FILE *file, rtx x, int round_constant)
05090 {
05091
05092
05093 if (GET_CODE (x) == HIGH)
05094 x = XEXP (x, 0);
05095
05096 if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x, VOIDmode))
05097 output_addr_const (file, x);
05098 else if (GET_CODE (x) == SYMBOL_REF && !flag_pic)
05099 {
05100 output_addr_const (file, x);
05101 fputs ("-$global$", file);
05102 }
05103 else if (GET_CODE (x) == CONST)
05104 {
05105 const char *sep = "";
05106 int offset = 0;
05107 rtx base = NULL_RTX;
05108
05109 switch (GET_CODE (XEXP (XEXP (x, 0), 0)))
05110 {
05111 case SYMBOL_REF:
05112 base = XEXP (XEXP (x, 0), 0);
05113 output_addr_const (file, base);
05114 break;
05115 case CONST_INT:
05116 offset = INTVAL (XEXP (XEXP (x, 0), 0));
05117 break;
05118 default:
05119 gcc_unreachable ();
05120 }
05121
05122 switch (GET_CODE (XEXP (XEXP (x, 0), 1)))
05123 {
05124 case SYMBOL_REF:
05125 base = XEXP (XEXP (x, 0), 1);
05126 output_addr_const (file, base);
05127 break;
05128 case CONST_INT:
05129 offset = INTVAL (XEXP (XEXP (x, 0), 1));
05130 break;
05131 default:
05132 gcc_unreachable ();
05133 }
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143
05144 if (round_constant)
05145 offset = ((offset + 0x1000) & ~0x1fff);
05146
05147 switch (GET_CODE (XEXP (x, 0)))
05148 {
05149 case PLUS:
05150 if (offset < 0)
05151 {
05152 offset = -offset;
05153 sep = "-";
05154 }
05155 else
05156 sep = "+";
05157 break;
05158
05159 case MINUS:
05160 gcc_assert (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF);
05161 sep = "-";
05162 break;
05163
05164 default:
05165 gcc_unreachable ();
05166 }
05167
05168 if (!read_only_operand (base, VOIDmode) && !flag_pic)
05169 fputs ("-$global$", file);
05170 if (offset)
05171 fprintf (file, "%s%d", sep, offset);
05172 }
05173 else
05174 output_addr_const (file, x);
05175 }
05176
05177
05178
05179 #define aputs(x) fputs(x, asm_out_file)
05180 static inline void
05181 pa_file_start_level (void)
05182 {
05183 if (TARGET_64BIT)
05184 aputs ("\t.LEVEL 2.0w\n");
05185 else if (TARGET_PA_20)
05186 aputs ("\t.LEVEL 2.0\n");
05187 else if (TARGET_PA_11)
05188 aputs ("\t.LEVEL 1.1\n");
05189 else
05190 aputs ("\t.LEVEL 1.0\n");
05191 }
05192
05193 static inline void
05194 pa_file_start_space (int sortspace)
05195 {
05196 aputs ("\t.SPACE $PRIVATE$");
05197 if (sortspace)
05198 aputs (",SORT=16");
05199 aputs ("\n\t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31"
05200 "\n\t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82"
05201 "\n\t.SPACE $TEXT$");
05202 if (sortspace)
05203 aputs (",SORT=8");
05204 aputs ("\n\t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44"
05205 "\n\t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n");
05206 }
05207
05208 static inline void
05209 pa_file_start_file (int want_version)
05210 {
05211 if (write_symbols != NO_DEBUG)
05212 {
05213 output_file_directive (asm_out_file, main_input_filename);
05214 if (want_version)
05215 aputs ("\t.version\t\"01.01\"\n");
05216 }
05217 }
05218
05219 static inline void
05220 pa_file_start_mcount (const char *aswhat)
05221 {
05222 if (profile_flag)
05223 fprintf (asm_out_file, "\t.IMPORT _mcount,%s\n", aswhat);
05224 }
05225
05226 static void
05227 pa_elf_file_start (void)
05228 {
05229 pa_file_start_level ();
05230 pa_file_start_mcount ("ENTRY");
05231 pa_file_start_file (0);
05232 }
05233
05234 static void
05235 pa_som_file_start (void)
05236 {
05237 pa_file_start_level ();
05238 pa_file_start_space (0);
05239 aputs ("\t.IMPORT $global$,DATA\n"
05240 "\t.IMPORT $$dyncall,MILLICODE\n");
05241 pa_file_start_mcount ("CODE");
05242 pa_file_start_file (0);
05243 }
05244
05245 static void
05246 pa_linux_file_start (void)
05247 {
05248 pa_file_start_file (1);
05249 pa_file_start_level ();
05250 pa_file_start_mcount ("CODE");
05251 }
05252
05253 static void
05254 pa_hpux64_gas_file_start (void)
05255 {
05256 pa_file_start_level ();
05257 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
05258 if (profile_flag)
05259 ASM_OUTPUT_TYPE_DIRECTIVE (asm_out_file, "_mcount", "function");
05260 #endif
05261 pa_file_start_file (1);
05262 }
05263
05264 static void
05265 pa_hpux64_hpas_file_start (void)
05266 {
05267 pa_file_start_level ();
05268 pa_file_start_space (1);
05269 pa_file_start_mcount ("CODE");
05270 pa_file_start_file (0);
05271 }
05272 #undef aputs
05273
05274
05275
05276
05277 rtx
05278 get_deferred_plabel (rtx symbol)
05279 {
05280 const char *fname = XSTR (symbol, 0);
05281 size_t i;
05282
05283
05284
05285
05286 for (i = 0; i < n_deferred_plabels; i++)
05287 if (strcmp (fname, XSTR (deferred_plabels[i].symbol, 0)) == 0)
05288 break;
05289
05290
05291
05292 if (deferred_plabels == NULL || i == n_deferred_plabels)
05293 {
05294 tree id;
05295
05296 if (deferred_plabels == 0)
05297 deferred_plabels = (struct deferred_plabel *)
05298 ggc_alloc (sizeof (struct deferred_plabel));
05299 else
05300 deferred_plabels = (struct deferred_plabel *)
05301 ggc_realloc (deferred_plabels,
05302 ((n_deferred_plabels + 1)
05303 * sizeof (struct deferred_plabel)));
05304
05305 i = n_deferred_plabels++;
05306 deferred_plabels[i].internal_label = gen_label_rtx ();
05307 deferred_plabels[i].symbol = symbol;
05308
05309
05310
05311 id = maybe_get_identifier (targetm.strip_name_encoding (fname));
05312 if (id)
05313 mark_referenced (id);
05314 }
05315
05316 return deferred_plabels[i].internal_label;
05317 }
05318
05319 static void
05320 output_deferred_plabels (void)
05321 {
05322 size_t i;
05323
05324
05325
05326
05327 if (n_deferred_plabels)
05328 {
05329 switch_to_section (flag_pic ? data_section : readonly_data_section);
05330 ASM_OUTPUT_ALIGN (asm_out_file, TARGET_64BIT ? 3 : 2);
05331 }
05332
05333
05334 for (i = 0; i < n_deferred_plabels; i++)
05335 {
05336 (*targetm.asm_out.internal_label) (asm_out_file, "L",
05337 CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
05338 assemble_integer (deferred_plabels[i].symbol,
05339 TARGET_64BIT ? 8 : 4, TARGET_64BIT ? 64 : 32, 1);
05340 }
05341 }
05342
05343 #ifdef HPUX_LONG_DOUBLE_LIBRARY
05344
05345 static void
05346 pa_hpux_init_libfuncs (void)
05347 {
05348 set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
05349 set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
05350 set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
05351 set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
05352 set_optab_libfunc (smin_optab, TFmode, "_U_Qmin");
05353 set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
05354 set_optab_libfunc (sqrt_optab, TFmode, "_U_Qfsqrt");
05355 set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
05356 set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
05357
05358 set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
05359 set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
05360 set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
05361 set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
05362 set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
05363 set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
05364 set_optab_libfunc (unord_optab, TFmode, "_U_Qfunord");
05365
05366 set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
05367 set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
05368 set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
05369 set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
05370
05371 set_conv_libfunc (sfix_optab, SImode, TFmode, TARGET_64BIT
05372 ? "__U_Qfcnvfxt_quad_to_sgl"
05373 : "_U_Qfcnvfxt_quad_to_sgl");
05374 set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
05375 set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_usgl");
05376 set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_udbl");
05377
05378 set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
05379 set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
05380 set_conv_libfunc (ufloat_optab, TFmode, SImode, "_U_Qfcnvxf_usgl_to_quad");
05381 set_conv_libfunc (ufloat_optab, TFmode, DImode, "_U_Qfcnvxf_udbl_to_quad");
05382 }
05383 #endif
05384
05385
05386
05387
05388 enum millicodes { remI, remU, divI, divU, mulI, end1000 };
05389 static void import_milli (enum millicodes);
05390 static char imported[(int) end1000];
05391 static const char * const milli_names[] = {"remI", "remU", "divI", "divU", "mulI"};
05392 static const char import_string[] = ".IMPORT $$....,MILLICODE";
05393 #define MILLI_START 10
05394
05395 static void
05396 import_milli (enum millicodes code)
05397 {
05398 char str[sizeof (import_string)];
05399
05400 if (!imported[(int) code])
05401 {
05402 imported[(int) code] = 1;
05403 strcpy (str, import_string);
05404 strncpy (str + MILLI_START, milli_names[(int) code], 4);
05405 output_asm_insn (str, 0);
05406 }
05407 }
05408
05409
05410
05411
05412 const char *
05413 output_mul_insn (int unsignedp ATTRIBUTE_UNUSED, rtx insn)
05414 {
05415 import_milli (mulI);
05416 return output_millicode_call (insn, gen_rtx_SYMBOL_REF (Pmode, "$$mulI"));
05417 }
05418
05419
05420
05421
05422 const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1};
05423
05424
05425
05426
05427
05428 static int div_milli[16][2];
05429
05430 int
05431 emit_hpdiv_const (rtx *operands, int unsignedp)
05432 {
05433 if (GET_CODE (operands[2]) == CONST_INT
05434 && INTVAL (operands[2]) > 0
05435 && INTVAL (operands[2]) < 16
05436 && magic_milli[INTVAL (operands[2])])
05437 {
05438 rtx ret = gen_rtx_REG (SImode, TARGET_64BIT ? 2 : 31);
05439
05440 emit_move_insn (gen_rtx_REG (SImode, 26), operands[1]);
05441 emit
05442 (gen_rtx_PARALLEL
05443 (VOIDmode,
05444 gen_rtvec (6, gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, 29),
05445 gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
05446 SImode,
05447 gen_rtx_REG (SImode, 26),
05448 operands[2])),
05449 gen_rtx_CLOBBER (VOIDmode, operands[4]),
05450 gen_rtx_CLOBBER (VOIDmode, operands[3]),
05451 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 26)),
05452 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 25)),
05453 gen_rtx_CLOBBER (VOIDmode, ret))));
05454 emit_move_insn (operands[0], gen_rtx_REG (SImode, 29));
05455 return 1;
05456 }
05457 return 0;
05458 }
05459
05460 const char *
05461 output_div_insn (rtx *operands, int unsignedp, rtx insn)
05462 {
05463 int divisor;
05464
05465
05466
05467 if (GET_CODE (operands[0]) == CONST_INT)
05468 {
05469 static char buf[100];
05470 divisor = INTVAL (operands[0]);
05471 if (!div_milli[divisor][unsignedp])
05472 {
05473 div_milli[divisor][unsignedp] = 1;
05474 if (unsignedp)
05475 output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands);
05476 else
05477 output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands);
05478 }
05479 if (unsignedp)
05480 {
05481 sprintf (buf, "$$divU_" HOST_WIDE_INT_PRINT_DEC,
05482 INTVAL (operands[0]));
05483 return output_millicode_call (insn,
05484 gen_rtx_SYMBOL_REF (SImode, buf));
05485 }
05486 else
05487 {
05488 sprintf (buf, "$$divI_" HOST_WIDE_INT_PRINT_DEC,
05489 INTVAL (operands[0]));
05490 return output_millicode_call (insn,
05491 gen_rtx_SYMBOL_REF (SImode, buf));
05492 }
05493 }
05494
05495 else
05496 {
05497 if (unsignedp)
05498 {
05499 import_milli (divU);
05500 return output_millicode_call (insn,
05501 gen_rtx_SYMBOL_REF (SImode, "$$divU"));
05502 }
05503 else
05504 {
05505 import_milli (divI);
05506 return output_millicode_call (insn,
05507 gen_rtx_SYMBOL_REF (SImode, "$$divI"));
05508 }
05509 }
05510 }
05511
05512
05513
05514 const char *
05515 output_mod_insn (int unsignedp, rtx insn)
05516 {
05517 if (unsignedp)
05518 {
05519 import_milli (remU);
05520 return output_millicode_call (insn,
05521 gen_rtx_SYMBOL_REF (SImode, "$$remU"));
05522 }
05523 else
05524 {
05525 import_milli (remI);
05526 return output_millicode_call (insn,
05527 gen_rtx_SYMBOL_REF (SImode, "$$remI"));
05528 }
05529 }
05530
05531 void
05532 output_arg_descriptor (rtx call_insn)
05533 {
05534 const char *arg_regs[4];
05535 enum machine_mode arg_mode;
05536 rtx link;
05537 int i, output_flag = 0;
05538 int regno;
05539
05540
05541
05542 if (TARGET_64BIT || TARGET_ELF32)
05543 return;
05544
05545 for (i = 0; i < 4; i++)
05546 arg_regs[i] = 0;
05547
05548
05549
05550 if (TARGET_PORTABLE_RUNTIME)
05551 {
05552 fputs ("\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n",
05553 asm_out_file);
05554 return;
05555 }
05556
05557 gcc_assert (GET_CODE (call_insn) == CALL_INSN);
05558 for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
05559 link; link = XEXP (link, 1))
05560 {
05561 rtx use = XEXP (link, 0);
05562
05563 if (! (GET_CODE (use) == USE
05564 && GET_CODE (XEXP (use, 0)) == REG
05565 && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
05566 continue;
05567
05568 arg_mode = GET_MODE (XEXP (use, 0));
05569 regno = REGNO (XEXP (use, 0));
05570 if (regno >= 23 && regno <= 26)
05571 {
05572 arg_regs[26 - regno] = "GR";
05573 if (arg_mode == DImode)
05574 arg_regs[25 - regno] = "GR";
05575 }
05576 else if (regno >= 32 && regno <= 39)
05577 {
05578 if (arg_mode == SFmode)
05579 arg_regs[(regno - 32) / 2] = "FR";
05580 else
05581 {
05582 #ifndef HP_FP_ARG_DESCRIPTOR_REVERSED
05583 arg_regs[(regno - 34) / 2] = "FR";
05584 arg_regs[(regno - 34) / 2 + 1] = "FU";
05585 #else
05586 arg_regs[(regno - 34) / 2] = "FU";
05587 arg_regs[(regno - 34) / 2 + 1] = "FR";
05588 #endif
05589 }
05590 }
05591 }
05592 fputs ("\t.CALL ", asm_out_file);
05593 for (i = 0; i < 4; i++)
05594 {
05595 if (arg_regs[i])
05596 {
05597 if (output_flag++)
05598 fputc (',', asm_out_file);
05599 fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]);
05600 }
05601 }
05602 fputc ('\n', asm_out_file);
05603 }
05604
05605 static enum reg_class
05606 pa_secondary_reload (bool in_p, rtx x, enum reg_class class,
05607 enum machine_mode mode, secondary_reload_info *sri)
05608 {
05609 int is_symbolic, regno;
05610
05611
05612 if (class == R1_REGS)
05613 return NO_REGS;
05614
05615 if (REG_P (x))
05616 {
05617 regno = REGNO (x);
05618 if (class == BASE_REG_CLASS && regno < FIRST_PSEUDO_REGISTER)
05619 return NO_REGS;
05620 }
05621 else
05622 regno = -1;
05623
05624
05625
05626
05627 if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == MEM)
05628 return NO_REGS;
05629
05630
05631
05632 if (flag_pic
05633 && (mode == SImode || mode == DImode)
05634 && FP_REG_CLASS_P (class)
05635 && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
05636 {
05637 sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
05638 : CODE_FOR_reload_indi_r1);
05639 return NO_REGS;
05640 }
05641
05642
05643
05644 if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (x) == SUBREG)
05645 regno = true_regnum (x);
05646
05647
05648
05649 if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
05650 && GET_MODE_CLASS (mode) == MODE_INT
05651 && FP_REG_CLASS_P (class))
05652 || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
05653 {
05654 sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
05655 return NO_REGS;
05656 }
05657
05658
05659
05660 if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
05661 && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
05662 || (class == SHIFT_REGS
05663 && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
05664 {
05665 sri->icode = in_p ? reload_in_optab[mode] : reload_out_optab[mode];
05666 return NO_REGS;
05667 }
05668
05669
05670
05671
05672 if (GET_CODE (x) == HIGH)
05673 x = XEXP (x, 0);
05674
05675
05676
05677
05678 switch (GET_CODE (x))
05679 {
05680 rtx op;
05681
05682 case SYMBOL_REF:
05683 is_symbolic = !SYMBOL_REF_TLS_MODEL (x);
05684 break;
05685 case LABEL_REF:
05686 is_symbolic = 1;
05687 break;
05688 case CONST:
05689 op = XEXP (x, 0);
05690 is_symbolic = (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
05691 && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
05692 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
05693 && GET_CODE (XEXP (op, 1)) == CONST_INT);
05694 break;
05695 default:
05696 is_symbolic = 0;
05697 break;
05698 }
05699
05700 if (is_symbolic && (flag_pic || !read_only_operand (x, VOIDmode)))
05701 {
05702 gcc_assert (mode == SImode || mode == DImode);
05703 sri->icode = (mode == SImode ? CODE_FOR_reload_insi_r1
05704 : CODE_FOR_reload_indi_r1);
05705 }
05706
05707 return NO_REGS;
05708 }
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719
05720
05721
05722
05723 static bool
05724 pa_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
05725 enum machine_mode mode, tree type,
05726 bool named ATTRIBUTE_UNUSED)
05727 {
05728 HOST_WIDE_INT size;
05729
05730 if (type)
05731 size = int_size_in_bytes (type);
05732 else
05733 size = GET_MODE_SIZE (mode);
05734
05735 if (TARGET_64BIT)
05736 return size <= 0;
05737 else
05738 return size <= 0 || size > 8;
05739 }
05740
05741 enum direction
05742 function_arg_padding (enum machine_mode mode, tree type)
05743 {
05744 if (mode == BLKmode
05745 || (TARGET_64BIT && type && AGGREGATE_TYPE_P (type)))
05746 {
05747
05748 if (type
05749 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
05750 && (int_size_in_bytes (type) * BITS_PER_UNIT) % PARM_BOUNDARY == 0)
05751 return none;
05752
05753
05754
05755
05756
05757
05758
05759 if (TARGET_64BIT)
05760
05761 return upward;
05762 else
05763
05764
05765
05766 return downward;
05767 }
05768
05769 if (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
05770 return downward;
05771 else
05772 return none;
05773 }
05774
05775
05776
05777
05778
05779
05780 static rtx
05781 hppa_builtin_saveregs (void)
05782 {
05783 rtx offset, dest;
05784 tree fntype = TREE_TYPE (current_function_decl);
05785 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
05786 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
05787 != void_type_node)))
05788 ? UNITS_PER_WORD : 0);
05789
05790 if (argadj)
05791 offset = plus_constant (current_function_arg_offset_rtx, argadj);
05792 else
05793 offset = current_function_arg_offset_rtx;
05794
05795 if (TARGET_64BIT)
05796 {
05797 int i, off;
05798
05799
05800 if (argadj)
05801 offset = plus_constant (current_function_arg_offset_rtx, -argadj);
05802 else
05803 offset = current_function_arg_offset_rtx;
05804
05805
05806
05807 for (i = 26, off = -64; i >= 19; i--, off += 8)
05808 emit_move_insn (gen_rtx_MEM (word_mode,
05809 plus_constant (arg_pointer_rtx, off)),
05810 gen_rtx_REG (word_mode, i));
05811
05812
05813
05814
05815
05816 emit_move_insn (virtual_incoming_args_rtx,
05817 plus_constant (arg_pointer_rtx, -64));
05818
05819
05820 return copy_to_reg (expand_binop (Pmode, add_optab,
05821 virtual_incoming_args_rtx,
05822 offset, 0, 0, OPTAB_LIB_WIDEN));
05823 }
05824
05825
05826 dest = gen_rtx_MEM (BLKmode,
05827 plus_constant (current_function_internal_arg_pointer,
05828 -16));
05829 set_mem_alias_set (dest, get_varargs_alias_set ());
05830 set_mem_align (dest, BITS_PER_WORD);
05831 move_block_from_reg (23, dest, 4);
05832
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842 emit_insn (gen_blockage ());
05843
05844 return copy_to_reg (expand_binop (Pmode, add_optab,
05845 current_function_internal_arg_pointer,
05846 offset, 0, 0, OPTAB_LIB_WIDEN));
05847 }
05848
05849 void
05850 hppa_va_start (tree valist, rtx nextarg)
05851 {
05852 nextarg = expand_builtin_saveregs ();
05853 std_expand_builtin_va_start (valist, nextarg);
05854 }
05855
05856 static tree
05857 hppa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
05858 {
05859 if (TARGET_64BIT)
05860 {
05861
05862 return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
05863 }
05864 else
05865 {
05866 tree ptr = build_pointer_type (type);
05867 tree valist_type;
05868 tree t, u;
05869 unsigned int size, ofs;
05870 bool indirect;
05871
05872 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
05873 if (indirect)
05874 {
05875 type = ptr;
05876 ptr = build_pointer_type (type);
05877 }
05878 size = int_size_in_bytes (type);
05879 valist_type = TREE_TYPE (valist);
05880
05881
05882
05883 u = fold_convert (valist_type, size_in_bytes (type));
05884 t = build2 (MINUS_EXPR, valist_type, valist, u);
05885
05886
05887
05888 u = build_int_cst (valist_type, (size > 4 ? -8 : -4));
05889 t = build2 (BIT_AND_EXPR, valist_type, t, u);
05890
05891 t = build2 (MODIFY_EXPR, valist_type, valist, t);
05892
05893 ofs = (8 - size) % 4;
05894 if (ofs != 0)
05895 {
05896 u = fold_convert (valist_type, size_int (ofs));
05897 t = build2 (PLUS_EXPR, valist_type, t, u);
05898 }
05899
05900 t = fold_convert (ptr, t);
05901 t = build_va_arg_indirect_ref (t);
05902
05903 if (indirect)
05904 t = build_va_arg_indirect_ref (t);
05905
05906 return t;
05907 }
05908 }
05909
05910
05911
05912
05913
05914
05915
05916
05917
05918
05919 static bool
05920 pa_scalar_mode_supported_p (enum machine_mode mode)
05921 {
05922 int precision = GET_MODE_PRECISION (mode);
05923
05924 switch (GET_MODE_CLASS (mode))
05925 {
05926 case MODE_PARTIAL_INT:
05927 case MODE_INT:
05928 if (precision == CHAR_TYPE_SIZE)
05929 return true;
05930 if (precision == SHORT_TYPE_SIZE)
05931 return true;
05932 if (precision == INT_TYPE_SIZE)
05933 return true;
05934 if (precision == LONG_TYPE_SIZE)
05935 return true;
05936 if (precision == LONG_LONG_TYPE_SIZE)
05937 return true;
05938 return false;
05939
05940 case MODE_FLOAT:
05941 if (precision == FLOAT_TYPE_SIZE)
05942 return true;
05943 if (precision == DOUBLE_TYPE_SIZE)
05944 return true;
05945 if (precision == LONG_DOUBLE_TYPE_SIZE)
05946 return true;
05947 return false;
05948
05949 case MODE_DECIMAL_FLOAT:
05950 return false;
05951
05952 default:
05953 gcc_unreachable ();
05954 }
05955 }
05956
05957
05958
05959
05960
05961
05962
05963
05964 const char *
05965 output_cbranch (rtx *operands, int negated, rtx insn)
05966 {
05967 static char buf[100];
05968 int useskip = 0;
05969 int nullify = INSN_ANNULLED_BRANCH_P (insn);
05970 int length = get_attr_length (insn);
05971 int xdelay;
05972
05973
05974
05975
05976
05977
05978
05979
05980
05981
05982 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
05983 return "nop";
05984
05985
05986
05987
05988 if (GET_MODE (operands[1]) == DImode && operands[2] == const0_rtx)
05989 operands[2] = gen_rtx_REG (DImode, 0);
05990 if (GET_MODE (operands[2]) == DImode && operands[1] == const0_rtx)
05991 operands[1] = gen_rtx_REG (DImode, 0);
05992
05993
05994
05995 if (length == 8 && dbr_sequence_length () == 0)
05996 nullify = 1;
05997
05998
05999
06000 if (! nullify && length == 4 && dbr_sequence_length () == 0)
06001 nullify = forward_branch_p (insn);
06002
06003
06004
06005
06006 if (length == 4
06007 && next_real_insn (insn) != 0
06008 && get_attr_length (next_real_insn (insn)) == 4
06009 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
06010 && nullify)
06011 useskip = 1;
06012
06013 switch (length)
06014 {
06015
06016
06017 case 4:
06018 if (useskip)
06019 strcpy (buf, "{com%I2clr,|cmp%I2clr,}");
06020 else
06021 strcpy (buf, "{com%I2b,|cmp%I2b,}");
06022 if (GET_MODE (operands[1]) == DImode)
06023 strcat (buf, "*");
06024 if (negated)
06025 strcat (buf, "%B3");
06026 else
06027 strcat (buf, "%S3");
06028 if (useskip)
06029 strcat (buf, " %2,%r1,%%r0");
06030 else if (nullify)
06031 strcat (buf, ",n %2,%r1,%0");
06032 else
06033 strcat (buf, " %2,%r1,%0");
06034 break;
06035
06036
06037
06038
06039 case 8:
06040
06041
06042 if (dbr_sequence_length () != 0
06043 && ! forward_branch_p (insn)
06044 && nullify)
06045 {
06046 strcpy (buf, "{com%I2b,|cmp%I2b,}");
06047 if (GET_MODE (operands[1]) == DImode)
06048 strcat (buf, "*");
06049 if (negated)
06050 strcat (buf, "%S3");
06051 else
06052 strcat (buf, "%B3");
06053 strcat (buf, ",n %2,%r1,.+12\n\tb %0");
06054 }
06055
06056
06057
06058 else if (dbr_sequence_length () == 0
06059 && ! forward_branch_p (insn)
06060 && INSN_ADDRESSES_SET_P ()
06061 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
06062 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
06063 {
06064 strcpy (buf, "{com%I2b,|cmp%I2b,}");
06065 if (GET_MODE (operands[1]) == DImode)
06066 strcat (buf, "*");
06067 if (negated)
06068 strcat (buf, "%B3 %2,%r1,%0%#");
06069 else
06070 strcat (buf, "%S3 %2,%r1,%0%#");
06071 }
06072 else
06073 {
06074 strcpy (buf, "{com%I2clr,|cmp%I2clr,}");
06075 if (GET_MODE (operands[1]) == DImode)
06076 strcat (buf, "*");
06077 if (negated)
06078 strcat (buf, "%S3");
06079 else
06080 strcat (buf, "%B3");
06081 if (nullify)
06082 strcat (buf, " %2,%r1,%%r0\n\tb,n %0");
06083 else
06084 strcat (buf, " %2,%r1,%%r0\n\tb %0");
06085 }
06086 break;
06087
06088 default:
06089
06090
06091
06092
06093
06094 if (dbr_sequence_length () == 0
06095 || (nullify && forward_branch_p (insn)))
06096 {
06097 nullify = 1;
06098 xdelay = 0;
06099 operands[4] = GEN_INT (length);
06100 }
06101 else
06102 {
06103 xdelay = 1;
06104 operands[4] = GEN_INT (length + 4);
06105 }
06106
06107
06108
06109 if (GET_MODE (operands[1]) != DImode)
06110 {
06111 if (nullify)
06112 {
06113 if (negated)
06114 strcpy (buf,
06115 "{com%I2b,%S3,n %2,%r1,.+%4|cmp%I2b,%S3,n %2,%r1,.+%4}");
06116 else
06117 strcpy (buf,
06118 "{com%I2b,%B3,n %2,%r1,.+%4|cmp%I2b,%B3,n %2,%r1,.+%4}");
06119 }
06120 else
06121 {
06122 if (negated)
06123 strcpy (buf,
06124 "{com%I2b,%S3 %2,%r1,.+%4|cmp%I2b,%S3 %2,%r1,.+%4}");
06125 else
06126 strcpy (buf,
06127 "{com%I2b,%B3 %2,%r1,.+%4|cmp%I2b,%B3 %2,%r1,.+%4}");
06128 }
06129 }
06130 else
06131 {
06132 if (nullify)
06133 {
06134 if (negated)
06135 strcpy (buf,
06136 "{com%I2b,*%S3,n %2,%r1,.+%4|cmp%I2b,*%S3,n %2,%r1,.+%4}");
06137 else
06138 strcpy (buf,
06139 "{com%I2b,*%B3,n %2,%r1,.+%4|cmp%I2b,*%B3,n %2,%r1,.+%4}");
06140 }
06141 else
06142 {
06143 if (negated)
06144 strcpy (buf,
06145 "{com%I2b,*%S3 %2,%r1,.+%4|cmp%I2b,*%S3 %2,%r1,.+%4}");
06146 else
06147 strcpy (buf,
06148 "{com%I2b,*%B3 %2,%r1,.+%4|cmp%I2b,*%B3 %2,%r1,.+%4}");
06149 }
06150 }
06151
06152 output_asm_insn (buf, operands);
06153 return output_lbranch (operands[0], insn, xdelay);
06154 }
06155 return buf;
06156 }
06157
06158
06159
06160
06161
06162
06163
06164
06165
06166
06167
06168
06169
06170
06171
06172
06173
06174
06175 const char *
06176 output_lbranch (rtx dest, rtx insn, int xdelay)
06177 {
06178 rtx xoperands[2];
06179
06180 xoperands[0] = dest;
06181
06182
06183 if (xdelay && dbr_sequence_length () != 0)
06184 {
06185
06186 gcc_assert (GET_CODE (NEXT_INSN (insn)) != JUMP_INSN);
06187
06188 final_scan_insn (NEXT_INSN (insn), asm_out_file,
06189 optimize, 0, NULL);
06190
06191
06192 PUT_CODE (NEXT_INSN (insn), NOTE);
06193 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06194 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06195 }
06196
06197
06198
06199
06200
06201
06202
06203
06204
06205
06206
06207
06208
06209
06210
06211
06212
06213
06214
06215
06216
06217 if (TARGET_64BIT)
06218 {
06219 if (actual_fsize == 0 && !regs_ever_live[2])
06220
06221 output_asm_insn ("std %%r1,-16(%%r30)", xoperands);
06222 else
06223
06224
06225 output_asm_insn ("std %%r1,-40(%%r30)", xoperands);
06226 }
06227 else
06228 {
06229 if (actual_fsize == 0 && !regs_ever_live[2])
06230
06231 output_asm_insn ("stw %%r1,-20(%%r30)", xoperands);
06232 else
06233
06234
06235
06236
06237
06238
06239 output_asm_insn ("stw %%r1,-12(%%r30)", xoperands);
06240 }
06241
06242 if (TARGET_PORTABLE_RUNTIME)
06243 {
06244 output_asm_insn ("ldil L'%0,%%r1", xoperands);
06245 output_asm_insn ("ldo R'%0(%%r1),%%r1", xoperands);
06246 output_asm_insn ("bv %%r0(%%r1)", xoperands);
06247 }
06248 else if (flag_pic)
06249 {
06250 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
06251 if (TARGET_SOM || !TARGET_GAS)
06252 {
06253 xoperands[1] = gen_label_rtx ();
06254 output_asm_insn ("addil L'%l0-%l1,%%r1", xoperands);
06255 (*targetm.asm_out.internal_label) (asm_out_file, "L",
06256 CODE_LABEL_NUMBER (xoperands[1]));
06257 output_asm_insn ("ldo R'%l0-%l1(%%r1),%%r1", xoperands);
06258 }
06259 else
06260 {
06261 output_asm_insn ("addil L'%l0-$PIC_pcrel$0+4,%%r1", xoperands);
06262 output_asm_insn ("ldo R'%l0-$PIC_pcrel$0+8(%%r1),%%r1", xoperands);
06263 }
06264 output_asm_insn ("bv %%r0(%%r1)", xoperands);
06265 }
06266 else
06267
06268 output_asm_insn ("ldil L'%l0,%%r1\n\tbe R'%l0(%%sr4,%%r1)", xoperands);
06269
06270
06271 if (TARGET_64BIT)
06272 {
06273 if (actual_fsize == 0 && !regs_ever_live[2])
06274 return "ldd -16(%%r30),%%r1";
06275 else
06276 return "ldd -40(%%r30),%%r1";
06277 }
06278 else
06279 {
06280 if (actual_fsize == 0 && !regs_ever_live[2])
06281 return "ldw -20(%%r30),%%r1";
06282 else
06283 return "ldw -12(%%r30),%%r1";
06284 }
06285 }
06286
06287
06288
06289
06290
06291
06292 const char *
06293 output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
06294 {
06295 static char buf[100];
06296 int useskip = 0;
06297 int nullify = INSN_ANNULLED_BRANCH_P (insn);
06298 int length = get_attr_length (insn);
06299 int xdelay;
06300
06301
06302
06303
06304
06305
06306 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
06307 return "nop";
06308
06309
06310
06311 if (length == 8 && dbr_sequence_length () == 0)
06312 nullify = 1;
06313
06314
06315
06316 if (! nullify && length == 4 && dbr_sequence_length () == 0)
06317 nullify = forward_branch_p (insn);
06318
06319
06320
06321
06322
06323 if (length == 4
06324 && next_real_insn (insn) != 0
06325 && get_attr_length (next_real_insn (insn)) == 4
06326 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
06327 && nullify)
06328 useskip = 1;
06329
06330 switch (length)
06331 {
06332
06333
06334
06335 case 4:
06336 if (useskip)
06337 strcpy (buf, "{extrs,|extrw,s,}");
06338 else
06339 strcpy (buf, "bb,");
06340 if (useskip && GET_MODE (operands[0]) == DImode)
06341 strcpy (buf, "extrd,s,*");
06342 else if (GET_MODE (operands[0]) == DImode)
06343 strcpy (buf, "bb,*");
06344 if ((which == 0 && negated)
06345 || (which == 1 && ! negated))
06346 strcat (buf, ">=");
06347 else
06348 strcat (buf, "<");
06349 if (useskip)
06350 strcat (buf, " %0,%1,1,%%r0");
06351 else if (nullify && negated)
06352 strcat (buf, ",n %0,%1,%3");
06353 else if (nullify && ! negated)
06354 strcat (buf, ",n %0,%1,%2");
06355 else if (! nullify && negated)
06356 strcat (buf, "%0,%1,%3");
06357 else if (! nullify && ! negated)
06358 strcat (buf, " %0,%1,%2");
06359 break;
06360
06361
06362
06363
06364 case 8:
06365
06366
06367 if (dbr_sequence_length () != 0
06368 && ! forward_branch_p (insn)
06369 && nullify)
06370 {
06371 strcpy (buf, "bb,");
06372 if (GET_MODE (operands[0]) == DImode)
06373 strcat (buf, "*");
06374 if ((which == 0 && negated)
06375 || (which == 1 && ! negated))
06376 strcat (buf, "<");
06377 else
06378 strcat (buf, ">=");
06379 if (negated)
06380 strcat (buf, ",n %0,%1,.+12\n\tb %3");
06381 else
06382 strcat (buf, ",n %0,%1,.+12\n\tb %2");
06383 }
06384
06385
06386
06387 else if (dbr_sequence_length () == 0
06388 && ! forward_branch_p (insn)
06389 && INSN_ADDRESSES_SET_P ()
06390 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
06391 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
06392 {
06393 strcpy (buf, "bb,");
06394 if (GET_MODE (operands[0]) == DImode)
06395 strcat (buf, "*");
06396 if ((which == 0 && negated)
06397 || (which == 1 && ! negated))
06398 strcat (buf, ">=");
06399 else
06400 strcat (buf, "<");
06401 if (negated)
06402 strcat (buf, " %0,%1,%3%#");
06403 else
06404 strcat (buf, " %0,%1,%2%#");
06405 }
06406 else
06407 {
06408 if (GET_MODE (operands[0]) == DImode)
06409 strcpy (buf, "extrd,s,*");
06410 else
06411 strcpy (buf, "{extrs,|extrw,s,}");
06412 if ((which == 0 && negated)
06413 || (which == 1 && ! negated))
06414 strcat (buf, "<");
06415 else
06416 strcat (buf, ">=");
06417 if (nullify && negated)
06418 strcat (buf, " %0,%1,1,%%r0\n\tb,n %3");
06419 else if (nullify && ! negated)
06420 strcat (buf, " %0,%1,1,%%r0\n\tb,n %2");
06421 else if (negated)
06422 strcat (buf, " %0,%1,1,%%r0\n\tb %3");
06423 else
06424 strcat (buf, " %0,%1,1,%%r0\n\tb %2");
06425 }
06426 break;
06427
06428 default:
06429
06430
06431
06432
06433
06434 if (dbr_sequence_length () == 0
06435 || (nullify && forward_branch_p (insn)))
06436 {
06437 nullify = 1;
06438 xdelay = 0;
06439 operands[4] = GEN_INT (length);
06440 }
06441 else
06442 {
06443 xdelay = 1;
06444 operands[4] = GEN_INT (length + 4);
06445 }
06446
06447 if (GET_MODE (operands[0]) == DImode)
06448 strcpy (buf, "bb,*");
06449 else
06450 strcpy (buf, "bb,");
06451 if ((which == 0 && negated)
06452 || (which == 1 && !negated))
06453 strcat (buf, "<");
06454 else
06455 strcat (buf, ">=");
06456 if (nullify)
06457 strcat (buf, ",n %0,%1,.+%4");
06458 else
06459 strcat (buf, " %0,%1,.+%4");
06460 output_asm_insn (buf, operands);
06461 return output_lbranch (negated ? operands[3] : operands[2],
06462 insn, xdelay);
06463 }
06464 return buf;
06465 }
06466
06467
06468
06469
06470
06471
06472
06473 const char *
06474 output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
06475 {
06476 static char buf[100];
06477 int useskip = 0;
06478 int nullify = INSN_ANNULLED_BRANCH_P (insn);
06479 int length = get_attr_length (insn);
06480 int xdelay;
06481
06482
06483
06484
06485
06486
06487 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
06488 return "nop";
06489
06490
06491
06492 if (length == 8 && dbr_sequence_length () == 0)
06493 nullify = 1;
06494
06495
06496
06497 if (! nullify && length == 4 && dbr_sequence_length () == 0)
06498 nullify = forward_branch_p (insn);
06499
06500
06501
06502
06503
06504 if (length == 4
06505 && next_real_insn (insn) != 0
06506 && get_attr_length (next_real_insn (insn)) == 4
06507 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
06508 && nullify)
06509 useskip = 1;
06510
06511 switch (length)
06512 {
06513
06514
06515
06516 case 4:
06517 if (useskip)
06518 strcpy (buf, "{vextrs,|extrw,s,}");
06519 else
06520 strcpy (buf, "{bvb,|bb,}");
06521 if (useskip && GET_MODE (operands[0]) == DImode)
06522 strcpy (buf, "extrd,s,*");
06523 else if (GET_MODE (operands[0]) == DImode)
06524 strcpy (buf, "bb,*");
06525 if ((which == 0 && negated)
06526 || (which == 1 && ! negated))
06527 strcat (buf, ">=");
06528 else
06529 strcat (buf, "<");
06530 if (useskip)
06531 strcat (buf, "{ %0,1,%%r0| %0,%%sar,1,%%r0}");
06532 else if (nullify && negated)
06533 strcat (buf, "{,n %0,%3|,n %0,%%sar,%3}");
06534 else if (nullify && ! negated)
06535 strcat (buf, "{,n %0,%2|,n %0,%%sar,%2}");
06536 else if (! nullify && negated)
06537 strcat (buf, "{%0,%3|%0,%%sar,%3}");
06538 else if (! nullify && ! negated)
06539 strcat (buf, "{ %0,%2| %0,%%sar,%2}");
06540 break;
06541
06542
06543
06544
06545 case 8:
06546
06547
06548 if (dbr_sequence_length () != 0
06549 && ! forward_branch_p (insn)
06550 && nullify)
06551 {
06552 strcpy (buf, "{bvb,|bb,}");
06553 if (GET_MODE (operands[0]) == DImode)
06554 strcat (buf, "*");
06555 if ((which == 0 && negated)
06556 || (which == 1 && ! negated))
06557 strcat (buf, "<");
06558 else
06559 strcat (buf, ">=");
06560 if (negated)
06561 strcat (buf, "{,n %0,.+12\n\tb %3|,n %0,%%sar,.+12\n\tb %3}");
06562 else
06563 strcat (buf, "{,n %0,.+12\n\tb %2|,n %0,%%sar,.+12\n\tb %2}");
06564 }
06565
06566
06567
06568 else if (dbr_sequence_length () == 0
06569 && ! forward_branch_p (insn)
06570 && INSN_ADDRESSES_SET_P ()
06571 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
06572 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
06573 {
06574 strcpy (buf, "{bvb,|bb,}");
06575 if (GET_MODE (operands[0]) == DImode)
06576 strcat (buf, "*");
06577 if ((which == 0 && negated)
06578 || (which == 1 && ! negated))
06579 strcat (buf, ">=");
06580 else
06581 strcat (buf, "<");
06582 if (negated)
06583 strcat (buf, "{ %0,%3%#| %0,%%sar,%3%#}");
06584 else
06585 strcat (buf, "{ %0,%2%#| %0,%%sar,%2%#}");
06586 }
06587 else
06588 {
06589 strcpy (buf, "{vextrs,|extrw,s,}");
06590 if (GET_MODE (operands[0]) == DImode)
06591 strcpy (buf, "extrd,s,*");
06592 if ((which == 0 && negated)
06593 || (which == 1 && ! negated))
06594 strcat (buf, "<");
06595 else
06596 strcat (buf, ">=");
06597 if (nullify && negated)
06598 strcat (buf, "{ %0,1,%%r0\n\tb,n %3| %0,%%sar,1,%%r0\n\tb,n %3}");
06599 else if (nullify && ! negated)
06600 strcat (buf, "{ %0,1,%%r0\n\tb,n %2| %0,%%sar,1,%%r0\n\tb,n %2}");
06601 else if (negated)
06602 strcat (buf, "{ %0,1,%%r0\n\tb %3| %0,%%sar,1,%%r0\n\tb %3}");
06603 else
06604 strcat (buf, "{ %0,1,%%r0\n\tb %2| %0,%%sar,1,%%r0\n\tb %2}");
06605 }
06606 break;
06607
06608 default:
06609
06610
06611
06612
06613
06614 if (dbr_sequence_length () == 0
06615 || (nullify && forward_branch_p (insn)))
06616 {
06617 nullify = 1;
06618 xdelay = 0;
06619 operands[4] = GEN_INT (length);
06620 }
06621 else
06622 {
06623 xdelay = 1;
06624 operands[4] = GEN_INT (length + 4);
06625 }
06626
06627 if (GET_MODE (operands[0]) == DImode)
06628 strcpy (buf, "bb,*");
06629 else
06630 strcpy (buf, "{bvb,|bb,}");
06631 if ((which == 0 && negated)
06632 || (which == 1 && !negated))
06633 strcat (buf, "<");
06634 else
06635 strcat (buf, ">=");
06636 if (nullify)
06637 strcat (buf, ",n {%0,.+%4|%0,%%sar,.+%4}");
06638 else
06639 strcat (buf, " {%0,.+%4|%0,%%sar,.+%4}");
06640 output_asm_insn (buf, operands);
06641 return output_lbranch (negated ? operands[3] : operands[2],
06642 insn, xdelay);
06643 }
06644 return buf;
06645 }
06646
06647
06648
06649
06650
06651 const char *
06652 output_dbra (rtx *operands, rtx insn, int which_alternative)
06653 {
06654 int length = get_attr_length (insn);
06655
06656
06657
06658
06659 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
06660 {
06661 if (which_alternative == 0)
06662 return "ldo %1(%0),%0";
06663 else if (which_alternative == 1)
06664 {
06665 output_asm_insn ("{fstws|fstw} %0,-16(%%r30)", operands);
06666 output_asm_insn ("ldw -16(%%r30),%4", operands);
06667 output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
06668 return "{fldws|fldw} -16(%%r30),%0";
06669 }
06670 else
06671 {
06672 output_asm_insn ("ldw %0,%4", operands);
06673 return "ldo %1(%4),%4\n\tstw %4,%0";
06674 }
06675 }
06676
06677 if (which_alternative == 0)
06678 {
06679 int nullify = INSN_ANNULLED_BRANCH_P (insn);
06680 int xdelay;
06681
06682
06683
06684 if (length == 8 && dbr_sequence_length () == 0)
06685 nullify = 1;
06686
06687
06688
06689 if (! nullify && length == 4 && dbr_sequence_length () == 0)
06690 nullify = forward_branch_p (insn);
06691
06692 switch (length)
06693 {
06694 case 4:
06695 if (nullify)
06696 return "addib,%C2,n %1,%0,%3";
06697 else
06698 return "addib,%C2 %1,%0,%3";
06699
06700 case 8:
06701
06702
06703 if (dbr_sequence_length () != 0
06704 && ! forward_branch_p (insn)
06705 && nullify)
06706 return "addib,%N2,n %1,%0,.+12\n\tb %3";
06707
06708
06709
06710 else if (dbr_sequence_length () == 0
06711 && ! forward_branch_p (insn)
06712 && INSN_ADDRESSES_SET_P ()
06713 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
06714 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
06715 return "addib,%C2 %1,%0,%3%#";
06716
06717
06718 if (nullify)
06719 return "addi,%N2 %1,%0,%0\n\tb,n %3";
06720 else
06721 return "addi,%N2 %1,%0,%0\n\tb %3";
06722
06723 default:
06724
06725
06726
06727
06728
06729 if (dbr_sequence_length () == 0
06730 || (nullify && forward_branch_p (insn)))
06731 {
06732 nullify = 1;
06733 xdelay = 0;
06734 operands[4] = GEN_INT (length);
06735 }
06736 else
06737 {
06738 xdelay = 1;
06739 operands[4] = GEN_INT (length + 4);
06740 }
06741
06742 if (nullify)
06743 output_asm_insn ("addib,%N2,n %1,%0,.+%4", operands);
06744 else
06745 output_asm_insn ("addib,%N2 %1,%0,.+%4", operands);
06746
06747 return output_lbranch (operands[3], insn, xdelay);
06748 }
06749
06750 }
06751
06752 else if (which_alternative == 1)
06753 {
06754
06755
06756
06757 output_asm_insn ("{fstws|fstw} %0,-16(%%r30)\n\tldw -16(%%r30),%4",
06758 operands);
06759 output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
06760 if (length == 24)
06761 return "{comb|cmpb},%S2 %%r0,%4,%3\n\t{fldws|fldw} -16(%%r30),%0";
06762 else if (length == 28)
06763 return "{comclr|cmpclr},%B2 %%r0,%4,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
06764 else
06765 {
06766 operands[5] = GEN_INT (length - 16);
06767 output_asm_insn ("{comb|cmpb},%B2 %%r0,%4,.+%5", operands);
06768 output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
06769 return output_lbranch (operands[3], insn, 0);
06770 }
06771 }
06772
06773 else
06774 {
06775
06776
06777 output_asm_insn ("ldw %0,%4", operands);
06778 if (length == 12)
06779 return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
06780 else if (length == 16)
06781 return "addi,%N2 %1,%4,%4\n\tb %3\n\tstw %4,%0";
06782 else
06783 {
06784 operands[5] = GEN_INT (length - 4);
06785 output_asm_insn ("addib,%N2 %1,%4,.+%5\n\tstw %4,%0", operands);
06786 return output_lbranch (operands[3], insn, 0);
06787 }
06788 }
06789 }
06790
06791
06792
06793
06794
06795 const char *
06796 output_movb (rtx *operands, rtx insn, int which_alternative,
06797 int reverse_comparison)
06798 {
06799 int length = get_attr_length (insn);
06800
06801
06802
06803
06804 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn))
06805 {
06806 if (which_alternative == 0)
06807 return "copy %1,%0";
06808 else if (which_alternative == 1)
06809 {
06810 output_asm_insn ("stw %1,-16(%%r30)", operands);
06811 return "{fldws|fldw} -16(%%r30),%0";
06812 }
06813 else if (which_alternative == 2)
06814 return "stw %1,%0";
06815 else
06816 return "mtsar %r1";
06817 }
06818
06819
06820 if (reverse_comparison)
06821 PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
06822
06823 if (which_alternative == 0)
06824 {
06825 int nullify = INSN_ANNULLED_BRANCH_P (insn);
06826 int xdelay;
06827
06828
06829
06830 if (length == 8 && dbr_sequence_length () == 0)
06831 nullify = 1;
06832
06833
06834
06835 if (! nullify && length == 4 && dbr_sequence_length () == 0)
06836 nullify = forward_branch_p (insn);
06837
06838 switch (length)
06839 {
06840 case 4:
06841 if (nullify)
06842 return "movb,%C2,n %1,%0,%3";
06843 else
06844 return "movb,%C2 %1,%0,%3";
06845
06846 case 8:
06847
06848
06849 if (dbr_sequence_length () != 0
06850 && ! forward_branch_p (insn)
06851 && nullify)
06852 return "movb,%N2,n %1,%0,.+12\n\tb %3";
06853
06854
06855
06856
06857 else if (dbr_sequence_length () == 0
06858 && ! forward_branch_p (insn)
06859 && INSN_ADDRESSES_SET_P ()
06860 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
06861 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
06862 return "movb,%C2 %1,%0,%3%#";
06863
06864 if (nullify)
06865 return "or,%N2 %1,%%r0,%0\n\tb,n %3";
06866 else
06867 return "or,%N2 %1,%%r0,%0\n\tb %3";
06868
06869 default:
06870
06871
06872
06873
06874
06875 if (dbr_sequence_length () == 0
06876 || (nullify && forward_branch_p (insn)))
06877 {
06878 nullify = 1;
06879 xdelay = 0;
06880 operands[4] = GEN_INT (length);
06881 }
06882 else
06883 {
06884 xdelay = 1;
06885 operands[4] = GEN_INT (length + 4);
06886 }
06887
06888 if (nullify)
06889 output_asm_insn ("movb,%N2,n %1,%0,.+%4", operands);
06890 else
06891 output_asm_insn ("movb,%N2 %1,%0,.+%4", operands);
06892
06893 return output_lbranch (operands[3], insn, xdelay);
06894 }
06895 }
06896
06897 else if (which_alternative == 1)
06898 {
06899
06900
06901
06902 output_asm_insn ("stw %1,-16(%%r30)", operands);
06903 if (length == 12)
06904 return "{comb|cmpb},%S2 %%r0,%1,%3\n\t{fldws|fldw} -16(%%r30),%0";
06905 else if (length == 16)
06906 return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
06907 else
06908 {
06909 operands[4] = GEN_INT (length - 4);
06910 output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4", operands);
06911 output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
06912 return output_lbranch (operands[3], insn, 0);
06913 }
06914 }
06915
06916 else if (which_alternative == 2)
06917 {
06918
06919
06920 if (length == 8)
06921 return "{comb|cmpb},%S2 %%r0,%1,%3\n\tstw %1,%0";
06922 else if (length == 12)
06923 return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tstw %1,%0";
06924 else
06925 {
06926 operands[4] = GEN_INT (length);
06927 output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4\n\tstw %1,%0",
06928 operands);
06929 return output_lbranch (operands[3], insn, 0);
06930 }
06931 }
06932
06933 else
06934 {
06935 if (length == 8)
06936 return "{comb|cmpb},%S2 %%r0,%1,%3\n\tmtsar %r1";
06937 else if (length == 12)
06938 return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tmtsar %r1";
06939 else
06940 {
06941 operands[4] = GEN_INT (length);
06942 output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4\n\tmtsar %r1",
06943 operands);
06944 return output_lbranch (operands[3], insn, 0);
06945 }
06946 }
06947 }
06948
06949
06950 static void
06951 copy_fp_args (rtx insn)
06952 {
06953 rtx link;
06954 rtx xoperands[2];
06955
06956 for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
06957 {
06958 int arg_mode, regno;
06959 rtx use = XEXP (link, 0);
06960
06961 if (! (GET_CODE (use) == USE
06962 && GET_CODE (XEXP (use, 0)) == REG
06963 && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
06964 continue;
06965
06966 arg_mode = GET_MODE (XEXP (use, 0));
06967 regno = REGNO (XEXP (use, 0));
06968
06969
06970 if (regno >= 32 && regno <= 39)
06971 {
06972
06973 if (arg_mode == SFmode)
06974 {
06975 xoperands[0] = XEXP (use, 0);
06976 xoperands[1] = gen_rtx_REG (SImode, 26 - (regno - 32) / 2);
06977 output_asm_insn ("{fstws|fstw} %0,-16(%%sr0,%%r30)", xoperands);
06978 output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
06979 }
06980 else
06981 {
06982 xoperands[0] = XEXP (use, 0);
06983 xoperands[1] = gen_rtx_REG (DImode, 25 - (regno - 34) / 2);
06984 output_asm_insn ("{fstds|fstd} %0,-16(%%sr0,%%r30)", xoperands);
06985 output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands);
06986 output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
06987 }
06988 }
06989 }
06990 }
06991
06992
06993 static int
06994 length_fp_args (rtx insn)
06995 {
06996 int length = 0;
06997 rtx link;
06998
06999 for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
07000 {
07001 int arg_mode, regno;
07002 rtx use = XEXP (link, 0);
07003
07004 if (! (GET_CODE (use) == USE
07005 && GET_CODE (XEXP (use, 0)) == REG
07006 && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
07007 continue;
07008
07009 arg_mode = GET_MODE (XEXP (use, 0));
07010 regno = REGNO (XEXP (use, 0));
07011
07012
07013 if (regno >= 32 && regno <= 39)
07014 {
07015 if (arg_mode == SFmode)
07016 length += 8;
07017 else
07018 length += 12;
07019 }
07020 }
07021
07022 return length;
07023 }
07024
07025
07026
07027
07028
07029
07030 int
07031 attr_length_millicode_call (rtx insn)
07032 {
07033 unsigned long distance = -1;
07034 unsigned long total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
07035
07036 if (INSN_ADDRESSES_SET_P ())
07037 {
07038 distance = (total + insn_current_reference_address (insn));
07039 if (distance < total)
07040 distance = -1;
07041 }
07042
07043 if (TARGET_64BIT)
07044 {
07045 if (!TARGET_LONG_CALLS && distance < 7600000)
07046 return 8;
07047
07048 return 20;
07049 }
07050 else if (TARGET_PORTABLE_RUNTIME)
07051 return 24;
07052 else
07053 {
07054 if (!TARGET_LONG_CALLS && distance < 240000)
07055 return 8;
07056
07057 if (TARGET_LONG_ABS_CALL && !flag_pic)
07058 return 12;
07059
07060 return 24;
07061 }
07062 }
07063
07064
07065
07066
07067
07068
07069 const char *
07070 output_millicode_call (rtx insn, rtx call_dest)
07071 {
07072 int attr_length = get_attr_length (insn);
07073 int seq_length = dbr_sequence_length ();
07074 int distance;
07075 rtx seq_insn;
07076 rtx xoperands[3];
07077
07078 xoperands[0] = call_dest;
07079 xoperands[2] = gen_rtx_REG (Pmode, TARGET_64BIT ? 2 : 31);
07080
07081
07082
07083
07084
07085
07086
07087 if (!TARGET_LONG_CALLS
07088 && ((seq_length == 0
07089 && (attr_length == 12
07090 || (attr_length == 28 && get_attr_type (insn) == TYPE_MULTI)))
07091 || (seq_length != 0 && attr_length == 8)))
07092 {
07093 output_asm_insn ("{bl|b,l} %0,%2", xoperands);
07094 }
07095 else
07096 {
07097 if (TARGET_64BIT)
07098 {
07099
07100
07101
07102
07103
07104 output_asm_insn ("b,l .+8,%%r1", xoperands);
07105
07106 if (TARGET_GAS)
07107 {
07108 output_asm_insn ("addil L'%0-$PIC_pcrel$0+4,%%r1", xoperands);
07109 output_asm_insn ("ldo R'%0-$PIC_pcrel$0+8(%%r1),%%r1", xoperands);
07110 }
07111 else
07112 {
07113 xoperands[1] = gen_label_rtx ();
07114 output_asm_insn ("addil L'%0-%l1,%%r1", xoperands);
07115 (*targetm.asm_out.internal_label) (asm_out_file, "L",
07116 CODE_LABEL_NUMBER (xoperands[1]));
07117 output_asm_insn ("ldo R'%0-%l1(%%r1),%%r1", xoperands);
07118 }
07119
07120 output_asm_insn ("bve,l (%%r1),%%r2", xoperands);
07121 }
07122 else if (TARGET_PORTABLE_RUNTIME)
07123 {
07124
07125
07126
07127
07128
07129 output_asm_insn ("ldil L'%0,%%r1", xoperands);
07130 output_asm_insn ("ldo R'%0(%%r1),%%r1", xoperands);
07131
07132
07133 output_asm_insn ("{bl|b,l} .+8,%%r31", xoperands);
07134 output_asm_insn ("addi 8,%%r31,%%r31", xoperands);
07135
07136
07137 output_asm_insn ("bv %%r0(%%r1)", xoperands);
07138 }
07139 else if (!flag_pic)
07140 {
07141 output_asm_insn ("ldil L'%0,%%r1", xoperands);
07142 if (TARGET_PA_20)
07143 output_asm_insn ("be,l R'%0(%%sr4,%%r1),%%sr0,%%r31", xoperands);
07144 else
07145 output_asm_insn ("ble R'%0(%%sr4,%%r1)", xoperands);
07146 }
07147 else
07148 {
07149 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
07150 output_asm_insn ("addi 16,%%r1,%%r31", xoperands);
07151
07152 if (TARGET_SOM || !TARGET_GAS)
07153 {
07154
07155
07156
07157
07158 xoperands[1] = gen_label_rtx ();
07159 (*targetm.asm_out.internal_label) (asm_out_file, "L",
07160 CODE_LABEL_NUMBER (xoperands[1]));
07161 output_asm_insn ("addil L'%0-%l1,%%r1", xoperands);
07162 output_asm_insn ("ldo R'%0-%l1(%%r1),%%r1", xoperands);
07163 }
07164 else
07165 {
07166 output_asm_insn ("addil L'%0-$PIC_pcrel$0+8,%%r1", xoperands);
07167 output_asm_insn ("ldo R'%0-$PIC_pcrel$0+12(%%r1),%%r1",
07168 xoperands);
07169 }
07170
07171
07172 output_asm_insn ("bv %%r0(%%r1)", xoperands);
07173 }
07174 }
07175
07176 if (seq_length == 0)
07177 output_asm_insn ("nop", xoperands);
07178
07179
07180 if (seq_length == 0 || GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
07181 return "";
07182
07183
07184 xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
07185
07186
07187
07188 if (INSN_ADDRESSES_SET_P ())
07189 {
07190 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
07191 distance = (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn))))
07192 - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8);
07193
07194 if (VAL_14_BITS_P (distance))
07195 {
07196 xoperands[1] = gen_label_rtx ();
07197 output_asm_insn ("ldo %0-%1(%2),%2", xoperands);
07198 (*targetm.asm_out.internal_label) (asm_out_file, "L",
07199 CODE_LABEL_NUMBER (xoperands[1]));
07200 }
07201 else
07202
07203 output_asm_insn ("nop\n\tb,n %0", xoperands);
07204 }
07205 else
07206
07207 output_asm_insn ("nop\n\tb,n %0", xoperands);
07208
07209
07210 PUT_CODE (NEXT_INSN (insn), NOTE);
07211 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
07212 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
07213
07214 return "";
07215 }
07216
07217
07218
07219
07220
07221
07222
07223
07224
07225
07226
07227
07228
07229
07230 int
07231 attr_length_call (rtx insn, int sibcall)
07232 {
07233 int local_call;
07234 rtx call_dest;
07235 tree call_decl;
07236 int length = 0;
07237 rtx pat = PATTERN (insn);
07238 unsigned long distance = -1;
07239
07240 if (INSN_ADDRESSES_SET_P ())
07241 {
07242 unsigned long total;
07243
07244 total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
07245 distance = (total + insn_current_reference_address (insn));
07246 if (distance < total)
07247 distance = -1;
07248 }
07249
07250
07251 if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL)
07252 call_dest = XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0);
07253 else
07254 call_dest = XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0);
07255
07256 call_decl = SYMBOL_REF_DECL (call_dest);
07257 local_call = call_decl && (*targetm.binds_local_p) (call_decl);
07258
07259
07260 if (!TARGET_LONG_CALLS
07261 && ((TARGET_PA_20 && !sibcall && distance < 7600000)
07262 || distance < 240000))
07263 length += 8;
07264
07265
07266 else if (TARGET_64BIT && !local_call)
07267 length += sibcall ? 28 : 24;
07268
07269
07270 else if ((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
07271 length += 12;
07272
07273
07274 else if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
07275 || (TARGET_64BIT && !TARGET_GAS)
07276 || (TARGET_GAS && !TARGET_SOM
07277 && (TARGET_LONG_PIC_PCREL_CALL || local_call)))
07278 {
07279 length += 20;
07280
07281 if (!TARGET_PA_20 && !TARGET_NO_SPACE_REGS)
07282 length += 8;
07283 }
07284
07285
07286 else
07287 {
07288 length += 32;
07289
07290 if (TARGET_SOM)
07291 length += length_fp_args (insn);
07292
07293 if (flag_pic)
07294 length += 4;
07295
07296 if (!TARGET_PA_20)
07297 {
07298 if (!sibcall)
07299 length += 8;
07300
07301 if (!TARGET_NO_SPACE_REGS)
07302 length += 8;
07303 }
07304 }
07305
07306 return length;
07307 }
07308
07309
07310
07311
07312
07313
07314 const char *
07315 output_call (rtx insn, rtx call_dest, int sibcall)
07316 {
07317 int delay_insn_deleted = 0;
07318 int delay_slot_filled = 0;
07319 int seq_length = dbr_sequence_length ();
07320 tree call_decl = SYMBOL_REF_DECL (call_dest);
07321 int local_call = call_decl && (*targetm.binds_local_p) (call_decl);
07322 rtx xoperands[2];
07323
07324 xoperands[0] = call_dest;
07325
07326
07327
07328
07329 if (!TARGET_LONG_CALLS && attr_length_call (insn, sibcall) == 8)
07330 {
07331 xoperands[1] = gen_rtx_REG (word_mode, sibcall ? 0 : 2);
07332 output_asm_insn ("{bl|b,l} %0,%1", xoperands);
07333 }
07334 else
07335 {
07336 if (TARGET_64BIT && !local_call)
07337 {
07338
07339
07340
07341 xoperands[0] = get_deferred_plabel (call_dest);
07342 xoperands[1] = gen_label_rtx ();
07343
07344
07345
07346
07347 if (seq_length != 0
07348 && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
07349 && !sibcall)
07350 {
07351 final_scan_insn (NEXT_INSN (insn), asm_out_file,
07352 optimize, 0, NULL);
07353
07354
07355 PUT_CODE (NEXT_INSN (insn), NOTE);
07356 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
07357 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
07358 delay_insn_deleted = 1;
07359 }
07360
07361 output_asm_insn ("addil LT'%0,%%r27", xoperands);
07362 output_asm_insn ("ldd RT'%0(%%r1),%%r1", xoperands);
07363 output_asm_insn ("ldd 0(%%r1),%%r1", xoperands);
07364
07365 if (sibcall)
07366 {
07367 output_asm_insn ("ldd 24(%%r1),%%r27", xoperands);
07368 output_asm_insn ("ldd 16(%%r1),%%r1", xoperands);
07369 output_asm_insn ("bve (%%r1)", xoperands);
07370 }
07371 else
07372 {
07373 output_asm_insn ("ldd 16(%%r1),%%r2", xoperands);
07374 output_asm_insn ("bve,l (%%r2),%%r2", xoperands);
07375 output_asm_insn ("ldd 24(%%r1),%%r27", xoperands);
07376 delay_slot_filled = 1;
07377 }
07378 }
07379 else
07380 {
07381 int indirect_call = 0;
07382
07383
07384
07385
07386 if (!((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
07387 && !(TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
07388 && !(TARGET_GAS && !TARGET_SOM
07389 && (TARGET_LONG_PIC_PCREL_CALL || local_call))
07390 && !TARGET_64BIT)
07391 indirect_call = 1;
07392
07393 if (seq_length != 0
07394 && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
07395 && !sibcall
07396 && (!TARGET_PA_20 || indirect_call))
07397 {
07398
07399
07400
07401 final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0,
07402 NULL);
07403
07404
07405 PUT_CODE (NEXT_INSN (insn), NOTE);
07406 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
07407 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
07408 delay_insn_deleted = 1;
07409 }
07410
07411 if ((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
07412 {
07413
07414
07415
07416
07417
07418 output_asm_insn ("ldil L'%0,%%r1", xoperands);
07419 if (sibcall)
07420 output_asm_insn ("be R'%0(%%sr4,%%r1)", xoperands);
07421 else
07422 {
07423 if (TARGET_PA_20)
07424 output_asm_insn ("be,l R'%0(%%sr4,%%r1),%%sr0,%%r31",
07425 xoperands);
07426 else
07427 output_asm_insn ("ble R'%0(%%sr4,%%r1)", xoperands);
07428
07429 output_asm_insn ("copy %%r31,%%r2", xoperands);
07430 delay_slot_filled = 1;
07431 }
07432 }
07433 else
07434 {
07435 if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
07436 || (TARGET_64BIT && !TARGET_GAS))
07437 {
07438
07439
07440
07441
07442 xoperands[1] = gen_label_rtx ();
07443 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
07444 output_asm_insn ("addil L'%0-%l1,%%r1", xoperands);
07445 (*targetm.asm_out.internal_label) (asm_out_file, "L",
07446 CODE_LABEL_NUMBER (xoperands[1]));
07447 output_asm_insn ("ldo R'%0-%l1(%%r1),%%r1", xoperands);
07448 }
07449 else if (TARGET_GAS && !TARGET_SOM
07450 && (TARGET_LONG_PIC_PCREL_CALL || local_call))
07451 {
07452
07453
07454
07455
07456
07457
07458 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
07459 output_asm_insn ("addil L'%0-$PIC_pcrel$0+4,%%r1",
07460 xoperands);
07461 output_asm_insn ("ldo R'%0-$PIC_pcrel$0+8(%%r1),%%r1",
07462 xoperands);
07463 }
07464 else
07465 {
07466
07467
07468
07469
07470 xoperands[0] = get_deferred_plabel (call_dest);
07471 xoperands[1] = gen_label_rtx ();
07472
07473
07474
07475
07476 if (TARGET_SOM)
07477 copy_fp_args (insn);
07478
07479 if (flag_pic)
07480 {
07481 output_asm_insn ("addil LT'%0,%%r19", xoperands);
07482 output_asm_insn ("ldw RT'%0(%%r1),%%r1", xoperands);
07483 output_asm_insn ("ldw 0(%%r1),%%r1", xoperands);
07484 }
07485 else
07486 {
07487 output_asm_insn ("addil LR'%0-$global$,%%r27",
07488 xoperands);
07489 output_asm_insn ("ldw RR'%0-$global$(%%r1),%%r1",
07490 xoperands);
07491 }
07492
07493 output_asm_insn ("bb,>=,n %%r1,30,.+16", xoperands);
07494 output_asm_insn ("depi 0,31,2,%%r1", xoperands);
07495 output_asm_insn ("ldw 4(%%sr0,%%r1),%%r19", xoperands);
07496 output_asm_insn ("ldw 0(%%sr0,%%r1),%%r1", xoperands);
07497
07498 if (!sibcall && !TARGET_PA_20)
07499 {
07500 output_asm_insn ("{bl|b,l} .+8,%%r2", xoperands);
07501 if (TARGET_NO_SPACE_REGS)
07502 output_asm_insn ("addi 8,%%r2,%%r2", xoperands);
07503 else
07504 output_asm_insn ("addi 16,%%r2,%%r2", xoperands);
07505 }
07506 }
07507
07508 if (TARGET_PA_20)
07509 {
07510 if (sibcall)
07511 output_asm_insn ("bve (%%r1)", xoperands);
07512 else
07513 {
07514 if (indirect_call)
07515 {
07516 output_asm_insn ("bve,l (%%r1),%%r2", xoperands);
07517 output_asm_insn ("stw %%r2,-24(%%sp)", xoperands);
07518 delay_slot_filled = 1;
07519 }
07520 else
07521 output_asm_insn ("bve,l (%%r1),%%r2", xoperands);
07522 }
07523 }
07524 else
07525 {
07526 if (!TARGET_NO_SPACE_REGS)
07527 output_asm_insn ("ldsid (%%r1),%%r31\n\tmtsp %%r31,%%sr0",
07528 xoperands);
07529
07530 if (sibcall)
07531 {
07532 if (TARGET_NO_SPACE_REGS)
07533 output_asm_insn ("be 0(%%sr4,%%r1)", xoperands);
07534 else
07535 output_asm_insn ("be 0(%%sr0,%%r1)", xoperands);
07536 }
07537 else
07538 {
07539 if (TARGET_NO_SPACE_REGS)
07540 output_asm_insn ("ble 0(%%sr4,%%r1)", xoperands);
07541 else
07542 output_asm_insn ("ble 0(%%sr0,%%r1)", xoperands);
07543
07544 if (indirect_call)
07545 output_asm_insn ("stw %%r31,-24(%%sp)", xoperands);
07546 else
07547 output_asm_insn ("copy %%r31,%%r2", xoperands);
07548 delay_slot_filled = 1;
07549 }
07550 }
07551 }
07552 }
07553 }
07554
07555 if (!delay_slot_filled && (seq_length == 0 || delay_insn_deleted))
07556 output_asm_insn ("nop", xoperands);
07557
07558
07559 if (seq_length == 0
07560 || delay_insn_deleted
07561 || GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
07562 return "";
07563
07564
07565 gcc_assert (!sibcall);
07566
07567
07568 xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
07569
07570 if (!delay_slot_filled && INSN_ADDRESSES_SET_P ())
07571 {
07572
07573
07574 rtx seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
07575 int distance = (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn))))
07576 - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8);
07577
07578 if (VAL_14_BITS_P (distance))
07579 {
07580 xoperands[1] = gen_label_rtx ();
07581 output_asm_insn ("ldo %0-%1(%%r2),%%r2", xoperands);
07582 (*targetm.asm_out.internal_label) (asm_out_file, "L",
07583 CODE_LABEL_NUMBER (xoperands[1]));
07584 }
07585 else
07586 output_asm_insn ("nop\n\tb,n %0", xoperands);
07587 }
07588 else
07589 output_asm_insn ("b,n %0", xoperands);
07590
07591
07592 PUT_CODE (NEXT_INSN (insn), NOTE);
07593 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
07594 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
07595
07596 return "";
07597 }
07598
07599
07600
07601
07602
07603
07604
07605 int
07606 attr_length_indirect_call (rtx insn)
07607 {
07608 unsigned long distance = -1;
07609 unsigned long total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
07610
07611 if (INSN_ADDRESSES_SET_P ())
07612 {
07613 distance = (total + insn_current_reference_address (insn));
07614 if (distance < total)
07615 distance = -1;
07616 }
07617
07618 if (TARGET_64BIT)
07619 return 12;
07620
07621 if (TARGET_FAST_INDIRECT_CALLS
07622 || (!TARGET_PORTABLE_RUNTIME
07623 && ((TARGET_PA_20 && !TARGET_SOM && distance < 7600000)
07624 || distance < 240000)))
07625 return 8;
07626
07627 if (flag_pic)
07628 return 24;
07629
07630 if (TARGET_PORTABLE_RUNTIME)
07631 return 20;
07632
07633
07634 return 12;
07635 }
07636
07637 const char *
07638 output_indirect_call (rtx insn, rtx call_dest)
07639 {
07640 rtx xoperands[1];
07641
07642 if (TARGET_64BIT)
07643 {
07644 xoperands[0] = call_dest;
07645 output_asm_insn ("ldd 16(%0),%%r2", xoperands);
07646 output_asm_insn ("bve,l (%%r2),%%r2\n\tldd 24(%0),%%r27", xoperands);
07647 return "";
07648 }
07649
07650
07651 if (TARGET_FAST_INDIRECT_CALLS)
07652 return "ble 0(%%sr4,%%r22)\n\tcopy %%r31,%%r2";
07653
07654
07655
07656
07657
07658
07659 if (attr_length_indirect_call (insn) == 8)
07660 {
07661
07662
07663
07664 if (TARGET_PA_20 && !TARGET_SOM)
07665 return ".CALL\tARGW0=GR\n\tb,l $$dyncall,%%r2\n\tcopy %%r2,%%r31";
07666 else
07667 return ".CALL\tARGW0=GR\n\tbl $$dyncall,%%r31\n\tcopy %%r31,%%r2";
07668 }
07669
07670
07671
07672 if (attr_length_indirect_call (insn) == 12)
07673 return ".CALL\tARGW0=GR\n\tldil L'$$dyncall,%%r2\n\tble R'$$dyncall(%%sr4,%%r2)\n\tcopy %%r31,%%r2";
07674
07675
07676 if (attr_length_indirect_call (insn) == 20)
07677 return "ldil L'$$dyncall,%%r31\n\tldo R'$$dyncall(%%r31),%%r31\n\tblr %%r0,%%r2\n\tbv,n %%r0(%%r31)\n\tnop";
07678
07679
07680 xoperands[0] = NULL_RTX;
07681 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
07682 if (TARGET_SOM || !TARGET_GAS)
07683 {
07684 xoperands[0] = gen_label_rtx ();
07685 output_asm_insn ("addil L'$$dyncall-%0,%%r1", xoperands);
07686 (*targetm.asm_out.internal_label) (asm_out_file, "L",
07687 CODE_LABEL_NUMBER (xoperands[0]));
07688 output_asm_insn ("ldo R'$$dyncall-%0(%%r1),%%r1", xoperands);
07689 }
07690 else
07691 {
07692 output_asm_insn ("addil L'$$dyncall-$PIC_pcrel$0+4,%%r1", xoperands);
07693 output_asm_insn ("ldo R'$$dyncall-$PIC_pcrel$0+8(%%r1),%%r1",
07694 xoperands);
07695 }
07696 output_asm_insn ("blr %%r0,%%r2", xoperands);
07697 output_asm_insn ("bv,n %%r0(%%r1)\n\tnop", xoperands);
07698 return "";
07699 }
07700
07701
07702
07703
07704
07705
07706
07707 int
07708 attr_length_save_restore_dltp (rtx insn)
07709 {
07710 if (find_reg_note (insn, REG_NORETURN, NULL_RTX))
07711 return 0;
07712
07713 return 8;
07714 }
07715
07716
07717
07718
07719
07720
07721 void
07722 hppa_encode_label (rtx sym)
07723 {
07724 const char *str = XSTR (sym, 0);
07725 int len = strlen (str) + 1;
07726 char *newstr, *p;
07727
07728 p = newstr = alloca (len + 1);
07729 *p++ = '@';
07730 strcpy (p, str);
07731
07732 XSTR (sym, 0) = ggc_alloc_string (newstr, len);
07733 }
07734
07735 static void
07736 pa_encode_section_info (tree decl, rtx rtl, int first)
07737 {
07738 default_encode_section_info (decl, rtl, first);
07739
07740 if (first && TEXT_SPACE_P (decl))
07741 {
07742 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
07743 if (TREE_CODE (decl) == FUNCTION_DECL)
07744 hppa_encode_label (XEXP (rtl, 0));
07745 }
07746 }
07747
07748
07749
07750 static const char *
07751 pa_strip_name_encoding (const char *str)
07752 {
07753 str += (*str == '@');
07754 str += (*str == '*');
07755 return str;
07756 }
07757
07758 int
07759 function_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
07760 {
07761 return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
07762 }
07763
07764
07765
07766
07767 int
07768 is_function_label_plus_const (rtx op)
07769 {
07770
07771 if (GET_CODE (op) == CONST)
07772 op = XEXP (op, 0);
07773
07774 return (GET_CODE (op) == PLUS
07775 && function_label_operand (XEXP (op, 0), Pmode)
07776 && GET_CODE (XEXP (op, 1)) == CONST_INT);
07777 }
07778
07779
07780
07781 static void
07782 pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
07783 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
07784 tree function)
07785 {
07786 static unsigned int current_thunk_number;
07787 int val_14 = VAL_14_BITS_P (delta);
07788 int nbytes = 0;
07789 char label[16];
07790 rtx xoperands[4];
07791
07792 xoperands[0] = XEXP (DECL_RTL (function), 0);
07793 xoperands[1] = XEXP (DECL_RTL (thunk_fndecl), 0);
07794 xoperands[2] = GEN_INT (delta);
07795
07796 ASM_OUTPUT_LABEL (file, XSTR (xoperands[1], 0));
07797 fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=0,NO_CALLS\n\t.ENTRY\n");
07798
07799
07800
07801
07802
07803
07804
07805
07806
07807
07808
07809
07810
07811
07812 if ((!TARGET_LONG_CALLS && TARGET_SOM && !TARGET_PORTABLE_RUNTIME
07813 && !(flag_pic && TREE_PUBLIC (function))
07814 && (TARGET_GAS || last_address < 262132))
07815 || (!TARGET_LONG_CALLS && !TARGET_SOM && !TARGET_PORTABLE_RUNTIME
07816 && ((targetm.have_named_sections
07817 && DECL_SECTION_NAME (thunk_fndecl) != NULL
07818
07819
07820
07821 && ((!TARGET_64BIT
07822 && (DECL_SECTION_NAME (thunk_fndecl)
07823 != DECL_SECTION_NAME (function)))
07824 || ((DECL_SECTION_NAME (thunk_fndecl)
07825 == DECL_SECTION_NAME (function))
07826 && last_address < 262132)))
07827 || (!targetm.have_named_sections && last_address < 262132))))
07828 {
07829 if (!val_14)
07830 output_asm_insn ("addil L'%2,%%r26", xoperands);
07831
07832 output_asm_insn ("b %0", xoperands);
07833
07834 if (val_14)
07835 {
07836 output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
07837 nbytes += 8;
07838 }
07839 else
07840 {
07841 output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
07842 nbytes += 12;
07843 }
07844 }
07845 else if (TARGET_64BIT)
07846 {
07847
07848
07849 if (!val_14)
07850 {
07851 output_asm_insn ("addil L'%2,%%r26", xoperands);
07852 output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
07853 }
07854
07855 output_asm_insn ("b,l .+8,%%r1", xoperands);
07856
07857 if (TARGET_GAS)
07858 {
07859 output_asm_insn ("addil L'%0-$PIC_pcrel$0+4,%%r1", xoperands);
07860 output_asm_insn ("ldo R'%0-$PIC_pcrel$0+8(%%r1),%%r1", xoperands);
07861 }
07862 else
07863 {
07864 xoperands[3] = GEN_INT (val_14 ? 8 : 16);
07865 output_asm_insn ("addil L'%0-%1-%3,%%r1", xoperands);
07866 }
07867
07868 if (val_14)
07869 {
07870 output_asm_insn ("bv %%r0(%%r1)", xoperands);
07871 output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
07872 nbytes += 20;
07873 }
07874 else
07875 {
07876 output_asm_insn ("bv,n %%r0(%%r1)", xoperands);
07877 nbytes += 24;
07878 }
07879 }
07880 else if (TARGET_PORTABLE_RUNTIME)
07881 {
07882 output_asm_insn ("ldil L'%0,%%r1", xoperands);
07883 output_asm_insn ("ldo R'%0(%%r1),%%r22", xoperands);
07884
07885 if (!val_14)
07886 output_asm_insn ("addil L'%2,%%r26", xoperands);
07887
07888 output_asm_insn ("bv %%r0(%%r22)", xoperands);
07889
07890 if (val_14)
07891 {
07892 output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
07893 nbytes += 16;
07894 }
07895 else
07896 {
07897 output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
07898 nbytes += 20;
07899 }
07900 }
07901 else if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
07902 {
07903
07904
07905
07906
07907
07908 ASM_GENERATE_INTERNAL_LABEL (label, "LTHN", current_thunk_number);
07909 xoperands[3] = gen_rtx_SYMBOL_REF (Pmode, label);
07910 output_asm_insn ("addil LT'%3,%%r19", xoperands);
07911 output_asm_insn ("ldw RT'%3(%%r1),%%r22", xoperands);
07912 output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
07913 output_asm_insn ("bb,>=,n %%r22,30,.+16", xoperands);
07914 output_asm_insn ("depi 0,31,2,%%r22", xoperands);
07915 output_asm_insn ("ldw 4(%%sr0,%%r22),%%r19", xoperands);
07916 output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
07917
07918 if (!val_14)
07919 {
07920 output_asm_insn ("addil L'%2,%%r26", xoperands);
07921 nbytes += 4;
07922 }
07923
07924 if (TARGET_PA_20)
07925 {
07926 output_asm_insn ("bve (%%r22)", xoperands);
07927 nbytes += 36;
07928 }
07929 else if (TARGET_NO_SPACE_REGS)
07930 {
07931 output_asm_insn ("be 0(%%sr4,%%r22)", xoperands);
07932 nbytes += 36;
07933 }
07934 else
07935 {
07936 output_asm_insn ("ldsid (%%sr0,%%r22),%%r21", xoperands);
07937 output_asm_insn ("mtsp %%r21,%%sr0", xoperands);
07938 output_asm_insn ("be 0(%%sr0,%%r22)", xoperands);
07939 nbytes += 44;
07940 }
07941
07942 if (val_14)
07943 output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
07944 else
07945 output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
07946 }
07947 else if (flag_pic)
07948 {
07949 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
07950
07951 if (TARGET_SOM || !TARGET_GAS)
07952 {
07953 output_asm_insn ("addil L'%0-%1-8,%%r1", xoperands);
07954 output_asm_insn ("ldo R'%0-%1-8(%%r1),%%r22", xoperands);
07955 }
07956 else
07957 {
07958 output_asm_insn ("addil L'%0-$PIC_pcrel$0+4,%%r1", xoperands);
07959 output_asm_insn ("ldo R'%0-$PIC_pcrel$0+8(%%r1),%%r22", xoperands);
07960 }
07961
07962 if (!val_14)
07963 output_asm_insn ("addil L'%2,%%r26", xoperands);
07964
07965 output_asm_insn ("bv %%r0(%%r22)", xoperands);
07966
07967 if (val_14)
07968 {
07969 output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
07970 nbytes += 20;
07971 }
07972 else
07973 {
07974 output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
07975 nbytes += 24;
07976 }
07977 }
07978 else
07979 {
07980 if (!val_14)
07981 output_asm_insn ("addil L'%2,%%r26", xoperands);
07982
07983 output_asm_insn ("ldil L'%0,%%r22", xoperands);
07984 output_asm_insn ("be R'%0(%%sr4,%%r22)", xoperands);
07985
07986 if (val_14)
07987 {
07988 output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
07989 nbytes += 12;
07990 }
07991 else
07992 {
07993 output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
07994 nbytes += 16;
07995 }
07996 }
07997
07998 fprintf (file, "\t.EXIT\n\t.PROCEND\n");
07999
08000 if (TARGET_SOM && TARGET_GAS)
08001 {
08002
08003
08004
08005 in_section = NULL;
08006 cfun->machine->in_nsubspa = 2;
08007 }
08008
08009 if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
08010 {
08011 switch_to_section (data_section);
08012 output_asm_insn (".align 4", xoperands);
08013 ASM_OUTPUT_LABEL (file, label);
08014 output_asm_insn (".word P'%0", xoperands);
08015 }
08016
08017 current_thunk_number++;
08018 nbytes = ((nbytes + FUNCTION_BOUNDARY / BITS_PER_UNIT - 1)
08019 & ~(FUNCTION_BOUNDARY / BITS_PER_UNIT - 1));
08020 last_address += nbytes;
08021 update_total_code_bytes (nbytes);
08022 }
08023
08024
08025
08026
08027
08028
08029
08030
08031
08032
08033
08034
08035
08036
08037
08038
08039
08040
08041
08042
08043
08044
08045
08046
08047 static bool
08048 pa_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
08049 {
08050 if (TARGET_PORTABLE_RUNTIME)
08051 return false;
08052
08053
08054
08055
08056
08057
08058 if (TARGET_ELF32)
08059 return (decl != NULL_TREE);
08060
08061
08062
08063
08064
08065
08066
08067 if (TARGET_64BIT)
08068 return false;
08069
08070
08071 return (decl && !TREE_PUBLIC (decl));
08072 }
08073
08074
08075
08076
08077 static bool
08078 pa_commutative_p (rtx x, int outer_code)
08079 {
08080 return (COMMUTATIVE_P (x)
08081 && (TARGET_NO_SPACE_REGS
08082 || (outer_code != UNKNOWN && outer_code != MEM)
08083 || GET_CODE (x) != PLUS));
08084 }
08085
08086
08087
08088 int
08089 fmpyaddoperands (rtx *operands)
08090 {
08091 enum machine_mode mode = GET_MODE (operands[0]);
08092
08093
08094 if (mode != SFmode && mode != DFmode)
08095 return 0;
08096
08097
08098 if (! (mode == GET_MODE (operands[1])
08099 && mode == GET_MODE (operands[2])
08100 && mode == GET_MODE (operands[3])
08101 && mode == GET_MODE (operands[4])
08102 && mode == GET_MODE (operands[5])))
08103 return 0;
08104
08105
08106 if (! (GET_CODE (operands[1]) == REG
08107 && GET_CODE (operands[2]) == REG
08108 && GET_CODE (operands[3]) == REG
08109 && GET_CODE (operands[4]) == REG
08110 && GET_CODE (operands[5]) == REG))
08111 return 0;
08112
08113
08114
08115 if (! rtx_equal_p (operands[3], operands[4])
08116 && ! rtx_equal_p (operands[3], operands[5]))
08117 return 0;
08118
08119
08120 if (rtx_equal_p (operands[3], operands[0])
08121 || rtx_equal_p (operands[3], operands[1])
08122 || rtx_equal_p (operands[3], operands[2]))
08123 return 0;
08124
08125
08126 if (rtx_equal_p (operands[4], operands[0])
08127 || rtx_equal_p (operands[5], operands[0]))
08128 return 0;
08129
08130
08131 if (mode == SFmode
08132 && (REGNO_REG_CLASS (REGNO (operands[0])) != FPUPPER_REGS
08133 || REGNO_REG_CLASS (REGNO (operands[1])) != FPUPPER_REGS
08134 || REGNO_REG_CLASS (REGNO (operands[2])) != FPUPPER_REGS
08135 || REGNO_REG_CLASS (REGNO (operands[3])) != FPUPPER_REGS
08136 || REGNO_REG_CLASS (REGNO (operands[4])) != FPUPPER_REGS
08137 || REGNO_REG_CLASS (REGNO (operands[5])) != FPUPPER_REGS))
08138 return 0;
08139
08140
08141 return 1;
08142 }
08143
08144 #if !defined(USE_COLLECT2)
08145 static void
08146 pa_asm_out_constructor (rtx symbol, int priority)
08147 {
08148 if (!function_label_operand (symbol, VOIDmode))
08149 hppa_encode_label (symbol);
08150
08151 #ifdef CTORS_SECTION_ASM_OP
08152 default_ctor_section_asm_out_constructor (symbol, priority);
08153 #else
08154 # ifdef TARGET_ASM_NAMED_SECTION
08155 default_named_section_asm_out_constructor (symbol, priority);
08156 # else
08157 default_stabs_asm_out_constructor (symbol, priority);
08158 # endif
08159 #endif
08160 }
08161
08162 static void
08163 pa_asm_out_destructor (rtx symbol, int priority)
08164 {
08165 if (!function_label_operand (symbol, VOIDmode))
08166 hppa_encode_label (symbol);
08167
08168 #ifdef DTORS_SECTION_ASM_OP
08169 default_dtor_section_asm_out_destructor (symbol, priority);
08170 #else
08171 # ifdef TARGET_ASM_NAMED_SECTION
08172 default_named_section_asm_out_destructor (symbol, priority);
08173 # else
08174 default_stabs_asm_out_destructor (symbol, priority);
08175 # endif
08176 #endif
08177 }
08178 #endif
08179
08180
08181
08182
08183
08184
08185 void
08186 pa_asm_output_aligned_bss (FILE *stream,
08187 const char *name,
08188 unsigned HOST_WIDE_INT size,
08189 unsigned int align)
08190 {
08191 switch_to_section (bss_section);
08192 fprintf (stream, "\t.align %u\n", align / BITS_PER_UNIT);
08193
08194 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
08195 ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
08196 #endif
08197
08198 #ifdef ASM_OUTPUT_SIZE_DIRECTIVE
08199 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
08200 #endif
08201
08202 fprintf (stream, "\t.align %u\n", align / BITS_PER_UNIT);
08203 ASM_OUTPUT_LABEL (stream, name);
08204 fprintf (stream, "\t.block "HOST_WIDE_INT_PRINT_UNSIGNED"\n", size);
08205 }
08206
08207
08208
08209
08210
08211
08212
08213
08214 void
08215 pa_asm_output_aligned_common (FILE *stream,
08216 const char *name,
08217 unsigned HOST_WIDE_INT size,
08218 unsigned int align)
08219 {
08220 unsigned int max_common_align;
08221
08222 max_common_align = TARGET_64BIT ? 128 : (size >= 4096 ? 256 : 64);
08223 if (align > max_common_align)
08224 {
08225 warning (0, "alignment (%u) for %s exceeds maximum alignment "
08226 "for global common data. Using %u",
08227 align / BITS_PER_UNIT, name, max_common_align / BITS_PER_UNIT);
08228 align = max_common_align;
08229 }
08230
08231 switch_to_section (bss_section);
08232
08233 assemble_name (stream, name);
08234 fprintf (stream, "\t.comm "HOST_WIDE_INT_PRINT_UNSIGNED"\n",
08235 MAX (size, align / BITS_PER_UNIT));
08236 }
08237
08238
08239
08240
08241
08242
08243
08244
08245 void
08246 pa_asm_output_aligned_local (FILE *stream,
08247 const char *name,
08248 unsigned HOST_WIDE_INT size,
08249 unsigned int align)
08250 {
08251 switch_to_section (bss_section);
08252 fprintf (stream, "\t.align %u\n", align / BITS_PER_UNIT);
08253
08254 #ifdef LOCAL_ASM_OP
08255 fprintf (stream, "%s", LOCAL_ASM_OP);
08256 assemble_name (stream, name);
08257 fprintf (stream, "\n");
08258 #endif
08259
08260 ASM_OUTPUT_LABEL (stream, name);
08261 fprintf (stream, "\t.block "HOST_WIDE_INT_PRINT_UNSIGNED"\n", size);
08262 }
08263
08264
08265
08266 int
08267 fmpysuboperands (rtx *operands)
08268 {
08269 enum machine_mode mode = GET_MODE (operands[0]);
08270
08271
08272 if (mode != SFmode && mode != DFmode)
08273 return 0;
08274
08275
08276 if (! (mode == GET_MODE (operands[1])
08277 && mode == GET_MODE (operands[2])
08278 && mode == GET_MODE (operands[3])
08279 && mode == GET_MODE (operands[4])
08280 && mode == GET_MODE (operands[5])))
08281 return 0;
08282
08283
08284 if (! (GET_CODE (operands[1]) == REG
08285 && GET_CODE (operands[2]) == REG
08286 && GET_CODE (operands[3]) == REG
08287 && GET_CODE (operands[4]) == REG
08288 && GET_CODE (operands[5]) == REG))
08289 return 0;
08290
08291
08292
08293 if (! rtx_equal_p (operands[3], operands[4]))
08294 return 0;
08295
08296
08297 if (rtx_equal_p (operands[5], operands[0]))
08298 return 0;
08299
08300
08301 if (rtx_equal_p (operands[3], operands[0])
08302 || rtx_equal_p (operands[3], operands[1])
08303 || rtx_equal_p (operands[3], operands[2]))
08304 return 0;
08305
08306
08307 if (mode == SFmode
08308 && (REGNO_REG_CLASS (REGNO (operands[0])) != FPUPPER_REGS
08309 || REGNO_REG_CLASS (REGNO (operands[1])) != FPUPPER_REGS
08310 || REGNO_REG_CLASS (REGNO (operands[2])) != FPUPPER_REGS
08311 || REGNO_REG_CLASS (REGNO (operands[3])) != FPUPPER_REGS
08312 || REGNO_REG_CLASS (REGNO (operands[4])) != FPUPPER_REGS
08313 || REGNO_REG_CLASS (REGNO (operands[5])) != FPUPPER_REGS))
08314 return 0;
08315
08316
08317 return 1;
08318 }
08319
08320
08321
08322 int
08323 shadd_constant_p (int val)
08324 {
08325 if (val == 2 || val == 4 || val == 8)
08326 return 1;
08327 else
08328 return 0;
08329 }
08330
08331
08332
08333
08334 int
08335 borx_reg_operand (rtx op, enum machine_mode mode)
08336 {
08337 if (GET_CODE (op) != REG)
08338 return 0;
08339
08340
08341
08342 if (op == virtual_incoming_args_rtx
08343 || op == virtual_stack_vars_rtx
08344 || op == virtual_stack_dynamic_rtx
08345 || op == virtual_outgoing_args_rtx
08346 || op == virtual_cfa_rtx)
08347 return 0;
08348
08349
08350
08351 if (!reload_completed
08352 && flag_omit_frame_pointer
08353 && !current_function_calls_alloca
08354 && op == frame_pointer_rtx)
08355 return 0;
08356
08357 return register_operand (op, mode);
08358 }
08359
08360
08361
08362 int
08363 non_hard_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
08364 {
08365 return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER);
08366 }
08367
08368
08369
08370 static int
08371 forward_branch_p (rtx insn)
08372 {
08373 rtx label = JUMP_LABEL (insn);
08374
08375 while (insn)
08376 {
08377 if (insn == label)
08378 break;
08379 else
08380 insn = NEXT_INSN (insn);
08381 }
08382
08383 return (insn == label);
08384 }
08385
08386
08387 int
08388 eq_neq_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
08389 {
08390 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
08391 }
08392
08393
08394 int
08395 jump_in_call_delay (rtx insn)
08396 {
08397
08398 if (GET_CODE (insn) != JUMP_INSN)
08399 return 0;
08400
08401 if (PREV_INSN (insn)
08402 && PREV_INSN (PREV_INSN (insn))
08403 && GET_CODE (next_real_insn (PREV_INSN (PREV_INSN (insn)))) == INSN)
08404 {
08405 rtx test_insn = next_real_insn (PREV_INSN (PREV_INSN (insn)));
08406
08407 return (GET_CODE (PATTERN (test_insn)) == SEQUENCE
08408 && XVECEXP (PATTERN (test_insn), 0, 1) == insn);
08409
08410 }
08411 else
08412 return 0;
08413 }
08414
08415
08416
08417 const char *
08418 output_parallel_movb (rtx *operands, rtx insn)
08419 {
08420 int length = get_attr_length (insn);
08421
08422
08423 if (length == 4)
08424 return "mov%I1b,tr %1,%0,%2";
08425
08426
08427 if (length == 8)
08428 {
08429 if (dbr_sequence_length () == 0)
08430 {
08431
08432
08433 if (GET_CODE (operands[1]) == CONST_INT)
08434 return "b %2\n\tldi %1,%0";
08435 else
08436 return "b %2\n\tcopy %1,%0";
08437 }
08438 else
08439 {
08440
08441 if (GET_CODE (operands[1]) == CONST_INT)
08442 return "ldi %1,%0\n\tb %2";
08443 else
08444 return "copy %1,%0\n\tb %2";
08445 }
08446 }
08447
08448 if (GET_CODE (operands[1]) == CONST_INT)
08449 output_asm_insn ("ldi %1,%0", operands);
08450 else
08451 output_asm_insn ("copy %1,%0", operands);
08452 return output_lbranch (operands[2], insn, 1);
08453 }
08454
08455
08456
08457 const char *
08458 output_parallel_addb (rtx *operands, rtx insn)
08459 {
08460 int length = get_attr_length (insn);
08461
08462
08463
08464 if (operands[0] == operands[1])
08465 operands[1] = operands[2];
08466
08467
08468 if (length == 4)
08469 return "add%I1b,tr %1,%0,%3";
08470
08471
08472 if (length == 8)
08473 {
08474 if (dbr_sequence_length () == 0)
08475
08476
08477 return "b %3\n\tadd%I1 %1,%0,%0";
08478 else
08479
08480 return "add%I1 %1,%0,%0\n\tb %3";
08481 }
08482
08483 output_asm_insn ("add%I1 %1,%0,%0", operands);
08484 return output_lbranch (operands[3], insn, 1);
08485 }
08486
08487
08488
08489
08490
08491
08492 int
08493 following_call (rtx insn)
08494 {
08495 if (! TARGET_JUMP_IN_DELAY)
08496 return 0;
08497
08498
08499 insn = PREV_INSN (insn);
08500 while (insn && GET_CODE (insn) == NOTE)
08501 insn = PREV_INSN (insn);
08502
08503
08504 if (insn
08505 && ((GET_CODE (insn) == CALL_INSN
08506 && get_attr_type (insn) != TYPE_DYNCALL)
08507 || (GET_CODE (insn) == INSN
08508 && GET_CODE (PATTERN (insn)) != SEQUENCE
08509 && GET_CODE (PATTERN (insn)) != USE
08510 && GET_CODE (PATTERN (insn)) != CLOBBER
08511 && get_attr_type (insn) == TYPE_MILLI)))
08512 return 1;
08513
08514 return 0;
08515 }
08516
08517
08518
08519
08520
08521
08522
08523
08524
08525
08526
08527
08528
08529
08530
08531
08532
08533
08534
08535
08536
08537
08538
08539
08540
08541
08542
08543
08544
08545
08546
08547
08548
08549
08550
08551 static void
08552 pa_reorg (void)
08553 {
08554 rtx insn;
08555
08556 remove_useless_addtr_insns (1);
08557
08558 if (pa_cpu < PROCESSOR_8000)
08559 pa_combine_instructions ();
08560
08561
08562
08563 if (optimize > 0 && !TARGET_BIG_SWITCH)
08564 {
08565
08566 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
08567 {
08568 rtx pattern, tmp, location, label;
08569 unsigned int length, i;
08570
08571
08572 if (GET_CODE (insn) != JUMP_INSN
08573 || (GET_CODE (PATTERN (insn)) != ADDR_VEC
08574 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
08575 continue;
08576
08577
08578 emit_insn_before (gen_begin_brtab (), insn);
08579
08580 pattern = PATTERN (insn);
08581 location = PREV_INSN (insn);
08582 length = XVECLEN (pattern, GET_CODE (pattern) == ADDR_DIFF_VEC);
08583
08584 for (i = 0; i < length; i++)
08585 {
08586
08587
08588 tmp = gen_label_rtx ();
08589 LABEL_NUSES (tmp) = 1;
08590 emit_label_after (tmp, location);
08591 location = NEXT_INSN (location);
08592
08593 if (GET_CODE (pattern) == ADDR_VEC)
08594 label = XEXP (XVECEXP (pattern, 0, i), 0);
08595 else
08596 label = XEXP (XVECEXP (pattern, 1, i), 0);
08597
08598 tmp = gen_short_jump (label);
08599
08600
08601 tmp = emit_jump_insn_after (tmp, location);
08602 JUMP_LABEL (tmp) = label;
08603 LABEL_NUSES (label)++;
08604 location = NEXT_INSN (location);
08605
08606
08607 emit_barrier_after (location);
08608 location = NEXT_INSN (location);
08609 }
08610
08611
08612 emit_insn_before (gen_end_brtab (), location);
08613 location = NEXT_INSN (location);
08614 emit_barrier_after (location);
08615
08616
08617 delete_insn (insn);
08618 }
08619 }
08620 else
08621 {
08622
08623
08624
08625
08626
08627
08628 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
08629 {
08630
08631 if (GET_CODE (insn) != JUMP_INSN
08632 || (GET_CODE (PATTERN (insn)) != ADDR_VEC
08633 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
08634 continue;
08635
08636
08637
08638 emit_insn_before (gen_begin_brtab (), insn);
08639 emit_insn_after (gen_end_brtab (), insn);
08640 }
08641 }
08642 }
08643
08644
08645
08646
08647
08648
08649
08650
08651
08652
08653
08654
08655
08656
08657
08658
08659
08660
08661
08662
08663
08664
08665
08666
08667
08668
08669
08670
08671
08672
08673
08674
08675
08676
08677
08678
08679
08680
08681
08682
08683
08684
08685
08686
08687 static void
08688 pa_combine_instructions (void)
08689 {
08690 rtx anchor, new;
08691
08692
08693
08694
08695 if (optimize < 2)
08696 return;
08697
08698
08699
08700
08701
08702 new = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, NULL_RTX, NULL_RTX));
08703 new = make_insn_raw (new);
08704
08705 for (anchor = get_insns (); anchor; anchor = NEXT_INSN (anchor))
08706 {
08707 enum attr_pa_combine_type anchor_attr;
08708 enum attr_pa_combine_type floater_attr;
08709
08710
08711
08712 if ((GET_CODE (anchor) != INSN
08713 && GET_CODE (anchor) != JUMP_INSN
08714 && GET_CODE (anchor) != CALL_INSN)
08715 || GET_CODE (PATTERN (anchor)) == USE
08716 || GET_CODE (PATTERN (anchor)) == CLOBBER
08717 || GET_CODE (PATTERN (anchor)) == ADDR_VEC
08718 || GET_CODE (PATTERN (anchor)) == ADDR_DIFF_VEC)
08719 continue;
08720
08721 anchor_attr = get_attr_pa_combine_type (anchor);
08722
08723 if (anchor_attr == PA_COMBINE_TYPE_FMPY
08724 || anchor_attr == PA_COMBINE_TYPE_FADDSUB
08725 || (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
08726 && ! forward_branch_p (anchor)))
08727 {
08728 rtx floater;
08729
08730 for (floater = PREV_INSN (anchor);
08731 floater;
08732 floater = PREV_INSN (floater))
08733 {
08734 if (GET_CODE (floater) == NOTE
08735 || (GET_CODE (floater) == INSN
08736 && (GET_CODE (PATTERN (floater)) == USE
08737 || GET_CODE (PATTERN (floater)) == CLOBBER)))
08738 continue;
08739
08740
08741 if (GET_CODE (floater) != INSN
08742 || GET_CODE (PATTERN (floater)) == ADDR_VEC
08743 || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
08744 {
08745 floater = NULL_RTX;
08746 break;
08747 }
08748
08749
08750
08751 floater_attr = get_attr_pa_combine_type (floater);
08752 if ((anchor_attr == PA_COMBINE_TYPE_FMPY
08753 && floater_attr == PA_COMBINE_TYPE_FADDSUB)
08754 || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
08755 && floater_attr == PA_COMBINE_TYPE_FMPY))
08756 {
08757
08758
08759 if (pa_can_combine_p (new, anchor, floater, 0,
08760 SET_DEST (PATTERN (floater)),
08761 XEXP (SET_SRC (PATTERN (floater)), 0),
08762 XEXP (SET_SRC (PATTERN (floater)), 1)))
08763 break;
08764 }
08765
08766 else if (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
08767 && floater_attr == PA_COMBINE_TYPE_ADDMOVE)
08768 {
08769 if (GET_CODE (SET_SRC (PATTERN (floater))) == PLUS)
08770 {
08771 if (pa_can_combine_p (new, anchor, floater, 0,
08772 SET_DEST (PATTERN (floater)),
08773 XEXP (SET_SRC (PATTERN (floater)), 0),
08774 XEXP (SET_SRC (PATTERN (floater)), 1)))
08775 break;
08776 }
08777 else
08778 {
08779 if (pa_can_combine_p (new, anchor, floater, 0,
08780 SET_DEST (PATTERN (floater)),
08781 SET_SRC (PATTERN (floater)),
08782 SET_SRC (PATTERN (floater))))
08783 break;
08784 }
08785 }
08786 }
08787
08788
08789 if (!floater
08790 && (anchor_attr == PA_COMBINE_TYPE_FMPY
08791 || anchor_attr == PA_COMBINE_TYPE_FADDSUB))
08792 {
08793 for (floater = anchor; floater; floater = NEXT_INSN (floater))
08794 {
08795 if (GET_CODE (floater) == NOTE
08796 || (GET_CODE (floater) == INSN
08797 && (GET_CODE (PATTERN (floater)) == USE
08798 || GET_CODE (PATTERN (floater)) == CLOBBER)))
08799
08800 continue;
08801
08802
08803 if (GET_CODE (floater) != INSN
08804 || GET_CODE (PATTERN (floater)) == ADDR_VEC
08805 || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
08806 {
08807 floater = NULL_RTX;
08808 break;
08809 }
08810
08811
08812
08813 floater_attr = get_attr_pa_combine_type (floater);
08814 if ((anchor_attr == PA_COMBINE_TYPE_FMPY
08815 && floater_attr == PA_COMBINE_TYPE_FADDSUB)
08816 || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
08817 && floater_attr == PA_COMBINE_TYPE_FMPY))
08818 {
08819
08820
08821 if (pa_can_combine_p (new, anchor, floater, 1,
08822 SET_DEST (PATTERN (floater)),
08823 XEXP (SET_SRC (PATTERN (floater)),
08824 0),
08825 XEXP (SET_SRC (PATTERN (floater)),
08826 1)))
08827 break;
08828 }
08829 }
08830 }
08831
08832
08833
08834 if (floater
08835 && (anchor_attr == PA_COMBINE_TYPE_FADDSUB
08836 || anchor_attr == PA_COMBINE_TYPE_FMPY))
08837 {
08838
08839 emit_insn_before (gen_rtx_PARALLEL
08840 (VOIDmode,
08841 gen_rtvec (2, PATTERN (anchor),
08842 PATTERN (floater))),
08843 anchor);
08844
08845 PUT_CODE (anchor, NOTE);
08846 NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
08847 NOTE_SOURCE_FILE (anchor) = 0;
08848
08849
08850
08851 emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater);
08852 delete_insn (floater);
08853
08854 continue;
08855 }
08856 else if (floater
08857 && anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH)
08858 {
08859 rtx temp;
08860
08861 temp
08862 = emit_jump_insn_before (gen_rtx_PARALLEL
08863 (VOIDmode,
08864 gen_rtvec (2, PATTERN (anchor),
08865 PATTERN (floater))),
08866 anchor);
08867
08868 JUMP_LABEL (temp) = JUMP_LABEL (anchor);
08869 PUT_CODE (anchor, NOTE);
08870 NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
08871 NOTE_SOURCE_FILE (anchor) = 0;
08872
08873
08874
08875 emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater);
08876 delete_insn (floater);
08877 continue;
08878 }
08879 }
08880 }
08881 }
08882
08883 static int
08884 pa_can_combine_p (rtx new, rtx anchor, rtx floater, int reversed, rtx dest,
08885 rtx src1, rtx src2)
08886 {
08887 int insn_code_number;
08888 rtx start, end;
08889
08890
08891
08892
08893
08894
08895
08896
08897 XVECEXP (PATTERN (new), 0, 0) = PATTERN (anchor);
08898 XVECEXP (PATTERN (new), 0, 1) = PATTERN (floater);
08899 INSN_CODE (new) = -1;
08900 insn_code_number = recog_memoized (new);
08901 if (insn_code_number < 0
08902 || (extract_insn (new), ! constrain_operands (1)))
08903 return 0;
08904
08905 if (reversed)
08906 {
08907 start = anchor;
08908 end = floater;
08909 }
08910 else
08911 {
08912 start = floater;
08913 end = anchor;
08914 }
08915
08916
08917
08918
08919
08920
08921
08922
08923 if (reg_used_between_p (dest, start, end))
08924 return 0;
08925
08926 if (reg_set_between_p (src1, start, end))
08927 return 0;
08928
08929 if (reg_set_between_p (src2, start, end))
08930 return 0;
08931
08932
08933 return 1;
08934 }
08935
08936
08937
08938
08939
08940
08941
08942
08943
08944
08945
08946
08947
08948
08949
08950
08951
08952
08953
08954
08955
08956
08957
08958
08959 int
08960 insn_refs_are_delayed (rtx insn)
08961 {
08962 return ((GET_CODE (insn) == INSN
08963 && GET_CODE (PATTERN (insn)) != SEQUENCE
08964 && GET_CODE (PATTERN (insn)) != USE
08965 && GET_CODE (PATTERN (insn)) != CLOBBER
08966 && get_attr_type (insn) == TYPE_MILLI));
08967 }
08968
08969
08970
08971
08972
08973
08974
08975
08976
08977
08978 rtx
08979 function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
08980 {
08981 enum machine_mode valmode;
08982
08983 if (AGGREGATE_TYPE_P (valtype)
08984 || TREE_CODE (valtype) == COMPLEX_TYPE
08985 || TREE_CODE (valtype) == VECTOR_TYPE)
08986 {
08987 if (TARGET_64BIT)
08988 {
08989
08990
08991
08992
08993 rtx loc[2];
08994 int i, offset = 0;
08995 int ub = int_size_in_bytes (valtype) <= UNITS_PER_WORD ? 1 : 2;
08996
08997 for (i = 0; i < ub; i++)
08998 {
08999 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
09000 gen_rtx_REG (DImode, 28 + i),
09001 GEN_INT (offset));
09002 offset += 8;
09003 }
09004
09005 return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (ub, loc));
09006 }
09007 else if (int_size_in_bytes (valtype) > UNITS_PER_WORD)
09008 {
09009
09010
09011
09012
09013
09014
09015 rtx loc = gen_rtx_EXPR_LIST (VOIDmode,
09016 gen_rtx_REG (DImode, 28), const0_rtx);
09017 return gen_rtx_PARALLEL (BLKmode, gen_rtvec (1, loc));
09018 }
09019 }
09020
09021 if ((INTEGRAL_TYPE_P (valtype)
09022 && TYPE_PRECISION (valtype) < BITS_PER_WORD)
09023 || POINTER_TYPE_P (valtype))
09024 valmode = word_mode;
09025 else
09026 valmode = TYPE_MODE (valtype);
09027
09028 if (TREE_CODE (valtype) == REAL_TYPE
09029 && !AGGREGATE_TYPE_P (valtype)
09030 && TYPE_MODE (valtype) != TFmode
09031 && !TARGET_SOFT_FLOAT)
09032 return gen_rtx_REG (valmode, 32);
09033
09034 return gen_rtx_REG (valmode, 28);
09035 }
09036
09037
09038
09039
09040
09041
09042
09043
09044
09045 rtx
09046 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
09047 int named ATTRIBUTE_UNUSED)
09048 {
09049 int max_arg_words = (TARGET_64BIT ? 8 : 4);
09050 int alignment = 0;
09051 int arg_size;
09052 int fpr_reg_base;
09053 int gpr_reg_base;
09054 rtx retval;
09055
09056 if (mode == VOIDmode)
09057 return NULL_RTX;
09058
09059 arg_size = FUNCTION_ARG_SIZE (mode, type);
09060
09061
09062
09063
09064
09065 if (!TARGET_64BIT)
09066 {
09067
09068 if (cum->words + arg_size > max_arg_words)
09069 return NULL_RTX;
09070 }
09071 else
09072 {
09073 if (arg_size > 1)
09074 alignment = cum->words & 1;
09075 if (cum->words + alignment >= max_arg_words)
09076 return NULL_RTX;
09077 }
09078
09079
09080
09081
09082
09083
09084
09085 if (TARGET_64BIT)
09086 {
09087
09088
09089
09090
09091
09092
09093 gpr_reg_base = 26 - cum->words;
09094 fpr_reg_base = 32 + cum->words;
09095
09096
09097
09098 if (arg_size > 1
09099 || mode == BLKmode
09100 || (type && (AGGREGATE_TYPE_P (type)
09101 || TREE_CODE (type) == COMPLEX_TYPE
09102 || TREE_CODE (type) == VECTOR_TYPE)))
09103 {
09104
09105
09106
09107
09108
09109
09110
09111
09112
09113
09114
09115 rtx loc[8];
09116 int i, offset = 0, ub = arg_size;
09117
09118
09119 gpr_reg_base -= alignment;
09120
09121 ub = MIN (ub, max_arg_words - cum->words - alignment);
09122 for (i = 0; i < ub; i++)
09123 {
09124 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
09125 gen_rtx_REG (DImode, gpr_reg_base),
09126 GEN_INT (offset));
09127 gpr_reg_base -= 1;
09128 offset += 8;
09129 }
09130
09131 return gen_rtx_PARALLEL (mode, gen_rtvec_v (ub, loc));
09132 }
09133 }
09134 else
09135 {
09136
09137
09138 if (arg_size > 1)
09139 {
09140 if (cum->words)
09141 {
09142 gpr_reg_base = 23;
09143 fpr_reg_base = 38;
09144 }
09145 else
09146 {
09147 gpr_reg_base = 25;
09148 fpr_reg_base = 34;
09149 }
09150
09151
09152
09153
09154
09155
09156
09157
09158
09159 if (mode == BLKmode
09160 || (type && (AGGREGATE_TYPE_P (type)
09161 || TREE_CODE (type) == COMPLEX_TYPE
09162 || TREE_CODE (type) == VECTOR_TYPE)))
09163 {
09164 rtx loc = gen_rtx_EXPR_LIST (VOIDmode,
09165 gen_rtx_REG (DImode, gpr_reg_base),
09166 const0_rtx);
09167 return gen_rtx_PARALLEL (BLKmode, gen_rtvec (1, loc));
09168 }
09169 }
09170 else
09171 {
09172
09173
09174 gpr_reg_base = 26 - cum->words;
09175 fpr_reg_base = 32 + 2 * cum->words;
09176 }
09177 }
09178
09179
09180
09181 if (((TARGET_PORTABLE_RUNTIME || TARGET_64BIT || TARGET_ELF32)
09182
09183
09184 && !TARGET_SOFT_FLOAT
09185
09186
09187 && GET_MODE_CLASS (mode) == MODE_FLOAT
09188
09189 && cum->nargs_prototype <= 0
09190
09191
09192 && type != NULL_TREE
09193
09194
09195 && !cum->incoming)
09196
09197
09198
09199 || (!TARGET_64BIT
09200 && !TARGET_GAS
09201 && !cum->incoming
09202 && cum->indirect
09203 && GET_MODE_CLASS (mode) == MODE_FLOAT))
09204 {
09205 retval
09206 = gen_rtx_PARALLEL
09207 (mode,
09208 gen_rtvec (2,
09209 gen_rtx_EXPR_LIST (VOIDmode,
09210 gen_rtx_REG (mode, fpr_reg_base),
09211 const0_rtx),
09212 gen_rtx_EXPR_LIST (VOIDmode,
09213 gen_rtx_REG (mode, gpr_reg_base),
09214 const0_rtx)));
09215 }
09216 else
09217 {
09218
09219 if (TARGET_SOFT_FLOAT
09220
09221
09222 || (!TARGET_PORTABLE_RUNTIME
09223 && !TARGET_64BIT
09224 && !TARGET_ELF32
09225 && cum->indirect)
09226
09227
09228 || GET_MODE_CLASS (mode) != MODE_FLOAT
09229
09230 || (type && AGGREGATE_TYPE_P (type)))
09231 retval = gen_rtx_REG (mode, gpr_reg_base);
09232 else
09233 retval = gen_rtx_REG (mode, fpr_reg_base);
09234 }
09235 return retval;
09236 }
09237
09238
09239
09240
09241
09242 static int
09243 pa_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
09244 tree type, bool named ATTRIBUTE_UNUSED)
09245 {
09246 unsigned int max_arg_words = 8;
09247 unsigned int offset = 0;
09248
09249 if (!TARGET_64BIT)
09250 return 0;
09251
09252 if (FUNCTION_ARG_SIZE (mode, type) > 1 && (cum->words & 1))
09253 offset = 1;
09254
09255 if (cum->words + offset + FUNCTION_ARG_SIZE (mode, type) <= max_arg_words)
09256
09257 return 0;
09258 else if (cum->words + offset >= max_arg_words)
09259
09260 return 0;
09261 else
09262
09263 return (max_arg_words - cum->words - offset) * UNITS_PER_WORD;
09264 }
09265
09266
09267
09268
09269
09270
09271
09272
09273 static void
09274 som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
09275 {
09276 gcc_assert (TARGET_SOM);
09277 if (TARGET_GAS)
09278 {
09279 if (cfun && cfun->machine && !cfun->machine->in_nsubspa)
09280 {
09281
09282
09283 cfun->machine->in_nsubspa = 1;
09284
09285
09286
09287 if (cfun->decl
09288 && DECL_ONE_ONLY (cfun->decl)
09289 && !DECL_WEAK (cfun->decl))
09290 {
09291 output_section_asm_op ("\t.SPACE $TEXT$\n"
09292 "\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,"
09293 "ACCESS=44,SORT=24,COMDAT");
09294 return;
09295 }
09296 }
09297 else
09298 {
09299
09300
09301
09302
09303
09304 gcc_assert (!cfun || !cfun->machine
09305 || cfun->machine->in_nsubspa == 2);
09306 in_section = NULL;
09307 }
09308 output_section_asm_op ("\t.SPACE $TEXT$\n\t.NSUBSPA $CODE$");
09309 return;
09310 }
09311 output_section_asm_op ("\t.SPACE $TEXT$\n\t.SUBSPA $CODE$");
09312 }
09313
09314
09315
09316
09317 static void
09318 som_output_comdat_data_section_asm_op (const void *data)
09319 {
09320 in_section = NULL;
09321 output_section_asm_op (data);
09322 }
09323
09324
09325
09326 static void
09327 pa_som_asm_init_sections (void)
09328 {
09329 text_section
09330 = get_unnamed_section (0, som_output_text_section_asm_op, NULL);
09331
09332
09333
09334 som_readonly_data_section
09335 = get_unnamed_section (0, output_section_asm_op,
09336 "\t.SPACE $TEXT$\n\t.SUBSPA $LIT$");
09337
09338
09339
09340
09341 som_one_only_readonly_data_section
09342 = get_unnamed_section (0, som_output_comdat_data_section_asm_op,
09343 "\t.SPACE $TEXT$\n"
09344 "\t.NSUBSPA $LIT$,QUAD=0,ALIGN=8,"
09345 "ACCESS=0x2c,SORT=16,COMDAT");
09346
09347
09348
09349
09350 som_one_only_data_section
09351 = get_unnamed_section (SECTION_WRITE,
09352 som_output_comdat_data_section_asm_op,
09353 "\t.SPACE $PRIVATE$\n"
09354 "\t.NSUBSPA $DATA$,QUAD=1,ALIGN=8,"
09355 "ACCESS=31,SORT=24,COMDAT");
09356
09357
09358
09359
09360
09361
09362
09363
09364
09365
09366
09367
09368
09369 readonly_data_section = flag_pic ? data_section : som_readonly_data_section;
09370
09371
09372
09373
09374
09375
09376 exception_section = data_section;
09377 }
09378
09379
09380
09381
09382
09383
09384 static section *
09385 pa_select_section (tree exp, int reloc,
09386 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
09387 {
09388 if (TREE_CODE (exp) == VAR_DECL
09389 && TREE_READONLY (exp)
09390 && !TREE_THIS_VOLATILE (exp)
09391 && DECL_INITIAL (exp)
09392 && (DECL_INITIAL (exp) == error_mark_node
09393 || TREE_CONSTANT (DECL_INITIAL (exp)))
09394 && !reloc)
09395 {
09396 if (TARGET_SOM
09397 && DECL_ONE_ONLY (exp)
09398 && !DECL_WEAK (exp))
09399 return som_one_only_readonly_data_section;
09400 else
09401 return readonly_data_section;
09402 }
09403 else if (CONSTANT_CLASS_P (exp) && !reloc)
09404 return readonly_data_section;
09405 else if (TARGET_SOM
09406 && TREE_CODE (exp) == VAR_DECL
09407 && DECL_ONE_ONLY (exp)
09408 && !DECL_WEAK (exp))
09409 return som_one_only_data_section;
09410 else
09411 return data_section;
09412 }
09413
09414 static void
09415 pa_globalize_label (FILE *stream, const char *name)
09416 {
09417
09418
09419 if (! FUNCTION_NAME_P (name))
09420 {
09421 fputs ("\t.EXPORT ", stream);
09422 assemble_name (stream, name);
09423 fputs (",DATA\n", stream);
09424 }
09425 }
09426
09427
09428
09429 static rtx
09430 pa_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
09431 int incoming ATTRIBUTE_UNUSED)
09432 {
09433 return gen_rtx_REG (Pmode, PA_STRUCT_VALUE_REGNUM);
09434 }
09435
09436
09437
09438 bool
09439 pa_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
09440 {
09441
09442
09443
09444
09445
09446
09447
09448
09449 return (int_size_in_bytes (type) > (TARGET_64BIT ? 16 : 8)
09450 || int_size_in_bytes (type) <= 0);
09451 }
09452
09453
09454
09455
09456
09457
09458 typedef struct extern_symbol GTY(())
09459 {
09460 tree decl;
09461 const char *name;
09462 } extern_symbol;
09463
09464
09465 DEF_VEC_O(extern_symbol);
09466 DEF_VEC_ALLOC_O(extern_symbol,gc);
09467
09468
09469 static GTY(()) VEC(extern_symbol,gc) *extern_symbols;
09470
09471 #ifdef ASM_OUTPUT_EXTERNAL_REAL
09472
09473
09474
09475
09476 void
09477 pa_hpux_asm_output_external (FILE *file, tree decl, const char *name)
09478 {
09479 extern_symbol * p = VEC_safe_push (extern_symbol, gc, extern_symbols, NULL);
09480
09481 gcc_assert (file == asm_out_file);
09482 p->decl = decl;
09483 p->name = name;
09484 }
09485
09486
09487
09488
09489
09490 static void
09491 pa_hpux_file_end (void)
09492 {
09493 unsigned int i;
09494 extern_symbol *p;
09495
09496 if (!NO_DEFERRED_PROFILE_COUNTERS)
09497 output_deferred_profile_counters ();
09498
09499 output_deferred_plabels ();
09500
09501 for (i = 0; VEC_iterate (extern_symbol, extern_symbols, i, p); i++)
09502 {
09503 tree decl = p->decl;
09504
09505 if (!TREE_ASM_WRITTEN (decl)
09506 && SYMBOL_REF_REFERENCED_P (XEXP (DECL_RTL (decl), 0)))
09507 ASM_OUTPUT_EXTERNAL_REAL (asm_out_file, decl, p->name);
09508 }
09509
09510 VEC_free (extern_symbol, gc, extern_symbols);
09511 }
09512 #endif
09513
09514 #include "gt-pa.h"