1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2004, 2005,
3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
33 #include "insn-attr.h"
38 #include "diagnostic-core.h"
42 #include "target-def.h"
46 #define FPU_REG_P(X) ((X)>=8 && (X)<14)
47 #define CPU_REG_P(X) ((X)>=0 && (X)<8)
50 /* this is the current value returned by the macro FIRST_PARM_OFFSET
52 int current_first_parm_offset;
54 /* Routines to encode/decode pdp11 floats */
55 static void encode_pdp11_f (const struct real_format *fmt,
56 long *, const REAL_VALUE_TYPE *);
57 static void decode_pdp11_f (const struct real_format *,
58 REAL_VALUE_TYPE *, const long *);
59 static void encode_pdp11_d (const struct real_format *fmt,
60 long *, const REAL_VALUE_TYPE *);
61 static void decode_pdp11_d (const struct real_format *,
62 REAL_VALUE_TYPE *, const long *);
64 /* These two are taken from the corresponding vax descriptors
65 in real.c, changing only the encode/decode routine pointers. */
66 const struct real_format pdp11_f_format =
87 const struct real_format pdp11_d_format =
109 encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
110 const REAL_VALUE_TYPE *r)
112 (*vax_f_format.encode) (fmt, buf, r);
113 buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
117 decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
118 REAL_VALUE_TYPE *r, const long *buf)
121 tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
122 (*vax_f_format.decode) (fmt, r, &tbuf);
126 encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
127 const REAL_VALUE_TYPE *r)
129 (*vax_d_format.encode) (fmt, buf, r);
130 buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
131 buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
135 decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
136 REAL_VALUE_TYPE *r, const long *buf)
139 tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
140 tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
141 (*vax_d_format.decode) (fmt, r, tbuf);
144 /* This is where the condition code register lives. */
145 /* rtx cc0_reg_rtx; - no longer needed? */
147 static bool pdp11_handle_option (size_t, const char *, int);
148 static void pdp11_option_optimization (int, int);
149 static rtx find_addr_reg (rtx);
150 static const char *singlemove_string (rtx *);
151 static bool pdp11_assemble_integer (rtx, unsigned int, int);
152 static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT);
153 static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT);
154 static bool pdp11_rtx_costs (rtx, int, int, int *, bool);
155 static bool pdp11_return_in_memory (const_tree, const_tree);
156 static rtx pdp11_function_value (const_tree, const_tree, bool);
157 static rtx pdp11_libcall_value (enum machine_mode, const_rtx);
158 static bool pdp11_function_value_regno_p (const unsigned int);
159 static void pdp11_trampoline_init (rtx, tree, rtx);
160 static rtx pdp11_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
162 static void pdp11_function_arg_advance (CUMULATIVE_ARGS *,
163 enum machine_mode, const_tree, bool);
165 /* Initialize the GCC target structure. */
166 #undef TARGET_ASM_BYTE_OP
167 #define TARGET_ASM_BYTE_OP NULL
168 #undef TARGET_ASM_ALIGNED_HI_OP
169 #define TARGET_ASM_ALIGNED_HI_OP NULL
170 #undef TARGET_ASM_ALIGNED_SI_OP
171 #define TARGET_ASM_ALIGNED_SI_OP NULL
172 #undef TARGET_ASM_INTEGER
173 #define TARGET_ASM_INTEGER pdp11_assemble_integer
175 #undef TARGET_ASM_FUNCTION_PROLOGUE
176 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
177 #undef TARGET_ASM_FUNCTION_EPILOGUE
178 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
180 #undef TARGET_ASM_OPEN_PAREN
181 #define TARGET_ASM_OPEN_PAREN "["
182 #undef TARGET_ASM_CLOSE_PAREN
183 #define TARGET_ASM_CLOSE_PAREN "]"
185 #undef TARGET_DEFAULT_TARGET_FLAGS
186 #define TARGET_DEFAULT_TARGET_FLAGS \
187 (MASK_FPU | MASK_45 | MASK_ABSHI_BUILTIN | TARGET_UNIX_ASM_DEFAULT)
188 #undef TARGET_HANDLE_OPTION
189 #define TARGET_HANDLE_OPTION pdp11_handle_option
190 #undef TARGET_OPTION_OPTIMIZATION
191 #define TARGET_OPTION_OPTIMIZATION pdp11_option_optimization
193 #undef TARGET_RTX_COSTS
194 #define TARGET_RTX_COSTS pdp11_rtx_costs
196 #undef TARGET_FUNCTION_ARG
197 #define TARGET_FUNCTION_ARG pdp11_function_arg
198 #undef TARGET_FUNCTION_ARG_ADVANCE
199 #define TARGET_FUNCTION_ARG_ADVANCE pdp11_function_arg_advance
201 #undef TARGET_RETURN_IN_MEMORY
202 #define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
204 #undef TARGET_FUNCTION_VALUE
205 #define TARGET_FUNCTION_VALUE pdp11_function_value
206 #undef TARGET_LIBCALL_VALUE
207 #define TARGET_LIBCALL_VALUE pdp11_libcall_value
208 #undef TARGET_FUNCTION_VALUE_REGNO_P
209 #define TARGET_FUNCTION_VALUE_REGNO_P pdp11_function_value_regno_p
211 #undef TARGET_TRAMPOLINE_INIT
212 #define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
214 struct gcc_target targetm = TARGET_INITIALIZER;
216 /* Implement TARGET_HANDLE_OPTION. */
219 pdp11_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED,
220 int value ATTRIBUTE_UNUSED)
225 target_flags &= ~(MASK_40 | MASK_45);
233 /* Implement TARGET_OPTION_OPTIMIZATION. */
236 pdp11_option_optimization (int level, int size ATTRIBUTE_UNUSED)
238 flag_finite_math_only = 0;
239 flag_trapping_math = 0;
240 flag_signaling_nans = 0;
243 flag_omit_frame_pointer = 1;
244 /* flag_unroll_loops = 1; */
248 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
251 arith_operand (rtx op, enum machine_mode mode)
253 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
257 const_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
259 return (GET_CODE (op) == CONST_INT);
263 immediate15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
265 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
269 expand_shift_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
271 return (GET_CODE (op) == CONST_INT
272 && abs (INTVAL(op)) > 1
273 && abs (INTVAL(op)) <= 4);
277 stream is a stdio stream to output the code to.
278 size is an int: how many units of temporary storage to allocate.
279 Refer to the array `regs_ever_live' to determine which registers
280 to save; `regs_ever_live[I]' is nonzero if register number I
281 is ever used in the function. This macro is responsible for
282 knowing which registers should not be saved even if used.
286 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
288 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
293 "\n\t; /* function prologue %s*/\n",
294 current_function_name ());
296 /* if we are outputting code for main,
297 the switch FPU to right mode if TARGET_FPU */
298 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
301 "\t;/* switch cpu to double float, single integer */\n");
302 fprintf(stream, "\tsetd\n");
303 fprintf(stream, "\tseti\n\n");
306 if (frame_pointer_needed)
308 fprintf(stream, "\tmov r5, -(sp)\n");
309 fprintf(stream, "\tmov sp, r5\n");
318 asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
320 /* save CPU registers */
321 for (regno = 0; regno < 8; regno++)
322 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
323 if (! ((regno == FRAME_POINTER_REGNUM)
324 && frame_pointer_needed))
325 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
326 /* fpu regs saving */
328 /* via_ac specifies the ac to use for saving ac4, ac5 */
331 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
334 if (LOAD_FPU_REG_P(regno)
335 && df_regs_ever_live_p (regno)
336 && ! call_used_regs[regno])
338 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
342 /* maybe make ac4, ac5 call used regs?? */
344 if (NO_LOAD_FPU_REG_P(regno)
345 && df_regs_ever_live_p (regno)
346 && ! call_used_regs[regno])
348 gcc_assert (via_ac != -1);
349 fprintf (stream, "\tldd %s, %s\n",
350 reg_names[regno], reg_names[via_ac]);
351 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
355 fprintf (stream, "\t;/* end of prologue */\n\n");
359 The function epilogue should not depend on the current stack pointer!
360 It should use the frame pointer only. This is mandatory because
361 of alloca; we also take advantage of it to omit stack adjustments
364 /* maybe we can make leaf functions faster by switching to the
365 second register file - this way we don't have to save regs!
366 leaf functions are ~ 50% of all functions (dynamically!)
368 set/clear bit 11 (dec. 2048) of status word for switching register files -
369 but how can we do this? the pdp11/45 manual says bit may only
370 be set (p.24), but not cleared!
372 switching to kernel is probably more expensive, so we'll leave it
373 like this and not use the second set of registers...
375 maybe as option if you want to generate code for kernel mode? */
378 pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
380 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
385 fprintf (stream, "\n\t; /*function epilogue */\n");
387 if (frame_pointer_needed)
389 /* hope this is safe - m68k does it also .... */
390 df_set_regs_ever_live (FRAME_POINTER_REGNUM, false);
392 for (i =7, j = 0 ; i >= 0 ; i--)
393 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
396 /* remember # of pushed bytes for CPU regs */
399 /* change fp -> r5 due to the compile error on libgcc2.c */
400 for (i =7 ; i >= 0 ; i--)
401 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
402 fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
403 (-fsize-2*j--)&0xffff, reg_names[i]);
406 via_ac = FIRST_PSEUDO_REGISTER -1;
408 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
409 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
415 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
417 if (LOAD_FPU_REG_P(i)
418 && df_regs_ever_live_p (i)
419 && ! call_used_regs[i])
421 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
422 (-fsize-k)&0xffff, reg_names[i]);
426 if (NO_LOAD_FPU_REG_P(i)
427 && df_regs_ever_live_p (i)
428 && ! call_used_regs[i])
430 gcc_assert (LOAD_FPU_REG_P(via_ac));
432 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
433 (-fsize-k)&0xffff, reg_names[via_ac]);
434 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
439 fprintf(stream, "\tmov r5, sp\n");
440 fprintf (stream, "\tmov (sp)+, r5\n");
444 via_ac = FIRST_PSEUDO_REGISTER -1;
447 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
448 if (df_regs_ever_live_p (i) && call_used_regs[i])
451 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
453 if (LOAD_FPU_REG_P(i)
454 && df_regs_ever_live_p (i)
455 && ! call_used_regs[i])
456 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
458 if (NO_LOAD_FPU_REG_P(i)
459 && df_regs_ever_live_p (i)
460 && ! call_used_regs[i])
462 gcc_assert (LOAD_FPU_REG_P(via_ac));
464 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
465 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
469 for (i=7; i >= 0; i--)
470 if (df_regs_ever_live_p (i) && !call_used_regs[i])
471 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
474 fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n",
478 fprintf (stream, "\trts pc\n");
479 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
482 /* Return the best assembler insn template
483 for moving operands[1] into operands[0] as a fullword. */
485 singlemove_string (rtx *operands)
487 if (operands[1] != const0_rtx)
494 /* Output assembler code to perform a doubleword move insn
495 with operands OPERANDS. */
498 output_move_double (rtx *operands)
500 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
502 rtx addreg0 = 0, addreg1 = 0;
504 /* First classify both operands. */
506 if (REG_P (operands[0]))
508 else if (offsettable_memref_p (operands[0]))
510 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
512 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
514 else if (GET_CODE (operands[0]) == MEM)
519 if (REG_P (operands[1]))
521 else if (CONSTANT_P (operands[1])
523 || GET_CODE (operands[1]) == CONST_DOUBLE
527 else if (offsettable_memref_p (operands[1]))
529 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
531 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
533 else if (GET_CODE (operands[1]) == MEM)
538 /* Check for the cases that the operand constraints are not
539 supposed to allow to happen. Abort if we get one,
540 because generating code for these cases is painful. */
542 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
544 /* If one operand is decrementing and one is incrementing
545 decrement the former register explicitly
546 and change that operand into ordinary indexing. */
548 if (optype0 == PUSHOP && optype1 == POPOP)
550 operands[0] = XEXP (XEXP (operands[0], 0), 0);
551 output_asm_insn ("sub $4,%0", operands);
552 operands[0] = gen_rtx_MEM (SImode, operands[0]);
555 if (optype0 == POPOP && optype1 == PUSHOP)
557 operands[1] = XEXP (XEXP (operands[1], 0), 0);
558 output_asm_insn ("sub $4,%1", operands);
559 operands[1] = gen_rtx_MEM (SImode, operands[1]);
563 /* If an operand is an unoffsettable memory ref, find a register
564 we can increment temporarily to make it refer to the second word. */
566 if (optype0 == MEMOP)
567 addreg0 = find_addr_reg (XEXP (operands[0], 0));
569 if (optype1 == MEMOP)
570 addreg1 = find_addr_reg (XEXP (operands[1], 0));
572 /* Ok, we can do one word at a time.
573 Normally we do the low-numbered word first,
574 but if either operand is autodecrementing then we
575 do the high-numbered word first.
577 In either case, set up in LATEHALF the operands to use
578 for the high-numbered word and in some cases alter the
579 operands in OPERANDS to be suitable for the low-numbered word. */
581 if (optype0 == REGOP)
582 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
583 else if (optype0 == OFFSOP)
584 latehalf[0] = adjust_address (operands[0], HImode, 2);
586 latehalf[0] = operands[0];
588 if (optype1 == REGOP)
589 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
590 else if (optype1 == OFFSOP)
591 latehalf[1] = adjust_address (operands[1], HImode, 2);
592 else if (optype1 == CNSTOP)
594 if (CONSTANT_P (operands[1]))
596 /* now the mess begins, high word is in lower word???
598 that's what ashc makes me think, but I don't remember :-( */
599 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
600 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
603 /* immediate 32-bit values not allowed */
604 gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE);
607 latehalf[1] = operands[1];
609 /* If insn is effectively movd N(sp),-(sp) then we will do the
610 high word first. We should use the adjusted operand 1 (which is N+4(sp))
611 for the low word as well, to compensate for the first decrement of sp. */
612 if (optype0 == PUSHOP
613 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
614 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
615 operands[1] = latehalf[1];
617 /* If one or both operands autodecrementing,
618 do the two words, high-numbered first. */
620 /* Likewise, the first move would clobber the source of the second one,
621 do them in the other order. This happens only for registers;
622 such overlap can't happen in memory unless the user explicitly
623 sets it up, and that is an undefined circumstance. */
625 if (optype0 == PUSHOP || optype1 == PUSHOP
626 || (optype0 == REGOP && optype1 == REGOP
627 && REGNO (operands[0]) == REGNO (latehalf[1])))
629 /* Make any unoffsettable addresses point at high-numbered word. */
631 output_asm_insn ("add $2,%0", &addreg0);
633 output_asm_insn ("add $2,%0", &addreg1);
636 output_asm_insn (singlemove_string (latehalf), latehalf);
638 /* Undo the adds we just did. */
640 output_asm_insn ("sub $2,%0", &addreg0);
642 output_asm_insn ("sub $2,%0", &addreg1);
644 /* Do low-numbered word. */
645 return singlemove_string (operands);
648 /* Normal case: do the two words, low-numbered first. */
650 output_asm_insn (singlemove_string (operands), operands);
652 /* Make any unoffsettable addresses point at high-numbered word. */
654 output_asm_insn ("add $2,%0", &addreg0);
656 output_asm_insn ("add $2,%0", &addreg1);
659 output_asm_insn (singlemove_string (latehalf), latehalf);
661 /* Undo the adds we just did. */
663 output_asm_insn ("sub $2,%0", &addreg0);
665 output_asm_insn ("sub $2,%0", &addreg1);
669 /* Output assembler code to perform a quadword move insn
670 with operands OPERANDS. */
673 output_move_quad (rtx *operands)
675 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
677 rtx addreg0 = 0, addreg1 = 0;
679 output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);
681 if (REG_P (operands[0]))
683 else if (offsettable_memref_p (operands[0]))
685 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
687 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
689 else if (GET_CODE (operands[0]) == MEM)
694 if (REG_P (operands[1]))
696 else if (CONSTANT_P (operands[1])
697 || GET_CODE (operands[1]) == CONST_DOUBLE)
699 else if (offsettable_memref_p (operands[1]))
701 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
703 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
705 else if (GET_CODE (operands[1]) == MEM)
710 /* Check for the cases that the operand constraints are not
711 supposed to allow to happen. Abort if we get one,
712 because generating code for these cases is painful. */
714 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
716 /* check if we move a CPU reg to an FPU reg, or vice versa! */
717 if (optype0 == REGOP && optype1 == REGOP)
718 /* bogus - 64 bit cannot reside in CPU! */
719 gcc_assert (!CPU_REG_P(REGNO(operands[0]))
720 && !CPU_REG_P (REGNO(operands[1])));
722 if (optype0 == REGOP || optype1 == REGOP)
724 /* check for use of clrd????
725 if you ever allow ac4 and ac5 (now we require secondary load)
726 you must check whether
727 you want to load into them or store from them -
728 then dump ac0 into $help$ movce ac4/5 to ac0, do the
729 store from ac0, and restore ac0 - if you can find
730 an unused ac[0-3], use that and you save a store and a load!*/
732 if (FPU_REG_P(REGNO(operands[0])))
734 if (GET_CODE(operands[1]) == CONST_DOUBLE)
737 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
739 if (REAL_VALUES_EQUAL (r, dconst0))
740 return "{clrd|clrf} %0";
743 return "{ldd|movf} %1, %0";
746 if (FPU_REG_P(REGNO(operands[1])))
747 return "{std|movf} %1, %0";
750 /* If one operand is decrementing and one is incrementing
751 decrement the former register explicitly
752 and change that operand into ordinary indexing. */
754 if (optype0 == PUSHOP && optype1 == POPOP)
756 operands[0] = XEXP (XEXP (operands[0], 0), 0);
757 output_asm_insn ("sub $8,%0", operands);
758 operands[0] = gen_rtx_MEM (DImode, operands[0]);
761 if (optype0 == POPOP && optype1 == PUSHOP)
763 operands[1] = XEXP (XEXP (operands[1], 0), 0);
764 output_asm_insn ("sub $8,%1", operands);
765 operands[1] = gen_rtx_MEM (SImode, operands[1]);
769 /* If an operand is an unoffsettable memory ref, find a register
770 we can increment temporarily to make it refer to the second word. */
772 if (optype0 == MEMOP)
773 addreg0 = find_addr_reg (XEXP (operands[0], 0));
775 if (optype1 == MEMOP)
776 addreg1 = find_addr_reg (XEXP (operands[1], 0));
778 /* Ok, we can do one word at a time.
779 Normally we do the low-numbered word first,
780 but if either operand is autodecrementing then we
781 do the high-numbered word first.
783 In either case, set up in LATEHALF the operands to use
784 for the high-numbered word and in some cases alter the
785 operands in OPERANDS to be suitable for the low-numbered word. */
787 if (optype0 == REGOP)
788 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
789 else if (optype0 == OFFSOP)
790 latehalf[0] = adjust_address (operands[0], SImode, 4);
792 latehalf[0] = operands[0];
794 if (optype1 == REGOP)
795 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
796 else if (optype1 == OFFSOP)
797 latehalf[1] = adjust_address (operands[1], SImode, 4);
798 else if (optype1 == CNSTOP)
800 if (GET_CODE (operands[1]) == CONST_DOUBLE)
804 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
805 REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
806 latehalf[1] = GEN_INT (dval[1]);
807 operands[1] = GEN_INT (dval[0]);
809 else if (GET_CODE(operands[1]) == CONST_INT)
811 latehalf[1] = const0_rtx;
817 latehalf[1] = operands[1];
819 /* If insn is effectively movd N(sp),-(sp) then we will do the
820 high word first. We should use the adjusted operand 1 (which is N+4(sp))
821 for the low word as well, to compensate for the first decrement of sp. */
822 if (optype0 == PUSHOP
823 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
824 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
825 operands[1] = latehalf[1];
827 /* If one or both operands autodecrementing,
828 do the two words, high-numbered first. */
830 /* Likewise, the first move would clobber the source of the second one,
831 do them in the other order. This happens only for registers;
832 such overlap can't happen in memory unless the user explicitly
833 sets it up, and that is an undefined circumstance. */
835 if (optype0 == PUSHOP || optype1 == PUSHOP
836 || (optype0 == REGOP && optype1 == REGOP
837 && REGNO (operands[0]) == REGNO (latehalf[1])))
839 /* Make any unoffsettable addresses point at high-numbered word. */
841 output_asm_insn ("add $4,%0", &addreg0);
843 output_asm_insn ("add $4,%0", &addreg1);
846 output_asm_insn(output_move_double(latehalf), latehalf);
848 /* Undo the adds we just did. */
850 output_asm_insn ("sub $4,%0", &addreg0);
852 output_asm_insn ("sub $4,%0", &addreg1);
854 /* Do low-numbered word. */
855 return output_move_double (operands);
858 /* Normal case: do the two words, low-numbered first. */
860 output_asm_insn (output_move_double (operands), operands);
862 /* Make any unoffsettable addresses point at high-numbered word. */
864 output_asm_insn ("add $4,%0", &addreg0);
866 output_asm_insn ("add $4,%0", &addreg1);
869 output_asm_insn (output_move_double (latehalf), latehalf);
871 /* Undo the adds we just did. */
873 output_asm_insn ("sub $4,%0", &addreg0);
875 output_asm_insn ("sub $4,%0", &addreg1);
881 /* Return a REG that occurs in ADDR with coefficient 1.
882 ADDR can be effectively incremented by incrementing REG. */
885 find_addr_reg (rtx addr)
887 while (GET_CODE (addr) == PLUS)
889 if (GET_CODE (XEXP (addr, 0)) == REG)
890 addr = XEXP (addr, 0);
891 if (GET_CODE (XEXP (addr, 1)) == REG)
892 addr = XEXP (addr, 1);
893 if (CONSTANT_P (XEXP (addr, 0)))
894 addr = XEXP (addr, 1);
895 if (CONSTANT_P (XEXP (addr, 1)))
896 addr = XEXP (addr, 0);
898 if (GET_CODE (addr) == REG)
903 /* Output an ascii string. */
905 output_ascii (FILE *file, const char *p, int size)
909 /* This used to output .byte "string", which doesn't work with the UNIX
910 assembler and I think not with DEC ones either. */
911 fprintf (file, "\t.byte ");
913 for (i = 0; i < size; i++)
915 register int c = p[i];
918 fprintf (file, "%#o", c);
926 /* --- stole from out-vax, needs changes */
929 print_operand_address (FILE *file, register rtx addr)
931 register rtx reg1, reg2, breg, ireg;
936 switch (GET_CODE (addr))
943 addr = XEXP (addr, 0);
947 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
952 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
957 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
964 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
965 || GET_CODE (XEXP (addr, 0)) == MEM)
967 offset = XEXP (addr, 0);
968 addr = XEXP (addr, 1);
970 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
971 || GET_CODE (XEXP (addr, 1)) == MEM)
973 offset = XEXP (addr, 1);
974 addr = XEXP (addr, 0);
976 if (GET_CODE (addr) != PLUS)
978 else if (GET_CODE (XEXP (addr, 0)) == MULT)
980 reg1 = XEXP (addr, 0);
981 addr = XEXP (addr, 1);
983 else if (GET_CODE (XEXP (addr, 1)) == MULT)
985 reg1 = XEXP (addr, 1);
986 addr = XEXP (addr, 0);
988 else if (GET_CODE (XEXP (addr, 0)) == REG)
990 reg1 = XEXP (addr, 0);
991 addr = XEXP (addr, 1);
993 else if (GET_CODE (XEXP (addr, 1)) == REG)
995 reg1 = XEXP (addr, 1);
996 addr = XEXP (addr, 0);
998 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
1008 gcc_assert (addr == 0);
1011 if (reg1 != 0 && GET_CODE (reg1) == MULT)
1016 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
1021 else if (reg2 != 0 || GET_CODE (addr) == MEM)
1032 output_address (addr);
1035 gcc_assert (GET_CODE (breg) == REG);
1036 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
1040 if (GET_CODE (ireg) == MULT)
1041 ireg = XEXP (ireg, 0);
1042 gcc_assert (GET_CODE (ireg) == REG);
1043 gcc_unreachable(); /* ??? */
1044 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
1049 output_addr_const_pdp11 (file, addr);
1053 /* Target hook to assemble integer objects. We need to use the
1054 pdp-specific version of output_addr_const. */
1057 pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
1063 fprintf (asm_out_file, "\t.byte\t");
1064 output_addr_const_pdp11 (asm_out_file, x);
1065 fprintf (asm_out_file, " /* char */\n");
1069 fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
1070 output_addr_const_pdp11 (asm_out_file, x);
1071 fprintf (asm_out_file, " /* short */\n");
1074 return default_assemble_integer (x, size, aligned_p);
1078 /* register move costs, indexed by regs */
1080 static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
1082 /* NO MUL GEN LFPU NLFPU FPU ALL */
1084 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
1085 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
1086 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
1087 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
1088 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
1089 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
1090 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
1094 /* -- note that some moves are tremendously expensive,
1095 because they require lots of tricks! do we have to
1096 charge the costs incurred by secondary reload class
1097 -- as we do here with 22 -- or not ? */
1100 pdp11_register_move_cost (enum reg_class c1, enum reg_class c2)
1102 return move_costs[(int)c1][(int)c2];
1106 pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
1107 bool speed ATTRIBUTE_UNUSED)
1112 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
1122 /* Twice as expensive as REG. */
1127 /* Twice (or 4 times) as expensive as 16 bit. */
1132 /* ??? There is something wrong in MULT because MULT is not
1133 as cheap as total = 2 even if we can shift! */
1134 /* If optimizing for size make mult etc cheap, but not 1, so when
1135 in doubt the faster insn is chosen. */
1137 *total = COSTS_N_INSNS (2);
1139 *total = COSTS_N_INSNS (11);
1144 *total = COSTS_N_INSNS (2);
1146 *total = COSTS_N_INSNS (25);
1151 *total = COSTS_N_INSNS (2);
1153 *total = COSTS_N_INSNS (26);
1157 /* Equivalent to length, so same for optimize_size. */
1158 *total = COSTS_N_INSNS (3);
1162 /* Only used for qi->hi. */
1163 *total = COSTS_N_INSNS (1);
1167 if (GET_MODE (x) == HImode)
1168 *total = COSTS_N_INSNS (1);
1169 else if (GET_MODE (x) == SImode)
1170 *total = COSTS_N_INSNS (6);
1172 *total = COSTS_N_INSNS (2);
1179 *total = COSTS_N_INSNS (1);
1180 else if (GET_MODE (x) == QImode)
1182 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
1183 *total = COSTS_N_INSNS (8); /* worst case */
1185 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
1187 else if (GET_MODE (x) == HImode)
1189 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1191 if (abs (INTVAL (XEXP (x, 1))) == 1)
1192 *total = COSTS_N_INSNS (1);
1194 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1197 *total = COSTS_N_INSNS (10); /* worst case */
1199 else if (GET_MODE (x) == SImode)
1201 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1202 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1203 else /* worst case */
1204 *total = COSTS_N_INSNS (18);
1214 output_jump (enum rtx_code code, int inv, int length)
1218 static char buf[1000];
1219 const char *pos, *neg;
1223 case EQ: pos = "beq", neg = "bne"; break;
1224 case NE: pos = "bne", neg = "beq"; break;
1225 case GT: pos = "bgt", neg = "ble"; break;
1226 case GTU: pos = "bhi", neg = "blos"; break;
1227 case LT: pos = "blt", neg = "bge"; break;
1228 case LTU: pos = "blo", neg = "bhis"; break;
1229 case GE: pos = "bge", neg = "blt"; break;
1230 case GEU: pos = "bhis", neg = "blo"; break;
1231 case LE: pos = "ble", neg = "bgt"; break;
1232 case LEU: pos = "blos", neg = "bhi"; break;
1233 default: gcc_unreachable ();
1237 /* currently we don't need this, because the tstdf and cmpdf
1238 copy the condition code immediately, and other float operations are not
1239 yet recognized as changing the FCC - if so, then the length-cost of all
1240 jump insns increases by one, because we have to potentially copy the
1242 if (cc_status.flags & CC_IN_FPU)
1243 output_asm_insn("cfcc", NULL);
1250 sprintf(buf, "%s %%l1", inv ? neg : pos);
1256 sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x);
1270 notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
1272 if (GET_CODE (SET_DEST (exp)) == CC0)
1274 cc_status.flags = 0;
1275 cc_status.value1 = SET_DEST (exp);
1276 cc_status.value2 = SET_SRC (exp);
1279 if (GET_MODE(SET_SRC(exp)) == DFmode)
1280 cc_status.flags |= CC_IN_FPU;
1283 else if ((GET_CODE (SET_DEST (exp)) == REG
1284 || GET_CODE (SET_DEST (exp)) == MEM)
1285 && GET_CODE (SET_SRC (exp)) != PC
1286 && (GET_MODE (SET_DEST(exp)) == HImode
1287 || GET_MODE (SET_DEST(exp)) == QImode)
1288 && (GET_CODE (SET_SRC(exp)) == PLUS
1289 || GET_CODE (SET_SRC(exp)) == MINUS
1290 || GET_CODE (SET_SRC(exp)) == AND
1291 || GET_CODE (SET_SRC(exp)) == IOR
1292 || GET_CODE (SET_SRC(exp)) == XOR
1293 || GET_CODE (SET_SRC(exp)) == NOT
1294 || GET_CODE (SET_SRC(exp)) == NEG
1295 || GET_CODE (SET_SRC(exp)) == REG
1296 || GET_CODE (SET_SRC(exp)) == MEM))
1298 cc_status.flags = 0;
1299 cc_status.value1 = SET_SRC (exp);
1300 cc_status.value2 = SET_DEST (exp);
1302 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1304 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1305 cc_status.value2 = 0;
1306 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1308 && GET_CODE (cc_status.value2) == MEM)
1309 cc_status.value2 = 0;
1311 else if (GET_CODE (SET_SRC (exp)) == CALL)
1315 else if (GET_CODE (SET_DEST (exp)) == REG)
1318 if ((cc_status.value1
1319 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1320 cc_status.value1 = 0;
1321 if ((cc_status.value2
1322 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1323 cc_status.value2 = 0;
1325 else if (SET_DEST(exp) == pc_rtx)
1329 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1331 /* the last else is a bit paranoiac, but since nearly all instructions
1332 play with condition codes, it's reasonable! */
1334 CC_STATUS_INIT; /* paranoia*/
1340 simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1344 /* Eliminate non-memory operations */
1345 if (GET_CODE (op) != MEM)
1349 /* dword operations really put out 2 instructions, so eliminate them. */
1350 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1354 /* Decode the address now. */
1358 addr = XEXP (op, 0);
1360 switch (GET_CODE (addr))
1363 /* (R0) - no extra cost */
1368 /* -(R0), (R0)+ - cheap! */
1372 /* cheap - is encoded in addressing mode info!
1374 -- except for @(R0), which has to be @0(R0) !!! */
1376 if (GET_CODE (XEXP (addr, 0)) == REG)
1386 /* @#address - extra cost */
1390 /* X(R0) - extra cost */
1402 * output a block move:
1404 * operands[0] ... to
1405 * operands[1] ... from
1406 * operands[2] ... length
1407 * operands[3] ... alignment
1408 * operands[4] ... scratch register
1413 output_block_move(rtx *operands)
1415 static int count = 0;
1418 if (GET_CODE(operands[2]) == CONST_INT
1421 if (INTVAL(operands[2]) < 16
1422 && INTVAL(operands[3]) == 1)
1426 for (i = 1; i <= INTVAL(operands[2]); i++)
1427 output_asm_insn("movb (%1)+, (%0)+", operands);
1431 else if (INTVAL(operands[2]) < 32)
1435 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1436 output_asm_insn("mov (%1)+, (%0)+", operands);
1438 /* may I assume that moved quantity is
1439 multiple of alignment ???
1448 /* can do other clever things, maybe... */
1451 if (CONSTANT_P(operands[2]) )
1453 /* just move count to scratch */
1454 output_asm_insn("mov %2, %4", operands);
1458 /* just clobber the register */
1459 operands[4] = operands[2];
1463 /* switch over alignment */
1464 switch (INTVAL(operands[3]))
1480 sprintf(buf, "\nmovestrhi%d:", count);
1481 output_asm_insn(buf, NULL);
1483 output_asm_insn("movb (%1)+, (%0)+", operands);
1487 sprintf(buf, "sob %%4, movestrhi%d", count);
1488 output_asm_insn(buf, operands);
1492 output_asm_insn("dec %4", operands);
1494 sprintf(buf, "bgt movestrhi%d", count);
1495 output_asm_insn(buf, NULL);
1517 generate_compact_code:
1519 output_asm_insn("asr %4", operands);
1521 sprintf(buf, "\nmovestrhi%d:", count);
1522 output_asm_insn(buf, NULL);
1524 output_asm_insn("mov (%1)+, (%0)+", operands);
1528 sprintf(buf, "sob %%4, movestrhi%d", count);
1529 output_asm_insn(buf, operands);
1533 output_asm_insn("dec %4", operands);
1535 sprintf(buf, "bgt movestrhi%d", count);
1536 output_asm_insn(buf, NULL);
1562 goto generate_compact_code;
1564 output_asm_insn("asr %4", operands);
1565 output_asm_insn("asr %4", operands);
1567 sprintf(buf, "\nmovestrhi%d:", count);
1568 output_asm_insn(buf, NULL);
1570 output_asm_insn("mov (%1)+, (%0)+", operands);
1571 output_asm_insn("mov (%1)+, (%0)+", operands);
1575 sprintf(buf, "sob %%4, movestrhi%d", count);
1576 output_asm_insn(buf, operands);
1580 output_asm_insn("dec %4", operands);
1582 sprintf(buf, "bgt movestrhi%d", count);
1583 output_asm_insn(buf, NULL);
1613 goto generate_compact_code;
1615 output_asm_insn("asr %4", operands);
1616 output_asm_insn("asr %4", operands);
1617 output_asm_insn("asr %4", operands);
1619 sprintf(buf, "\nmovestrhi%d:", count);
1620 output_asm_insn(buf, NULL);
1622 output_asm_insn("mov (%1)+, (%0)+", operands);
1623 output_asm_insn("mov (%1)+, (%0)+", operands);
1624 output_asm_insn("mov (%1)+, (%0)+", operands);
1625 output_asm_insn("mov (%1)+, (%0)+", operands);
1629 sprintf(buf, "sob %%4, movestrhi%d", count);
1630 output_asm_insn(buf, operands);
1634 output_asm_insn("dec %4", operands);
1636 sprintf(buf, "bgt movestrhi%d", count);
1637 output_asm_insn(buf, NULL);
1650 /* This function checks whether a real value can be encoded as
1651 a literal, i.e., addressing mode 27. In that mode, real values
1652 are one word values, so the remaining 48 bits have to be zero. */
1654 legitimate_const_double_p (rtx address)
1658 REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1659 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1660 if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1665 /* A copy of output_addr_const modified for pdp11 expression syntax.
1666 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1667 use, and for debugging output, which we don't support with this port either.
1668 So this copy should get called whenever needed.
1671 output_addr_const_pdp11 (FILE *file, rtx x)
1676 switch (GET_CODE (x))
1679 gcc_assert (flag_pic);
1684 assemble_name (file, XSTR (x, 0));
1688 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1689 assemble_name (file, buf);
1693 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1694 assemble_name (file, buf);
1698 /* Should we check for constants which are too big? Maybe cutting
1699 them off to 16 bits is OK? */
1700 fprintf (file, "%#ho", (unsigned short) INTVAL (x));
1704 /* This used to output parentheses around the expression,
1705 but that does not work on the 386 (either ATT or BSD assembler). */
1706 output_addr_const_pdp11 (file, XEXP (x, 0));
1710 if (GET_MODE (x) == VOIDmode)
1712 /* We can use %o if the number is one word and positive. */
1713 gcc_assert (!CONST_DOUBLE_HIGH (x));
1714 fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
1717 /* We can't handle floating point constants;
1718 PRINT_OPERAND must handle them. */
1719 output_operand_lossage ("floating constant misused");
1723 /* Some assemblers need integer constants to appear last (e.g. masm). */
1724 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1726 output_addr_const_pdp11 (file, XEXP (x, 1));
1727 if (INTVAL (XEXP (x, 0)) >= 0)
1728 fprintf (file, "+");
1729 output_addr_const_pdp11 (file, XEXP (x, 0));
1733 output_addr_const_pdp11 (file, XEXP (x, 0));
1734 if (INTVAL (XEXP (x, 1)) >= 0)
1735 fprintf (file, "+");
1736 output_addr_const_pdp11 (file, XEXP (x, 1));
1741 /* Avoid outputting things like x-x or x+5-x,
1742 since some assemblers can't handle that. */
1743 x = simplify_subtraction (x);
1744 if (GET_CODE (x) != MINUS)
1747 output_addr_const_pdp11 (file, XEXP (x, 0));
1748 fprintf (file, "-");
1749 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1750 && INTVAL (XEXP (x, 1)) < 0)
1752 fprintf (file, targetm.asm_out.open_paren);
1753 output_addr_const_pdp11 (file, XEXP (x, 1));
1754 fprintf (file, targetm.asm_out.close_paren);
1757 output_addr_const_pdp11 (file, XEXP (x, 1));
1762 output_addr_const_pdp11 (file, XEXP (x, 0));
1766 output_operand_lossage ("invalid expression as operand");
1770 /* Worker function for TARGET_RETURN_IN_MEMORY. */
1773 pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1775 /* Should probably return DImode and DFmode in memory, lest
1776 we fill up all regs!
1778 have to, else we crash - exception: maybe return result in
1779 ac0 if DFmode and FPU present - compatibility problem with
1780 libraries for non-floating point.... */
1781 return (TYPE_MODE (type) == DImode
1782 || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
1785 /* Worker function for TARGET_FUNCTION_VALUE.
1787 On the pdp11 the value is found in R0 (or ac0??? not without FPU!!!! ) */
1790 pdp11_function_value (const_tree valtype,
1791 const_tree fntype_or_decl ATTRIBUTE_UNUSED,
1792 bool outgoing ATTRIBUTE_UNUSED)
1794 return gen_rtx_REG (TYPE_MODE (valtype),
1795 BASE_RETURN_VALUE_REG(TYPE_MODE(valtype)));
1798 /* Worker function for TARGET_LIBCALL_VALUE. */
1801 pdp11_libcall_value (enum machine_mode mode,
1802 const_rtx fun ATTRIBUTE_UNUSED)
1804 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode));
1807 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.
1809 On the pdp, the first "output" reg is the only register thus used.
1811 maybe ac0 ? - as option someday! */
1814 pdp11_function_value_regno_p (const unsigned int regno)
1816 return (regno == 0) || (TARGET_AC0 && (regno == 8));
1819 /* Worker function for TARGET_TRAMPOLINE_INIT.
1821 trampoline - how should i do it in separate i+d ?
1822 have some allocate_trampoline magic???
1824 the following should work for shared I/D:
1826 MV #STATIC, $4 0x940Y 0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
1827 JMP FUNCTION 0x0058 0x0000 <- FUNCTION
1831 pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1833 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
1836 gcc_assert (!TARGET_SPLIT);
1838 mem = adjust_address (m_tramp, HImode, 0);
1839 emit_move_insn (mem, GEN_INT (0x9400+STATIC_CHAIN_REGNUM));
1840 mem = adjust_address (m_tramp, HImode, 2);
1841 emit_move_insn (mem, chain_value);
1842 mem = adjust_address (m_tramp, HImode, 4);
1843 emit_move_insn (mem, GEN_INT (0x0058));
1844 emit_move_insn (mem, fnaddr);
1847 /* Worker function for TARGET_FUNCTION_ARG.
1849 Determine where to put an argument to a function.
1850 Value is zero to push the argument on the stack,
1851 or a hard register in which to store the argument.
1853 MODE is the argument's machine mode.
1854 TYPE is the data type of the argument (as a tree).
1855 This is null for libcalls where that information may
1857 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1858 the preceding args and about the function being called.
1859 NAMED is nonzero if this argument is a named parameter
1860 (otherwise it is an extra parameter matching an ellipsis). */
1863 pdp11_function_arg (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1864 enum machine_mode mode ATTRIBUTE_UNUSED,
1865 const_tree type ATTRIBUTE_UNUSED,
1866 bool named ATTRIBUTE_UNUSED)
1871 /* Worker function for TARGET_FUNCTION_ARG_ADVANCE.
1873 Update the data in CUM to advance over an argument of mode MODE and
1874 data type TYPE. (TYPE is null for libcalls where that information
1875 may not be available.) */
1878 pdp11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1879 const_tree type, bool named ATTRIBUTE_UNUSED)
1881 *cum += (mode != BLKmode
1882 ? GET_MODE_SIZE (mode)
1883 : int_size_in_bytes (type));