comparison gcc/config/pa/pa.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents 3bfb6c00c1e0
children b7f97abdc517
comparison
equal deleted inserted replaced
52:c156f1bd5cd9 55:77e2b8dfacca
91 static bool hppa_rtx_costs (rtx, int, int, int *, bool); 91 static bool hppa_rtx_costs (rtx, int, int, int *, bool);
92 static inline rtx force_mode (enum machine_mode, rtx); 92 static inline rtx force_mode (enum machine_mode, rtx);
93 static void pa_reorg (void); 93 static void pa_reorg (void);
94 static void pa_combine_instructions (void); 94 static void pa_combine_instructions (void);
95 static int pa_can_combine_p (rtx, rtx, rtx, int, rtx, rtx, rtx); 95 static int pa_can_combine_p (rtx, rtx, rtx, int, rtx, rtx, rtx);
96 static int forward_branch_p (rtx); 96 static bool forward_branch_p (rtx);
97 static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *); 97 static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *);
98 static int compute_movmem_length (rtx); 98 static int compute_movmem_length (rtx);
99 static int compute_clrmem_length (rtx); 99 static int compute_clrmem_length (rtx);
100 static bool pa_assemble_integer (rtx, unsigned int, int); 100 static bool pa_assemble_integer (rtx, unsigned int, int);
101 static void remove_useless_addtr_insns (int); 101 static void remove_useless_addtr_insns (int);
102 static void store_reg (int, HOST_WIDE_INT, int); 102 static void store_reg (int, HOST_WIDE_INT, int);
103 static void store_reg_modify (int, int, HOST_WIDE_INT); 103 static void store_reg_modify (int, int, HOST_WIDE_INT);
104 static void load_reg (int, HOST_WIDE_INT, int); 104 static void load_reg (int, HOST_WIDE_INT, int);
105 static void set_reg_plus_d (int, int, HOST_WIDE_INT, int); 105 static void set_reg_plus_d (int, int, HOST_WIDE_INT, int);
106 static rtx pa_function_value (const_tree, const_tree, bool);
106 static void pa_output_function_prologue (FILE *, HOST_WIDE_INT); 107 static void pa_output_function_prologue (FILE *, HOST_WIDE_INT);
107 static void update_total_code_bytes (unsigned int); 108 static void update_total_code_bytes (unsigned int);
108 static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT); 109 static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT);
109 static int pa_adjust_cost (rtx, rtx, rtx, int); 110 static int pa_adjust_cost (rtx, rtx, rtx, int);
110 static int pa_adjust_priority (rtx, int); 111 static int pa_adjust_priority (rtx, int);
129 static tree hppa_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); 130 static tree hppa_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
130 static bool pa_scalar_mode_supported_p (enum machine_mode); 131 static bool pa_scalar_mode_supported_p (enum machine_mode);
131 static bool pa_commutative_p (const_rtx x, int outer_code); 132 static bool pa_commutative_p (const_rtx x, int outer_code);
132 static void copy_fp_args (rtx) ATTRIBUTE_UNUSED; 133 static void copy_fp_args (rtx) ATTRIBUTE_UNUSED;
133 static int length_fp_args (rtx) ATTRIBUTE_UNUSED; 134 static int length_fp_args (rtx) ATTRIBUTE_UNUSED;
135 static rtx hppa_legitimize_address (rtx, rtx, enum machine_mode);
134 static inline void pa_file_start_level (void) ATTRIBUTE_UNUSED; 136 static inline void pa_file_start_level (void) ATTRIBUTE_UNUSED;
135 static inline void pa_file_start_space (int) ATTRIBUTE_UNUSED; 137 static inline void pa_file_start_space (int) ATTRIBUTE_UNUSED;
136 static inline void pa_file_start_file (int) ATTRIBUTE_UNUSED; 138 static inline void pa_file_start_file (int) ATTRIBUTE_UNUSED;
137 static inline void pa_file_start_mcount (const char*) ATTRIBUTE_UNUSED; 139 static inline void pa_file_start_mcount (const char*) ATTRIBUTE_UNUSED;
138 static void pa_elf_file_start (void) ATTRIBUTE_UNUSED; 140 static void pa_elf_file_start (void) ATTRIBUTE_UNUSED;
156 static struct machine_function * pa_init_machine_status (void); 158 static struct machine_function * pa_init_machine_status (void);
157 static enum reg_class pa_secondary_reload (bool, rtx, enum reg_class, 159 static enum reg_class pa_secondary_reload (bool, rtx, enum reg_class,
158 enum machine_mode, 160 enum machine_mode,
159 secondary_reload_info *); 161 secondary_reload_info *);
160 static void pa_extra_live_on_entry (bitmap); 162 static void pa_extra_live_on_entry (bitmap);
163 static enum machine_mode pa_promote_function_mode (const_tree,
164 enum machine_mode, int *,
165 const_tree, int);
166
167 static void pa_asm_trampoline_template (FILE *);
168 static void pa_trampoline_init (rtx, tree, rtx);
169 static rtx pa_trampoline_adjust_address (rtx);
161 170
162 /* The following extra sections are only used for SOM. */ 171 /* The following extra sections are only used for SOM. */
163 static GTY(()) section *som_readonly_data_section; 172 static GTY(()) section *som_readonly_data_section;
164 static GTY(()) section *som_one_only_readonly_data_section; 173 static GTY(()) section *som_one_only_readonly_data_section;
165 static GTY(()) section *som_one_only_data_section; 174 static GTY(()) section *som_one_only_data_section;
166 175
167 /* Save the operands last given to a compare for use when we
168 generate a scc or bcc insn. */
169 rtx hppa_compare_op0, hppa_compare_op1;
170 enum cmp_type hppa_branch_type;
171
172 /* Which cpu we are scheduling for. */ 176 /* Which cpu we are scheduling for. */
173 enum processor_type pa_cpu = TARGET_SCHED_DEFAULT; 177 enum processor_type pa_cpu = TARGET_SCHED_DEFAULT;
174 178
175 /* The UNIX standard to use for predefines and linking. */ 179 /* The UNIX standard to use for predefines and linking. */
176 int flag_pa_unix = TARGET_HPUX_11_11 ? 1998 : TARGET_HPUX_10_10 ? 1995 : 1993; 180 int flag_pa_unix = TARGET_HPUX_11_11 ? 1998 : TARGET_HPUX_10_10 ? 1995 : 1993;
194 a thunk can use an IA-relative branch to reach its target function. */ 198 a thunk can use an IA-relative branch to reach its target function. */
195 static unsigned int last_address; 199 static unsigned int last_address;
196 200
197 /* Variables to handle plabels that we discover are necessary at assembly 201 /* Variables to handle plabels that we discover are necessary at assembly
198 output time. They are output after the current function. */ 202 output time. They are output after the current function. */
199 struct deferred_plabel GTY(()) 203 struct GTY(()) deferred_plabel
200 { 204 {
201 rtx internal_label; 205 rtx internal_label;
202 rtx symbol; 206 rtx symbol;
203 }; 207 };
204 static GTY((length ("n_deferred_plabels"))) struct deferred_plabel * 208 static GTY((length ("n_deferred_plabels"))) struct deferred_plabel *
226 #undef TARGET_ASM_FUNCTION_PROLOGUE 230 #undef TARGET_ASM_FUNCTION_PROLOGUE
227 #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue 231 #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue
228 #undef TARGET_ASM_FUNCTION_EPILOGUE 232 #undef TARGET_ASM_FUNCTION_EPILOGUE
229 #define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue 233 #define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue
230 234
235 #undef TARGET_FUNCTION_VALUE
236 #define TARGET_FUNCTION_VALUE pa_function_value
237
238 #undef TARGET_LEGITIMIZE_ADDRESS
239 #define TARGET_LEGITIMIZE_ADDRESS hppa_legitimize_address
240
231 #undef TARGET_SCHED_ADJUST_COST 241 #undef TARGET_SCHED_ADJUST_COST
232 #define TARGET_SCHED_ADJUST_COST pa_adjust_cost 242 #define TARGET_SCHED_ADJUST_COST pa_adjust_cost
233 #undef TARGET_SCHED_ADJUST_PRIORITY 243 #undef TARGET_SCHED_ADJUST_PRIORITY
234 #define TARGET_SCHED_ADJUST_PRIORITY pa_adjust_priority 244 #define TARGET_SCHED_ADJUST_PRIORITY pa_adjust_priority
235 #undef TARGET_SCHED_ISSUE_RATE 245 #undef TARGET_SCHED_ISSUE_RATE
284 #ifdef HPUX_LONG_DOUBLE_LIBRARY 294 #ifdef HPUX_LONG_DOUBLE_LIBRARY
285 #undef TARGET_INIT_LIBFUNCS 295 #undef TARGET_INIT_LIBFUNCS
286 #define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs 296 #define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs
287 #endif 297 #endif
288 298
289 #undef TARGET_PROMOTE_FUNCTION_RETURN 299 #undef TARGET_PROMOTE_FUNCTION_MODE
290 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true 300 #define TARGET_PROMOTE_FUNCTION_MODE pa_promote_function_mode
291 #undef TARGET_PROMOTE_PROTOTYPES 301 #undef TARGET_PROMOTE_PROTOTYPES
292 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true 302 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
293 303
294 #undef TARGET_STRUCT_VALUE_RTX 304 #undef TARGET_STRUCT_VALUE_RTX
295 #define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx 305 #define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx
320 #undef TARGET_SECONDARY_RELOAD 330 #undef TARGET_SECONDARY_RELOAD
321 #define TARGET_SECONDARY_RELOAD pa_secondary_reload 331 #define TARGET_SECONDARY_RELOAD pa_secondary_reload
322 332
323 #undef TARGET_EXTRA_LIVE_ON_ENTRY 333 #undef TARGET_EXTRA_LIVE_ON_ENTRY
324 #define TARGET_EXTRA_LIVE_ON_ENTRY pa_extra_live_on_entry 334 #define TARGET_EXTRA_LIVE_ON_ENTRY pa_extra_live_on_entry
335
336 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
337 #define TARGET_ASM_TRAMPOLINE_TEMPLATE pa_asm_trampoline_template
338 #undef TARGET_TRAMPOLINE_INIT
339 #define TARGET_TRAMPOLINE_INIT pa_trampoline_init
340 #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
341 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS pa_trampoline_adjust_address
325 342
326 struct gcc_target targetm = TARGET_INITIALIZER; 343 struct gcc_target targetm = TARGET_INITIALIZER;
327 344
328 /* Parse the -mfixed-range= option string. */ 345 /* Parse the -mfixed-range= option string. */
329 346
682 expanders completely. */ 699 expanders completely. */
683 mark_reg_pointer (reg, BITS_PER_UNIT); 700 mark_reg_pointer (reg, BITS_PER_UNIT);
684 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, orig)); 701 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, orig));
685 702
686 /* Put a REG_EQUAL note on this insn, so that it can be optimized. */ 703 /* Put a REG_EQUAL note on this insn, so that it can be optimized. */
687 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, REG_NOTES (insn)); 704 add_reg_note (insn, REG_EQUAL, orig);
688 705
689 /* During and after reload, we need to generate a REG_LABEL_OPERAND note 706 /* During and after reload, we need to generate a REG_LABEL_OPERAND note
690 and update LABEL_NUSES because this is not done automatically. */ 707 and update LABEL_NUSES because this is not done automatically. */
691 if (reload_in_progress || reload_completed) 708 if (reload_in_progress || reload_completed)
692 { 709 {
869 to be legitimate. If we find one, return the new, valid address. 886 to be legitimate. If we find one, return the new, valid address.
870 This macro is used in only one place: `memory_address' in explow.c. 887 This macro is used in only one place: `memory_address' in explow.c.
871 888
872 OLDX is the address as it was before break_out_memory_refs was called. 889 OLDX is the address as it was before break_out_memory_refs was called.
873 In some cases it is useful to look at this to decide what needs to be done. 890 In some cases it is useful to look at this to decide what needs to be done.
874
875 MODE and WIN are passed so that this macro can use
876 GO_IF_LEGITIMATE_ADDRESS.
877 891
878 It is always safe for this macro to do nothing. It exists to recognize 892 It is always safe for this macro to do nothing. It exists to recognize
879 opportunities to optimize the output. 893 opportunities to optimize the output.
880 894
881 For the PA, transform: 895 For the PA, transform:
3398 3412
3399 emit_move_insn (tmpreg, delta); 3413 emit_move_insn (tmpreg, delta);
3400 insn = emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg)); 3414 insn = emit_move_insn (tmpreg, gen_rtx_PLUS (Pmode, tmpreg, basereg));
3401 if (DO_FRAME_NOTES) 3415 if (DO_FRAME_NOTES)
3402 { 3416 {
3403 REG_NOTES (insn) 3417 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
3404 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 3418 gen_rtx_SET (VOIDmode, tmpreg,
3405 gen_rtx_SET (VOIDmode, tmpreg, 3419 gen_rtx_PLUS (Pmode, basereg, delta)));
3406 gen_rtx_PLUS (Pmode, basereg, delta)),
3407 REG_NOTES (insn));
3408 RTX_FRAME_RELATED_P (insn) = 1; 3420 RTX_FRAME_RELATED_P (insn) = 1;
3409 } 3421 }
3410 dest = gen_rtx_MEM (word_mode, tmpreg); 3422 dest = gen_rtx_MEM (word_mode, tmpreg);
3411 insn = emit_move_insn (dest, src); 3423 insn = emit_move_insn (dest, src);
3412 } 3424 }
3418 3430
3419 emit_move_insn (tmpreg, high); 3431 emit_move_insn (tmpreg, high);
3420 dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta)); 3432 dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
3421 insn = emit_move_insn (dest, src); 3433 insn = emit_move_insn (dest, src);
3422 if (DO_FRAME_NOTES) 3434 if (DO_FRAME_NOTES)
3423 { 3435 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
3424 REG_NOTES (insn) 3436 gen_rtx_SET (VOIDmode,
3425 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 3437 gen_rtx_MEM (word_mode,
3426 gen_rtx_SET (VOIDmode, 3438 gen_rtx_PLUS (word_mode,
3427 gen_rtx_MEM (word_mode, 3439 basereg,
3428 gen_rtx_PLUS (word_mode, basereg, 3440 delta)),
3429 delta)), 3441 src));
3430 src),
3431 REG_NOTES (insn));
3432 }
3433 } 3442 }
3434 3443
3435 if (DO_FRAME_NOTES) 3444 if (DO_FRAME_NOTES)
3436 RTX_FRAME_RELATED_P (insn) = 1; 3445 RTX_FRAME_RELATED_P (insn) = 1;
3437 } 3446 }
3487 3496
3488 emit_move_insn (tmpreg, delta); 3497 emit_move_insn (tmpreg, delta);
3489 insn = emit_move_insn (gen_rtx_REG (Pmode, reg), 3498 insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
3490 gen_rtx_PLUS (Pmode, tmpreg, basereg)); 3499 gen_rtx_PLUS (Pmode, tmpreg, basereg));
3491 if (DO_FRAME_NOTES) 3500 if (DO_FRAME_NOTES)
3492 REG_NOTES (insn) 3501 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
3493 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 3502 gen_rtx_SET (VOIDmode, tmpreg,
3494 gen_rtx_SET (VOIDmode, tmpreg, 3503 gen_rtx_PLUS (Pmode, basereg, delta)));
3495 gen_rtx_PLUS (Pmode, basereg, delta)),
3496 REG_NOTES (insn));
3497 } 3504 }
3498 else 3505 else
3499 { 3506 {
3500 rtx basereg = gen_rtx_REG (Pmode, base); 3507 rtx basereg = gen_rtx_REG (Pmode, base);
3501 rtx delta = GEN_INT (disp); 3508 rtx delta = GEN_INT (disp);
3915 RTX_FRAME_RELATED_P (insn) = 1; 3922 RTX_FRAME_RELATED_P (insn) = 1;
3916 if (TARGET_64BIT) 3923 if (TARGET_64BIT)
3917 { 3924 {
3918 rtx mem = gen_rtx_MEM (DFmode, 3925 rtx mem = gen_rtx_MEM (DFmode,
3919 plus_constant (base, offset)); 3926 plus_constant (base, offset));
3920 REG_NOTES (insn) 3927 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
3921 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 3928 gen_rtx_SET (VOIDmode, mem, reg));
3922 gen_rtx_SET (VOIDmode, mem, reg),
3923 REG_NOTES (insn));
3924 } 3929 }
3925 else 3930 else
3926 { 3931 {
3927 rtx meml = gen_rtx_MEM (SFmode, 3932 rtx meml = gen_rtx_MEM (SFmode,
3928 plus_constant (base, offset)); 3933 plus_constant (base, offset));
3935 rtvec vec; 3940 rtvec vec;
3936 3941
3937 RTX_FRAME_RELATED_P (setl) = 1; 3942 RTX_FRAME_RELATED_P (setl) = 1;
3938 RTX_FRAME_RELATED_P (setr) = 1; 3943 RTX_FRAME_RELATED_P (setr) = 1;
3939 vec = gen_rtvec (2, setl, setr); 3944 vec = gen_rtvec (2, setl, setr);
3940 REG_NOTES (insn) 3945 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
3941 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, 3946 gen_rtx_SEQUENCE (VOIDmode, vec));
3942 gen_rtx_SEQUENCE (VOIDmode, vec),
3943 REG_NOTES (insn));
3944 } 3947 }
3945 } 3948 }
3946 offset += GET_MODE_SIZE (DFmode); 3949 offset += GET_MODE_SIZE (DFmode);
3947 fr_saved++; 3950 fr_saved++;
3948 } 3951 }
4356 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 25)); 4359 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 25));
4357 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 26)); 4360 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 26));
4358 4361
4359 /* Indicate the _mcount call cannot throw, nor will it execute a 4362 /* Indicate the _mcount call cannot throw, nor will it execute a
4360 non-local goto. */ 4363 non-local goto. */
4361 REG_NOTES (call_insn) 4364 make_reg_eh_region_note_nothrow_nononlocal (call_insn);
4362 = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx, REG_NOTES (call_insn));
4363 } 4365 }
4364 4366
4365 /* Fetch the return address for the frame COUNT steps up from 4367 /* Fetch the return address for the frame COUNT steps up from
4366 the current frame, after the prologue. FRAMEADDR is the 4368 the current frame, after the prologue. FRAMEADDR is the
4367 frame pointer of the COUNT frame. 4369 frame pointer of the COUNT frame.
4394 rtx label; 4396 rtx label;
4395 rtx rp; 4397 rtx rp;
4396 rtx saved_rp; 4398 rtx saved_rp;
4397 rtx ins; 4399 rtx ins;
4398 4400
4401 /* Instruction stream at the normal return address for the export stub:
4402
4403 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp
4404 0x004010a1 | stub+12: ldsid (sr0,rp),r1
4405 0x00011820 | stub+16: mtsp r1,sr0
4406 0xe0400002 | stub+20: be,n 0(sr0,rp)
4407
4408 0xe0400002 must be specified as -532676606 so that it won't be
4409 rejected as an invalid immediate operand on 64-bit hosts. */
4410
4411 HOST_WIDE_INT insns[4] = {0x4bc23fd1, 0x004010a1, 0x00011820, -532676606};
4412 int i;
4413
4399 if (count != 0) 4414 if (count != 0)
4400 return NULL_RTX; 4415 return NULL_RTX;
4401 4416
4402 rp = get_hard_reg_initial_val (Pmode, 2); 4417 rp = get_hard_reg_initial_val (Pmode, 2);
4403 4418
4404 if (TARGET_64BIT || TARGET_NO_SPACE_REGS) 4419 if (TARGET_64BIT || TARGET_NO_SPACE_REGS)
4405 return rp; 4420 return rp;
4421
4422 /* If there is no export stub then just use the value saved from
4423 the return pointer register. */
4406 4424
4407 saved_rp = gen_reg_rtx (Pmode); 4425 saved_rp = gen_reg_rtx (Pmode);
4408 emit_move_insn (saved_rp, rp); 4426 emit_move_insn (saved_rp, rp);
4409 4427
4410 /* Get pointer to the instruction stream. We have to mask out the 4428 /* Get pointer to the instruction stream. We have to mask out the
4413 instruction that would have been executed if we returned. */ 4431 instruction that would have been executed if we returned. */
4414 ins = copy_to_reg (gen_rtx_AND (Pmode, rp, MASK_RETURN_ADDR)); 4432 ins = copy_to_reg (gen_rtx_AND (Pmode, rp, MASK_RETURN_ADDR));
4415 label = gen_label_rtx (); 4433 label = gen_label_rtx ();
4416 4434
4417 /* Check the instruction stream at the normal return address for the 4435 /* Check the instruction stream at the normal return address for the
4418 export stub: 4436 export stub. If it is an export stub, than our return address is
4419 4437 really in -24[frameaddr]. */
4420 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp 4438
4421 0x004010a1 | stub+12: ldsid (sr0,rp),r1 4439 for (i = 0; i < 3; i++)
4422 0x00011820 | stub+16: mtsp r1,sr0 4440 {
4423 0xe0400002 | stub+20: be,n 0(sr0,rp) 4441 rtx op0 = gen_rtx_MEM (SImode, plus_constant (ins, i * 4));
4424 4442 rtx op1 = GEN_INT (insns[i]);
4425 If it is an export stub, than our return address is really in 4443 emit_cmp_and_jump_insns (op0, op1, NE, NULL, SImode, 0, label);
4426 -24[frameaddr]. */ 4444 }
4427
4428 emit_cmp_insn (gen_rtx_MEM (SImode, ins), GEN_INT (0x4bc23fd1), NE,
4429 NULL_RTX, SImode, 1);
4430 emit_jump_insn (gen_bne (label));
4431
4432 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)),
4433 GEN_INT (0x004010a1), NE, NULL_RTX, SImode, 1);
4434 emit_jump_insn (gen_bne (label));
4435
4436 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)),
4437 GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1);
4438 emit_jump_insn (gen_bne (label));
4439
4440 /* 0xe0400002 must be specified as -532676606 so that it won't be
4441 rejected as an invalid immediate operand on 64-bit hosts. */
4442 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)),
4443 GEN_INT (-532676606), NE, NULL_RTX, SImode, 1);
4444
4445 /* If there is no export stub then just use the value saved from
4446 the return pointer register. */
4447
4448 emit_jump_insn (gen_bne (label));
4449 4445
4450 /* Here we know that our return address points to an export 4446 /* Here we know that our return address points to an export
4451 stub. We don't want to return the address of the export stub, 4447 stub. We don't want to return the address of the export stub,
4452 but rather the return address of the export stub. That return 4448 but rather the return address of the export stub. That return
4453 address is stored at -24[frameaddr]. */ 4449 address is stored at -24[frameaddr]. */
4457 memory_address (Pmode, 4453 memory_address (Pmode,
4458 plus_constant (frameaddr, 4454 plus_constant (frameaddr,
4459 -24)))); 4455 -24))));
4460 4456
4461 emit_label (label); 4457 emit_label (label);
4458
4462 return saved_rp; 4459 return saved_rp;
4463 } 4460 }
4464 4461
4465 void 4462 void
4466 emit_bcond_fp (enum rtx_code code, rtx operand0) 4463 emit_bcond_fp (rtx operands[])
4467 { 4464 {
4465 enum rtx_code code = GET_CODE (operands[0]);
4466 rtx operand0 = operands[1];
4467 rtx operand1 = operands[2];
4468 rtx label = operands[3];
4469
4470 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
4471 gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1)));
4472
4468 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 4473 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
4469 gen_rtx_IF_THEN_ELSE (VOIDmode, 4474 gen_rtx_IF_THEN_ELSE (VOIDmode,
4470 gen_rtx_fmt_ee (code, 4475 gen_rtx_fmt_ee (NE,
4471 VOIDmode, 4476 VOIDmode,
4472 gen_rtx_REG (CCFPmode, 0), 4477 gen_rtx_REG (CCFPmode, 0),
4473 const0_rtx), 4478 const0_rtx),
4474 gen_rtx_LABEL_REF (VOIDmode, operand0), 4479 gen_rtx_LABEL_REF (VOIDmode, label),
4475 pc_rtx))); 4480 pc_rtx)));
4476 4481
4477 }
4478
4479 rtx
4480 gen_cmp_fp (enum rtx_code code, rtx operand0, rtx operand1)
4481 {
4482 return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
4483 gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1));
4484 } 4482 }
4485 4483
4486 /* Adjust the cost of a scheduling dependency. Return the new cost of 4484 /* Adjust the cost of a scheduling dependency. Return the new cost of
4487 a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ 4485 a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
4488 4486
4774 else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn)) 4772 else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn))
4775 { 4773 {
4776 /* Adjust a short backwards conditional with an unfilled delay slot. */ 4774 /* Adjust a short backwards conditional with an unfilled delay slot. */
4777 if (GET_CODE (pat) == SET 4775 if (GET_CODE (pat) == SET
4778 && length == 4 4776 && length == 4
4777 && JUMP_LABEL (insn) != NULL_RTX
4779 && ! forward_branch_p (insn)) 4778 && ! forward_branch_p (insn))
4780 return 4; 4779 return 4;
4781 else if (GET_CODE (pat) == PARALLEL 4780 else if (GET_CODE (pat) == PARALLEL
4782 && get_attr_type (insn) == TYPE_PARALLEL_BRANCH 4781 && get_attr_type (insn) == TYPE_PARALLEL_BRANCH
4783 && length == 4) 4782 && length == 4)
5807 case LABEL_REF: 5806 case LABEL_REF:
5808 is_symbolic = 1; 5807 is_symbolic = 1;
5809 break; 5808 break;
5810 case CONST: 5809 case CONST:
5811 op = XEXP (x, 0); 5810 op = XEXP (x, 0);
5812 is_symbolic = (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 5811 is_symbolic = (GET_CODE (op) == PLUS
5813 && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0))) 5812 && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
5814 || GET_CODE (XEXP (op, 0)) == LABEL_REF) 5813 && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
5814 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
5815 && GET_CODE (XEXP (op, 1)) == CONST_INT); 5815 && GET_CODE (XEXP (op, 1)) == CONST_INT);
5816 break; 5816 break;
5817 default: 5817 default:
5818 is_symbolic = 0; 5818 is_symbolic = 0;
5819 break; 5819 break;
6109 default: 6109 default:
6110 gcc_unreachable (); 6110 gcc_unreachable ();
6111 } 6111 }
6112 } 6112 }
6113 6113
6114 /* Return TRUE if INSN, a jump insn, has an unfilled delay slot and
6115 it branches to the next real instruction. Otherwise, return FALSE. */
6116
6117 static bool
6118 branch_to_delay_slot_p (rtx insn)
6119 {
6120 if (dbr_sequence_length ())
6121 return FALSE;
6122
6123 return next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn);
6124 }
6125
6126 /* Return TRUE if INSN, a jump insn, needs a nop in its delay slot.
6127
6128 This occurs when INSN has an unfilled delay slot and is followed
6129 by an ASM_INPUT. Disaster can occur if the ASM_INPUT is empty and
6130 the jump branches into the delay slot. So, we add a nop in the delay
6131 slot just to be safe. This messes up our instruction count, but we
6132 don't know how big the ASM_INPUT insn is anyway. */
6133
6134 static bool
6135 branch_needs_nop_p (rtx insn)
6136 {
6137 rtx next_insn;
6138
6139 if (dbr_sequence_length ())
6140 return FALSE;
6141
6142 next_insn = next_real_insn (insn);
6143 return GET_CODE (PATTERN (next_insn)) == ASM_INPUT;
6144 }
6145
6114 /* This routine handles all the normal conditional branch sequences we 6146 /* This routine handles all the normal conditional branch sequences we
6115 might need to generate. It handles compare immediate vs compare 6147 might need to generate. It handles compare immediate vs compare
6116 register, nullification of delay slots, varying length branches, 6148 register, nullification of delay slots, varying length branches,
6117 negated branches, and all combinations of the above. It returns the 6149 negated branches, and all combinations of the above. It returns the
6118 output appropriate to emit the branch corresponding to all given 6150 output appropriate to emit the branch corresponding to all given
6134 While it is usually safe to emit nothing, this can fail if the 6166 While it is usually safe to emit nothing, this can fail if the
6135 preceding instruction is a nullified branch with an empty delay 6167 preceding instruction is a nullified branch with an empty delay
6136 slot and the same branch target as this branch. We could check 6168 slot and the same branch target as this branch. We could check
6137 for this but jump optimization should eliminate nop jumps. It 6169 for this but jump optimization should eliminate nop jumps. It
6138 is always safe to emit a nop. */ 6170 is always safe to emit a nop. */
6139 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn)) 6171 if (branch_to_delay_slot_p (insn))
6140 return "nop"; 6172 return "nop";
6141 6173
6142 /* The doubleword form of the cmpib instruction doesn't have the LEU 6174 /* The doubleword form of the cmpib instruction doesn't have the LEU
6143 and GTU conditions while the cmpb instruction does. Since we accept 6175 and GTU conditions while the cmpb instruction does. Since we accept
6144 zero for cmpb, we must ensure that we use cmpb for the comparison. */ 6176 zero for cmpb, we must ensure that we use cmpb for the comparison. */
6183 else 6215 else
6184 strcat (buf, "%S3"); 6216 strcat (buf, "%S3");
6185 if (useskip) 6217 if (useskip)
6186 strcat (buf, " %2,%r1,%%r0"); 6218 strcat (buf, " %2,%r1,%%r0");
6187 else if (nullify) 6219 else if (nullify)
6188 strcat (buf, ",n %2,%r1,%0"); 6220 {
6221 if (branch_needs_nop_p (insn))
6222 strcat (buf, ",n %2,%r1,%0%#");
6223 else
6224 strcat (buf, ",n %2,%r1,%0");
6225 }
6189 else 6226 else
6190 strcat (buf, " %2,%r1,%0"); 6227 strcat (buf, " %2,%r1,%0");
6191 break; 6228 break;
6192 6229
6193 /* All long conditionals. Note a short backward branch with an 6230 /* All long conditionals. Note a short backward branch with an
6456 /* A conditional branch to the following instruction (e.g. the delay slot) is 6493 /* A conditional branch to the following instruction (e.g. the delay slot) is
6457 asking for a disaster. I do not think this can happen as this pattern 6494 asking for a disaster. I do not think this can happen as this pattern
6458 is only used when optimizing; jump optimization should eliminate the 6495 is only used when optimizing; jump optimization should eliminate the
6459 jump. But be prepared just in case. */ 6496 jump. But be prepared just in case. */
6460 6497
6461 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn)) 6498 if (branch_to_delay_slot_p (insn))
6462 return "nop"; 6499 return "nop";
6463 6500
6464 /* If this is a long branch with its delay slot unfilled, set `nullify' 6501 /* If this is a long branch with its delay slot unfilled, set `nullify'
6465 as it can nullify the delay slot and save a nop. */ 6502 as it can nullify the delay slot and save a nop. */
6466 if (length == 8 && dbr_sequence_length () == 0) 6503 if (length == 8 && dbr_sequence_length () == 0)
6502 else 6539 else
6503 strcat (buf, "<"); 6540 strcat (buf, "<");
6504 if (useskip) 6541 if (useskip)
6505 strcat (buf, " %0,%1,1,%%r0"); 6542 strcat (buf, " %0,%1,1,%%r0");
6506 else if (nullify && negated) 6543 else if (nullify && negated)
6507 strcat (buf, ",n %0,%1,%3"); 6544 {
6545 if (branch_needs_nop_p (insn))
6546 strcat (buf, ",n %0,%1,%3%#");
6547 else
6548 strcat (buf, ",n %0,%1,%3");
6549 }
6508 else if (nullify && ! negated) 6550 else if (nullify && ! negated)
6509 strcat (buf, ",n %0,%1,%2"); 6551 {
6552 if (branch_needs_nop_p (insn))
6553 strcat (buf, ",n %0,%1,%2%#");
6554 else
6555 strcat (buf, ",n %0,%1,%2");
6556 }
6510 else if (! nullify && negated) 6557 else if (! nullify && negated)
6511 strcat (buf, "%0,%1,%3"); 6558 strcat (buf, " %0,%1,%3");
6512 else if (! nullify && ! negated) 6559 else if (! nullify && ! negated)
6513 strcat (buf, " %0,%1,%2"); 6560 strcat (buf, " %0,%1,%2");
6514 break; 6561 break;
6515 6562
6516 /* All long conditionals. Note a short backward branch with an 6563 /* All long conditionals. Note a short backward branch with an
6637 /* A conditional branch to the following instruction (e.g. the delay slot) is 6684 /* A conditional branch to the following instruction (e.g. the delay slot) is
6638 asking for a disaster. I do not think this can happen as this pattern 6685 asking for a disaster. I do not think this can happen as this pattern
6639 is only used when optimizing; jump optimization should eliminate the 6686 is only used when optimizing; jump optimization should eliminate the
6640 jump. But be prepared just in case. */ 6687 jump. But be prepared just in case. */
6641 6688
6642 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn)) 6689 if (branch_to_delay_slot_p (insn))
6643 return "nop"; 6690 return "nop";
6644 6691
6645 /* If this is a long branch with its delay slot unfilled, set `nullify' 6692 /* If this is a long branch with its delay slot unfilled, set `nullify'
6646 as it can nullify the delay slot and save a nop. */ 6693 as it can nullify the delay slot and save a nop. */
6647 if (length == 8 && dbr_sequence_length () == 0) 6694 if (length == 8 && dbr_sequence_length () == 0)
6683 else 6730 else
6684 strcat (buf, "<"); 6731 strcat (buf, "<");
6685 if (useskip) 6732 if (useskip)
6686 strcat (buf, "{ %0,1,%%r0| %0,%%sar,1,%%r0}"); 6733 strcat (buf, "{ %0,1,%%r0| %0,%%sar,1,%%r0}");
6687 else if (nullify && negated) 6734 else if (nullify && negated)
6688 strcat (buf, "{,n %0,%3|,n %0,%%sar,%3}"); 6735 {
6736 if (branch_needs_nop_p (insn))
6737 strcat (buf, "{,n %0,%3%#|,n %0,%%sar,%3%#}");
6738 else
6739 strcat (buf, "{,n %0,%3|,n %0,%%sar,%3}");
6740 }
6689 else if (nullify && ! negated) 6741 else if (nullify && ! negated)
6690 strcat (buf, "{,n %0,%2|,n %0,%%sar,%2}"); 6742 {
6743 if (branch_needs_nop_p (insn))
6744 strcat (buf, "{,n %0,%2%#|,n %0,%%sar,%2%#}");
6745 else
6746 strcat (buf, "{,n %0,%2|,n %0,%%sar,%2}");
6747 }
6691 else if (! nullify && negated) 6748 else if (! nullify && negated)
6692 strcat (buf, "{%0,%3|%0,%%sar,%3}"); 6749 strcat (buf, "{ %0,%3| %0,%%sar,%3}");
6693 else if (! nullify && ! negated) 6750 else if (! nullify && ! negated)
6694 strcat (buf, "{ %0,%2| %0,%%sar,%2}"); 6751 strcat (buf, "{ %0,%2| %0,%%sar,%2}");
6695 break; 6752 break;
6696 6753
6697 /* All long conditionals. Note a short backward branch with an 6754 /* All long conditionals. Note a short backward branch with an
6809 int length = get_attr_length (insn); 6866 int length = get_attr_length (insn);
6810 6867
6811 /* A conditional branch to the following instruction (e.g. the delay slot) is 6868 /* A conditional branch to the following instruction (e.g. the delay slot) is
6812 asking for a disaster. Be prepared! */ 6869 asking for a disaster. Be prepared! */
6813 6870
6814 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn)) 6871 if (branch_to_delay_slot_p (insn))
6815 { 6872 {
6816 if (which_alternative == 0) 6873 if (which_alternative == 0)
6817 return "ldo %1(%0),%0"; 6874 return "ldo %1(%0),%0";
6818 else if (which_alternative == 1) 6875 else if (which_alternative == 1)
6819 { 6876 {
6846 6903
6847 switch (length) 6904 switch (length)
6848 { 6905 {
6849 case 4: 6906 case 4:
6850 if (nullify) 6907 if (nullify)
6851 return "addib,%C2,n %1,%0,%3"; 6908 {
6909 if (branch_needs_nop_p (insn))
6910 return "addib,%C2,n %1,%0,%3%#";
6911 else
6912 return "addib,%C2,n %1,%0,%3";
6913 }
6852 else 6914 else
6853 return "addib,%C2 %1,%0,%3"; 6915 return "addib,%C2 %1,%0,%3";
6854 6916
6855 case 8: 6917 case 8:
6856 /* Handle weird backwards branch with a fulled delay slot 6918 /* Handle weird backwards branch with a fulled delay slot
6954 int length = get_attr_length (insn); 7016 int length = get_attr_length (insn);
6955 7017
6956 /* A conditional branch to the following instruction (e.g. the delay slot) is 7018 /* A conditional branch to the following instruction (e.g. the delay slot) is
6957 asking for a disaster. Be prepared! */ 7019 asking for a disaster. Be prepared! */
6958 7020
6959 if (next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn)) 7021 if (branch_to_delay_slot_p (insn))
6960 { 7022 {
6961 if (which_alternative == 0) 7023 if (which_alternative == 0)
6962 return "copy %1,%0"; 7024 return "copy %1,%0";
6963 else if (which_alternative == 1) 7025 else if (which_alternative == 1)
6964 { 7026 {
6992 7054
6993 switch (length) 7055 switch (length)
6994 { 7056 {
6995 case 4: 7057 case 4:
6996 if (nullify) 7058 if (nullify)
6997 return "movb,%C2,n %1,%0,%3"; 7059 {
7060 if (branch_needs_nop_p (insn))
7061 return "movb,%C2,n %1,%0,%3%#";
7062 else
7063 return "movb,%C2,n %1,%0,%3";
7064 }
6998 else 7065 else
6999 return "movb,%C2 %1,%0,%3"; 7066 return "movb,%C2 %1,%0,%3";
7000 7067
7001 case 8: 7068 case 8:
7002 /* Handle weird backwards branch with a filled delay slot 7069 /* Handle weird backwards branch with a filled delay slot
7724 xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1); 7791 xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
7725 7792
7726 if (!delay_slot_filled && INSN_ADDRESSES_SET_P ()) 7793 if (!delay_slot_filled && INSN_ADDRESSES_SET_P ())
7727 { 7794 {
7728 /* See if the return address can be adjusted. Use the containing 7795 /* See if the return address can be adjusted. Use the containing
7729 sequence insn's address. */ 7796 sequence insn's address. This would break the regular call/return@
7797 relationship assumed by the table based eh unwinder, so only do that
7798 if the call is not possibly throwing. */
7730 rtx seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0))); 7799 rtx seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
7731 int distance = (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn)))) 7800 int distance = (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn))))
7732 - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8); 7801 - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8);
7733 7802
7734 if (VAL_14_BITS_P (distance)) 7803 if (VAL_14_BITS_P (distance)
7804 && !(can_throw_internal (insn) || can_throw_external (insn)))
7735 { 7805 {
7736 xoperands[1] = gen_label_rtx (); 7806 xoperands[1] = gen_label_rtx ();
7737 output_asm_insn ("ldo %0-%1(%%r2),%%r2", xoperands); 7807 output_asm_insn ("ldo %0-%1(%%r2),%%r2", xoperands);
7738 targetm.asm_out.internal_label (asm_out_file, "L", 7808 targetm.asm_out.internal_label (asm_out_file, "L",
7739 CODE_LABEL_NUMBER (xoperands[1])); 7809 CODE_LABEL_NUMBER (xoperands[1]));
8531 non_hard_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 8601 non_hard_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
8532 { 8602 {
8533 return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER); 8603 return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER);
8534 } 8604 }
8535 8605
8536 /* Return 1 if INSN branches forward. Should be using insn_addresses 8606 /* Return TRUE if INSN branches forward. */
8537 to avoid walking through all the insns... */ 8607
8538 static int 8608 static bool
8539 forward_branch_p (rtx insn) 8609 forward_branch_p (rtx insn)
8540 { 8610 {
8541 rtx label = JUMP_LABEL (insn); 8611 rtx lab = JUMP_LABEL (insn);
8612
8613 /* The INSN must have a jump label. */
8614 gcc_assert (lab != NULL_RTX);
8615
8616 if (INSN_ADDRESSES_SET_P ())
8617 return INSN_ADDRESSES (INSN_UID (lab)) > INSN_ADDRESSES (INSN_UID (insn));
8542 8618
8543 while (insn) 8619 while (insn)
8544 { 8620 {
8545 if (insn == label) 8621 if (insn == lab)
8546 break; 8622 return true;
8547 else 8623 else
8548 insn = NEXT_INSN (insn); 8624 insn = NEXT_INSN (insn);
8549 } 8625 }
8550 8626
8551 return (insn == label); 8627 return false;
8552 } 8628 }
8553 8629
8554 /* Return 1 if OP is an equality comparison, else return 0. */ 8630 /* Return 1 if OP is an equality comparison, else return 0. */
8555 int 8631 int
8556 eq_neq_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 8632 eq_neq_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
9128 && GET_CODE (PATTERN (insn)) != USE 9204 && GET_CODE (PATTERN (insn)) != USE
9129 && GET_CODE (PATTERN (insn)) != CLOBBER 9205 && GET_CODE (PATTERN (insn)) != CLOBBER
9130 && get_attr_type (insn) == TYPE_MILLI)); 9206 && get_attr_type (insn) == TYPE_MILLI));
9131 } 9207 }
9132 9208
9209 /* Promote the return value, but not the arguments. */
9210
9211 static enum machine_mode
9212 pa_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
9213 enum machine_mode mode,
9214 int *punsignedp ATTRIBUTE_UNUSED,
9215 const_tree fntype ATTRIBUTE_UNUSED,
9216 int for_return)
9217 {
9218 if (for_return == 0)
9219 return mode;
9220 return promote_mode (type, mode, punsignedp);
9221 }
9222
9133 /* On the HP-PA the value is found in register(s) 28(-29), unless 9223 /* On the HP-PA the value is found in register(s) 28(-29), unless
9134 the mode is SF or DF. Then the value is returned in fr4 (32). 9224 the mode is SF or DF. Then the value is returned in fr4 (32).
9135 9225
9136 This must perform the same promotions as PROMOTE_MODE, else 9226 This must perform the same promotions as PROMOTE_MODE, else promoting
9137 TARGET_PROMOTE_FUNCTION_RETURN will not work correctly. 9227 return values in TARGET_PROMOTE_FUNCTION_MODE will not work correctly.
9138 9228
9139 Small structures must be returned in a PARALLEL on PA64 in order 9229 Small structures must be returned in a PARALLEL on PA64 in order
9140 to match the HP Compiler ABI. */ 9230 to match the HP Compiler ABI. */
9141 9231
9142 rtx 9232 rtx
9143 function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) 9233 pa_function_value (const_tree valtype,
9234 const_tree func ATTRIBUTE_UNUSED,
9235 bool outgoing ATTRIBUTE_UNUSED)
9144 { 9236 {
9145 enum machine_mode valmode; 9237 enum machine_mode valmode;
9146 9238
9147 if (AGGREGATE_TYPE_P (valtype) 9239 if (AGGREGATE_TYPE_P (valtype)
9148 || TREE_CODE (valtype) == COMPLEX_TYPE 9240 || TREE_CODE (valtype) == COMPLEX_TYPE
9617 /* Structure to hold declaration and name of external symbols that are 9709 /* Structure to hold declaration and name of external symbols that are
9618 emitted by GCC. We generate a vector of these symbols and output them 9710 emitted by GCC. We generate a vector of these symbols and output them
9619 at the end of the file if and only if SYMBOL_REF_REFERENCED_P is true. 9711 at the end of the file if and only if SYMBOL_REF_REFERENCED_P is true.
9620 This avoids putting out names that are never really used. */ 9712 This avoids putting out names that are never really used. */
9621 9713
9622 typedef struct extern_symbol GTY(()) 9714 typedef struct GTY(()) extern_symbol
9623 { 9715 {
9624 tree decl; 9716 tree decl;
9625 const char *name; 9717 const char *name;
9626 } extern_symbol; 9718 } extern_symbol;
9627 9719
9731 return false; 9823 return false;
9732 9824
9733 return true; 9825 return true;
9734 } 9826 }
9735 9827
9828
9829 /* Length in units of the trampoline instruction code. */
9830
9831 #define TRAMPOLINE_CODE_SIZE (TARGET_64BIT ? 24 : (TARGET_PA_20 ? 32 : 40))
9832
9833
9834 /* Output assembler code for a block containing the constant parts
9835 of a trampoline, leaving space for the variable parts.\
9836
9837 The trampoline sets the static chain pointer to STATIC_CHAIN_REGNUM
9838 and then branches to the specified routine.
9839
9840 This code template is copied from text segment to stack location
9841 and then patched with pa_trampoline_init to contain valid values,
9842 and then entered as a subroutine.
9843
9844 It is best to keep this as small as possible to avoid having to
9845 flush multiple lines in the cache. */
9846
9847 static void
9848 pa_asm_trampoline_template (FILE *f)
9849 {
9850 if (!TARGET_64BIT)
9851 {
9852 fputs ("\tldw 36(%r22),%r21\n", f);
9853 fputs ("\tbb,>=,n %r21,30,.+16\n", f);
9854 if (ASSEMBLER_DIALECT == 0)
9855 fputs ("\tdepi 0,31,2,%r21\n", f);
9856 else
9857 fputs ("\tdepwi 0,31,2,%r21\n", f);
9858 fputs ("\tldw 4(%r21),%r19\n", f);
9859 fputs ("\tldw 0(%r21),%r21\n", f);
9860 if (TARGET_PA_20)
9861 {
9862 fputs ("\tbve (%r21)\n", f);
9863 fputs ("\tldw 40(%r22),%r29\n", f);
9864 fputs ("\t.word 0\n", f);
9865 fputs ("\t.word 0\n", f);
9866 }
9867 else
9868 {
9869 fputs ("\tldsid (%r21),%r1\n", f);
9870 fputs ("\tmtsp %r1,%sr0\n", f);
9871 fputs ("\tbe 0(%sr0,%r21)\n", f);
9872 fputs ("\tldw 40(%r22),%r29\n", f);
9873 }
9874 fputs ("\t.word 0\n", f);
9875 fputs ("\t.word 0\n", f);
9876 fputs ("\t.word 0\n", f);
9877 fputs ("\t.word 0\n", f);
9878 }
9879 else
9880 {
9881 fputs ("\t.dword 0\n", f);
9882 fputs ("\t.dword 0\n", f);
9883 fputs ("\t.dword 0\n", f);
9884 fputs ("\t.dword 0\n", f);
9885 fputs ("\tmfia %r31\n", f);
9886 fputs ("\tldd 24(%r31),%r1\n", f);
9887 fputs ("\tldd 24(%r1),%r27\n", f);
9888 fputs ("\tldd 16(%r1),%r1\n", f);
9889 fputs ("\tbve (%r1)\n", f);
9890 fputs ("\tldd 32(%r31),%r31\n", f);
9891 fputs ("\t.dword 0 ; fptr\n", f);
9892 fputs ("\t.dword 0 ; static link\n", f);
9893 }
9894 }
9895
9896 /* Emit RTL insns to initialize the variable parts of a trampoline.
9897 FNADDR is an RTX for the address of the function's pure code.
9898 CXT is an RTX for the static chain value for the function.
9899
9900 Move the function address to the trampoline template at offset 36.
9901 Move the static chain value to trampoline template at offset 40.
9902 Move the trampoline address to trampoline template at offset 44.
9903 Move r19 to trampoline template at offset 48. The latter two
9904 words create a plabel for the indirect call to the trampoline.
9905
9906 A similar sequence is used for the 64-bit port but the plabel is
9907 at the beginning of the trampoline.
9908
9909 Finally, the cache entries for the trampoline code are flushed.
9910 This is necessary to ensure that the trampoline instruction sequence
9911 is written to memory prior to any attempts at prefetching the code
9912 sequence. */
9913
9914 static void
9915 pa_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
9916 {
9917 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
9918 rtx start_addr = gen_reg_rtx (Pmode);
9919 rtx end_addr = gen_reg_rtx (Pmode);
9920 rtx line_length = gen_reg_rtx (Pmode);
9921 rtx r_tramp, tmp;
9922
9923 emit_block_move (m_tramp, assemble_trampoline_template (),
9924 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
9925 r_tramp = force_reg (Pmode, XEXP (m_tramp, 0));
9926
9927 if (!TARGET_64BIT)
9928 {
9929 tmp = adjust_address (m_tramp, Pmode, 36);
9930 emit_move_insn (tmp, fnaddr);
9931 tmp = adjust_address (m_tramp, Pmode, 40);
9932 emit_move_insn (tmp, chain_value);
9933
9934 /* Create a fat pointer for the trampoline. */
9935 tmp = adjust_address (m_tramp, Pmode, 44);
9936 emit_move_insn (tmp, r_tramp);
9937 tmp = adjust_address (m_tramp, Pmode, 48);
9938 emit_move_insn (tmp, gen_rtx_REG (Pmode, 19));
9939
9940 /* fdc and fic only use registers for the address to flush,
9941 they do not accept integer displacements. We align the
9942 start and end addresses to the beginning of their respective
9943 cache lines to minimize the number of lines flushed. */
9944 emit_insn (gen_andsi3 (start_addr, r_tramp,
9945 GEN_INT (-MIN_CACHELINE_SIZE)));
9946 tmp = force_reg (Pmode, plus_constant (r_tramp, TRAMPOLINE_CODE_SIZE-1));
9947 emit_insn (gen_andsi3 (end_addr, tmp,
9948 GEN_INT (-MIN_CACHELINE_SIZE)));
9949 emit_move_insn (line_length, GEN_INT (MIN_CACHELINE_SIZE));
9950 emit_insn (gen_dcacheflushsi (start_addr, end_addr, line_length));
9951 emit_insn (gen_icacheflushsi (start_addr, end_addr, line_length,
9952 gen_reg_rtx (Pmode),
9953 gen_reg_rtx (Pmode)));
9954 }
9955 else
9956 {
9957 tmp = adjust_address (m_tramp, Pmode, 56);
9958 emit_move_insn (tmp, fnaddr);
9959 tmp = adjust_address (m_tramp, Pmode, 64);
9960 emit_move_insn (tmp, chain_value);
9961
9962 /* Create a fat pointer for the trampoline. */
9963 tmp = adjust_address (m_tramp, Pmode, 16);
9964 emit_move_insn (tmp, force_reg (Pmode, plus_constant (r_tramp, 32)));
9965 tmp = adjust_address (m_tramp, Pmode, 24);
9966 emit_move_insn (tmp, gen_rtx_REG (Pmode, 27));
9967
9968 /* fdc and fic only use registers for the address to flush,
9969 they do not accept integer displacements. We align the
9970 start and end addresses to the beginning of their respective
9971 cache lines to minimize the number of lines flushed. */
9972 tmp = force_reg (Pmode, plus_constant (r_tramp, 32));
9973 emit_insn (gen_anddi3 (start_addr, tmp,
9974 GEN_INT (-MIN_CACHELINE_SIZE)));
9975 tmp = force_reg (Pmode, plus_constant (tmp, TRAMPOLINE_CODE_SIZE - 1));
9976 emit_insn (gen_anddi3 (end_addr, tmp,
9977 GEN_INT (-MIN_CACHELINE_SIZE)));
9978 emit_move_insn (line_length, GEN_INT (MIN_CACHELINE_SIZE));
9979 emit_insn (gen_dcacheflushdi (start_addr, end_addr, line_length));
9980 emit_insn (gen_icacheflushdi (start_addr, end_addr, line_length,
9981 gen_reg_rtx (Pmode),
9982 gen_reg_rtx (Pmode)));
9983 }
9984 }
9985
9986 /* Perform any machine-specific adjustment in the address of the trampoline.
9987 ADDR contains the address that was passed to pa_trampoline_init.
9988 Adjust the trampoline address to point to the plabel at offset 44. */
9989
9990 static rtx
9991 pa_trampoline_adjust_address (rtx addr)
9992 {
9993 if (!TARGET_64BIT)
9994 addr = memory_address (Pmode, plus_constant (addr, 46));
9995 return addr;
9996 }
9997
9736 #include "gt-pa.h" 9998 #include "gt-pa.h"