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