]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pdp11/pdp11.c
re PR middle-end/46500 (target.h includes tm.h)
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.c
CommitLineData
2c9c2489 1/* Subroutines for gcc2 for pdp11.
6fb5fa3c 2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2004, 2005,
96e45421 3 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
2c9c2489
RK
4 Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5
7ec022b2 6This file is part of GCC.
2c9c2489 7
7ec022b2 8GCC is free software; you can redistribute it and/or modify
2c9c2489 9it under the terms of the GNU General Public License as published by
2f83c7d6 10the Free Software Foundation; either version 3, or (at your option)
2c9c2489
RK
11any later version.
12
7ec022b2 13GCC is distributed in the hope that it will be useful,
2c9c2489
RK
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
2f83c7d6
NC
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
2c9c2489 21
2c9c2489 22#include "config.h"
c5c76735 23#include "system.h"
4977bab6
ZW
24#include "coretypes.h"
25#include "tm.h"
2c9c2489
RK
26#include "rtl.h"
27#include "regs.h"
28#include "hard-reg-set.h"
2c9c2489
RK
29#include "insn-config.h"
30#include "conditions.h"
49ad7cfa 31#include "function.h"
2c9c2489
RK
32#include "output.h"
33#include "insn-attr.h"
7ac09502 34#include "flags.h"
09b893bb 35#include "recog.h"
51296ba0 36#include "tree.h"
19652adf 37#include "expr.h"
718f9c0f 38#include "diagnostic-core.h"
b0106b24 39#include "tm_p.h"
672a6f42
NB
40#include "target.h"
41#include "target-def.h"
899cc0f4 42#include "df.h"
96e45421 43#include "opts.h"
2c9c2489 44
2c9c2489
RK
45/* this is the current value returned by the macro FIRST_PARM_OFFSET
46 defined in tm.h */
47int current_first_parm_offset;
48
e621b588
PK
49/* Routines to encode/decode pdp11 floats */
50static void encode_pdp11_f (const struct real_format *fmt,
51 long *, const REAL_VALUE_TYPE *);
52static void decode_pdp11_f (const struct real_format *,
53 REAL_VALUE_TYPE *, const long *);
54static void encode_pdp11_d (const struct real_format *fmt,
55 long *, const REAL_VALUE_TYPE *);
56static void decode_pdp11_d (const struct real_format *,
57 REAL_VALUE_TYPE *, const long *);
58
59/* These two are taken from the corresponding vax descriptors
60 in real.c, changing only the encode/decode routine pointers. */
61const struct real_format pdp11_f_format =
62 {
63 encode_pdp11_f,
64 decode_pdp11_f,
65 2,
e621b588
PK
66 24,
67 24,
68 -127,
69 127,
70 15,
6e2f8c15 71 15,
e621b588
PK
72 false,
73 false,
74 false,
75 false,
58145e4d 76 false,
3e479de3 77 false,
4099e2c2 78 false,
e621b588
PK
79 false
80 };
81
82const struct real_format pdp11_d_format =
83 {
84 encode_pdp11_d,
85 decode_pdp11_d,
86 2,
e621b588
PK
87 56,
88 56,
89 -127,
90 127,
91 15,
6e2f8c15 92 15,
e621b588
PK
93 false,
94 false,
95 false,
96 false,
58145e4d 97 false,
3e479de3 98 false,
4099e2c2 99 false,
e621b588
PK
100 false
101 };
102
103static void
104encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
105 const REAL_VALUE_TYPE *r)
106{
107 (*vax_f_format.encode) (fmt, buf, r);
108 buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
109}
110
111static void
112decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
113 REAL_VALUE_TYPE *r, const long *buf)
114{
115 long tbuf;
116 tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
117 (*vax_f_format.decode) (fmt, r, &tbuf);
118}
119
120static void
121encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
122 const REAL_VALUE_TYPE *r)
123{
124 (*vax_d_format.encode) (fmt, buf, r);
125 buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
126 buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
127}
128
129static void
130decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
131 REAL_VALUE_TYPE *r, const long *buf)
132{
133 long tbuf[2];
134 tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
135 tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
136 (*vax_d_format.decode) (fmt, r, tbuf);
137}
138
2c9c2489
RK
139/* This is where the condition code register lives. */
140/* rtx cc0_reg_rtx; - no longer needed? */
141
f12b3fc8
SB
142static const char *singlemove_string (rtx *);
143static bool pdp11_assemble_integer (rtx, unsigned int, int);
144static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT);
145static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT);
f40751dd 146static bool pdp11_rtx_costs (rtx, int, int, int *, bool);
586de218 147static bool pdp11_return_in_memory (const_tree, const_tree);
c547eb0d
AS
148static rtx pdp11_function_value (const_tree, const_tree, bool);
149static rtx pdp11_libcall_value (enum machine_mode, const_rtx);
150static bool pdp11_function_value_regno_p (const unsigned int);
8dd65c37 151static void pdp11_trampoline_init (rtx, tree, rtx);
d5cc9181 152static rtx pdp11_function_arg (cumulative_args_t, enum machine_mode,
a5f4f531 153 const_tree, bool);
d5cc9181 154static void pdp11_function_arg_advance (cumulative_args_t,
a5f4f531 155 enum machine_mode, const_tree, bool);
5efd84c5 156static void pdp11_conditional_register_usage (void);
1a627b35 157static bool pdp11_legitimate_constant_p (enum machine_mode, rtx);
672a6f42
NB
158\f
159/* Initialize the GCC target structure. */
301d03af
RS
160#undef TARGET_ASM_BYTE_OP
161#define TARGET_ASM_BYTE_OP NULL
162#undef TARGET_ASM_ALIGNED_HI_OP
163#define TARGET_ASM_ALIGNED_HI_OP NULL
164#undef TARGET_ASM_ALIGNED_SI_OP
165#define TARGET_ASM_ALIGNED_SI_OP NULL
166#undef TARGET_ASM_INTEGER
167#define TARGET_ASM_INTEGER pdp11_assemble_integer
168
08c148a8
NB
169#undef TARGET_ASM_FUNCTION_PROLOGUE
170#define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
171#undef TARGET_ASM_FUNCTION_EPILOGUE
172#define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
2c9c2489 173
17b53c33
NB
174#undef TARGET_ASM_OPEN_PAREN
175#define TARGET_ASM_OPEN_PAREN "["
176#undef TARGET_ASM_CLOSE_PAREN
177#define TARGET_ASM_CLOSE_PAREN "]"
178
3c50106f
RH
179#undef TARGET_RTX_COSTS
180#define TARGET_RTX_COSTS pdp11_rtx_costs
181
a5f4f531
NF
182#undef TARGET_FUNCTION_ARG
183#define TARGET_FUNCTION_ARG pdp11_function_arg
184#undef TARGET_FUNCTION_ARG_ADVANCE
185#define TARGET_FUNCTION_ARG_ADVANCE pdp11_function_arg_advance
186
04e9daaf
KH
187#undef TARGET_RETURN_IN_MEMORY
188#define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
189
c547eb0d
AS
190#undef TARGET_FUNCTION_VALUE
191#define TARGET_FUNCTION_VALUE pdp11_function_value
192#undef TARGET_LIBCALL_VALUE
193#define TARGET_LIBCALL_VALUE pdp11_libcall_value
194#undef TARGET_FUNCTION_VALUE_REGNO_P
195#define TARGET_FUNCTION_VALUE_REGNO_P pdp11_function_value_regno_p
196
8dd65c37
RH
197#undef TARGET_TRAMPOLINE_INIT
198#define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
199
a01c666c
PK
200#undef TARGET_SECONDARY_RELOAD
201#define TARGET_SECONDARY_RELOAD pdp11_secondary_reload
202
203#undef TARGET_REGISTER_MOVE_COST
204#define TARGET_REGISTER_MOVE_COST pdp11_register_move_cost
205
206#undef TARGET_PREFERRED_RELOAD_CLASS
207#define TARGET_PREFERRED_RELOAD_CLASS pdp11_preferred_reload_class
208
209#undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
210#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS pdp11_preferred_output_reload_class
e4942929
PK
211
212#undef TARGET_LEGITIMATE_ADDRESS_P
213#define TARGET_LEGITIMATE_ADDRESS_P pdp11_legitimate_address_p
5efd84c5
NF
214
215#undef TARGET_CONDITIONAL_REGISTER_USAGE
216#define TARGET_CONDITIONAL_REGISTER_USAGE pdp11_conditional_register_usage
baddb677
PK
217
218#undef TARGET_ASM_FUNCTION_SECTION
219#define TARGET_ASM_FUNCTION_SECTION pdp11_function_section
12eb6ed3
PK
220
221#undef TARGET_PRINT_OPERAND
222#define TARGET_PRINT_OPERAND pdp11_asm_print_operand
223
224#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
225#define TARGET_PRINT_OPERAND_PUNCT_VALID_P pdp11_asm_print_operand_punct_valid_p
1a627b35
RS
226
227#undef TARGET_LEGITIMATE_CONSTANT_P
228#define TARGET_LEGITIMATE_CONSTANT_P pdp11_legitimate_constant_p
672a6f42 229\f
2c9c2489
RK
230/*
231 stream is a stdio stream to output the code to.
232 size is an int: how many units of temporary storage to allocate.
233 Refer to the array `regs_ever_live' to determine which registers
234 to save; `regs_ever_live[I]' is nonzero if register number I
235 is ever used in the function. This macro is responsible for
236 knowing which registers should not be saved even if used.
237*/
238
08c148a8 239static void
f12b3fc8 240pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
08c148a8
NB
241{
242 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
243 int regno;
2c9c2489 244 int via_ac = -1;
08c148a8
NB
245
246 fprintf (stream,
faed5cc3
SB
247 "\n\t; /* function prologue %s*/\n",
248 current_function_name ());
2c9c2489
RK
249
250 /* if we are outputting code for main,
251 the switch FPU to right mode if TARGET_FPU */
5b47282c 252 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
2c9c2489 253 {
08c148a8
NB
254 fprintf(stream,
255 "\t;/* switch cpu to double float, single integer */\n");
2c9c2489
RK
256 fprintf(stream, "\tsetd\n");
257 fprintf(stream, "\tseti\n\n");
258 }
259
260 if (frame_pointer_needed)
261 {
e7f9979a
NS
262 fprintf(stream, "\tmov r5, -(sp)\n");
263 fprintf(stream, "\tmov sp, r5\n");
2c9c2489
RK
264 }
265 else
266 {
267 /* DON'T SAVE FP */
268 }
269
270 /* make frame */
271 if (fsize)
ea40ba9c 272 asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
2c9c2489
RK
273
274 /* save CPU registers */
58dd8e86 275 for (regno = R0_REGNUM; regno <= PC_REGNUM; regno++)
6fb5fa3c 276 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
2c9c2489
RK
277 if (! ((regno == FRAME_POINTER_REGNUM)
278 && frame_pointer_needed))
279 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
280 /* fpu regs saving */
281
282 /* via_ac specifies the ac to use for saving ac4, ac5 */
283 via_ac = -1;
284
7021d5df 285 for (regno = AC0_REGNUM; regno <= AC5_REGNUM ; regno++)
2c9c2489
RK
286 {
287 /* ac0 - ac3 */
288 if (LOAD_FPU_REG_P(regno)
6fb5fa3c 289 && df_regs_ever_live_p (regno)
2c9c2489
RK
290 && ! call_used_regs[regno])
291 {
e7f9979a 292 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
2c9c2489
RK
293 via_ac = regno;
294 }
295
296 /* maybe make ac4, ac5 call used regs?? */
297 /* ac4 - ac5 */
298 if (NO_LOAD_FPU_REG_P(regno)
6fb5fa3c 299 && df_regs_ever_live_p (regno)
2c9c2489
RK
300 && ! call_used_regs[regno])
301 {
d35d9223
NS
302 gcc_assert (via_ac != -1);
303 fprintf (stream, "\tldd %s, %s\n",
304 reg_names[regno], reg_names[via_ac]);
305 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
2c9c2489
RK
306 }
307 }
308
309 fprintf (stream, "\t;/* end of prologue */\n\n");
310}
311
312/*
313 The function epilogue should not depend on the current stack pointer!
314 It should use the frame pointer only. This is mandatory because
315 of alloca; we also take advantage of it to omit stack adjustments
316 before returning. */
317
318/* maybe we can make leaf functions faster by switching to the
319 second register file - this way we don't have to save regs!
320 leaf functions are ~ 50% of all functions (dynamically!)
321
c65916a6
RK
322 set/clear bit 11 (dec. 2048) of status word for switching register files -
323 but how can we do this? the pdp11/45 manual says bit may only
324 be set (p.24), but not cleared!
325
2c9c2489 326 switching to kernel is probably more expensive, so we'll leave it
c65916a6 327 like this and not use the second set of registers...
2c9c2489
RK
328
329 maybe as option if you want to generate code for kernel mode? */
330
08c148a8 331static void
f12b3fc8 332pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
2c9c2489 333{
08c148a8 334 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
09b893bb 335 int i, j, k;
2c9c2489
RK
336
337 int via_ac;
338
339 fprintf (stream, "\n\t; /*function epilogue */\n");
340
341 if (frame_pointer_needed)
342 {
343 /* hope this is safe - m68k does it also .... */
899cc0f4 344 df_set_regs_ever_live (FRAME_POINTER_REGNUM, false);
2c9c2489 345
7021d5df 346 for (i = PC_REGNUM, j = 0 ; i >= 0 ; i--)
6fb5fa3c 347 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
2c9c2489
RK
348 j++;
349
350 /* remember # of pushed bytes for CPU regs */
351 k = 2*j;
352
e7f9979a 353 /* change fp -> r5 due to the compile error on libgcc2.c */
58dd8e86 354 for (i = PC_REGNUM ; i >= R0_REGNUM ; i--)
6fb5fa3c 355 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
586de218
KG
356 fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
357 (-fsize-2*j--)&0xffff, reg_names[i]);
2c9c2489
RK
358
359 /* get ACs */
7021d5df 360 via_ac = AC5_REGNUM;
2c9c2489 361
7021d5df 362 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
6fb5fa3c 363 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
2c9c2489
RK
364 {
365 via_ac = i;
366 k += 8;
367 }
368
7021d5df 369 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
2c9c2489
RK
370 {
371 if (LOAD_FPU_REG_P(i)
6fb5fa3c 372 && df_regs_ever_live_p (i)
2c9c2489
RK
373 && ! call_used_regs[i])
374 {
586de218
KG
375 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
376 (-fsize-k)&0xffff, reg_names[i]);
2c9c2489
RK
377 k -= 8;
378 }
379
380 if (NO_LOAD_FPU_REG_P(i)
6fb5fa3c 381 && df_regs_ever_live_p (i)
2c9c2489
RK
382 && ! call_used_regs[i])
383 {
d35d9223 384 gcc_assert (LOAD_FPU_REG_P(via_ac));
2c9c2489 385
586de218
KG
386 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
387 (-fsize-k)&0xffff, reg_names[via_ac]);
e7f9979a 388 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
2c9c2489
RK
389 k -= 8;
390 }
391 }
392
e7f9979a
NS
393 fprintf(stream, "\tmov r5, sp\n");
394 fprintf (stream, "\tmov (sp)+, r5\n");
2c9c2489
RK
395 }
396 else
397 {
7021d5df 398 via_ac = AC5_REGNUM;
2c9c2489
RK
399
400 /* get ACs */
7021d5df 401 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
a01c666c 402 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
2c9c2489
RK
403 via_ac = i;
404
7021d5df 405 for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
2c9c2489
RK
406 {
407 if (LOAD_FPU_REG_P(i)
6fb5fa3c 408 && df_regs_ever_live_p (i)
2c9c2489 409 && ! call_used_regs[i])
e7f9979a 410 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
2c9c2489
RK
411
412 if (NO_LOAD_FPU_REG_P(i)
6fb5fa3c 413 && df_regs_ever_live_p (i)
2c9c2489
RK
414 && ! call_used_regs[i])
415 {
d35d9223 416 gcc_assert (LOAD_FPU_REG_P(via_ac));
2c9c2489 417
e7f9979a
NS
418 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
419 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
2c9c2489
RK
420 }
421 }
422
7021d5df 423 for (i = PC_REGNUM; i >= 0; i--)
6fb5fa3c 424 if (df_regs_ever_live_p (i) && !call_used_regs[i])
2c9c2489
RK
425 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
426
427 if (fsize)
586de218
KG
428 fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n",
429 (fsize)&0xffff);
2c9c2489
RK
430 }
431
432 fprintf (stream, "\trts pc\n");
433 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
434}
08c148a8 435
2c9c2489
RK
436/* Return the best assembler insn template
437 for moving operands[1] into operands[0] as a fullword. */
b0106b24 438static const char *
f12b3fc8 439singlemove_string (rtx *operands)
2c9c2489
RK
440{
441 if (operands[1] != const0_rtx)
442 return "mov %1,%0";
443
444 return "clr %0";
445}
446
447\f
30442c59
PK
448/* Expand multi-word operands (SImode or DImode) into the 2 or 4
449 corresponding HImode operands. The number of operands is given
450 as the third argument, and the required order of the parts as
451 the fourth argument. */
452bool
453pdp11_expand_operands (rtx *operands, rtx exops[][2], int opcount,
454 pdp11_action *action, pdp11_partorder order)
2c9c2489 455{
30442c59
PK
456 int words, op, w, i, sh;
457 pdp11_partorder useorder;
458 bool sameoff = false;
459 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype;
460 REAL_VALUE_TYPE r;
461 long sval[2];
462
463 words = GET_MODE_BITSIZE (GET_MODE (operands[0])) / 16;
464
465 /* If either piece order is accepted and one is pre-decrement
466 while the other is post-increment, set order to be high order
467 word first. That will force the pre-decrement to be turned
468 into a pointer adjust, then offset addressing.
469 Otherwise, if either operand uses pre-decrement, that means
470 the order is low order first.
471 Otherwise, if both operands are registers and destination is
472 higher than source and they overlap, do low order word (highest
473 register number) first. */
474 useorder = either;
475 if (opcount == 2)
2c9c2489 476 {
30442c59
PK
477 if (!REG_P (operands[0]) && !REG_P (operands[1]) &&
478 !(CONSTANT_P (operands[1]) ||
479 GET_CODE (operands[1]) == CONST_DOUBLE) &&
480 ((GET_CODE (XEXP (operands[0], 0)) == POST_INC &&
481 GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) ||
482 (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC &&
483 GET_CODE (XEXP (operands[1], 0)) == POST_INC)))
484 useorder = big;
485 else if ((!REG_P (operands[0]) &&
486 GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) ||
487 (!REG_P (operands[1]) &&
488 !(CONSTANT_P (operands[1]) ||
489 GET_CODE (operands[1]) == CONST_DOUBLE) &&
490 GET_CODE (XEXP (operands[1], 0)) == PRE_DEC))
491 useorder = little;
492 else if (REG_P (operands[0]) && REG_P (operands[1]) &&
493 REGNO (operands[0]) > REGNO (operands[1]) &&
494 REGNO (operands[0]) < REGNO (operands[1]) + words)
495 useorder = little;
496
497 /* Check for source == offset from register and dest == push of
498 the same register. In that case, we have to use the same
499 offset (the one for the low order word) for all words, because
500 the push increases the offset to each source word.
501 In theory there are other cases like this, for example dest == pop,
502 but those don't occur in real life so ignore those. */
503 if (GET_CODE (operands[0]) == MEM
504 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
505 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
506 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
507 sameoff = true;
2c9c2489
RK
508 }
509
30442c59
PK
510 /* If the caller didn't specify order, use the one we computed,
511 or high word first if we don't care either. If the caller did
512 specify, verify we don't have a problem with that order.
513 (If it matters to the caller, constraints need to be used to
514 ensure this case doesn't occur). */
515 if (order == either)
516 order = (useorder == either) ? big : useorder;
2c9c2489 517 else
30442c59 518 gcc_assert (useorder == either || useorder == order);
2c9c2489 519
30442c59
PK
520
521 for (op = 0; op < opcount; op++)
2c9c2489 522 {
30442c59
PK
523 /* First classify the operand. */
524 if (REG_P (operands[op]))
525 optype = REGOP;
526 else if (CONSTANT_P (operands[op])
527 || GET_CODE (operands[op]) == CONST_DOUBLE)
528 optype = CNSTOP;
529 else if (GET_CODE (XEXP (operands[op], 0)) == POST_INC)
530 optype = POPOP;
531 else if (GET_CODE (XEXP (operands[op], 0)) == PRE_DEC)
532 optype = PUSHOP;
533 else if (!reload_in_progress || offsettable_memref_p (operands[op]))
534 optype = OFFSOP;
535 else if (GET_CODE (operands[op]) == MEM)
536 optype = MEMOP;
537 else
538 optype = RNDOP;
539
540 /* Check for the cases that the operand constraints are not
541 supposed to allow to happen. Return failure for such cases. */
542 if (optype == RNDOP)
543 return false;
544
545 if (action != NULL)
546 action[op] = no_action;
547
548 /* If the operand uses pre-decrement addressing but we
549 want to get the parts high order first,
550 decrement the former register explicitly
551 and change the operand into ordinary indexing. */
552 if (optype == PUSHOP && order == big)
553 {
554 gcc_assert (action != NULL);
555 action[op] = dec_before;
556 operands[op] = gen_rtx_MEM (GET_MODE (operands[op]),
557 XEXP (XEXP (operands[op], 0), 0));
558 optype = OFFSOP;
559 }
560 /* If the operand uses post-increment mode but we want
561 to get the parts low order first, change the operand
562 into ordinary indexing and remember to increment
563 the register explicitly when we're done. */
564 else if (optype == POPOP && order == little)
2c9c2489 565 {
30442c59
PK
566 gcc_assert (action != NULL);
567 action[op] = inc_after;
568 operands[op] = gen_rtx_MEM (GET_MODE (operands[op]),
569 XEXP (XEXP (operands[op], 0), 0));
570 optype = OFFSOP;
571 }
2c9c2489 572
30442c59
PK
573 if (GET_CODE (operands[op]) == CONST_DOUBLE)
574 {
575 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[op]);
576 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
577 }
578
579 for (i = 0; i < words; i++)
580 {
581 if (order == big)
582 w = i;
583 else if (sameoff)
584 w = words - 1;
585 else
586 w = words - 1 - i;
587
588 /* Set the output operand to be word "w" of the input. */
589 if (optype == REGOP)
590 exops[i][op] = gen_rtx_REG (HImode, REGNO (operands[op]) + w);
591 else if (optype == OFFSOP)
592 exops[i][op] = adjust_address (operands[op], HImode, w * 2);
593 else if (optype == CNSTOP)
594 {
595 if (GET_CODE (operands[op]) == CONST_DOUBLE)
596 {
597 sh = 16 - (w & 1) * 16;
598 exops[i][op] = gen_rtx_CONST_INT (HImode, (sval[w / 2] >> sh) & 0xffff);
599 }
600 else
601 {
602 sh = ((words - 1 - w) * 16);
603 exops[i][op] = gen_rtx_CONST_INT (HImode, trunc_int_for_mode (INTVAL(operands[op]) >> sh, HImode));
604 }
605 }
606 else
607 exops[i][op] = operands[op];
2c9c2489 608 }
2c9c2489 609 }
30442c59 610 return true;
2c9c2489 611}
30442c59
PK
612
613/* Output assembler code to perform a multiple-word move insn
614 with operands OPERANDS. This moves 2 or 4 words depending
615 on the machine mode of the operands. */
2c9c2489 616
b0106b24 617const char *
30442c59 618output_move_multiple (rtx *operands)
2c9c2489 619{
30442c59
PK
620 rtx exops[4][2];
621 pdp11_action action[2];
622 int i, words;
2c9c2489 623
30442c59 624 words = GET_MODE_BITSIZE (GET_MODE (operands[0])) / 16;
2c9c2489 625
30442c59 626 pdp11_expand_operands (operands, exops, 2, action, either);
2c9c2489 627
30442c59
PK
628 /* Check for explicit decrement before. */
629 if (action[0] == dec_before)
2c9c2489 630 {
30442c59
PK
631 operands[0] = XEXP (operands[0], 0);
632 output_asm_insn ("sub $4,%0", operands);
2c9c2489 633 }
30442c59 634 if (action[1] == dec_before)
2c9c2489 635 {
30442c59
PK
636 operands[1] = XEXP (operands[1], 0);
637 output_asm_insn ("sub $4,%1", operands);
2c9c2489
RK
638 }
639
30442c59
PK
640 /* Do the words. */
641 for (i = 0; i < words; i++)
642 output_asm_insn (singlemove_string (exops[i]), exops[i]);
2c9c2489 643
30442c59
PK
644 /* Check for increment after. */
645 if (action[0] == inc_after)
2c9c2489 646 {
30442c59
PK
647 operands[0] = XEXP (operands[0], 0);
648 output_asm_insn ("add $4,%0", operands);
2c9c2489 649 }
30442c59 650 if (action[1] == inc_after)
2c9c2489 651 {
30442c59
PK
652 operands[1] = XEXP (operands[1], 0);
653 output_asm_insn ("add $4,%1", operands);
2c9c2489
RK
654 }
655
2c9c2489
RK
656 return "";
657}
2c9c2489
RK
658\f
659/* Output an ascii string. */
09b893bb 660void
f12b3fc8 661output_ascii (FILE *file, const char *p, int size)
2c9c2489
RK
662{
663 int i;
664
d14ff9bd
JM
665 /* This used to output .byte "string", which doesn't work with the UNIX
666 assembler and I think not with DEC ones either. */
667 fprintf (file, "\t.byte ");
2c9c2489
RK
668
669 for (i = 0; i < size; i++)
670 {
671 register int c = p[i];
d14ff9bd
JM
672 if (c < 0)
673 c += 256;
cf860dc2 674 fprintf (file, "%#o", c);
d14ff9bd
JM
675 if (i < size - 1)
676 putc (',', file);
2c9c2489 677 }
d14ff9bd 678 putc ('\n', file);
2c9c2489
RK
679}
680
681
dad6bca9
PK
682void
683pdp11_asm_output_var (FILE *file, const char *name, int size,
684 int align, bool global)
685{
686 if (align > 8)
687 fprintf (file, "\n\t.even\n");
12eb6ed3
PK
688 if (global)
689 {
690 fprintf (file, ".globl ");
691 assemble_name (file, name);
692 }
dad6bca9
PK
693 fprintf (file, "\n");
694 assemble_name (file, name);
695 fprintf (file, ": .=.+ %#ho\n", (unsigned short)size);
696}
697
12eb6ed3
PK
698static void
699pdp11_asm_print_operand (FILE *file, rtx x, int code)
700{
701 REAL_VALUE_TYPE r;
702 long sval[2];
703
704 if (code == '#')
705 fprintf (file, "#");
706 else if (code == '@')
707 {
708 if (TARGET_UNIX_ASM)
709 fprintf (file, "*");
710 else
711 fprintf (file, "@");
712 }
713 else if (GET_CODE (x) == REG)
714 fprintf (file, "%s", reg_names[REGNO (x)]);
715 else if (GET_CODE (x) == MEM)
716 output_address (XEXP (x, 0));
717 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != SImode)
718 {
719 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
720 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
721 fprintf (file, "$%#lo", sval[0] >> 16);
722 }
723 else
724 {
725 putc ('$', file);
726 output_addr_const_pdp11 (file, x);
727 }
728}
729
730static bool
522654e6 731pdp11_asm_print_operand_punct_valid_p (unsigned char c)
12eb6ed3
PK
732{
733 return (c == '#' || c == '@');
734}
735
09b893bb 736void
f12b3fc8 737print_operand_address (FILE *file, register rtx addr)
2c9c2489 738{
c153355f 739 register rtx breg;
2c9c2489 740 rtx offset;
c153355f
PK
741 int again = 0;
742
2c9c2489
RK
743 retry:
744
745 switch (GET_CODE (addr))
746 {
747 case MEM:
d14ff9bd
JM
748 if (TARGET_UNIX_ASM)
749 fprintf (file, "*");
750 else
751 fprintf (file, "@");
2c9c2489 752 addr = XEXP (addr, 0);
c153355f 753 again = 1;
2c9c2489
RK
754 goto retry;
755
756 case REG:
757 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
758 break;
759
e7f9979a 760 case PRE_MODIFY:
2c9c2489
RK
761 case PRE_DEC:
762 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
763 break;
764
e7f9979a 765 case POST_MODIFY:
2c9c2489
RK
766 case POST_INC:
767 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
768 break;
769
770 case PLUS:
c153355f 771 breg = 0;
2c9c2489
RK
772 offset = 0;
773 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
774 || GET_CODE (XEXP (addr, 0)) == MEM)
775 {
776 offset = XEXP (addr, 0);
777 addr = XEXP (addr, 1);
778 }
779 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
780 || GET_CODE (XEXP (addr, 1)) == MEM)
781 {
782 offset = XEXP (addr, 1);
783 addr = XEXP (addr, 0);
784 }
785 if (GET_CODE (addr) != PLUS)
786 ;
2c9c2489
RK
787 else if (GET_CODE (XEXP (addr, 0)) == REG)
788 {
c153355f 789 breg = XEXP (addr, 0);
2c9c2489
RK
790 addr = XEXP (addr, 1);
791 }
792 else if (GET_CODE (XEXP (addr, 1)) == REG)
793 {
c153355f 794 breg = XEXP (addr, 1);
2c9c2489
RK
795 addr = XEXP (addr, 0);
796 }
c153355f 797 if (GET_CODE (addr) == REG)
2c9c2489 798 {
c153355f
PK
799 gcc_assert (breg == 0);
800 breg = addr;
2c9c2489
RK
801 addr = 0;
802 }
803 if (offset != 0)
804 {
d35d9223 805 gcc_assert (addr == 0);
2c9c2489
RK
806 addr = offset;
807 }
2c9c2489 808 if (addr != 0)
c153355f 809 output_addr_const_pdp11 (file, addr);
2c9c2489
RK
810 if (breg != 0)
811 {
d35d9223 812 gcc_assert (GET_CODE (breg) == REG);
2c9c2489
RK
813 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
814 }
2c9c2489
RK
815 break;
816
817 default:
c153355f
PK
818 if (!again && GET_CODE (addr) == CONST_INT)
819 {
820 /* Absolute (integer number) address. */
821 if (!TARGET_UNIX_ASM)
822 fprintf (file, "@$");
823 }
af36a4d2 824 output_addr_const_pdp11 (file, addr);
2c9c2489
RK
825 }
826}
827
301d03af
RS
828/* Target hook to assemble integer objects. We need to use the
829 pdp-specific version of output_addr_const. */
830
831static bool
f12b3fc8 832pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
301d03af
RS
833{
834 if (aligned_p)
835 switch (size)
836 {
837 case 1:
838 fprintf (asm_out_file, "\t.byte\t");
b9cb66d2 839 output_addr_const_pdp11 (asm_out_file, GEN_INT (INTVAL (x) & 0xff));
e285a2c6 840;
301d03af
RS
841 fprintf (asm_out_file, " /* char */\n");
842 return true;
843
844 case 2:
845 fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
846 output_addr_const_pdp11 (asm_out_file, x);
847 fprintf (asm_out_file, " /* short */\n");
848 return true;
849 }
850 return default_assemble_integer (x, size, aligned_p);
851}
852
853
2c9c2489
RK
854/* register move costs, indexed by regs */
855
0139adca 856static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
2c9c2489
RK
857{
858 /* NO MUL GEN LFPU NLFPU FPU ALL */
859
860/* NO */ { 0, 0, 0, 0, 0, 0, 0},
a01c666c
PK
861/* MUL */ { 0, 2, 2, 22, 22, 22, 22},
862/* GEN */ { 0, 2, 2, 22, 22, 22, 22},
863/* LFPU */ { 0, 22, 22, 2, 2, 2, 22},
864/* NLFPU */ { 0, 22, 22, 2, 10, 10, 22},
865/* FPU */ { 0, 22, 22, 2, 10, 10, 22},
866/* ALL */ { 0, 22, 22, 22, 22, 22, 22}
2c9c2489
RK
867} ;
868
869
870/* -- note that some moves are tremendously expensive,
c65916a6 871 because they require lots of tricks! do we have to
2c9c2489 872 charge the costs incurred by secondary reload class
a01c666c 873 -- as we do here with 10 -- or not ? */
2c9c2489 874
a01c666c
PK
875static int
876pdp11_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
877 reg_class_t c1, reg_class_t c2)
2c9c2489
RK
878{
879 return move_costs[(int)c1][(int)c2];
880}
881
3c50106f 882static bool
f40751dd
JH
883pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
884 bool speed ATTRIBUTE_UNUSED)
3c50106f
RH
885{
886 switch (code)
887 {
888 case CONST_INT:
889 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
890 {
891 *total = 0;
892 return true;
893 }
5efb1046 894 /* FALLTHRU */
3c50106f
RH
895
896 case CONST:
897 case LABEL_REF:
898 case SYMBOL_REF:
899 /* Twice as expensive as REG. */
900 *total = 2;
901 return true;
902
903 case CONST_DOUBLE:
904 /* Twice (or 4 times) as expensive as 16 bit. */
905 *total = 4;
906 return true;
907
908 case MULT:
909 /* ??? There is something wrong in MULT because MULT is not
910 as cheap as total = 2 even if we can shift! */
911 /* If optimizing for size make mult etc cheap, but not 1, so when
912 in doubt the faster insn is chosen. */
913 if (optimize_size)
914 *total = COSTS_N_INSNS (2);
915 else
916 *total = COSTS_N_INSNS (11);
917 return false;
918
919 case DIV:
920 if (optimize_size)
921 *total = COSTS_N_INSNS (2);
922 else
923 *total = COSTS_N_INSNS (25);
924 return false;
925
926 case MOD:
927 if (optimize_size)
928 *total = COSTS_N_INSNS (2);
929 else
930 *total = COSTS_N_INSNS (26);
931 return false;
932
933 case ABS:
934 /* Equivalent to length, so same for optimize_size. */
935 *total = COSTS_N_INSNS (3);
936 return false;
937
938 case ZERO_EXTEND:
939 /* Only used for qi->hi. */
940 *total = COSTS_N_INSNS (1);
941 return false;
942
943 case SIGN_EXTEND:
944 if (GET_MODE (x) == HImode)
945 *total = COSTS_N_INSNS (1);
946 else if (GET_MODE (x) == SImode)
947 *total = COSTS_N_INSNS (6);
948 else
949 *total = COSTS_N_INSNS (2);
950 return false;
951
952 case ASHIFT:
953 case LSHIFTRT:
954 case ASHIFTRT:
955 if (optimize_size)
956 *total = COSTS_N_INSNS (1);
957 else if (GET_MODE (x) == QImode)
958 {
959 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
960 *total = COSTS_N_INSNS (8); /* worst case */
961 else
962 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
963 }
964 else if (GET_MODE (x) == HImode)
965 {
966 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
967 {
968 if (abs (INTVAL (XEXP (x, 1))) == 1)
969 *total = COSTS_N_INSNS (1);
970 else
971 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
972 }
973 else
974 *total = COSTS_N_INSNS (10); /* worst case */
975 }
976 else if (GET_MODE (x) == SImode)
977 {
978 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
979 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
980 else /* worst case */
981 *total = COSTS_N_INSNS (18);
982 }
983 return false;
984
985 default:
986 return false;
987 }
988}
989
b0106b24 990const char *
f90b7a5a 991output_jump (enum rtx_code code, int inv, int length)
2c9c2489
RK
992{
993 static int x = 0;
994
995 static char buf[1000];
f90b7a5a
PB
996 const char *pos, *neg;
997
e9e4977e
PK
998 if (cc_prev_status.flags & CC_NO_OVERFLOW)
999 {
1000 switch (code)
1001 {
1002 case GTU: code = GT; break;
1003 case LTU: code = LT; break;
1004 case GEU: code = GE; break;
1005 case LEU: code = LE; break;
1006 default: ;
1007 }
1008 }
f90b7a5a
PB
1009 switch (code)
1010 {
1011 case EQ: pos = "beq", neg = "bne"; break;
1012 case NE: pos = "bne", neg = "beq"; break;
1013 case GT: pos = "bgt", neg = "ble"; break;
1014 case GTU: pos = "bhi", neg = "blos"; break;
1015 case LT: pos = "blt", neg = "bge"; break;
1016 case LTU: pos = "blo", neg = "bhis"; break;
1017 case GE: pos = "bge", neg = "blt"; break;
1018 case GEU: pos = "bhis", neg = "blo"; break;
1019 case LE: pos = "ble", neg = "bgt"; break;
1020 case LEU: pos = "blos", neg = "bhi"; break;
1021 default: gcc_unreachable ();
1022 }
2c9c2489
RK
1023
1024#if 0
1025/* currently we don't need this, because the tstdf and cmpdf
1026 copy the condition code immediately, and other float operations are not
1027 yet recognized as changing the FCC - if so, then the length-cost of all
1028 jump insns increases by one, because we have to potentially copy the
1029 FCC! */
1030 if (cc_status.flags & CC_IN_FPU)
1031 output_asm_insn("cfcc", NULL);
1032#endif
1033
1034 switch (length)
1035 {
0f237806 1036 case 2:
2c9c2489 1037
f90b7a5a 1038 sprintf(buf, "%s %%l1", inv ? neg : pos);
2c9c2489
RK
1039
1040 return buf;
1041
0f237806 1042 case 6:
2c9c2489 1043
f90b7a5a 1044 sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x);
2c9c2489
RK
1045
1046 x++;
1047
1048 return buf;
1049
1050 default:
1051
d35d9223 1052 gcc_unreachable ();
2c9c2489
RK
1053 }
1054
1055}
1056
1057void
f12b3fc8 1058notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
2c9c2489
RK
1059{
1060 if (GET_CODE (SET_DEST (exp)) == CC0)
1061 {
e9e4977e
PK
1062 cc_status.flags = 0;
1063 cc_status.value1 = SET_DEST (exp);
1064 cc_status.value2 = SET_SRC (exp);
2c9c2489
RK
1065 }
1066 else if (GET_CODE (SET_SRC (exp)) == CALL)
1067 {
e9e4977e 1068 CC_STATUS_INIT;
2c9c2489 1069 }
2c9c2489
RK
1070 else if (SET_DEST(exp) == pc_rtx)
1071 {
e9e4977e
PK
1072 /* jump */
1073 }
1074 else if (GET_MODE (SET_DEST(exp)) == HImode
1075 || GET_MODE (SET_DEST(exp)) == QImode)
1076 {
1077 cc_status.flags = GET_CODE (SET_SRC(exp)) == MINUS ? 0 : CC_NO_OVERFLOW;
1078 cc_status.value1 = SET_SRC (exp);
1079 cc_status.value2 = SET_DEST (exp);
1080
1081 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1082 && cc_status.value2
1083 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1084 cc_status.value2 = 0;
1085 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1086 && cc_status.value2
1087 && GET_CODE (cc_status.value2) == MEM)
1088 cc_status.value2 = 0;
2c9c2489 1089 }
e9e4977e
PK
1090 else
1091 {
1092 CC_STATUS_INIT;
1093 }
2c9c2489
RK
1094}
1095
1096
b0106b24 1097int
f12b3fc8 1098simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2c9c2489 1099{
09b893bb 1100 rtx addr;
2c9c2489
RK
1101
1102 /* Eliminate non-memory operations */
1103 if (GET_CODE (op) != MEM)
1104 return FALSE;
1105
1106#if 0
1107 /* dword operations really put out 2 instructions, so eliminate them. */
1108 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1109 return FALSE;
1110#endif
1111
1112 /* Decode the address now. */
1113
1114 indirection:
1115
1116 addr = XEXP (op, 0);
1117
1118 switch (GET_CODE (addr))
1119 {
1120 case REG:
1121 /* (R0) - no extra cost */
1122 return 1;
1123
1124 case PRE_DEC:
1125 case POST_INC:
1126 /* -(R0), (R0)+ - cheap! */
1127 return 0;
1128
1129 case MEM:
1130 /* cheap - is encoded in addressing mode info!
1131
1132 -- except for @(R0), which has to be @0(R0) !!! */
1133
1134 if (GET_CODE (XEXP (addr, 0)) == REG)
1135 return 0;
1136
1137 op=addr;
1138 goto indirection;
1139
1140 case CONST_INT:
1141 case LABEL_REF:
1142 case CONST:
1143 case SYMBOL_REF:
1144 /* @#address - extra cost */
1145 return 0;
1146
1147 case PLUS:
1148 /* X(R0) - extra cost */
1149 return 0;
ed03c6cd
JM
1150
1151 default:
1152 break;
2c9c2489
RK
1153 }
1154
1155 return FALSE;
1156}
1157
1158
1159/*
1160 * output a block move:
1161 *
1162 * operands[0] ... to
1163 * operands[1] ... from
1164 * operands[2] ... length
1165 * operands[3] ... alignment
1166 * operands[4] ... scratch register
1167 */
1168
1169
b0106b24 1170const char *
f12b3fc8 1171output_block_move(rtx *operands)
2c9c2489
RK
1172{
1173 static int count = 0;
1174 char buf[200];
dea44e56
PK
1175 int unroll;
1176 int lastbyte = 0;
2c9c2489 1177
dea44e56
PK
1178 /* Move of zero bytes is a NOP. */
1179 if (operands[2] == const0_rtx)
1180 return "";
1181
1182 /* Look for moves by small constant byte counts, those we'll
1183 expand to straight line code. */
1184 if (CONSTANT_P (operands[2]))
2c9c2489 1185 {
dea44e56
PK
1186 if (INTVAL (operands[2]) < 16
1187 && (!optimize_size || INTVAL (operands[2]) < 5)
1188 && INTVAL (operands[3]) == 1)
2c9c2489
RK
1189 {
1190 register int i;
1191
dea44e56 1192 for (i = 1; i <= INTVAL (operands[2]); i++)
2c9c2489
RK
1193 output_asm_insn("movb (%1)+, (%0)+", operands);
1194
1195 return "";
1196 }
dea44e56
PK
1197 else if (INTVAL(operands[2]) < 32
1198 && (!optimize_size || INTVAL (operands[2]) < 9)
1199 && INTVAL (operands[3]) >= 2)
2c9c2489
RK
1200 {
1201 register int i;
1202
dea44e56
PK
1203 for (i = 1; i <= INTVAL (operands[2]) / 2; i++)
1204 output_asm_insn ("mov (%1)+, (%0)+", operands);
1205 if (INTVAL (operands[2]) & 1)
1206 output_asm_insn ("movb (%1), (%0)", operands);
2c9c2489 1207
2c9c2489
RK
1208 return "";
1209 }
2c9c2489
RK
1210 }
1211
dea44e56
PK
1212 /* Ideally we'd look for moves that are multiples of 4 or 8
1213 bytes and handle those by unrolling the move loop. That
1214 makes for a lot of code if done at run time, but it's ok
1215 for constant counts. Also, for variable counts we have
1216 to worry about odd byte count with even aligned pointers.
1217 On 11/40 and up we handle that case; on older machines
1218 we don't and just use byte-wise moves all the time. */
1219
1220 if (CONSTANT_P (operands[2]) )
2c9c2489 1221 {
dea44e56
PK
1222 if (INTVAL (operands[3]) < 2)
1223 unroll = 0;
1224 else
1225 {
1226 lastbyte = INTVAL (operands[2]) & 1;
1227
1228 if (optimize_size || INTVAL (operands[2]) & 2)
1229 unroll = 1;
1230 else if (INTVAL (operands[2]) & 4)
1231 unroll = 2;
1232 else
1233 unroll = 3;
1234 }
1235
1236 /* Loop count is byte count scaled by unroll. */
1237 operands[2] = GEN_INT (INTVAL (operands[2]) >> unroll);
1238 output_asm_insn ("mov %2, %4", operands);
2c9c2489
RK
1239 }
1240 else
1241 {
dea44e56
PK
1242 /* Variable byte count; use the input register
1243 as the scratch. */
2c9c2489 1244 operands[4] = operands[2];
2c9c2489 1245
dea44e56
PK
1246 /* Decide whether to move by words, and check
1247 the byte count for zero. */
1248 if (TARGET_40_PLUS && INTVAL (operands[3]) > 1)
1249 {
1250 unroll = 1;
1251 output_asm_insn ("asr %4", operands);
1252 }
1253 else
1254 {
1255 unroll = 0;
1256 output_asm_insn ("tst %4", operands);
1257 }
1258 sprintf (buf, "beq movestrhi%d", count + 1);
1259 output_asm_insn (buf, NULL);
1260 }
2c9c2489 1261
dea44e56
PK
1262 /* Output the loop label. */
1263 sprintf (buf, "\nmovestrhi%d:", count);
1264 output_asm_insn (buf, NULL);
2c9c2489 1265
dea44e56
PK
1266 /* Output the appropriate move instructions. */
1267 switch (unroll)
1268 {
1269 case 0:
1270 output_asm_insn ("movb (%1)+, (%0)+", operands);
1271 break;
2c9c2489 1272
dea44e56
PK
1273 case 1:
1274 output_asm_insn ("mov (%1)+, (%0)+", operands);
2c9c2489
RK
1275 break;
1276
1277 case 2:
dea44e56
PK
1278 output_asm_insn ("mov (%1)+, (%0)+", operands);
1279 output_asm_insn ("mov (%1)+, (%0)+", operands);
2c9c2489 1280 break;
2c9c2489 1281
2c9c2489 1282 default:
dea44e56
PK
1283 output_asm_insn ("mov (%1)+, (%0)+", operands);
1284 output_asm_insn ("mov (%1)+, (%0)+", operands);
1285 output_asm_insn ("mov (%1)+, (%0)+", operands);
1286 output_asm_insn ("mov (%1)+, (%0)+", operands);
2c9c2489 1287 break;
2c9c2489 1288 }
dea44e56
PK
1289
1290 /* Output the decrement and test. */
1291 if (TARGET_40_PLUS)
1292 {
1293 sprintf (buf, "sob %%4, movestrhi%d", count);
1294 output_asm_insn (buf, operands);
1295 }
1296 else
1297 {
1298 output_asm_insn ("dec %4", operands);
1299 sprintf (buf, "bgt movestrhi%d", count);
1300 output_asm_insn (buf, NULL);
1301 }
1302 count ++;
1303
1304 /* If constant odd byte count, move the last byte. */
1305 if (lastbyte)
1306 output_asm_insn ("movb (%1), (%0)", operands);
1307 else if (!CONSTANT_P (operands[2]))
1308 {
1309 /* Output the destination label for the zero byte count check. */
1310 sprintf (buf, "\nmovestrhi%d:", count);
1311 output_asm_insn (buf, NULL);
1312 count++;
2c9c2489 1313
dea44e56
PK
1314 /* If we did word moves, check for trailing last byte. */
1315 if (unroll)
1316 {
1317 sprintf (buf, "bcc movestrhi%d", count);
1318 output_asm_insn (buf, NULL);
1319 output_asm_insn ("movb (%1), (%0)", operands);
1320 sprintf (buf, "\nmovestrhi%d:", count);
1321 output_asm_insn (buf, NULL);
1322 count++;
1323 }
1324 }
1325
2c9c2489
RK
1326 return "";
1327}
1328
e621b588
PK
1329/* This function checks whether a real value can be encoded as
1330 a literal, i.e., addressing mode 27. In that mode, real values
1331 are one word values, so the remaining 48 bits have to be zero. */
1332int
1333legitimate_const_double_p (rtx address)
1334{
1335 REAL_VALUE_TYPE r;
1336 long sval[2];
1337 REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1338 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1339 if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1340 return 1;
1341 return 0;
1342}
1343
a01c666c
PK
1344/* Implement CANNOT_CHANGE_MODE_CLASS. */
1345bool
1346pdp11_cannot_change_mode_class (enum machine_mode from,
1347 enum machine_mode to,
1348 enum reg_class rclass)
1349{
1350 /* Also, FPU registers contain a whole float value and the parts of
1351 it are not separately accessible.
1352
1353 So we disallow all mode changes involving FPRs. */
1354 if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to))
1355 return true;
1356
1357 return reg_classes_intersect_p (FPU_REGS, rclass);
1358}
1359
1360/* TARGET_PREFERRED_RELOAD_CLASS
1361
1362 Given an rtx X being reloaded into a reg required to be
1363 in class CLASS, return the class of reg to actually use.
1364 In general this is just CLASS; but on some machines
1365 in some cases it is preferable to use a more restrictive class.
1366
1367loading is easier into LOAD_FPU_REGS than FPU_REGS! */
1368
1369static reg_class_t
f89a0507 1370pdp11_preferred_reload_class (rtx x, reg_class_t rclass)
a01c666c 1371{
f89a0507 1372 if (rclass == FPU_REGS)
a01c666c 1373 return LOAD_FPU_REGS;
f89a0507 1374 if (rclass == ALL_REGS)
a01c666c
PK
1375 {
1376 if (FLOAT_MODE_P (GET_MODE (x)))
1377 return LOAD_FPU_REGS;
1378 else
1379 return GENERAL_REGS;
1380 }
f89a0507 1381 return rclass;
a01c666c
PK
1382}
1383
1384/* TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
1385
1386 Given an rtx X being reloaded into a reg required to be
1387 in class CLASS, return the class of reg to actually use.
1388 In general this is just CLASS; but on some machines
1389 in some cases it is preferable to use a more restrictive class.
1390
1391loading is easier into LOAD_FPU_REGS than FPU_REGS! */
1392
1393static reg_class_t
f89a0507 1394pdp11_preferred_output_reload_class (rtx x, reg_class_t rclass)
a01c666c 1395{
f89a0507 1396 if (rclass == FPU_REGS)
a01c666c 1397 return LOAD_FPU_REGS;
f89a0507 1398 if (rclass == ALL_REGS)
a01c666c
PK
1399 {
1400 if (FLOAT_MODE_P (GET_MODE (x)))
1401 return LOAD_FPU_REGS;
1402 else
1403 return GENERAL_REGS;
1404 }
f89a0507 1405 return rclass;
a01c666c
PK
1406}
1407
1408
1409/* TARGET_SECONDARY_RELOAD.
1410
1411 FPU registers AC4 and AC5 (class NO_LOAD_FPU_REGS) require an
1412 intermediate register (AC0-AC3: LOAD_FPU_REGS). Everything else
1413 can be loade/stored directly. */
f89a0507 1414static reg_class_t
a01c666c
PK
1415pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED,
1416 rtx x,
1417 reg_class_t reload_class,
1418 enum machine_mode reload_mode ATTRIBUTE_UNUSED,
1419 secondary_reload_info *sri ATTRIBUTE_UNUSED)
1420{
1421 if (reload_class != NO_LOAD_FPU_REGS || GET_CODE (x) != REG ||
1422 REGNO_REG_CLASS (REGNO (x)) == LOAD_FPU_REGS)
1423 return NO_REGS;
1424
1425 return LOAD_FPU_REGS;
1426}
1427
1428/* Target routine to check if register to register move requires memory.
1429
1430 The answer is yes if we're going between general register and FPU
1431 registers. The mode doesn't matter in making this check.
1432*/
1433bool
1434pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2,
1435 enum machine_mode mode ATTRIBUTE_UNUSED)
1436{
1437 int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS ||
1438 c1 == FPU_REGS);
1439 int tofloat = (c2 == LOAD_FPU_REGS || c2 == NO_LOAD_FPU_REGS ||
1440 c2 == FPU_REGS);
1441
1442 return (fromfloat != tofloat);
1443}
1444
e4942929
PK
1445/* TARGET_LEGITIMATE_ADDRESS_P recognizes an RTL expression
1446 that is a valid memory address for an instruction.
1447 The MODE argument is the machine mode for the MEM expression
1448 that wants to use this address.
1449
1450*/
1451
1452static bool
1453pdp11_legitimate_address_p (enum machine_mode mode,
1454 rtx operand, bool strict)
1455{
1456 rtx xfoob;
1457
1458 /* accept @#address */
1459 if (CONSTANT_ADDRESS_P (operand))
1460 return true;
1461
1462 switch (GET_CODE (operand))
1463 {
1464 case REG:
1465 /* accept (R0) */
1466 return !strict || REGNO_OK_FOR_BASE_P (REGNO (operand));
1467
1468 case PLUS:
1469 /* accept X(R0) */
1470 return GET_CODE (XEXP (operand, 0)) == REG
1471 && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (operand, 0))))
1472 && CONSTANT_ADDRESS_P (XEXP (operand, 1));
1473
1474 case PRE_DEC:
1475 /* accept -(R0) */
1476 return GET_CODE (XEXP (operand, 0)) == REG
1477 && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (operand, 0))));
1478
1479 case POST_INC:
1480 /* accept (R0)+ */
1481 return GET_CODE (XEXP (operand, 0)) == REG
1482 && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (operand, 0))));
1483
1484 case PRE_MODIFY:
1485 /* accept -(SP) -- which uses PRE_MODIFY for byte mode */
1486 return GET_CODE (XEXP (operand, 0)) == REG
1487 && REGNO (XEXP (operand, 0)) == STACK_POINTER_REGNUM
1488 && GET_CODE ((xfoob = XEXP (operand, 1))) == PLUS
1489 && GET_CODE (XEXP (xfoob, 0)) == REG
1490 && REGNO (XEXP (xfoob, 0)) == STACK_POINTER_REGNUM
1491 && CONSTANT_P (XEXP (xfoob, 1))
1492 && INTVAL (XEXP (xfoob,1)) == -2;
1493
1494 case POST_MODIFY:
1495 /* accept (SP)+ -- which uses POST_MODIFY for byte mode */
1496 return GET_CODE (XEXP (operand, 0)) == REG
1497 && REGNO (XEXP (operand, 0)) == STACK_POINTER_REGNUM
1498 && GET_CODE ((xfoob = XEXP (operand, 1))) == PLUS
1499 && GET_CODE (XEXP (xfoob, 0)) == REG
1500 && REGNO (XEXP (xfoob, 0)) == STACK_POINTER_REGNUM
1501 && CONSTANT_P (XEXP (xfoob, 1))
1502 && INTVAL (XEXP (xfoob,1)) == 2;
1503
1504 case MEM:
1505 /* handle another level of indirection ! */
1506 xfoob = XEXP (operand, 0);
1507
1508 /* (MEM:xx (MEM:xx ())) is not valid for SI, DI and currently
1509 also forbidden for float, because we have to handle this
1510 in output_move_double and/or output_move_quad() - we could
1511 do it, but currently it's not worth it!!!
1512 now that DFmode cannot go into CPU register file,
1513 maybe I should allow float ...
1514 but then I have to handle memory-to-memory moves in movdf ?? */
1515 if (GET_MODE_BITSIZE(mode) > 16)
1516 return false;
1517
1518 /* accept @address */
1519 if (CONSTANT_ADDRESS_P (xfoob))
1520 return true;
1521
1522 switch (GET_CODE (xfoob))
1523 {
1524 case REG:
1525 /* accept @(R0) - which is @0(R0) */
1526 return !strict || REGNO_OK_FOR_BASE_P(REGNO (xfoob));
1527
1528 case PLUS:
1529 /* accept @X(R0) */
1530 return GET_CODE (XEXP (xfoob, 0)) == REG
1531 && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (xfoob, 0))))
1532 && CONSTANT_ADDRESS_P (XEXP (xfoob, 1));
1533
1534 case PRE_DEC:
1535 /* accept @-(R0) */
1536 return GET_CODE (XEXP (xfoob, 0)) == REG
1537 && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (xfoob, 0))));
1538
1539 case POST_INC:
1540 /* accept @(R0)+ */
1541 return GET_CODE (XEXP (xfoob, 0)) == REG
1542 && (!strict || REGNO_OK_FOR_BASE_P (REGNO (XEXP (xfoob, 0))));
1543
1544 default:
1545 /* anything else is invalid */
1546 return false;
1547 }
1548
1549 default:
1550 /* anything else is invalid */
1551 return false;
1552 }
1553}
30442c59 1554
58dd8e86
PK
1555/* Return the class number of the smallest class containing
1556 reg number REGNO. */
1557enum reg_class
1558pdp11_regno_reg_class (int regno)
1559{
1560 if (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM)
1561 return GENERAL_REGS;
1562 else if (regno > AC3_REGNUM)
1563 return NO_LOAD_FPU_REGS;
1564 else if (regno >= AC0_REGNUM)
1565 return LOAD_FPU_REGS;
1566 else if (regno & 1)
1567 return MUL_REGS;
1568 else
1569 return GENERAL_REGS;
1570}
1571
1572
1573static int
1574pdp11_sp_frame_offset (void)
1575{
1576 int offset = 0, regno;
1577 offset = get_frame_size();
1578 for (regno = 0; regno <= PC_REGNUM; regno++)
1579 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
1580 offset += 2;
1581 for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++)
1582 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
1583 offset += 8;
1584
1585 return offset;
1586}
1587
1588/* Return the offset between two registers, one to be eliminated, and the other
1589 its replacement, at the start of a routine. */
1590
1591int
1592pdp11_initial_elimination_offset (int from, int to)
1593{
1594 int spoff;
1595
1596 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
1597 return 4;
1598 else if (from == FRAME_POINTER_REGNUM
1599 && to == HARD_FRAME_POINTER_REGNUM)
1600 return 0;
1601 else
1602 {
1603 gcc_assert (to == STACK_POINTER_REGNUM);
1604
1605 /* Get the size of the register save area. */
1606 spoff = pdp11_sp_frame_offset ();
1607 if (from == FRAME_POINTER_REGNUM)
1608 return spoff;
1609
1610 gcc_assert (from == ARG_POINTER_REGNUM);
1611
1612 /* If there is a frame pointer, that is saved too. */
1613 if (frame_pointer_needed)
1614 spoff += 2;
1615
1616 /* Account for the saved PC in the function call. */
1617 return spoff + 2;
1618 }
1619}
a01c666c 1620
af36a4d2
JM
1621/* A copy of output_addr_const modified for pdp11 expression syntax.
1622 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1623 use, and for debugging output, which we don't support with this port either.
1624 So this copy should get called whenever needed.
1625*/
1626void
f12b3fc8 1627output_addr_const_pdp11 (FILE *file, rtx x)
af36a4d2
JM
1628{
1629 char buf[256];
6b208988
PK
1630 int i;
1631
af36a4d2
JM
1632 restart:
1633 switch (GET_CODE (x))
1634 {
1635 case PC:
d35d9223
NS
1636 gcc_assert (flag_pic);
1637 putc ('.', file);
af36a4d2
JM
1638 break;
1639
1640 case SYMBOL_REF:
1641 assemble_name (file, XSTR (x, 0));
1642 break;
1643
1644 case LABEL_REF:
1645 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1646 assemble_name (file, buf);
1647 break;
1648
1649 case CODE_LABEL:
1650 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1651 assemble_name (file, buf);
1652 break;
1653
1654 case CONST_INT:
6b208988
PK
1655 i = INTVAL (x);
1656 if (i < 0)
1657 {
1658 i = -i;
1659 fprintf (file, "-");
1660 }
1661 fprintf (file, "%#o", i & 0xffff);
af36a4d2
JM
1662 break;
1663
1664 case CONST:
1665 /* This used to output parentheses around the expression,
1666 but that does not work on the 386 (either ATT or BSD assembler). */
1667 output_addr_const_pdp11 (file, XEXP (x, 0));
1668 break;
1669
1670 case CONST_DOUBLE:
1671 if (GET_MODE (x) == VOIDmode)
1672 {
1673 /* We can use %o if the number is one word and positive. */
d35d9223
NS
1674 gcc_assert (!CONST_DOUBLE_HIGH (x));
1675 fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
af36a4d2
JM
1676 }
1677 else
1678 /* We can't handle floating point constants;
1679 PRINT_OPERAND must handle them. */
1680 output_operand_lossage ("floating constant misused");
1681 break;
1682
1683 case PLUS:
112cdef5 1684 /* Some assemblers need integer constants to appear last (e.g. masm). */
af36a4d2
JM
1685 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1686 {
1687 output_addr_const_pdp11 (file, XEXP (x, 1));
1688 if (INTVAL (XEXP (x, 0)) >= 0)
1689 fprintf (file, "+");
1690 output_addr_const_pdp11 (file, XEXP (x, 0));
1691 }
1692 else
1693 {
1694 output_addr_const_pdp11 (file, XEXP (x, 0));
1695 if (INTVAL (XEXP (x, 1)) >= 0)
1696 fprintf (file, "+");
1697 output_addr_const_pdp11 (file, XEXP (x, 1));
1698 }
1699 break;
1700
1701 case MINUS:
1702 /* Avoid outputting things like x-x or x+5-x,
1703 since some assemblers can't handle that. */
1704 x = simplify_subtraction (x);
1705 if (GET_CODE (x) != MINUS)
1706 goto restart;
1707
1708 output_addr_const_pdp11 (file, XEXP (x, 0));
6b208988
PK
1709 if (GET_CODE (XEXP (x, 1)) != CONST_INT
1710 || INTVAL (XEXP (x, 1)) >= 0)
1711 fprintf (file, "-");
1712 output_addr_const_pdp11 (file, XEXP (x, 1));
af36a4d2
JM
1713 break;
1714
1715 case ZERO_EXTEND:
1716 case SIGN_EXTEND:
1717 output_addr_const_pdp11 (file, XEXP (x, 0));
1718 break;
1719
1720 default:
1721 output_operand_lossage ("invalid expression as operand");
1722 }
1723}
04e9daaf 1724
bd5bd7ac
KH
1725/* Worker function for TARGET_RETURN_IN_MEMORY. */
1726
04e9daaf 1727static bool
586de218 1728pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
04e9daaf 1729{
c6d3802a
PK
1730 /* Integers 32 bits and under, and scalar floats (if FPU), are returned
1731 in registers. The rest go into memory. */
04e9daaf 1732 return (TYPE_MODE (type) == DImode
c6d3802a
PK
1733 || (FLOAT_MODE_P (TYPE_MODE (type)) && ! TARGET_AC0)
1734 || TREE_CODE (type) == VECTOR_TYPE
1735 || COMPLEX_MODE_P (TYPE_MODE (type)));
04e9daaf 1736}
8dd65c37 1737
c547eb0d
AS
1738/* Worker function for TARGET_FUNCTION_VALUE.
1739
1740 On the pdp11 the value is found in R0 (or ac0??? not without FPU!!!! ) */
1741
1742static rtx
1743pdp11_function_value (const_tree valtype,
1744 const_tree fntype_or_decl ATTRIBUTE_UNUSED,
1745 bool outgoing ATTRIBUTE_UNUSED)
1746{
1747 return gen_rtx_REG (TYPE_MODE (valtype),
1748 BASE_RETURN_VALUE_REG(TYPE_MODE(valtype)));
1749}
1750
1751/* Worker function for TARGET_LIBCALL_VALUE. */
1752
1753static rtx
1754pdp11_libcall_value (enum machine_mode mode,
1755 const_rtx fun ATTRIBUTE_UNUSED)
1756{
1757 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode));
1758}
1759
1760/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.
1761
1762 On the pdp, the first "output" reg is the only register thus used.
1763
1764 maybe ac0 ? - as option someday! */
1765
1766static bool
1767pdp11_function_value_regno_p (const unsigned int regno)
1768{
e4942929 1769 return (regno == RETVAL_REGNUM) || (TARGET_AC0 && (regno == AC0_REGNUM));
c547eb0d
AS
1770}
1771
8dd65c37
RH
1772/* Worker function for TARGET_TRAMPOLINE_INIT.
1773
1774 trampoline - how should i do it in separate i+d ?
1775 have some allocate_trampoline magic???
1776
1777 the following should work for shared I/D:
1778
ed8eb563
PK
1779 MOV #STATIC, $4 01270Y 0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
1780 JMP @#FUNCTION 000137 0x0000 <- FUNCTION
8dd65c37
RH
1781*/
1782
1783static void
1784pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1785{
1786 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
1787 rtx mem;
1788
1789 gcc_assert (!TARGET_SPLIT);
1790
1791 mem = adjust_address (m_tramp, HImode, 0);
ed8eb563 1792 emit_move_insn (mem, GEN_INT (012700+STATIC_CHAIN_REGNUM));
8dd65c37
RH
1793 mem = adjust_address (m_tramp, HImode, 2);
1794 emit_move_insn (mem, chain_value);
1795 mem = adjust_address (m_tramp, HImode, 4);
ed8eb563 1796 emit_move_insn (mem, GEN_INT (000137));
8dd65c37
RH
1797 emit_move_insn (mem, fnaddr);
1798}
a5f4f531
NF
1799
1800/* Worker function for TARGET_FUNCTION_ARG.
1801
1802 Determine where to put an argument to a function.
1803 Value is zero to push the argument on the stack,
1804 or a hard register in which to store the argument.
1805
1806 MODE is the argument's machine mode.
1807 TYPE is the data type of the argument (as a tree).
1808 This is null for libcalls where that information may
1809 not be available.
1810 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1811 the preceding args and about the function being called.
1812 NAMED is nonzero if this argument is a named parameter
1813 (otherwise it is an extra parameter matching an ellipsis). */
1814
1815static rtx
d5cc9181 1816pdp11_function_arg (cumulative_args_t cum ATTRIBUTE_UNUSED,
a5f4f531
NF
1817 enum machine_mode mode ATTRIBUTE_UNUSED,
1818 const_tree type ATTRIBUTE_UNUSED,
1819 bool named ATTRIBUTE_UNUSED)
1820{
1821 return NULL_RTX;
1822}
1823
1824/* Worker function for TARGET_FUNCTION_ARG_ADVANCE.
1825
1826 Update the data in CUM to advance over an argument of mode MODE and
1827 data type TYPE. (TYPE is null for libcalls where that information
1828 may not be available.) */
1829
1830static void
d5cc9181 1831pdp11_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
a5f4f531
NF
1832 const_tree type, bool named ATTRIBUTE_UNUSED)
1833{
d5cc9181
JR
1834 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1835
a5f4f531
NF
1836 *cum += (mode != BLKmode
1837 ? GET_MODE_SIZE (mode)
1838 : int_size_in_bytes (type));
1839}
a01c666c 1840
5efd84c5
NF
1841/* Make sure everything's fine if we *don't* have an FPU.
1842 This assumes that putting a register in fixed_regs will keep the
1843 compiler's mitts completely off it. We don't bother to zero it out
1844 of register classes. Also fix incompatible register naming with
1845 the UNIX assembler. */
1846
1847static void
1848pdp11_conditional_register_usage (void)
1849{
1850 int i;
1851 HARD_REG_SET x;
1852 if (!TARGET_FPU)
1853 {
1854 COPY_HARD_REG_SET (x, reg_class_contents[(int)FPU_REGS]);
1855 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ )
1856 if (TEST_HARD_REG_BIT (x, i))
1857 fixed_regs[i] = call_used_regs[i] = 1;
1858 }
1859
1860 if (TARGET_AC0)
1861 call_used_regs[AC0_REGNUM] = 1;
1862 if (TARGET_UNIX_ASM)
1863 {
1864 /* Change names of FPU registers for the UNIX assembler. */
1865 reg_names[8] = "fr0";
1866 reg_names[9] = "fr1";
1867 reg_names[10] = "fr2";
1868 reg_names[11] = "fr3";
1869 reg_names[12] = "fr4";
1870 reg_names[13] = "fr5";
1871 }
1872}
1873
baddb677
PK
1874static section *
1875pdp11_function_section (tree decl ATTRIBUTE_UNUSED,
1876 enum node_frequency freq ATTRIBUTE_UNUSED,
1877 bool startup ATTRIBUTE_UNUSED,
1878 bool exit ATTRIBUTE_UNUSED)
1879{
1880 return NULL;
1881}
1882
1a627b35
RS
1883/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
1884
1885static bool
1886pdp11_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
1887{
1888 return GET_CODE (x) != CONST_DOUBLE || legitimate_const_double_p (x);
1889}
1890
a01c666c 1891struct gcc_target targetm = TARGET_INITIALIZER;