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_init_struct (struct gcc_options *);
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 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
167 static const struct default_options pdp11_option_optimization_table[] =
169 { OPT_LEVELS_3_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
170 { OPT_LEVELS_NONE, 0, NULL, 0 }
173 /* Initialize the GCC target structure. */
174 #undef TARGET_ASM_BYTE_OP
175 #define TARGET_ASM_BYTE_OP NULL
176 #undef TARGET_ASM_ALIGNED_HI_OP
177 #define TARGET_ASM_ALIGNED_HI_OP NULL
178 #undef TARGET_ASM_ALIGNED_SI_OP
179 #define TARGET_ASM_ALIGNED_SI_OP NULL
180 #undef TARGET_ASM_INTEGER
181 #define TARGET_ASM_INTEGER pdp11_assemble_integer
183 #undef TARGET_ASM_FUNCTION_PROLOGUE
184 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
185 #undef TARGET_ASM_FUNCTION_EPILOGUE
186 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
188 #undef TARGET_ASM_OPEN_PAREN
189 #define TARGET_ASM_OPEN_PAREN "["
190 #undef TARGET_ASM_CLOSE_PAREN
191 #define TARGET_ASM_CLOSE_PAREN "]"
193 #undef TARGET_DEFAULT_TARGET_FLAGS
194 #define TARGET_DEFAULT_TARGET_FLAGS \
195 (MASK_FPU | MASK_45 | MASK_ABSHI_BUILTIN | TARGET_UNIX_ASM_DEFAULT)
196 #undef TARGET_HANDLE_OPTION
197 #define TARGET_HANDLE_OPTION pdp11_handle_option
198 #undef TARGET_OPTION_OPTIMIZATION_TABLE
199 #define TARGET_OPTION_OPTIMIZATION_TABLE pdp11_option_optimization_table
200 #undef TARGET_OPTION_INIT_STRUCT
201 #define TARGET_OPTION_INIT_STRUCT pdp11_option_init_struct
203 #undef TARGET_RTX_COSTS
204 #define TARGET_RTX_COSTS pdp11_rtx_costs
206 #undef TARGET_FUNCTION_ARG
207 #define TARGET_FUNCTION_ARG pdp11_function_arg
208 #undef TARGET_FUNCTION_ARG_ADVANCE
209 #define TARGET_FUNCTION_ARG_ADVANCE pdp11_function_arg_advance
211 #undef TARGET_RETURN_IN_MEMORY
212 #define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
214 #undef TARGET_FUNCTION_VALUE
215 #define TARGET_FUNCTION_VALUE pdp11_function_value
216 #undef TARGET_LIBCALL_VALUE
217 #define TARGET_LIBCALL_VALUE pdp11_libcall_value
218 #undef TARGET_FUNCTION_VALUE_REGNO_P
219 #define TARGET_FUNCTION_VALUE_REGNO_P pdp11_function_value_regno_p
221 #undef TARGET_TRAMPOLINE_INIT
222 #define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
224 struct gcc_target targetm = TARGET_INITIALIZER;
226 /* Implement TARGET_HANDLE_OPTION. */
229 pdp11_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED,
230 int value ATTRIBUTE_UNUSED)
235 target_flags &= ~(MASK_40 | MASK_45);
243 /* Implement TARGET_OPTION_INIT_STRUCT. */
246 pdp11_option_init_struct (struct gcc_options *opts)
248 opts->x_flag_finite_math_only = 0;
249 opts->x_flag_trapping_math = 0;
250 opts->x_flag_signaling_nans = 0;
254 stream is a stdio stream to output the code to.
255 size is an int: how many units of temporary storage to allocate.
256 Refer to the array `regs_ever_live' to determine which registers
257 to save; `regs_ever_live[I]' is nonzero if register number I
258 is ever used in the function. This macro is responsible for
259 knowing which registers should not be saved even if used.
263 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
265 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
270 "\n\t; /* function prologue %s*/\n",
271 current_function_name ());
273 /* if we are outputting code for main,
274 the switch FPU to right mode if TARGET_FPU */
275 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
278 "\t;/* switch cpu to double float, single integer */\n");
279 fprintf(stream, "\tsetd\n");
280 fprintf(stream, "\tseti\n\n");
283 if (frame_pointer_needed)
285 fprintf(stream, "\tmov r5, -(sp)\n");
286 fprintf(stream, "\tmov sp, r5\n");
295 asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
297 /* save CPU registers */
298 for (regno = 0; regno < 8; regno++)
299 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
300 if (! ((regno == FRAME_POINTER_REGNUM)
301 && frame_pointer_needed))
302 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
303 /* fpu regs saving */
305 /* via_ac specifies the ac to use for saving ac4, ac5 */
308 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
311 if (LOAD_FPU_REG_P(regno)
312 && df_regs_ever_live_p (regno)
313 && ! call_used_regs[regno])
315 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
319 /* maybe make ac4, ac5 call used regs?? */
321 if (NO_LOAD_FPU_REG_P(regno)
322 && df_regs_ever_live_p (regno)
323 && ! call_used_regs[regno])
325 gcc_assert (via_ac != -1);
326 fprintf (stream, "\tldd %s, %s\n",
327 reg_names[regno], reg_names[via_ac]);
328 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
332 fprintf (stream, "\t;/* end of prologue */\n\n");
336 The function epilogue should not depend on the current stack pointer!
337 It should use the frame pointer only. This is mandatory because
338 of alloca; we also take advantage of it to omit stack adjustments
341 /* maybe we can make leaf functions faster by switching to the
342 second register file - this way we don't have to save regs!
343 leaf functions are ~ 50% of all functions (dynamically!)
345 set/clear bit 11 (dec. 2048) of status word for switching register files -
346 but how can we do this? the pdp11/45 manual says bit may only
347 be set (p.24), but not cleared!
349 switching to kernel is probably more expensive, so we'll leave it
350 like this and not use the second set of registers...
352 maybe as option if you want to generate code for kernel mode? */
355 pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
357 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
362 fprintf (stream, "\n\t; /*function epilogue */\n");
364 if (frame_pointer_needed)
366 /* hope this is safe - m68k does it also .... */
367 df_set_regs_ever_live (FRAME_POINTER_REGNUM, false);
369 for (i =7, j = 0 ; i >= 0 ; i--)
370 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
373 /* remember # of pushed bytes for CPU regs */
376 /* change fp -> r5 due to the compile error on libgcc2.c */
377 for (i =7 ; i >= 0 ; i--)
378 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
379 fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
380 (-fsize-2*j--)&0xffff, reg_names[i]);
383 via_ac = FIRST_PSEUDO_REGISTER -1;
385 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
386 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
392 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
394 if (LOAD_FPU_REG_P(i)
395 && df_regs_ever_live_p (i)
396 && ! call_used_regs[i])
398 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
399 (-fsize-k)&0xffff, reg_names[i]);
403 if (NO_LOAD_FPU_REG_P(i)
404 && df_regs_ever_live_p (i)
405 && ! call_used_regs[i])
407 gcc_assert (LOAD_FPU_REG_P(via_ac));
409 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
410 (-fsize-k)&0xffff, reg_names[via_ac]);
411 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
416 fprintf(stream, "\tmov r5, sp\n");
417 fprintf (stream, "\tmov (sp)+, r5\n");
421 via_ac = FIRST_PSEUDO_REGISTER -1;
424 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
425 if (df_regs_ever_live_p (i) && call_used_regs[i])
428 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
430 if (LOAD_FPU_REG_P(i)
431 && df_regs_ever_live_p (i)
432 && ! call_used_regs[i])
433 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
435 if (NO_LOAD_FPU_REG_P(i)
436 && df_regs_ever_live_p (i)
437 && ! call_used_regs[i])
439 gcc_assert (LOAD_FPU_REG_P(via_ac));
441 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
442 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
446 for (i=7; i >= 0; i--)
447 if (df_regs_ever_live_p (i) && !call_used_regs[i])
448 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
451 fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n",
455 fprintf (stream, "\trts pc\n");
456 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
459 /* Return the best assembler insn template
460 for moving operands[1] into operands[0] as a fullword. */
462 singlemove_string (rtx *operands)
464 if (operands[1] != const0_rtx)
471 /* Output assembler code to perform a doubleword move insn
472 with operands OPERANDS. */
475 output_move_double (rtx *operands)
477 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
479 rtx addreg0 = 0, addreg1 = 0;
481 /* First classify both operands. */
483 if (REG_P (operands[0]))
485 else if (offsettable_memref_p (operands[0]))
487 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
489 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
491 else if (GET_CODE (operands[0]) == MEM)
496 if (REG_P (operands[1]))
498 else if (CONSTANT_P (operands[1])
500 || GET_CODE (operands[1]) == CONST_DOUBLE
504 else if (offsettable_memref_p (operands[1]))
506 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
508 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
510 else if (GET_CODE (operands[1]) == MEM)
515 /* Check for the cases that the operand constraints are not
516 supposed to allow to happen. Abort if we get one,
517 because generating code for these cases is painful. */
519 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
521 /* If one operand is decrementing and one is incrementing
522 decrement the former register explicitly
523 and change that operand into ordinary indexing. */
525 if (optype0 == PUSHOP && optype1 == POPOP)
527 operands[0] = XEXP (XEXP (operands[0], 0), 0);
528 output_asm_insn ("sub $4,%0", operands);
529 operands[0] = gen_rtx_MEM (SImode, operands[0]);
532 if (optype0 == POPOP && optype1 == PUSHOP)
534 operands[1] = XEXP (XEXP (operands[1], 0), 0);
535 output_asm_insn ("sub $4,%1", operands);
536 operands[1] = gen_rtx_MEM (SImode, operands[1]);
540 /* If an operand is an unoffsettable memory ref, find a register
541 we can increment temporarily to make it refer to the second word. */
543 if (optype0 == MEMOP)
544 addreg0 = find_addr_reg (XEXP (operands[0], 0));
546 if (optype1 == MEMOP)
547 addreg1 = find_addr_reg (XEXP (operands[1], 0));
549 /* Ok, we can do one word at a time.
550 Normally we do the low-numbered word first,
551 but if either operand is autodecrementing then we
552 do the high-numbered word first.
554 In either case, set up in LATEHALF the operands to use
555 for the high-numbered word and in some cases alter the
556 operands in OPERANDS to be suitable for the low-numbered word. */
558 if (optype0 == REGOP)
559 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
560 else if (optype0 == OFFSOP)
561 latehalf[0] = adjust_address (operands[0], HImode, 2);
563 latehalf[0] = operands[0];
565 if (optype1 == REGOP)
566 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
567 else if (optype1 == OFFSOP)
568 latehalf[1] = adjust_address (operands[1], HImode, 2);
569 else if (optype1 == CNSTOP)
571 if (CONSTANT_P (operands[1]))
573 /* now the mess begins, high word is in lower word???
575 that's what ashc makes me think, but I don't remember :-( */
576 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
577 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
580 /* immediate 32-bit values not allowed */
581 gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE);
584 latehalf[1] = operands[1];
586 /* If insn is effectively movd N(sp),-(sp) then we will do the
587 high word first. We should use the adjusted operand 1 (which is N+4(sp))
588 for the low word as well, to compensate for the first decrement of sp. */
589 if (optype0 == PUSHOP
590 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
591 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
592 operands[1] = latehalf[1];
594 /* If one or both operands autodecrementing,
595 do the two words, high-numbered first. */
597 /* Likewise, the first move would clobber the source of the second one,
598 do them in the other order. This happens only for registers;
599 such overlap can't happen in memory unless the user explicitly
600 sets it up, and that is an undefined circumstance. */
602 if (optype0 == PUSHOP || optype1 == PUSHOP
603 || (optype0 == REGOP && optype1 == REGOP
604 && REGNO (operands[0]) == REGNO (latehalf[1])))
606 /* Make any unoffsettable addresses point at high-numbered word. */
608 output_asm_insn ("add $2,%0", &addreg0);
610 output_asm_insn ("add $2,%0", &addreg1);
613 output_asm_insn (singlemove_string (latehalf), latehalf);
615 /* Undo the adds we just did. */
617 output_asm_insn ("sub $2,%0", &addreg0);
619 output_asm_insn ("sub $2,%0", &addreg1);
621 /* Do low-numbered word. */
622 return singlemove_string (operands);
625 /* Normal case: do the two words, low-numbered first. */
627 output_asm_insn (singlemove_string (operands), operands);
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);
646 /* Output assembler code to perform a quadword move insn
647 with operands OPERANDS. */
650 output_move_quad (rtx *operands)
652 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
654 rtx addreg0 = 0, addreg1 = 0;
656 output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);
658 if (REG_P (operands[0]))
660 else if (offsettable_memref_p (operands[0]))
662 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
664 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
666 else if (GET_CODE (operands[0]) == MEM)
671 if (REG_P (operands[1]))
673 else if (CONSTANT_P (operands[1])
674 || GET_CODE (operands[1]) == CONST_DOUBLE)
676 else if (offsettable_memref_p (operands[1]))
678 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
680 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
682 else if (GET_CODE (operands[1]) == MEM)
687 /* Check for the cases that the operand constraints are not
688 supposed to allow to happen. Abort if we get one,
689 because generating code for these cases is painful. */
691 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
693 /* check if we move a CPU reg to an FPU reg, or vice versa! */
694 if (optype0 == REGOP && optype1 == REGOP)
695 /* bogus - 64 bit cannot reside in CPU! */
696 gcc_assert (!CPU_REG_P(REGNO(operands[0]))
697 && !CPU_REG_P (REGNO(operands[1])));
699 if (optype0 == REGOP || optype1 == REGOP)
701 /* check for use of clrd????
702 if you ever allow ac4 and ac5 (now we require secondary load)
703 you must check whether
704 you want to load into them or store from them -
705 then dump ac0 into $help$ movce ac4/5 to ac0, do the
706 store from ac0, and restore ac0 - if you can find
707 an unused ac[0-3], use that and you save a store and a load!*/
709 if (FPU_REG_P(REGNO(operands[0])))
711 if (GET_CODE(operands[1]) == CONST_DOUBLE)
714 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
716 if (REAL_VALUES_EQUAL (r, dconst0))
717 return "{clrd|clrf} %0";
720 return "{ldd|movf} %1, %0";
723 if (FPU_REG_P(REGNO(operands[1])))
724 return "{std|movf} %1, %0";
727 /* If one operand is decrementing and one is incrementing
728 decrement the former register explicitly
729 and change that operand into ordinary indexing. */
731 if (optype0 == PUSHOP && optype1 == POPOP)
733 operands[0] = XEXP (XEXP (operands[0], 0), 0);
734 output_asm_insn ("sub $8,%0", operands);
735 operands[0] = gen_rtx_MEM (DImode, operands[0]);
738 if (optype0 == POPOP && optype1 == PUSHOP)
740 operands[1] = XEXP (XEXP (operands[1], 0), 0);
741 output_asm_insn ("sub $8,%1", operands);
742 operands[1] = gen_rtx_MEM (SImode, operands[1]);
746 /* If an operand is an unoffsettable memory ref, find a register
747 we can increment temporarily to make it refer to the second word. */
749 if (optype0 == MEMOP)
750 addreg0 = find_addr_reg (XEXP (operands[0], 0));
752 if (optype1 == MEMOP)
753 addreg1 = find_addr_reg (XEXP (operands[1], 0));
755 /* Ok, we can do one word at a time.
756 Normally we do the low-numbered word first,
757 but if either operand is autodecrementing then we
758 do the high-numbered word first.
760 In either case, set up in LATEHALF the operands to use
761 for the high-numbered word and in some cases alter the
762 operands in OPERANDS to be suitable for the low-numbered word. */
764 if (optype0 == REGOP)
765 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
766 else if (optype0 == OFFSOP)
767 latehalf[0] = adjust_address (operands[0], SImode, 4);
769 latehalf[0] = operands[0];
771 if (optype1 == REGOP)
772 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
773 else if (optype1 == OFFSOP)
774 latehalf[1] = adjust_address (operands[1], SImode, 4);
775 else if (optype1 == CNSTOP)
777 if (GET_CODE (operands[1]) == CONST_DOUBLE)
781 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
782 REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
783 latehalf[1] = GEN_INT (dval[1]);
784 operands[1] = GEN_INT (dval[0]);
786 else if (GET_CODE(operands[1]) == CONST_INT)
788 latehalf[1] = const0_rtx;
794 latehalf[1] = operands[1];
796 /* If insn is effectively movd N(sp),-(sp) then we will do the
797 high word first. We should use the adjusted operand 1 (which is N+4(sp))
798 for the low word as well, to compensate for the first decrement of sp. */
799 if (optype0 == PUSHOP
800 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
801 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
802 operands[1] = latehalf[1];
804 /* If one or both operands autodecrementing,
805 do the two words, high-numbered first. */
807 /* Likewise, the first move would clobber the source of the second one,
808 do them in the other order. This happens only for registers;
809 such overlap can't happen in memory unless the user explicitly
810 sets it up, and that is an undefined circumstance. */
812 if (optype0 == PUSHOP || optype1 == PUSHOP
813 || (optype0 == REGOP && optype1 == REGOP
814 && REGNO (operands[0]) == REGNO (latehalf[1])))
816 /* Make any unoffsettable addresses point at high-numbered word. */
818 output_asm_insn ("add $4,%0", &addreg0);
820 output_asm_insn ("add $4,%0", &addreg1);
823 output_asm_insn(output_move_double(latehalf), latehalf);
825 /* Undo the adds we just did. */
827 output_asm_insn ("sub $4,%0", &addreg0);
829 output_asm_insn ("sub $4,%0", &addreg1);
831 /* Do low-numbered word. */
832 return output_move_double (operands);
835 /* Normal case: do the two words, low-numbered first. */
837 output_asm_insn (output_move_double (operands), operands);
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);
858 /* Return a REG that occurs in ADDR with coefficient 1.
859 ADDR can be effectively incremented by incrementing REG. */
862 find_addr_reg (rtx addr)
864 while (GET_CODE (addr) == PLUS)
866 if (GET_CODE (XEXP (addr, 0)) == REG)
867 addr = XEXP (addr, 0);
868 if (GET_CODE (XEXP (addr, 1)) == REG)
869 addr = XEXP (addr, 1);
870 if (CONSTANT_P (XEXP (addr, 0)))
871 addr = XEXP (addr, 1);
872 if (CONSTANT_P (XEXP (addr, 1)))
873 addr = XEXP (addr, 0);
875 if (GET_CODE (addr) == REG)
880 /* Output an ascii string. */
882 output_ascii (FILE *file, const char *p, int size)
886 /* This used to output .byte "string", which doesn't work with the UNIX
887 assembler and I think not with DEC ones either. */
888 fprintf (file, "\t.byte ");
890 for (i = 0; i < size; i++)
892 register int c = p[i];
895 fprintf (file, "%#o", c);
903 /* --- stole from out-vax, needs changes */
906 print_operand_address (FILE *file, register rtx addr)
908 register rtx reg1, reg2, breg, ireg;
913 switch (GET_CODE (addr))
920 addr = XEXP (addr, 0);
924 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
929 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
934 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
941 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
942 || GET_CODE (XEXP (addr, 0)) == MEM)
944 offset = XEXP (addr, 0);
945 addr = XEXP (addr, 1);
947 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
948 || GET_CODE (XEXP (addr, 1)) == MEM)
950 offset = XEXP (addr, 1);
951 addr = XEXP (addr, 0);
953 if (GET_CODE (addr) != PLUS)
955 else if (GET_CODE (XEXP (addr, 0)) == MULT)
957 reg1 = XEXP (addr, 0);
958 addr = XEXP (addr, 1);
960 else if (GET_CODE (XEXP (addr, 1)) == MULT)
962 reg1 = XEXP (addr, 1);
963 addr = XEXP (addr, 0);
965 else if (GET_CODE (XEXP (addr, 0)) == REG)
967 reg1 = XEXP (addr, 0);
968 addr = XEXP (addr, 1);
970 else if (GET_CODE (XEXP (addr, 1)) == REG)
972 reg1 = XEXP (addr, 1);
973 addr = XEXP (addr, 0);
975 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
985 gcc_assert (addr == 0);
988 if (reg1 != 0 && GET_CODE (reg1) == MULT)
993 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
998 else if (reg2 != 0 || GET_CODE (addr) == MEM)
1009 output_address (addr);
1012 gcc_assert (GET_CODE (breg) == REG);
1013 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
1017 if (GET_CODE (ireg) == MULT)
1018 ireg = XEXP (ireg, 0);
1019 gcc_assert (GET_CODE (ireg) == REG);
1020 gcc_unreachable(); /* ??? */
1021 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
1026 output_addr_const_pdp11 (file, addr);
1030 /* Target hook to assemble integer objects. We need to use the
1031 pdp-specific version of output_addr_const. */
1034 pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
1040 fprintf (asm_out_file, "\t.byte\t");
1041 output_addr_const_pdp11 (asm_out_file, x);
1042 fprintf (asm_out_file, " /* char */\n");
1046 fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
1047 output_addr_const_pdp11 (asm_out_file, x);
1048 fprintf (asm_out_file, " /* short */\n");
1051 return default_assemble_integer (x, size, aligned_p);
1055 /* register move costs, indexed by regs */
1057 static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
1059 /* NO MUL GEN LFPU NLFPU FPU ALL */
1061 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
1062 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
1063 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
1064 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
1065 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
1066 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
1067 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
1071 /* -- note that some moves are tremendously expensive,
1072 because they require lots of tricks! do we have to
1073 charge the costs incurred by secondary reload class
1074 -- as we do here with 22 -- or not ? */
1077 pdp11_register_move_cost (enum reg_class c1, enum reg_class c2)
1079 return move_costs[(int)c1][(int)c2];
1083 pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
1084 bool speed ATTRIBUTE_UNUSED)
1089 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
1099 /* Twice as expensive as REG. */
1104 /* Twice (or 4 times) as expensive as 16 bit. */
1109 /* ??? There is something wrong in MULT because MULT is not
1110 as cheap as total = 2 even if we can shift! */
1111 /* If optimizing for size make mult etc cheap, but not 1, so when
1112 in doubt the faster insn is chosen. */
1114 *total = COSTS_N_INSNS (2);
1116 *total = COSTS_N_INSNS (11);
1121 *total = COSTS_N_INSNS (2);
1123 *total = COSTS_N_INSNS (25);
1128 *total = COSTS_N_INSNS (2);
1130 *total = COSTS_N_INSNS (26);
1134 /* Equivalent to length, so same for optimize_size. */
1135 *total = COSTS_N_INSNS (3);
1139 /* Only used for qi->hi. */
1140 *total = COSTS_N_INSNS (1);
1144 if (GET_MODE (x) == HImode)
1145 *total = COSTS_N_INSNS (1);
1146 else if (GET_MODE (x) == SImode)
1147 *total = COSTS_N_INSNS (6);
1149 *total = COSTS_N_INSNS (2);
1156 *total = COSTS_N_INSNS (1);
1157 else if (GET_MODE (x) == QImode)
1159 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
1160 *total = COSTS_N_INSNS (8); /* worst case */
1162 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
1164 else if (GET_MODE (x) == HImode)
1166 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1168 if (abs (INTVAL (XEXP (x, 1))) == 1)
1169 *total = COSTS_N_INSNS (1);
1171 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1174 *total = COSTS_N_INSNS (10); /* worst case */
1176 else if (GET_MODE (x) == SImode)
1178 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1179 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1180 else /* worst case */
1181 *total = COSTS_N_INSNS (18);
1191 output_jump (enum rtx_code code, int inv, int length)
1195 static char buf[1000];
1196 const char *pos, *neg;
1200 case EQ: pos = "beq", neg = "bne"; break;
1201 case NE: pos = "bne", neg = "beq"; break;
1202 case GT: pos = "bgt", neg = "ble"; break;
1203 case GTU: pos = "bhi", neg = "blos"; break;
1204 case LT: pos = "blt", neg = "bge"; break;
1205 case LTU: pos = "blo", neg = "bhis"; break;
1206 case GE: pos = "bge", neg = "blt"; break;
1207 case GEU: pos = "bhis", neg = "blo"; break;
1208 case LE: pos = "ble", neg = "bgt"; break;
1209 case LEU: pos = "blos", neg = "bhi"; break;
1210 default: gcc_unreachable ();
1214 /* currently we don't need this, because the tstdf and cmpdf
1215 copy the condition code immediately, and other float operations are not
1216 yet recognized as changing the FCC - if so, then the length-cost of all
1217 jump insns increases by one, because we have to potentially copy the
1219 if (cc_status.flags & CC_IN_FPU)
1220 output_asm_insn("cfcc", NULL);
1227 sprintf(buf, "%s %%l1", inv ? neg : pos);
1233 sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x);
1247 notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
1249 if (GET_CODE (SET_DEST (exp)) == CC0)
1251 cc_status.flags = 0;
1252 cc_status.value1 = SET_DEST (exp);
1253 cc_status.value2 = SET_SRC (exp);
1256 if (GET_MODE(SET_SRC(exp)) == DFmode)
1257 cc_status.flags |= CC_IN_FPU;
1260 else if ((GET_CODE (SET_DEST (exp)) == REG
1261 || GET_CODE (SET_DEST (exp)) == MEM)
1262 && GET_CODE (SET_SRC (exp)) != PC
1263 && (GET_MODE (SET_DEST(exp)) == HImode
1264 || GET_MODE (SET_DEST(exp)) == QImode)
1265 && (GET_CODE (SET_SRC(exp)) == PLUS
1266 || GET_CODE (SET_SRC(exp)) == MINUS
1267 || GET_CODE (SET_SRC(exp)) == AND
1268 || GET_CODE (SET_SRC(exp)) == IOR
1269 || GET_CODE (SET_SRC(exp)) == XOR
1270 || GET_CODE (SET_SRC(exp)) == NOT
1271 || GET_CODE (SET_SRC(exp)) == NEG
1272 || GET_CODE (SET_SRC(exp)) == REG
1273 || GET_CODE (SET_SRC(exp)) == MEM))
1275 cc_status.flags = 0;
1276 cc_status.value1 = SET_SRC (exp);
1277 cc_status.value2 = SET_DEST (exp);
1279 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1281 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1282 cc_status.value2 = 0;
1283 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1285 && GET_CODE (cc_status.value2) == MEM)
1286 cc_status.value2 = 0;
1288 else if (GET_CODE (SET_SRC (exp)) == CALL)
1292 else if (GET_CODE (SET_DEST (exp)) == REG)
1295 if ((cc_status.value1
1296 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1297 cc_status.value1 = 0;
1298 if ((cc_status.value2
1299 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1300 cc_status.value2 = 0;
1302 else if (SET_DEST(exp) == pc_rtx)
1306 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1308 /* the last else is a bit paranoiac, but since nearly all instructions
1309 play with condition codes, it's reasonable! */
1311 CC_STATUS_INIT; /* paranoia*/
1317 simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1321 /* Eliminate non-memory operations */
1322 if (GET_CODE (op) != MEM)
1326 /* dword operations really put out 2 instructions, so eliminate them. */
1327 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1331 /* Decode the address now. */
1335 addr = XEXP (op, 0);
1337 switch (GET_CODE (addr))
1340 /* (R0) - no extra cost */
1345 /* -(R0), (R0)+ - cheap! */
1349 /* cheap - is encoded in addressing mode info!
1351 -- except for @(R0), which has to be @0(R0) !!! */
1353 if (GET_CODE (XEXP (addr, 0)) == REG)
1363 /* @#address - extra cost */
1367 /* X(R0) - extra cost */
1379 * output a block move:
1381 * operands[0] ... to
1382 * operands[1] ... from
1383 * operands[2] ... length
1384 * operands[3] ... alignment
1385 * operands[4] ... scratch register
1390 output_block_move(rtx *operands)
1392 static int count = 0;
1395 if (GET_CODE(operands[2]) == CONST_INT
1398 if (INTVAL(operands[2]) < 16
1399 && INTVAL(operands[3]) == 1)
1403 for (i = 1; i <= INTVAL(operands[2]); i++)
1404 output_asm_insn("movb (%1)+, (%0)+", operands);
1408 else if (INTVAL(operands[2]) < 32)
1412 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1413 output_asm_insn("mov (%1)+, (%0)+", operands);
1415 /* may I assume that moved quantity is
1416 multiple of alignment ???
1425 /* can do other clever things, maybe... */
1428 if (CONSTANT_P(operands[2]) )
1430 /* just move count to scratch */
1431 output_asm_insn("mov %2, %4", operands);
1435 /* just clobber the register */
1436 operands[4] = operands[2];
1440 /* switch over alignment */
1441 switch (INTVAL(operands[3]))
1457 sprintf(buf, "\nmovestrhi%d:", count);
1458 output_asm_insn(buf, NULL);
1460 output_asm_insn("movb (%1)+, (%0)+", operands);
1464 sprintf(buf, "sob %%4, movestrhi%d", count);
1465 output_asm_insn(buf, operands);
1469 output_asm_insn("dec %4", operands);
1471 sprintf(buf, "bgt movestrhi%d", count);
1472 output_asm_insn(buf, NULL);
1494 generate_compact_code:
1496 output_asm_insn("asr %4", operands);
1498 sprintf(buf, "\nmovestrhi%d:", count);
1499 output_asm_insn(buf, NULL);
1501 output_asm_insn("mov (%1)+, (%0)+", operands);
1505 sprintf(buf, "sob %%4, movestrhi%d", count);
1506 output_asm_insn(buf, operands);
1510 output_asm_insn("dec %4", operands);
1512 sprintf(buf, "bgt movestrhi%d", count);
1513 output_asm_insn(buf, NULL);
1539 goto generate_compact_code;
1541 output_asm_insn("asr %4", operands);
1542 output_asm_insn("asr %4", operands);
1544 sprintf(buf, "\nmovestrhi%d:", count);
1545 output_asm_insn(buf, NULL);
1547 output_asm_insn("mov (%1)+, (%0)+", operands);
1548 output_asm_insn("mov (%1)+, (%0)+", operands);
1552 sprintf(buf, "sob %%4, movestrhi%d", count);
1553 output_asm_insn(buf, operands);
1557 output_asm_insn("dec %4", operands);
1559 sprintf(buf, "bgt movestrhi%d", count);
1560 output_asm_insn(buf, NULL);
1590 goto generate_compact_code;
1592 output_asm_insn("asr %4", operands);
1593 output_asm_insn("asr %4", operands);
1594 output_asm_insn("asr %4", operands);
1596 sprintf(buf, "\nmovestrhi%d:", count);
1597 output_asm_insn(buf, NULL);
1599 output_asm_insn("mov (%1)+, (%0)+", operands);
1600 output_asm_insn("mov (%1)+, (%0)+", operands);
1601 output_asm_insn("mov (%1)+, (%0)+", operands);
1602 output_asm_insn("mov (%1)+, (%0)+", operands);
1606 sprintf(buf, "sob %%4, movestrhi%d", count);
1607 output_asm_insn(buf, operands);
1611 output_asm_insn("dec %4", operands);
1613 sprintf(buf, "bgt movestrhi%d", count);
1614 output_asm_insn(buf, NULL);
1627 /* This function checks whether a real value can be encoded as
1628 a literal, i.e., addressing mode 27. In that mode, real values
1629 are one word values, so the remaining 48 bits have to be zero. */
1631 legitimate_const_double_p (rtx address)
1635 REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1636 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1637 if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1642 /* A copy of output_addr_const modified for pdp11 expression syntax.
1643 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1644 use, and for debugging output, which we don't support with this port either.
1645 So this copy should get called whenever needed.
1648 output_addr_const_pdp11 (FILE *file, rtx x)
1653 switch (GET_CODE (x))
1656 gcc_assert (flag_pic);
1661 assemble_name (file, XSTR (x, 0));
1665 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1666 assemble_name (file, buf);
1670 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1671 assemble_name (file, buf);
1675 /* Should we check for constants which are too big? Maybe cutting
1676 them off to 16 bits is OK? */
1677 fprintf (file, "%#ho", (unsigned short) INTVAL (x));
1681 /* This used to output parentheses around the expression,
1682 but that does not work on the 386 (either ATT or BSD assembler). */
1683 output_addr_const_pdp11 (file, XEXP (x, 0));
1687 if (GET_MODE (x) == VOIDmode)
1689 /* We can use %o if the number is one word and positive. */
1690 gcc_assert (!CONST_DOUBLE_HIGH (x));
1691 fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
1694 /* We can't handle floating point constants;
1695 PRINT_OPERAND must handle them. */
1696 output_operand_lossage ("floating constant misused");
1700 /* Some assemblers need integer constants to appear last (e.g. masm). */
1701 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1703 output_addr_const_pdp11 (file, XEXP (x, 1));
1704 if (INTVAL (XEXP (x, 0)) >= 0)
1705 fprintf (file, "+");
1706 output_addr_const_pdp11 (file, XEXP (x, 0));
1710 output_addr_const_pdp11 (file, XEXP (x, 0));
1711 if (INTVAL (XEXP (x, 1)) >= 0)
1712 fprintf (file, "+");
1713 output_addr_const_pdp11 (file, XEXP (x, 1));
1718 /* Avoid outputting things like x-x or x+5-x,
1719 since some assemblers can't handle that. */
1720 x = simplify_subtraction (x);
1721 if (GET_CODE (x) != MINUS)
1724 output_addr_const_pdp11 (file, XEXP (x, 0));
1725 fprintf (file, "-");
1726 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1727 && INTVAL (XEXP (x, 1)) < 0)
1729 fprintf (file, targetm.asm_out.open_paren);
1730 output_addr_const_pdp11 (file, XEXP (x, 1));
1731 fprintf (file, targetm.asm_out.close_paren);
1734 output_addr_const_pdp11 (file, XEXP (x, 1));
1739 output_addr_const_pdp11 (file, XEXP (x, 0));
1743 output_operand_lossage ("invalid expression as operand");
1747 /* Worker function for TARGET_RETURN_IN_MEMORY. */
1750 pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1752 /* Should probably return DImode and DFmode in memory, lest
1753 we fill up all regs!
1755 have to, else we crash - exception: maybe return result in
1756 ac0 if DFmode and FPU present - compatibility problem with
1757 libraries for non-floating point.... */
1758 return (TYPE_MODE (type) == DImode
1759 || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
1762 /* Worker function for TARGET_FUNCTION_VALUE.
1764 On the pdp11 the value is found in R0 (or ac0??? not without FPU!!!! ) */
1767 pdp11_function_value (const_tree valtype,
1768 const_tree fntype_or_decl ATTRIBUTE_UNUSED,
1769 bool outgoing ATTRIBUTE_UNUSED)
1771 return gen_rtx_REG (TYPE_MODE (valtype),
1772 BASE_RETURN_VALUE_REG(TYPE_MODE(valtype)));
1775 /* Worker function for TARGET_LIBCALL_VALUE. */
1778 pdp11_libcall_value (enum machine_mode mode,
1779 const_rtx fun ATTRIBUTE_UNUSED)
1781 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode));
1784 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.
1786 On the pdp, the first "output" reg is the only register thus used.
1788 maybe ac0 ? - as option someday! */
1791 pdp11_function_value_regno_p (const unsigned int regno)
1793 return (regno == 0) || (TARGET_AC0 && (regno == 8));
1796 /* Worker function for TARGET_TRAMPOLINE_INIT.
1798 trampoline - how should i do it in separate i+d ?
1799 have some allocate_trampoline magic???
1801 the following should work for shared I/D:
1803 MV #STATIC, $4 0x940Y 0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
1804 JMP FUNCTION 0x0058 0x0000 <- FUNCTION
1808 pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1810 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
1813 gcc_assert (!TARGET_SPLIT);
1815 mem = adjust_address (m_tramp, HImode, 0);
1816 emit_move_insn (mem, GEN_INT (0x9400+STATIC_CHAIN_REGNUM));
1817 mem = adjust_address (m_tramp, HImode, 2);
1818 emit_move_insn (mem, chain_value);
1819 mem = adjust_address (m_tramp, HImode, 4);
1820 emit_move_insn (mem, GEN_INT (0x0058));
1821 emit_move_insn (mem, fnaddr);
1824 /* Worker function for TARGET_FUNCTION_ARG.
1826 Determine where to put an argument to a function.
1827 Value is zero to push the argument on the stack,
1828 or a hard register in which to store the argument.
1830 MODE is the argument's machine mode.
1831 TYPE is the data type of the argument (as a tree).
1832 This is null for libcalls where that information may
1834 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1835 the preceding args and about the function being called.
1836 NAMED is nonzero if this argument is a named parameter
1837 (otherwise it is an extra parameter matching an ellipsis). */
1840 pdp11_function_arg (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1841 enum machine_mode mode ATTRIBUTE_UNUSED,
1842 const_tree type ATTRIBUTE_UNUSED,
1843 bool named ATTRIBUTE_UNUSED)
1848 /* Worker function for TARGET_FUNCTION_ARG_ADVANCE.
1850 Update the data in CUM to advance over an argument of mode MODE and
1851 data type TYPE. (TYPE is null for libcalls where that information
1852 may not be available.) */
1855 pdp11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1856 const_tree type, bool named ATTRIBUTE_UNUSED)
1858 *cum += (mode != BLKmode
1859 ? GET_MODE_SIZE (mode)
1860 : int_size_in_bytes (type));