Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/pdp11/pdp11.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Subroutines for gcc2 for pdp11. | 1 /* Subroutines for gcc2 for pdp11. |
2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2004, 2005, | 2 Copyright (C) 1994-2017 Free Software Foundation, Inc. |
3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. | |
4 Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at). | 3 Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at). |
5 | 4 |
6 This file is part of GCC. | 5 This file is part of GCC. |
7 | 6 |
8 GCC is free software; you can redistribute it and/or modify | 7 GCC is free software; you can redistribute it and/or modify |
20 <http://www.gnu.org/licenses/>. */ | 19 <http://www.gnu.org/licenses/>. */ |
21 | 20 |
22 #include "config.h" | 21 #include "config.h" |
23 #include "system.h" | 22 #include "system.h" |
24 #include "coretypes.h" | 23 #include "coretypes.h" |
25 #include "tm.h" | 24 #include "backend.h" |
25 #include "target.h" | |
26 #include "rtl.h" | 26 #include "rtl.h" |
27 #include "tree.h" | |
28 #include "stringpool.h" | |
29 #include "attribs.h" | |
30 #include "df.h" | |
31 #include "memmodel.h" | |
32 #include "tm_p.h" | |
33 #include "insn-config.h" | |
27 #include "regs.h" | 34 #include "regs.h" |
28 #include "hard-reg-set.h" | 35 #include "emit-rtl.h" |
29 #include "insn-config.h" | 36 #include "recog.h" |
30 #include "conditions.h" | 37 #include "conditions.h" |
31 #include "function.h" | |
32 #include "output.h" | 38 #include "output.h" |
33 #include "insn-attr.h" | 39 #include "stor-layout.h" |
34 #include "flags.h" | 40 #include "varasm.h" |
35 #include "recog.h" | 41 #include "calls.h" |
36 #include "tree.h" | |
37 #include "expr.h" | 42 #include "expr.h" |
38 #include "diagnostic-core.h" | 43 #include "builtins.h" |
39 #include "tm_p.h" | 44 #include "dbxout.h" |
40 #include "target.h" | 45 |
46 /* This file should be included last. */ | |
41 #include "target-def.h" | 47 #include "target-def.h" |
42 #include "df.h" | |
43 | 48 |
44 /* this is the current value returned by the macro FIRST_PARM_OFFSET | 49 /* this is the current value returned by the macro FIRST_PARM_OFFSET |
45 defined in tm.h */ | 50 defined in tm.h */ |
46 int current_first_parm_offset; | 51 int current_first_parm_offset; |
47 | 52 |
66 24, | 71 24, |
67 -127, | 72 -127, |
68 127, | 73 127, |
69 15, | 74 15, |
70 15, | 75 15, |
76 0, | |
71 false, | 77 false, |
72 false, | 78 false, |
73 false, | 79 false, |
74 false, | 80 false, |
75 false, | 81 false, |
76 false, | 82 false, |
77 false, | 83 false, |
78 false | 84 false, |
85 "pdp11_f" | |
79 }; | 86 }; |
80 | 87 |
81 const struct real_format pdp11_d_format = | 88 const struct real_format pdp11_d_format = |
82 { | 89 { |
83 encode_pdp11_d, | 90 encode_pdp11_d, |
87 56, | 94 56, |
88 -127, | 95 -127, |
89 127, | 96 127, |
90 15, | 97 15, |
91 15, | 98 15, |
99 0, | |
92 false, | 100 false, |
93 false, | 101 false, |
94 false, | 102 false, |
95 false, | 103 false, |
96 false, | 104 false, |
97 false, | 105 false, |
98 false, | 106 false, |
99 false | 107 false, |
108 "pdp11_d" | |
100 }; | 109 }; |
101 | 110 |
102 static void | 111 static void |
103 encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, | 112 encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, |
104 const REAL_VALUE_TYPE *r) | 113 const REAL_VALUE_TYPE *r) |
136 } | 145 } |
137 | 146 |
138 /* This is where the condition code register lives. */ | 147 /* This is where the condition code register lives. */ |
139 /* rtx cc0_reg_rtx; - no longer needed? */ | 148 /* rtx cc0_reg_rtx; - no longer needed? */ |
140 | 149 |
141 static bool pdp11_handle_option (size_t, const char *, int); | |
142 static void pdp11_option_init_struct (struct gcc_options *); | |
143 static const char *singlemove_string (rtx *); | 150 static const char *singlemove_string (rtx *); |
144 static bool pdp11_assemble_integer (rtx, unsigned int, int); | 151 static bool pdp11_assemble_integer (rtx, unsigned int, int); |
145 static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT); | 152 static bool pdp11_rtx_costs (rtx, machine_mode, int, int, int *, bool); |
146 static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT); | |
147 static bool pdp11_rtx_costs (rtx, int, int, int *, bool); | |
148 static bool pdp11_return_in_memory (const_tree, const_tree); | 153 static bool pdp11_return_in_memory (const_tree, const_tree); |
149 static rtx pdp11_function_value (const_tree, const_tree, bool); | 154 static rtx pdp11_function_value (const_tree, const_tree, bool); |
150 static rtx pdp11_libcall_value (enum machine_mode, const_rtx); | 155 static rtx pdp11_libcall_value (machine_mode, const_rtx); |
151 static bool pdp11_function_value_regno_p (const unsigned int); | 156 static bool pdp11_function_value_regno_p (const unsigned int); |
152 static void pdp11_trampoline_init (rtx, tree, rtx); | 157 static void pdp11_trampoline_init (rtx, tree, rtx); |
153 static rtx pdp11_function_arg (CUMULATIVE_ARGS *, enum machine_mode, | 158 static rtx pdp11_function_arg (cumulative_args_t, machine_mode, |
154 const_tree, bool); | 159 const_tree, bool); |
155 static void pdp11_function_arg_advance (CUMULATIVE_ARGS *, | 160 static void pdp11_function_arg_advance (cumulative_args_t, |
156 enum machine_mode, const_tree, bool); | 161 machine_mode, const_tree, bool); |
157 static void pdp11_conditional_register_usage (void); | 162 static void pdp11_conditional_register_usage (void); |
158 | 163 static bool pdp11_legitimate_constant_p (machine_mode, rtx); |
159 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ | 164 |
160 | 165 static bool pdp11_scalar_mode_supported_p (scalar_mode); |
161 static const struct default_options pdp11_option_optimization_table[] = | |
162 { | |
163 { OPT_LEVELS_3_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | |
164 { OPT_LEVELS_NONE, 0, NULL, 0 } | |
165 }; | |
166 | 166 |
167 /* Initialize the GCC target structure. */ | 167 /* Initialize the GCC target structure. */ |
168 #undef TARGET_ASM_BYTE_OP | 168 #undef TARGET_ASM_BYTE_OP |
169 #define TARGET_ASM_BYTE_OP NULL | 169 #define TARGET_ASM_BYTE_OP NULL |
170 #undef TARGET_ASM_ALIGNED_HI_OP | 170 #undef TARGET_ASM_ALIGNED_HI_OP |
172 #undef TARGET_ASM_ALIGNED_SI_OP | 172 #undef TARGET_ASM_ALIGNED_SI_OP |
173 #define TARGET_ASM_ALIGNED_SI_OP NULL | 173 #define TARGET_ASM_ALIGNED_SI_OP NULL |
174 #undef TARGET_ASM_INTEGER | 174 #undef TARGET_ASM_INTEGER |
175 #define TARGET_ASM_INTEGER pdp11_assemble_integer | 175 #define TARGET_ASM_INTEGER pdp11_assemble_integer |
176 | 176 |
177 #undef TARGET_ASM_FUNCTION_PROLOGUE | |
178 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue | |
179 #undef TARGET_ASM_FUNCTION_EPILOGUE | |
180 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue | |
181 | |
182 #undef TARGET_ASM_OPEN_PAREN | 177 #undef TARGET_ASM_OPEN_PAREN |
183 #define TARGET_ASM_OPEN_PAREN "[" | 178 #define TARGET_ASM_OPEN_PAREN "[" |
184 #undef TARGET_ASM_CLOSE_PAREN | 179 #undef TARGET_ASM_CLOSE_PAREN |
185 #define TARGET_ASM_CLOSE_PAREN "]" | 180 #define TARGET_ASM_CLOSE_PAREN "]" |
186 | |
187 #undef TARGET_DEFAULT_TARGET_FLAGS | |
188 #define TARGET_DEFAULT_TARGET_FLAGS \ | |
189 (MASK_FPU | MASK_45 | TARGET_UNIX_ASM_DEFAULT) | |
190 #undef TARGET_HANDLE_OPTION | |
191 #define TARGET_HANDLE_OPTION pdp11_handle_option | |
192 #undef TARGET_OPTION_OPTIMIZATION_TABLE | |
193 #define TARGET_OPTION_OPTIMIZATION_TABLE pdp11_option_optimization_table | |
194 #undef TARGET_OPTION_INIT_STRUCT | |
195 #define TARGET_OPTION_INIT_STRUCT pdp11_option_init_struct | |
196 | 181 |
197 #undef TARGET_RTX_COSTS | 182 #undef TARGET_RTX_COSTS |
198 #define TARGET_RTX_COSTS pdp11_rtx_costs | 183 #define TARGET_RTX_COSTS pdp11_rtx_costs |
199 | 184 |
200 #undef TARGET_FUNCTION_ARG | 185 #undef TARGET_FUNCTION_ARG |
225 #define TARGET_PREFERRED_RELOAD_CLASS pdp11_preferred_reload_class | 210 #define TARGET_PREFERRED_RELOAD_CLASS pdp11_preferred_reload_class |
226 | 211 |
227 #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS | 212 #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS |
228 #define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS pdp11_preferred_output_reload_class | 213 #define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS pdp11_preferred_output_reload_class |
229 | 214 |
215 #undef TARGET_LRA_P | |
216 #define TARGET_LRA_P hook_bool_void_false | |
217 | |
230 #undef TARGET_LEGITIMATE_ADDRESS_P | 218 #undef TARGET_LEGITIMATE_ADDRESS_P |
231 #define TARGET_LEGITIMATE_ADDRESS_P pdp11_legitimate_address_p | 219 #define TARGET_LEGITIMATE_ADDRESS_P pdp11_legitimate_address_p |
232 | 220 |
233 #undef TARGET_CONDITIONAL_REGISTER_USAGE | 221 #undef TARGET_CONDITIONAL_REGISTER_USAGE |
234 #define TARGET_CONDITIONAL_REGISTER_USAGE pdp11_conditional_register_usage | 222 #define TARGET_CONDITIONAL_REGISTER_USAGE pdp11_conditional_register_usage |
239 #undef TARGET_PRINT_OPERAND | 227 #undef TARGET_PRINT_OPERAND |
240 #define TARGET_PRINT_OPERAND pdp11_asm_print_operand | 228 #define TARGET_PRINT_OPERAND pdp11_asm_print_operand |
241 | 229 |
242 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P | 230 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P |
243 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P pdp11_asm_print_operand_punct_valid_p | 231 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P pdp11_asm_print_operand_punct_valid_p |
232 | |
233 #undef TARGET_LEGITIMATE_CONSTANT_P | |
234 #define TARGET_LEGITIMATE_CONSTANT_P pdp11_legitimate_constant_p | |
235 | |
236 #undef TARGET_SCALAR_MODE_SUPPORTED_P | |
237 #define TARGET_SCALAR_MODE_SUPPORTED_P pdp11_scalar_mode_supported_p | |
238 | |
239 #undef TARGET_HARD_REGNO_NREGS | |
240 #define TARGET_HARD_REGNO_NREGS pdp11_hard_regno_nregs | |
241 #undef TARGET_HARD_REGNO_MODE_OK | |
242 #define TARGET_HARD_REGNO_MODE_OK pdp11_hard_regno_mode_ok | |
243 | |
244 #undef TARGET_MODES_TIEABLE_P | |
245 #define TARGET_MODES_TIEABLE_P pdp11_modes_tieable_p | |
246 | |
247 #undef TARGET_SECONDARY_MEMORY_NEEDED | |
248 #define TARGET_SECONDARY_MEMORY_NEEDED pdp11_secondary_memory_needed | |
249 | |
250 #undef TARGET_CAN_CHANGE_MODE_CLASS | |
251 #define TARGET_CAN_CHANGE_MODE_CLASS pdp11_can_change_mode_class | |
244 | 252 |
245 /* Implement TARGET_HANDLE_OPTION. */ | 253 /* A helper function to determine if REGNO should be saved in the |
246 | 254 current function's stack frame. */ |
247 static bool | 255 |
248 pdp11_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, | 256 static inline bool |
249 int value ATTRIBUTE_UNUSED) | 257 pdp11_saved_regno (unsigned regno) |
250 { | 258 { |
251 switch (code) | 259 return !call_used_regs[regno] && df_regs_ever_live_p (regno); |
252 { | 260 } |
253 case OPT_m10: | 261 |
254 target_flags &= ~(MASK_40 | MASK_45); | 262 /* Expand the function prologue. */ |
255 return true; | 263 |
256 | 264 void |
257 default: | 265 pdp11_expand_prologue (void) |
258 return true; | |
259 } | |
260 } | |
261 | |
262 /* Implement TARGET_OPTION_INIT_STRUCT. */ | |
263 | |
264 static void | |
265 pdp11_option_init_struct (struct gcc_options *opts) | |
266 { | |
267 opts->x_flag_finite_math_only = 0; | |
268 opts->x_flag_trapping_math = 0; | |
269 opts->x_flag_signaling_nans = 0; | |
270 } | |
271 | |
272 /* | |
273 stream is a stdio stream to output the code to. | |
274 size is an int: how many units of temporary storage to allocate. | |
275 Refer to the array `regs_ever_live' to determine which registers | |
276 to save; `regs_ever_live[I]' is nonzero if register number I | |
277 is ever used in the function. This macro is responsible for | |
278 knowing which registers should not be saved even if used. | |
279 */ | |
280 | |
281 static void | |
282 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size) | |
283 { | 266 { |
284 HOST_WIDE_INT fsize = ((size) + 1) & ~1; | 267 HOST_WIDE_INT fsize = get_frame_size (); |
285 int regno; | 268 unsigned regno; |
286 int via_ac = -1; | 269 rtx x, via_ac = NULL; |
287 | 270 |
288 fprintf (stream, | 271 /* If we are outputting code for main, the switch FPU to the |
289 "\n\t; /* function prologue %s*/\n", | 272 right mode if TARGET_FPU. */ |
290 current_function_name ()); | 273 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU) |
291 | 274 { |
292 /* if we are outputting code for main, | 275 emit_insn (gen_setd ()); |
293 the switch FPU to right mode if TARGET_FPU */ | 276 emit_insn (gen_seti ()); |
294 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU) | |
295 { | |
296 fprintf(stream, | |
297 "\t;/* switch cpu to double float, single integer */\n"); | |
298 fprintf(stream, "\tsetd\n"); | |
299 fprintf(stream, "\tseti\n\n"); | |
300 } | 277 } |
301 | 278 |
302 if (frame_pointer_needed) | 279 if (frame_pointer_needed) |
303 { | 280 { |
304 fprintf(stream, "\tmov r5, -(sp)\n"); | 281 x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx); |
305 fprintf(stream, "\tmov sp, r5\n"); | 282 x = gen_frame_mem (Pmode, x); |
283 emit_move_insn (x, hard_frame_pointer_rtx); | |
284 | |
285 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); | |
306 } | 286 } |
307 else | 287 |
308 { | 288 /* Make frame. */ |
309 /* DON'T SAVE FP */ | 289 if (fsize) |
310 } | 290 { |
311 | 291 emit_insn (gen_addhi3 (stack_pointer_rtx, stack_pointer_rtx, |
312 /* make frame */ | 292 GEN_INT (-fsize))); |
313 if (fsize) | 293 |
314 asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize); | 294 /* Prevent frame references via the frame pointer from being |
315 | 295 scheduled before the frame is allocated. */ |
316 /* save CPU registers */ | 296 if (frame_pointer_needed) |
317 for (regno = R0_REGNUM; regno <= PC_REGNUM; regno++) | 297 emit_insn (gen_blockage ()); |
318 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) | 298 } |
319 if (! ((regno == FRAME_POINTER_REGNUM) | 299 |
320 && frame_pointer_needed)) | 300 /* Save CPU registers. */ |
321 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]); | 301 for (regno = R0_REGNUM; regno <= PC_REGNUM; regno++) |
322 /* fpu regs saving */ | 302 if (pdp11_saved_regno (regno) |
323 | 303 && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed)) |
324 /* via_ac specifies the ac to use for saving ac4, ac5 */ | 304 { |
325 via_ac = -1; | 305 x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx); |
326 | 306 x = gen_frame_mem (Pmode, x); |
327 for (regno = AC0_REGNUM; regno <= AC5_REGNUM ; regno++) | 307 emit_move_insn (x, gen_rtx_REG (Pmode, regno)); |
328 { | 308 } |
329 /* ac0 - ac3 */ | 309 |
330 if (LOAD_FPU_REG_P(regno) | 310 /* Save FPU registers. */ |
331 && df_regs_ever_live_p (regno) | 311 for (regno = AC0_REGNUM; regno <= AC3_REGNUM; regno++) |
332 && ! call_used_regs[regno]) | 312 if (pdp11_saved_regno (regno)) |
333 { | 313 { |
334 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]); | 314 x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx); |
335 via_ac = regno; | 315 x = gen_frame_mem (DFmode, x); |
336 } | 316 via_ac = gen_rtx_REG (DFmode, regno); |
337 | 317 emit_move_insn (x, via_ac); |
338 /* maybe make ac4, ac5 call used regs?? */ | 318 } |
339 /* ac4 - ac5 */ | 319 |
340 if (NO_LOAD_FPU_REG_P(regno) | 320 /* ??? Maybe make ac4, ac5 call used regs?? */ |
341 && df_regs_ever_live_p (regno) | 321 for (regno = AC4_REGNUM; regno <= AC5_REGNUM; regno++) |
342 && ! call_used_regs[regno]) | 322 if (pdp11_saved_regno (regno)) |
343 { | 323 { |
344 gcc_assert (via_ac != -1); | 324 gcc_assert (via_ac != NULL); |
345 fprintf (stream, "\tldd %s, %s\n", | 325 emit_move_insn (via_ac, gen_rtx_REG (DFmode, regno)); |
346 reg_names[regno], reg_names[via_ac]); | 326 |
347 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]); | 327 x = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx); |
348 } | 328 x = gen_frame_mem (DFmode, x); |
349 } | 329 emit_move_insn (x, via_ac); |
350 | 330 } |
351 fprintf (stream, "\t;/* end of prologue */\n\n"); | 331 } |
352 } | 332 |
353 | 333 /* The function epilogue should not depend on the current stack pointer! |
354 /* | |
355 The function epilogue should not depend on the current stack pointer! | |
356 It should use the frame pointer only. This is mandatory because | 334 It should use the frame pointer only. This is mandatory because |
357 of alloca; we also take advantage of it to omit stack adjustments | 335 of alloca; we also take advantage of it to omit stack adjustments |
358 before returning. */ | 336 before returning. */ |
359 | 337 |
360 /* maybe we can make leaf functions faster by switching to the | 338 /* Maybe we can make leaf functions faster by switching to the |
361 second register file - this way we don't have to save regs! | 339 second register file - this way we don't have to save regs! |
362 leaf functions are ~ 50% of all functions (dynamically!) | 340 leaf functions are ~ 50% of all functions (dynamically!) |
363 | 341 |
364 set/clear bit 11 (dec. 2048) of status word for switching register files - | 342 set/clear bit 11 (dec. 2048) of status word for switching register files - |
365 but how can we do this? the pdp11/45 manual says bit may only | 343 but how can we do this? the pdp11/45 manual says bit may only |
368 switching to kernel is probably more expensive, so we'll leave it | 346 switching to kernel is probably more expensive, so we'll leave it |
369 like this and not use the second set of registers... | 347 like this and not use the second set of registers... |
370 | 348 |
371 maybe as option if you want to generate code for kernel mode? */ | 349 maybe as option if you want to generate code for kernel mode? */ |
372 | 350 |
373 static void | 351 void |
374 pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size) | 352 pdp11_expand_epilogue (void) |
375 { | 353 { |
376 HOST_WIDE_INT fsize = ((size) + 1) & ~1; | 354 HOST_WIDE_INT fsize = get_frame_size (); |
377 int i, j, k; | 355 unsigned regno; |
378 | 356 rtx x, reg, via_ac = NULL; |
379 int via_ac; | 357 |
380 | 358 if (pdp11_saved_regno (AC4_REGNUM) || pdp11_saved_regno (AC5_REGNUM)) |
381 fprintf (stream, "\n\t; /*function epilogue */\n"); | 359 { |
382 | 360 /* Find a temporary with which to restore AC4/5. */ |
383 if (frame_pointer_needed) | 361 for (regno = AC0_REGNUM; regno <= AC3_REGNUM; regno++) |
384 { | 362 if (pdp11_saved_regno (regno)) |
385 /* hope this is safe - m68k does it also .... */ | 363 { |
386 df_set_regs_ever_live (FRAME_POINTER_REGNUM, false); | 364 via_ac = gen_rtx_REG (DFmode, regno); |
387 | 365 break; |
388 for (i = PC_REGNUM, j = 0 ; i >= 0 ; i--) | 366 } |
389 if (df_regs_ever_live_p (i) && ! call_used_regs[i]) | 367 } |
390 j++; | 368 |
391 | 369 /* If possible, restore registers via pops. */ |
392 /* remember # of pushed bytes for CPU regs */ | 370 if (!frame_pointer_needed || crtl->sp_is_unchanging) |
393 k = 2*j; | 371 { |
394 | 372 /* Restore registers via pops. */ |
395 /* change fp -> r5 due to the compile error on libgcc2.c */ | 373 |
396 for (i = PC_REGNUM ; i >= R0_REGNUM ; i--) | 374 for (regno = AC5_REGNUM; regno >= AC0_REGNUM; regno--) |
397 if (df_regs_ever_live_p (i) && ! call_used_regs[i]) | 375 if (pdp11_saved_regno (regno)) |
398 fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n", | 376 { |
399 (-fsize-2*j--)&0xffff, reg_names[i]); | 377 x = gen_rtx_POST_INC (Pmode, stack_pointer_rtx); |
400 | 378 x = gen_frame_mem (DFmode, x); |
401 /* get ACs */ | 379 reg = gen_rtx_REG (DFmode, regno); |
402 via_ac = AC5_REGNUM; | 380 |
403 | 381 if (LOAD_FPU_REG_P (regno)) |
404 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--) | 382 emit_move_insn (reg, x); |
405 if (df_regs_ever_live_p (i) && ! call_used_regs[i]) | 383 else |
406 { | 384 { |
407 via_ac = i; | 385 emit_move_insn (via_ac, x); |
408 k += 8; | 386 emit_move_insn (reg, via_ac); |
409 } | 387 } |
410 | 388 } |
411 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--) | 389 |
390 for (regno = PC_REGNUM; regno >= R0_REGNUM + 2; regno--) | |
391 if (pdp11_saved_regno (regno) | |
392 && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed)) | |
393 { | |
394 x = gen_rtx_POST_INC (Pmode, stack_pointer_rtx); | |
395 x = gen_frame_mem (Pmode, x); | |
396 emit_move_insn (gen_rtx_REG (Pmode, regno), x); | |
397 } | |
398 } | |
399 else | |
400 { | |
401 /* Restore registers via moves. */ | |
402 /* ??? If more than a few registers need to be restored, it's smaller | |
403 to generate a pointer through which we can emit pops. Consider | |
404 that moves cost 2*NREG words and pops cost NREG+3 words. This | |
405 means that the crossover is NREG=3. | |
406 | |
407 Possible registers to use are: | |
408 (1) The first call-saved general register. This register will | |
409 be restored with the last pop. | |
410 (2) R1, if it's not used as a return register. | |
411 (3) FP itself. This option may result in +4 words, since we | |
412 may need two add imm,rn instructions instead of just one. | |
413 This also has the downside that we're not representing | |
414 the unwind info in any way, so during the epilogue the | |
415 debugger may get lost. */ | |
416 | |
417 HOST_WIDE_INT ofs = -pdp11_sp_frame_offset (); | |
418 | |
419 for (regno = AC5_REGNUM; regno >= AC0_REGNUM; regno--) | |
420 if (pdp11_saved_regno (regno)) | |
421 { | |
422 x = plus_constant (Pmode, hard_frame_pointer_rtx, ofs); | |
423 x = gen_frame_mem (DFmode, x); | |
424 reg = gen_rtx_REG (DFmode, regno); | |
425 | |
426 if (LOAD_FPU_REG_P (regno)) | |
427 emit_move_insn (reg, x); | |
428 else | |
429 { | |
430 emit_move_insn (via_ac, x); | |
431 emit_move_insn (reg, via_ac); | |
432 } | |
433 ofs += 8; | |
434 } | |
435 | |
436 for (regno = PC_REGNUM; regno >= R0_REGNUM + 2; regno--) | |
437 if (pdp11_saved_regno (regno) | |
438 && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed)) | |
439 { | |
440 x = plus_constant (Pmode, hard_frame_pointer_rtx, ofs); | |
441 x = gen_frame_mem (Pmode, x); | |
442 emit_move_insn (gen_rtx_REG (Pmode, regno), x); | |
443 ofs += 2; | |
444 } | |
445 } | |
446 | |
447 /* Deallocate the stack frame. */ | |
448 if (fsize) | |
449 { | |
450 /* Prevent frame references via any pointer from being | |
451 scheduled after the frame is deallocated. */ | |
452 emit_insn (gen_blockage ()); | |
453 | |
454 if (frame_pointer_needed) | |
412 { | 455 { |
413 if (LOAD_FPU_REG_P(i) | 456 /* We can deallocate the frame with a single move. */ |
414 && df_regs_ever_live_p (i) | 457 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); |
415 && ! call_used_regs[i]) | |
416 { | |
417 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n", | |
418 (-fsize-k)&0xffff, reg_names[i]); | |
419 k -= 8; | |
420 } | |
421 | |
422 if (NO_LOAD_FPU_REG_P(i) | |
423 && df_regs_ever_live_p (i) | |
424 && ! call_used_regs[i]) | |
425 { | |
426 gcc_assert (LOAD_FPU_REG_P(via_ac)); | |
427 | |
428 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n", | |
429 (-fsize-k)&0xffff, reg_names[via_ac]); | |
430 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]); | |
431 k -= 8; | |
432 } | |
433 } | 458 } |
434 | 459 else |
435 fprintf(stream, "\tmov r5, sp\n"); | 460 emit_insn (gen_addhi3 (stack_pointer_rtx, stack_pointer_rtx, |
436 fprintf (stream, "\tmov (sp)+, r5\n"); | 461 GEN_INT (fsize))); |
437 } | 462 } |
438 else | 463 |
439 { | 464 if (frame_pointer_needed) |
440 via_ac = AC5_REGNUM; | 465 { |
441 | 466 x = gen_rtx_POST_INC (Pmode, stack_pointer_rtx); |
442 /* get ACs */ | 467 x = gen_frame_mem (Pmode, x); |
443 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--) | 468 emit_move_insn (hard_frame_pointer_rtx, x); |
444 if (df_regs_ever_live_p (i) && ! call_used_regs[i]) | 469 } |
445 via_ac = i; | 470 |
446 | 471 emit_jump_insn (gen_return ()); |
447 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--) | |
448 { | |
449 if (LOAD_FPU_REG_P(i) | |
450 && df_regs_ever_live_p (i) | |
451 && ! call_used_regs[i]) | |
452 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]); | |
453 | |
454 if (NO_LOAD_FPU_REG_P(i) | |
455 && df_regs_ever_live_p (i) | |
456 && ! call_used_regs[i]) | |
457 { | |
458 gcc_assert (LOAD_FPU_REG_P(via_ac)); | |
459 | |
460 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]); | |
461 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]); | |
462 } | |
463 } | |
464 | |
465 for (i = PC_REGNUM; i >= 0; i--) | |
466 if (df_regs_ever_live_p (i) && !call_used_regs[i]) | |
467 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]); | |
468 | |
469 if (fsize) | |
470 fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n", | |
471 (fsize)&0xffff); | |
472 } | |
473 | |
474 fprintf (stream, "\trts pc\n"); | |
475 fprintf (stream, "\t;/* end of epilogue*/\n\n\n"); | |
476 } | 472 } |
477 | 473 |
478 /* Return the best assembler insn template | 474 /* Return the best assembler insn template |
479 for moving operands[1] into operands[0] as a fullword. */ | 475 for moving operands[1] into operands[0] as a fullword. */ |
480 static const char * | 476 static const char * |
497 { | 493 { |
498 int words, op, w, i, sh; | 494 int words, op, w, i, sh; |
499 pdp11_partorder useorder; | 495 pdp11_partorder useorder; |
500 bool sameoff = false; | 496 bool sameoff = false; |
501 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype; | 497 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype; |
502 REAL_VALUE_TYPE r; | |
503 long sval[2]; | 498 long sval[2]; |
504 | 499 |
505 words = GET_MODE_BITSIZE (GET_MODE (operands[0])) / 16; | 500 words = GET_MODE_BITSIZE (GET_MODE (operands[0])) / 16; |
506 | 501 |
507 /* If either piece order is accepted and one is pre-decrement | 502 /* If either piece order is accepted and one is pre-decrement |
611 XEXP (XEXP (operands[op], 0), 0)); | 606 XEXP (XEXP (operands[op], 0), 0)); |
612 optype = OFFSOP; | 607 optype = OFFSOP; |
613 } | 608 } |
614 | 609 |
615 if (GET_CODE (operands[op]) == CONST_DOUBLE) | 610 if (GET_CODE (operands[op]) == CONST_DOUBLE) |
616 { | 611 REAL_VALUE_TO_TARGET_DOUBLE |
617 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[op]); | 612 (*CONST_DOUBLE_REAL_VALUE (operands[op]), sval); |
618 REAL_VALUE_TO_TARGET_DOUBLE (r, sval); | |
619 } | |
620 | 613 |
621 for (i = 0; i < words; i++) | 614 for (i = 0; i < words; i++) |
622 { | 615 { |
623 if (order == big) | 616 if (order == big) |
624 w = i; | 617 w = i; |
738 } | 731 } |
739 | 732 |
740 static void | 733 static void |
741 pdp11_asm_print_operand (FILE *file, rtx x, int code) | 734 pdp11_asm_print_operand (FILE *file, rtx x, int code) |
742 { | 735 { |
743 REAL_VALUE_TYPE r; | |
744 long sval[2]; | 736 long sval[2]; |
745 | 737 |
746 if (code == '#') | 738 if (code == '#') |
747 fprintf (file, "#"); | 739 fprintf (file, "#"); |
748 else if (code == '@') | 740 else if (code == '@') |
753 fprintf (file, "@"); | 745 fprintf (file, "@"); |
754 } | 746 } |
755 else if (GET_CODE (x) == REG) | 747 else if (GET_CODE (x) == REG) |
756 fprintf (file, "%s", reg_names[REGNO (x)]); | 748 fprintf (file, "%s", reg_names[REGNO (x)]); |
757 else if (GET_CODE (x) == MEM) | 749 else if (GET_CODE (x) == MEM) |
758 output_address (XEXP (x, 0)); | 750 output_address (GET_MODE (x), XEXP (x, 0)); |
759 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != SImode) | 751 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != SImode) |
760 { | 752 { |
761 REAL_VALUE_FROM_CONST_DOUBLE (r, x); | 753 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), sval); |
762 REAL_VALUE_TO_TARGET_DOUBLE (r, sval); | |
763 fprintf (file, "$%#lo", sval[0] >> 16); | 754 fprintf (file, "$%#lo", sval[0] >> 16); |
764 } | 755 } |
765 else | 756 else |
766 { | 757 { |
767 putc ('$', file); | 758 putc ('$', file); |
913 because they require lots of tricks! do we have to | 904 because they require lots of tricks! do we have to |
914 charge the costs incurred by secondary reload class | 905 charge the costs incurred by secondary reload class |
915 -- as we do here with 10 -- or not ? */ | 906 -- as we do here with 10 -- or not ? */ |
916 | 907 |
917 static int | 908 static int |
918 pdp11_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, | 909 pdp11_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, |
919 reg_class_t c1, reg_class_t c2) | 910 reg_class_t c1, reg_class_t c2) |
920 { | 911 { |
921 return move_costs[(int)c1][(int)c2]; | 912 return move_costs[(int)c1][(int)c2]; |
922 } | 913 } |
923 | 914 |
924 static bool | 915 static bool |
925 pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total, | 916 pdp11_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED, |
917 int opno ATTRIBUTE_UNUSED, int *total, | |
926 bool speed ATTRIBUTE_UNUSED) | 918 bool speed ATTRIBUTE_UNUSED) |
927 { | 919 { |
920 int code = GET_CODE (x); | |
921 | |
928 switch (code) | 922 switch (code) |
929 { | 923 { |
930 case CONST_INT: | 924 case CONST_INT: |
931 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1) | 925 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1) |
932 { | 926 { |
981 /* Only used for qi->hi. */ | 975 /* Only used for qi->hi. */ |
982 *total = COSTS_N_INSNS (1); | 976 *total = COSTS_N_INSNS (1); |
983 return false; | 977 return false; |
984 | 978 |
985 case SIGN_EXTEND: | 979 case SIGN_EXTEND: |
986 if (GET_MODE (x) == HImode) | 980 if (mode == HImode) |
987 *total = COSTS_N_INSNS (1); | 981 *total = COSTS_N_INSNS (1); |
988 else if (GET_MODE (x) == SImode) | 982 else if (mode == SImode) |
989 *total = COSTS_N_INSNS (6); | 983 *total = COSTS_N_INSNS (6); |
990 else | 984 else |
991 *total = COSTS_N_INSNS (2); | 985 *total = COSTS_N_INSNS (2); |
992 return false; | 986 return false; |
993 | 987 |
994 case ASHIFT: | 988 case ASHIFT: |
995 case LSHIFTRT: | 989 case LSHIFTRT: |
996 case ASHIFTRT: | 990 case ASHIFTRT: |
997 if (optimize_size) | 991 if (optimize_size) |
998 *total = COSTS_N_INSNS (1); | 992 *total = COSTS_N_INSNS (1); |
999 else if (GET_MODE (x) == QImode) | 993 else if (mode == QImode) |
1000 { | 994 { |
1001 if (GET_CODE (XEXP (x, 1)) != CONST_INT) | 995 if (GET_CODE (XEXP (x, 1)) != CONST_INT) |
1002 *total = COSTS_N_INSNS (8); /* worst case */ | 996 *total = COSTS_N_INSNS (8); /* worst case */ |
1003 else | 997 else |
1004 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1))); | 998 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1))); |
1005 } | 999 } |
1006 else if (GET_MODE (x) == HImode) | 1000 else if (mode == HImode) |
1007 { | 1001 { |
1008 if (GET_CODE (XEXP (x, 1)) == CONST_INT) | 1002 if (GET_CODE (XEXP (x, 1)) == CONST_INT) |
1009 { | 1003 { |
1010 if (abs (INTVAL (XEXP (x, 1))) == 1) | 1004 if (abs (INTVAL (XEXP (x, 1))) == 1) |
1011 *total = COSTS_N_INSNS (1); | 1005 *total = COSTS_N_INSNS (1); |
1013 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1))); | 1007 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1))); |
1014 } | 1008 } |
1015 else | 1009 else |
1016 *total = COSTS_N_INSNS (10); /* worst case */ | 1010 *total = COSTS_N_INSNS (10); /* worst case */ |
1017 } | 1011 } |
1018 else if (GET_MODE (x) == SImode) | 1012 else if (mode == SImode) |
1019 { | 1013 { |
1020 if (GET_CODE (XEXP (x, 1)) == CONST_INT) | 1014 if (GET_CODE (XEXP (x, 1)) == CONST_INT) |
1021 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1))); | 1015 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1))); |
1022 else /* worst case */ | 1016 else /* worst case */ |
1023 *total = COSTS_N_INSNS (18); | 1017 *total = COSTS_N_INSNS (18); |
1135 } | 1129 } |
1136 } | 1130 } |
1137 | 1131 |
1138 | 1132 |
1139 int | 1133 int |
1140 simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) | 1134 simple_memory_operand(rtx op, machine_mode mode ATTRIBUTE_UNUSED) |
1141 { | 1135 { |
1142 rtx addr; | 1136 rtx addr; |
1143 | 1137 |
1144 /* Eliminate non-memory operations */ | 1138 /* Eliminate non-memory operations */ |
1145 if (GET_CODE (op) != MEM) | 1139 if (GET_CODE (op) != MEM) |
1372 a literal, i.e., addressing mode 27. In that mode, real values | 1366 a literal, i.e., addressing mode 27. In that mode, real values |
1373 are one word values, so the remaining 48 bits have to be zero. */ | 1367 are one word values, so the remaining 48 bits have to be zero. */ |
1374 int | 1368 int |
1375 legitimate_const_double_p (rtx address) | 1369 legitimate_const_double_p (rtx address) |
1376 { | 1370 { |
1377 REAL_VALUE_TYPE r; | |
1378 long sval[2]; | 1371 long sval[2]; |
1379 REAL_VALUE_FROM_CONST_DOUBLE (r, address); | 1372 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (address), sval); |
1380 REAL_VALUE_TO_TARGET_DOUBLE (r, sval); | |
1381 if ((sval[0] & 0xffff) == 0 && sval[1] == 0) | 1373 if ((sval[0] & 0xffff) == 0 && sval[1] == 0) |
1382 return 1; | 1374 return 1; |
1383 return 0; | 1375 return 0; |
1384 } | 1376 } |
1385 | 1377 |
1386 /* Implement CANNOT_CHANGE_MODE_CLASS. */ | 1378 /* Implement TARGET_CAN_CHANGE_MODE_CLASS. */ |
1387 bool | 1379 static bool |
1388 pdp11_cannot_change_mode_class (enum machine_mode from, | 1380 pdp11_can_change_mode_class (machine_mode from, |
1389 enum machine_mode to, | 1381 machine_mode to, |
1390 enum reg_class rclass) | 1382 reg_class_t rclass) |
1391 { | 1383 { |
1392 /* Also, FPU registers contain a whole float value and the parts of | 1384 /* Also, FPU registers contain a whole float value and the parts of |
1393 it are not separately accessible. | 1385 it are not separately accessible. |
1394 | 1386 |
1395 So we disallow all mode changes involving FPRs. */ | 1387 So we disallow all mode changes involving FPRs. */ |
1396 if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to)) | 1388 if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to)) |
1397 return true; | 1389 return false; |
1398 | 1390 |
1399 return reg_classes_intersect_p (FPU_REGS, rclass); | 1391 return !reg_classes_intersect_p (FPU_REGS, rclass); |
1400 } | 1392 } |
1401 | 1393 |
1402 /* TARGET_PREFERRED_RELOAD_CLASS | 1394 /* TARGET_PREFERRED_RELOAD_CLASS |
1403 | 1395 |
1404 Given an rtx X being reloaded into a reg required to be | 1396 Given an rtx X being reloaded into a reg required to be |
1455 can be loade/stored directly. */ | 1447 can be loade/stored directly. */ |
1456 static reg_class_t | 1448 static reg_class_t |
1457 pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED, | 1449 pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED, |
1458 rtx x, | 1450 rtx x, |
1459 reg_class_t reload_class, | 1451 reg_class_t reload_class, |
1460 enum machine_mode reload_mode ATTRIBUTE_UNUSED, | 1452 machine_mode reload_mode ATTRIBUTE_UNUSED, |
1461 secondary_reload_info *sri ATTRIBUTE_UNUSED) | 1453 secondary_reload_info *sri ATTRIBUTE_UNUSED) |
1462 { | 1454 { |
1463 if (reload_class != NO_LOAD_FPU_REGS || GET_CODE (x) != REG || | 1455 if (reload_class != NO_LOAD_FPU_REGS || GET_CODE (x) != REG || |
1464 REGNO_REG_CLASS (REGNO (x)) == LOAD_FPU_REGS) | 1456 REGNO_REG_CLASS (REGNO (x)) == LOAD_FPU_REGS) |
1465 return NO_REGS; | 1457 return NO_REGS; |
1466 | 1458 |
1467 return LOAD_FPU_REGS; | 1459 return LOAD_FPU_REGS; |
1468 } | 1460 } |
1469 | 1461 |
1470 /* Target routine to check if register to register move requires memory. | 1462 /* Implement TARGET_SECONDARY_MEMORY_NEEDED. |
1471 | 1463 |
1472 The answer is yes if we're going between general register and FPU | 1464 The answer is yes if we're going between general register and FPU |
1473 registers. The mode doesn't matter in making this check. | 1465 registers. The mode doesn't matter in making this check. |
1474 */ | 1466 */ |
1475 bool | 1467 static bool |
1476 pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2, | 1468 pdp11_secondary_memory_needed (machine_mode, reg_class_t c1, reg_class_t c2) |
1477 enum machine_mode mode ATTRIBUTE_UNUSED) | |
1478 { | 1469 { |
1479 int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS || | 1470 int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS || |
1480 c1 == FPU_REGS); | 1471 c1 == FPU_REGS); |
1481 int tofloat = (c2 == LOAD_FPU_REGS || c2 == NO_LOAD_FPU_REGS || | 1472 int tofloat = (c2 == LOAD_FPU_REGS || c2 == NO_LOAD_FPU_REGS || |
1482 c2 == FPU_REGS); | 1473 c2 == FPU_REGS); |
1490 that wants to use this address. | 1481 that wants to use this address. |
1491 | 1482 |
1492 */ | 1483 */ |
1493 | 1484 |
1494 static bool | 1485 static bool |
1495 pdp11_legitimate_address_p (enum machine_mode mode, | 1486 pdp11_legitimate_address_p (machine_mode mode, |
1496 rtx operand, bool strict) | 1487 rtx operand, bool strict) |
1497 { | 1488 { |
1498 rtx xfoob; | 1489 rtx xfoob; |
1499 | 1490 |
1500 /* accept @#address */ | 1491 /* accept @#address */ |
1610 else | 1601 else |
1611 return GENERAL_REGS; | 1602 return GENERAL_REGS; |
1612 } | 1603 } |
1613 | 1604 |
1614 | 1605 |
1615 static int | 1606 int |
1616 pdp11_sp_frame_offset (void) | 1607 pdp11_sp_frame_offset (void) |
1617 { | 1608 { |
1618 int offset = 0, regno; | 1609 int offset = 0, regno; |
1619 offset = get_frame_size(); | 1610 offset = get_frame_size(); |
1620 for (regno = 0; regno <= PC_REGNUM; regno++) | 1611 for (regno = 0; regno <= PC_REGNUM; regno++) |
1621 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) | 1612 if (pdp11_saved_regno (regno)) |
1622 offset += 2; | 1613 offset += 2; |
1623 for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++) | 1614 for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++) |
1624 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) | 1615 if (pdp11_saved_regno (regno)) |
1625 offset += 8; | 1616 offset += 8; |
1626 | 1617 |
1627 return offset; | 1618 return offset; |
1628 } | 1619 } |
1629 | 1620 |
1791 } | 1782 } |
1792 | 1783 |
1793 /* Worker function for TARGET_LIBCALL_VALUE. */ | 1784 /* Worker function for TARGET_LIBCALL_VALUE. */ |
1794 | 1785 |
1795 static rtx | 1786 static rtx |
1796 pdp11_libcall_value (enum machine_mode mode, | 1787 pdp11_libcall_value (machine_mode mode, |
1797 const_rtx fun ATTRIBUTE_UNUSED) | 1788 const_rtx fun ATTRIBUTE_UNUSED) |
1798 { | 1789 { |
1799 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode)); | 1790 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode)); |
1800 } | 1791 } |
1801 | 1792 |
1853 the preceding args and about the function being called. | 1844 the preceding args and about the function being called. |
1854 NAMED is nonzero if this argument is a named parameter | 1845 NAMED is nonzero if this argument is a named parameter |
1855 (otherwise it is an extra parameter matching an ellipsis). */ | 1846 (otherwise it is an extra parameter matching an ellipsis). */ |
1856 | 1847 |
1857 static rtx | 1848 static rtx |
1858 pdp11_function_arg (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, | 1849 pdp11_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED, |
1859 enum machine_mode mode ATTRIBUTE_UNUSED, | 1850 machine_mode mode ATTRIBUTE_UNUSED, |
1860 const_tree type ATTRIBUTE_UNUSED, | 1851 const_tree type ATTRIBUTE_UNUSED, |
1861 bool named ATTRIBUTE_UNUSED) | 1852 bool named ATTRIBUTE_UNUSED) |
1862 { | 1853 { |
1863 return NULL_RTX; | 1854 return NULL_RTX; |
1864 } | 1855 } |
1868 Update the data in CUM to advance over an argument of mode MODE and | 1859 Update the data in CUM to advance over an argument of mode MODE and |
1869 data type TYPE. (TYPE is null for libcalls where that information | 1860 data type TYPE. (TYPE is null for libcalls where that information |
1870 may not be available.) */ | 1861 may not be available.) */ |
1871 | 1862 |
1872 static void | 1863 static void |
1873 pdp11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 1864 pdp11_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, |
1874 const_tree type, bool named ATTRIBUTE_UNUSED) | 1865 const_tree type, bool named ATTRIBUTE_UNUSED) |
1875 { | 1866 { |
1867 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
1868 | |
1876 *cum += (mode != BLKmode | 1869 *cum += (mode != BLKmode |
1877 ? GET_MODE_SIZE (mode) | 1870 ? GET_MODE_SIZE (mode) |
1878 : int_size_in_bytes (type)); | 1871 : int_size_in_bytes (type)); |
1879 } | 1872 } |
1880 | 1873 |
1918 bool exit ATTRIBUTE_UNUSED) | 1911 bool exit ATTRIBUTE_UNUSED) |
1919 { | 1912 { |
1920 return NULL; | 1913 return NULL; |
1921 } | 1914 } |
1922 | 1915 |
1916 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */ | |
1917 | |
1918 static bool | |
1919 pdp11_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) | |
1920 { | |
1921 return GET_CODE (x) != CONST_DOUBLE || legitimate_const_double_p (x); | |
1922 } | |
1923 | |
1924 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */ | |
1925 | |
1926 static bool | |
1927 pdp11_scalar_mode_supported_p (scalar_mode mode) | |
1928 { | |
1929 /* Support SFmode even with -mfloat64. */ | |
1930 if (mode == SFmode) | |
1931 return true; | |
1932 return default_scalar_mode_supported_p (mode); | |
1933 } | |
1934 | |
1935 int | |
1936 pdp11_branch_cost () | |
1937 { | |
1938 return (TARGET_BRANCH_CHEAP ? 0 : 1); | |
1939 } | |
1940 | |
1941 /* Implement TARGET_HARD_REGNO_NREGS. */ | |
1942 | |
1943 static unsigned int | |
1944 pdp11_hard_regno_nregs (unsigned int regno, machine_mode mode) | |
1945 { | |
1946 if (regno <= PC_REGNUM) | |
1947 return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD); | |
1948 return 1; | |
1949 } | |
1950 | |
1951 /* Implement TARGET_HARD_REGNO_MODE_OK. On the pdp, the cpu registers | |
1952 can hold any mode other than float (because otherwise we may end up | |
1953 being asked to move from CPU to FPU register, which isn't a valid | |
1954 operation on the PDP11). For CPU registers, check alignment. | |
1955 | |
1956 FPU accepts SF and DF but actually holds a DF - simplifies life! */ | |
1957 | |
1958 static bool | |
1959 pdp11_hard_regno_mode_ok (unsigned int regno, machine_mode mode) | |
1960 { | |
1961 if (regno <= PC_REGNUM) | |
1962 return (GET_MODE_BITSIZE (mode) <= 16 | |
1963 || (GET_MODE_BITSIZE (mode) >= 32 | |
1964 && !(regno & 1) | |
1965 && !FLOAT_MODE_P (mode))); | |
1966 | |
1967 return FLOAT_MODE_P (mode); | |
1968 } | |
1969 | |
1970 /* Implement TARGET_MODES_TIEABLE_P. */ | |
1971 | |
1972 static bool | |
1973 pdp11_modes_tieable_p (machine_mode, machine_mode) | |
1974 { | |
1975 return false; | |
1976 } | |
1977 | |
1923 struct gcc_target targetm = TARGET_INITIALIZER; | 1978 struct gcc_target targetm = TARGET_INITIALIZER; |