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);
161 /* Initialize the GCC target structure. */
162 #undef TARGET_ASM_BYTE_OP
163 #define TARGET_ASM_BYTE_OP NULL
164 #undef TARGET_ASM_ALIGNED_HI_OP
165 #define TARGET_ASM_ALIGNED_HI_OP NULL
166 #undef TARGET_ASM_ALIGNED_SI_OP
167 #define TARGET_ASM_ALIGNED_SI_OP NULL
168 #undef TARGET_ASM_INTEGER
169 #define TARGET_ASM_INTEGER pdp11_assemble_integer
171 #undef TARGET_ASM_FUNCTION_PROLOGUE
172 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
173 #undef TARGET_ASM_FUNCTION_EPILOGUE
174 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
176 #undef TARGET_ASM_OPEN_PAREN
177 #define TARGET_ASM_OPEN_PAREN "["
178 #undef TARGET_ASM_CLOSE_PAREN
179 #define TARGET_ASM_CLOSE_PAREN "]"
181 #undef TARGET_DEFAULT_TARGET_FLAGS
182 #define TARGET_DEFAULT_TARGET_FLAGS \
183 (MASK_FPU | MASK_45 | MASK_ABSHI_BUILTIN | TARGET_UNIX_ASM_DEFAULT)
184 #undef TARGET_HANDLE_OPTION
185 #define TARGET_HANDLE_OPTION pdp11_handle_option
186 #undef TARGET_OPTION_OPTIMIZATION
187 #define TARGET_OPTION_OPTIMIZATION pdp11_option_optimization
189 #undef TARGET_RTX_COSTS
190 #define TARGET_RTX_COSTS pdp11_rtx_costs
192 #undef TARGET_RETURN_IN_MEMORY
193 #define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
195 #undef TARGET_FUNCTION_VALUE
196 #define TARGET_FUNCTION_VALUE pdp11_function_value
197 #undef TARGET_LIBCALL_VALUE
198 #define TARGET_LIBCALL_VALUE pdp11_libcall_value
199 #undef TARGET_FUNCTION_VALUE_REGNO_P
200 #define TARGET_FUNCTION_VALUE_REGNO_P pdp11_function_value_regno_p
202 #undef TARGET_TRAMPOLINE_INIT
203 #define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
205 struct gcc_target targetm = TARGET_INITIALIZER;
207 /* Implement TARGET_HANDLE_OPTION. */
210 pdp11_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED,
211 int value ATTRIBUTE_UNUSED)
216 target_flags &= ~(MASK_40 | MASK_45);
224 /* Implement TARGET_OPTION_OPTIMIZATION. */
227 pdp11_option_optimization (int level, int size ATTRIBUTE_UNUSED)
229 flag_finite_math_only = 0;
230 flag_trapping_math = 0;
231 flag_signaling_nans = 0;
234 flag_omit_frame_pointer = 1;
235 /* flag_unroll_loops = 1; */
239 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
242 arith_operand (rtx op, enum machine_mode mode)
244 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
248 const_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
250 return (GET_CODE (op) == CONST_INT);
254 immediate15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
256 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
260 expand_shift_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
262 return (GET_CODE (op) == CONST_INT
263 && abs (INTVAL(op)) > 1
264 && abs (INTVAL(op)) <= 4);
268 stream is a stdio stream to output the code to.
269 size is an int: how many units of temporary storage to allocate.
270 Refer to the array `regs_ever_live' to determine which registers
271 to save; `regs_ever_live[I]' is nonzero if register number I
272 is ever used in the function. This macro is responsible for
273 knowing which registers should not be saved even if used.
277 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
279 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
284 "\n\t; /* function prologue %s*/\n",
285 current_function_name ());
287 /* if we are outputting code for main,
288 the switch FPU to right mode if TARGET_FPU */
289 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
292 "\t;/* switch cpu to double float, single integer */\n");
293 fprintf(stream, "\tsetd\n");
294 fprintf(stream, "\tseti\n\n");
297 if (frame_pointer_needed)
299 fprintf(stream, "\tmov r5, -(sp)\n");
300 fprintf(stream, "\tmov sp, r5\n");
309 asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
311 /* save CPU registers */
312 for (regno = 0; regno < 8; regno++)
313 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
314 if (! ((regno == FRAME_POINTER_REGNUM)
315 && frame_pointer_needed))
316 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
317 /* fpu regs saving */
319 /* via_ac specifies the ac to use for saving ac4, ac5 */
322 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
325 if (LOAD_FPU_REG_P(regno)
326 && df_regs_ever_live_p (regno)
327 && ! call_used_regs[regno])
329 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
333 /* maybe make ac4, ac5 call used regs?? */
335 if (NO_LOAD_FPU_REG_P(regno)
336 && df_regs_ever_live_p (regno)
337 && ! call_used_regs[regno])
339 gcc_assert (via_ac != -1);
340 fprintf (stream, "\tldd %s, %s\n",
341 reg_names[regno], reg_names[via_ac]);
342 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
346 fprintf (stream, "\t;/* end of prologue */\n\n");
350 The function epilogue should not depend on the current stack pointer!
351 It should use the frame pointer only. This is mandatory because
352 of alloca; we also take advantage of it to omit stack adjustments
355 /* maybe we can make leaf functions faster by switching to the
356 second register file - this way we don't have to save regs!
357 leaf functions are ~ 50% of all functions (dynamically!)
359 set/clear bit 11 (dec. 2048) of status word for switching register files -
360 but how can we do this? the pdp11/45 manual says bit may only
361 be set (p.24), but not cleared!
363 switching to kernel is probably more expensive, so we'll leave it
364 like this and not use the second set of registers...
366 maybe as option if you want to generate code for kernel mode? */
369 pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
371 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
376 fprintf (stream, "\n\t; /*function epilogue */\n");
378 if (frame_pointer_needed)
380 /* hope this is safe - m68k does it also .... */
381 df_set_regs_ever_live (FRAME_POINTER_REGNUM, false);
383 for (i =7, j = 0 ; i >= 0 ; i--)
384 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
387 /* remember # of pushed bytes for CPU regs */
390 /* change fp -> r5 due to the compile error on libgcc2.c */
391 for (i =7 ; i >= 0 ; i--)
392 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
393 fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
394 (-fsize-2*j--)&0xffff, reg_names[i]);
397 via_ac = FIRST_PSEUDO_REGISTER -1;
399 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
400 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
406 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
408 if (LOAD_FPU_REG_P(i)
409 && df_regs_ever_live_p (i)
410 && ! call_used_regs[i])
412 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
413 (-fsize-k)&0xffff, reg_names[i]);
417 if (NO_LOAD_FPU_REG_P(i)
418 && df_regs_ever_live_p (i)
419 && ! call_used_regs[i])
421 gcc_assert (LOAD_FPU_REG_P(via_ac));
423 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
424 (-fsize-k)&0xffff, reg_names[via_ac]);
425 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
430 fprintf(stream, "\tmov r5, sp\n");
431 fprintf (stream, "\tmov (sp)+, r5\n");
435 via_ac = FIRST_PSEUDO_REGISTER -1;
438 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
439 if (df_regs_ever_live_p (i) && call_used_regs[i])
442 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
444 if (LOAD_FPU_REG_P(i)
445 && df_regs_ever_live_p (i)
446 && ! call_used_regs[i])
447 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
449 if (NO_LOAD_FPU_REG_P(i)
450 && df_regs_ever_live_p (i)
451 && ! call_used_regs[i])
453 gcc_assert (LOAD_FPU_REG_P(via_ac));
455 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
456 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
460 for (i=7; i >= 0; i--)
461 if (df_regs_ever_live_p (i) && !call_used_regs[i])
462 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
465 fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n",
469 fprintf (stream, "\trts pc\n");
470 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
473 /* Return the best assembler insn template
474 for moving operands[1] into operands[0] as a fullword. */
476 singlemove_string (rtx *operands)
478 if (operands[1] != const0_rtx)
485 /* Output assembler code to perform a doubleword move insn
486 with operands OPERANDS. */
489 output_move_double (rtx *operands)
491 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
493 rtx addreg0 = 0, addreg1 = 0;
495 /* First classify both operands. */
497 if (REG_P (operands[0]))
499 else if (offsettable_memref_p (operands[0]))
501 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
503 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
505 else if (GET_CODE (operands[0]) == MEM)
510 if (REG_P (operands[1]))
512 else if (CONSTANT_P (operands[1])
514 || GET_CODE (operands[1]) == CONST_DOUBLE
518 else if (offsettable_memref_p (operands[1]))
520 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
522 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
524 else if (GET_CODE (operands[1]) == MEM)
529 /* Check for the cases that the operand constraints are not
530 supposed to allow to happen. Abort if we get one,
531 because generating code for these cases is painful. */
533 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
535 /* If one operand is decrementing and one is incrementing
536 decrement the former register explicitly
537 and change that operand into ordinary indexing. */
539 if (optype0 == PUSHOP && optype1 == POPOP)
541 operands[0] = XEXP (XEXP (operands[0], 0), 0);
542 output_asm_insn ("sub $4,%0", operands);
543 operands[0] = gen_rtx_MEM (SImode, operands[0]);
546 if (optype0 == POPOP && optype1 == PUSHOP)
548 operands[1] = XEXP (XEXP (operands[1], 0), 0);
549 output_asm_insn ("sub $4,%1", operands);
550 operands[1] = gen_rtx_MEM (SImode, operands[1]);
554 /* If an operand is an unoffsettable memory ref, find a register
555 we can increment temporarily to make it refer to the second word. */
557 if (optype0 == MEMOP)
558 addreg0 = find_addr_reg (XEXP (operands[0], 0));
560 if (optype1 == MEMOP)
561 addreg1 = find_addr_reg (XEXP (operands[1], 0));
563 /* Ok, we can do one word at a time.
564 Normally we do the low-numbered word first,
565 but if either operand is autodecrementing then we
566 do the high-numbered word first.
568 In either case, set up in LATEHALF the operands to use
569 for the high-numbered word and in some cases alter the
570 operands in OPERANDS to be suitable for the low-numbered word. */
572 if (optype0 == REGOP)
573 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
574 else if (optype0 == OFFSOP)
575 latehalf[0] = adjust_address (operands[0], HImode, 2);
577 latehalf[0] = operands[0];
579 if (optype1 == REGOP)
580 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
581 else if (optype1 == OFFSOP)
582 latehalf[1] = adjust_address (operands[1], HImode, 2);
583 else if (optype1 == CNSTOP)
585 if (CONSTANT_P (operands[1]))
587 /* now the mess begins, high word is in lower word???
589 that's what ashc makes me think, but I don't remember :-( */
590 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
591 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
594 /* immediate 32-bit values not allowed */
595 gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE);
598 latehalf[1] = operands[1];
600 /* If insn is effectively movd N(sp),-(sp) then we will do the
601 high word first. We should use the adjusted operand 1 (which is N+4(sp))
602 for the low word as well, to compensate for the first decrement of sp. */
603 if (optype0 == PUSHOP
604 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
605 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
606 operands[1] = latehalf[1];
608 /* If one or both operands autodecrementing,
609 do the two words, high-numbered first. */
611 /* Likewise, the first move would clobber the source of the second one,
612 do them in the other order. This happens only for registers;
613 such overlap can't happen in memory unless the user explicitly
614 sets it up, and that is an undefined circumstance. */
616 if (optype0 == PUSHOP || optype1 == PUSHOP
617 || (optype0 == REGOP && optype1 == REGOP
618 && REGNO (operands[0]) == REGNO (latehalf[1])))
620 /* Make any unoffsettable addresses point at high-numbered word. */
622 output_asm_insn ("add $2,%0", &addreg0);
624 output_asm_insn ("add $2,%0", &addreg1);
627 output_asm_insn (singlemove_string (latehalf), latehalf);
629 /* Undo the adds we just did. */
631 output_asm_insn ("sub $2,%0", &addreg0);
633 output_asm_insn ("sub $2,%0", &addreg1);
635 /* Do low-numbered word. */
636 return singlemove_string (operands);
639 /* Normal case: do the two words, low-numbered first. */
641 output_asm_insn (singlemove_string (operands), operands);
643 /* Make any unoffsettable addresses point at high-numbered word. */
645 output_asm_insn ("add $2,%0", &addreg0);
647 output_asm_insn ("add $2,%0", &addreg1);
650 output_asm_insn (singlemove_string (latehalf), latehalf);
652 /* Undo the adds we just did. */
654 output_asm_insn ("sub $2,%0", &addreg0);
656 output_asm_insn ("sub $2,%0", &addreg1);
660 /* Output assembler code to perform a quadword move insn
661 with operands OPERANDS. */
664 output_move_quad (rtx *operands)
666 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
668 rtx addreg0 = 0, addreg1 = 0;
670 output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);
672 if (REG_P (operands[0]))
674 else if (offsettable_memref_p (operands[0]))
676 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
678 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
680 else if (GET_CODE (operands[0]) == MEM)
685 if (REG_P (operands[1]))
687 else if (CONSTANT_P (operands[1])
688 || GET_CODE (operands[1]) == CONST_DOUBLE)
690 else if (offsettable_memref_p (operands[1]))
692 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
694 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
696 else if (GET_CODE (operands[1]) == MEM)
701 /* Check for the cases that the operand constraints are not
702 supposed to allow to happen. Abort if we get one,
703 because generating code for these cases is painful. */
705 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
707 /* check if we move a CPU reg to an FPU reg, or vice versa! */
708 if (optype0 == REGOP && optype1 == REGOP)
709 /* bogus - 64 bit cannot reside in CPU! */
710 gcc_assert (!CPU_REG_P(REGNO(operands[0]))
711 && !CPU_REG_P (REGNO(operands[1])));
713 if (optype0 == REGOP || optype1 == REGOP)
715 /* check for use of clrd????
716 if you ever allow ac4 and ac5 (now we require secondary load)
717 you must check whether
718 you want to load into them or store from them -
719 then dump ac0 into $help$ movce ac4/5 to ac0, do the
720 store from ac0, and restore ac0 - if you can find
721 an unused ac[0-3], use that and you save a store and a load!*/
723 if (FPU_REG_P(REGNO(operands[0])))
725 if (GET_CODE(operands[1]) == CONST_DOUBLE)
728 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
730 if (REAL_VALUES_EQUAL (r, dconst0))
731 return "{clrd|clrf} %0";
734 return "{ldd|movf} %1, %0";
737 if (FPU_REG_P(REGNO(operands[1])))
738 return "{std|movf} %1, %0";
741 /* If one operand is decrementing and one is incrementing
742 decrement the former register explicitly
743 and change that operand into ordinary indexing. */
745 if (optype0 == PUSHOP && optype1 == POPOP)
747 operands[0] = XEXP (XEXP (operands[0], 0), 0);
748 output_asm_insn ("sub $8,%0", operands);
749 operands[0] = gen_rtx_MEM (DImode, operands[0]);
752 if (optype0 == POPOP && optype1 == PUSHOP)
754 operands[1] = XEXP (XEXP (operands[1], 0), 0);
755 output_asm_insn ("sub $8,%1", operands);
756 operands[1] = gen_rtx_MEM (SImode, operands[1]);
760 /* If an operand is an unoffsettable memory ref, find a register
761 we can increment temporarily to make it refer to the second word. */
763 if (optype0 == MEMOP)
764 addreg0 = find_addr_reg (XEXP (operands[0], 0));
766 if (optype1 == MEMOP)
767 addreg1 = find_addr_reg (XEXP (operands[1], 0));
769 /* Ok, we can do one word at a time.
770 Normally we do the low-numbered word first,
771 but if either operand is autodecrementing then we
772 do the high-numbered word first.
774 In either case, set up in LATEHALF the operands to use
775 for the high-numbered word and in some cases alter the
776 operands in OPERANDS to be suitable for the low-numbered word. */
778 if (optype0 == REGOP)
779 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
780 else if (optype0 == OFFSOP)
781 latehalf[0] = adjust_address (operands[0], SImode, 4);
783 latehalf[0] = operands[0];
785 if (optype1 == REGOP)
786 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
787 else if (optype1 == OFFSOP)
788 latehalf[1] = adjust_address (operands[1], SImode, 4);
789 else if (optype1 == CNSTOP)
791 if (GET_CODE (operands[1]) == CONST_DOUBLE)
795 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
796 REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
797 latehalf[1] = GEN_INT (dval[1]);
798 operands[1] = GEN_INT (dval[0]);
800 else if (GET_CODE(operands[1]) == CONST_INT)
802 latehalf[1] = const0_rtx;
808 latehalf[1] = operands[1];
810 /* If insn is effectively movd N(sp),-(sp) then we will do the
811 high word first. We should use the adjusted operand 1 (which is N+4(sp))
812 for the low word as well, to compensate for the first decrement of sp. */
813 if (optype0 == PUSHOP
814 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
815 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
816 operands[1] = latehalf[1];
818 /* If one or both operands autodecrementing,
819 do the two words, high-numbered first. */
821 /* Likewise, the first move would clobber the source of the second one,
822 do them in the other order. This happens only for registers;
823 such overlap can't happen in memory unless the user explicitly
824 sets it up, and that is an undefined circumstance. */
826 if (optype0 == PUSHOP || optype1 == PUSHOP
827 || (optype0 == REGOP && optype1 == REGOP
828 && REGNO (operands[0]) == REGNO (latehalf[1])))
830 /* Make any unoffsettable addresses point at high-numbered word. */
832 output_asm_insn ("add $4,%0", &addreg0);
834 output_asm_insn ("add $4,%0", &addreg1);
837 output_asm_insn(output_move_double(latehalf), latehalf);
839 /* Undo the adds we just did. */
841 output_asm_insn ("sub $4,%0", &addreg0);
843 output_asm_insn ("sub $4,%0", &addreg1);
845 /* Do low-numbered word. */
846 return output_move_double (operands);
849 /* Normal case: do the two words, low-numbered first. */
851 output_asm_insn (output_move_double (operands), operands);
853 /* Make any unoffsettable addresses point at high-numbered word. */
855 output_asm_insn ("add $4,%0", &addreg0);
857 output_asm_insn ("add $4,%0", &addreg1);
860 output_asm_insn (output_move_double (latehalf), latehalf);
862 /* Undo the adds we just did. */
864 output_asm_insn ("sub $4,%0", &addreg0);
866 output_asm_insn ("sub $4,%0", &addreg1);
872 /* Return a REG that occurs in ADDR with coefficient 1.
873 ADDR can be effectively incremented by incrementing REG. */
876 find_addr_reg (rtx addr)
878 while (GET_CODE (addr) == PLUS)
880 if (GET_CODE (XEXP (addr, 0)) == REG)
881 addr = XEXP (addr, 0);
882 if (GET_CODE (XEXP (addr, 1)) == REG)
883 addr = XEXP (addr, 1);
884 if (CONSTANT_P (XEXP (addr, 0)))
885 addr = XEXP (addr, 1);
886 if (CONSTANT_P (XEXP (addr, 1)))
887 addr = XEXP (addr, 0);
889 if (GET_CODE (addr) == REG)
894 /* Output an ascii string. */
896 output_ascii (FILE *file, const char *p, int size)
900 /* This used to output .byte "string", which doesn't work with the UNIX
901 assembler and I think not with DEC ones either. */
902 fprintf (file, "\t.byte ");
904 for (i = 0; i < size; i++)
906 register int c = p[i];
909 fprintf (file, "%#o", c);
917 /* --- stole from out-vax, needs changes */
920 print_operand_address (FILE *file, register rtx addr)
922 register rtx reg1, reg2, breg, ireg;
927 switch (GET_CODE (addr))
934 addr = XEXP (addr, 0);
938 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
943 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
948 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
955 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
956 || GET_CODE (XEXP (addr, 0)) == MEM)
958 offset = XEXP (addr, 0);
959 addr = XEXP (addr, 1);
961 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
962 || GET_CODE (XEXP (addr, 1)) == MEM)
964 offset = XEXP (addr, 1);
965 addr = XEXP (addr, 0);
967 if (GET_CODE (addr) != PLUS)
969 else if (GET_CODE (XEXP (addr, 0)) == MULT)
971 reg1 = XEXP (addr, 0);
972 addr = XEXP (addr, 1);
974 else if (GET_CODE (XEXP (addr, 1)) == MULT)
976 reg1 = XEXP (addr, 1);
977 addr = XEXP (addr, 0);
979 else if (GET_CODE (XEXP (addr, 0)) == REG)
981 reg1 = XEXP (addr, 0);
982 addr = XEXP (addr, 1);
984 else if (GET_CODE (XEXP (addr, 1)) == REG)
986 reg1 = XEXP (addr, 1);
987 addr = XEXP (addr, 0);
989 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
999 gcc_assert (addr == 0);
1002 if (reg1 != 0 && GET_CODE (reg1) == MULT)
1007 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
1012 else if (reg2 != 0 || GET_CODE (addr) == MEM)
1023 output_address (addr);
1026 gcc_assert (GET_CODE (breg) == REG);
1027 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
1031 if (GET_CODE (ireg) == MULT)
1032 ireg = XEXP (ireg, 0);
1033 gcc_assert (GET_CODE (ireg) == REG);
1034 gcc_unreachable(); /* ??? */
1035 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
1040 output_addr_const_pdp11 (file, addr);
1044 /* Target hook to assemble integer objects. We need to use the
1045 pdp-specific version of output_addr_const. */
1048 pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
1054 fprintf (asm_out_file, "\t.byte\t");
1055 output_addr_const_pdp11 (asm_out_file, x);
1056 fprintf (asm_out_file, " /* char */\n");
1060 fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
1061 output_addr_const_pdp11 (asm_out_file, x);
1062 fprintf (asm_out_file, " /* short */\n");
1065 return default_assemble_integer (x, size, aligned_p);
1069 /* register move costs, indexed by regs */
1071 static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
1073 /* NO MUL GEN LFPU NLFPU FPU ALL */
1075 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
1076 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
1077 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
1078 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
1079 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
1080 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
1081 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
1085 /* -- note that some moves are tremendously expensive,
1086 because they require lots of tricks! do we have to
1087 charge the costs incurred by secondary reload class
1088 -- as we do here with 22 -- or not ? */
1091 pdp11_register_move_cost (enum reg_class c1, enum reg_class c2)
1093 return move_costs[(int)c1][(int)c2];
1097 pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
1098 bool speed ATTRIBUTE_UNUSED)
1103 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
1113 /* Twice as expensive as REG. */
1118 /* Twice (or 4 times) as expensive as 16 bit. */
1123 /* ??? There is something wrong in MULT because MULT is not
1124 as cheap as total = 2 even if we can shift! */
1125 /* If optimizing for size make mult etc cheap, but not 1, so when
1126 in doubt the faster insn is chosen. */
1128 *total = COSTS_N_INSNS (2);
1130 *total = COSTS_N_INSNS (11);
1135 *total = COSTS_N_INSNS (2);
1137 *total = COSTS_N_INSNS (25);
1142 *total = COSTS_N_INSNS (2);
1144 *total = COSTS_N_INSNS (26);
1148 /* Equivalent to length, so same for optimize_size. */
1149 *total = COSTS_N_INSNS (3);
1153 /* Only used for qi->hi. */
1154 *total = COSTS_N_INSNS (1);
1158 if (GET_MODE (x) == HImode)
1159 *total = COSTS_N_INSNS (1);
1160 else if (GET_MODE (x) == SImode)
1161 *total = COSTS_N_INSNS (6);
1163 *total = COSTS_N_INSNS (2);
1170 *total = COSTS_N_INSNS (1);
1171 else if (GET_MODE (x) == QImode)
1173 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
1174 *total = COSTS_N_INSNS (8); /* worst case */
1176 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
1178 else if (GET_MODE (x) == HImode)
1180 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1182 if (abs (INTVAL (XEXP (x, 1))) == 1)
1183 *total = COSTS_N_INSNS (1);
1185 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1188 *total = COSTS_N_INSNS (10); /* worst case */
1190 else if (GET_MODE (x) == SImode)
1192 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1193 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1194 else /* worst case */
1195 *total = COSTS_N_INSNS (18);
1205 output_jump (enum rtx_code code, int inv, int length)
1209 static char buf[1000];
1210 const char *pos, *neg;
1214 case EQ: pos = "beq", neg = "bne"; break;
1215 case NE: pos = "bne", neg = "beq"; break;
1216 case GT: pos = "bgt", neg = "ble"; break;
1217 case GTU: pos = "bhi", neg = "blos"; break;
1218 case LT: pos = "blt", neg = "bge"; break;
1219 case LTU: pos = "blo", neg = "bhis"; break;
1220 case GE: pos = "bge", neg = "blt"; break;
1221 case GEU: pos = "bhis", neg = "blo"; break;
1222 case LE: pos = "ble", neg = "bgt"; break;
1223 case LEU: pos = "blos", neg = "bhi"; break;
1224 default: gcc_unreachable ();
1228 /* currently we don't need this, because the tstdf and cmpdf
1229 copy the condition code immediately, and other float operations are not
1230 yet recognized as changing the FCC - if so, then the length-cost of all
1231 jump insns increases by one, because we have to potentially copy the
1233 if (cc_status.flags & CC_IN_FPU)
1234 output_asm_insn("cfcc", NULL);
1241 sprintf(buf, "%s %%l1", inv ? neg : pos);
1247 sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x);
1261 notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
1263 if (GET_CODE (SET_DEST (exp)) == CC0)
1265 cc_status.flags = 0;
1266 cc_status.value1 = SET_DEST (exp);
1267 cc_status.value2 = SET_SRC (exp);
1270 if (GET_MODE(SET_SRC(exp)) == DFmode)
1271 cc_status.flags |= CC_IN_FPU;
1274 else if ((GET_CODE (SET_DEST (exp)) == REG
1275 || GET_CODE (SET_DEST (exp)) == MEM)
1276 && GET_CODE (SET_SRC (exp)) != PC
1277 && (GET_MODE (SET_DEST(exp)) == HImode
1278 || GET_MODE (SET_DEST(exp)) == QImode)
1279 && (GET_CODE (SET_SRC(exp)) == PLUS
1280 || GET_CODE (SET_SRC(exp)) == MINUS
1281 || GET_CODE (SET_SRC(exp)) == AND
1282 || GET_CODE (SET_SRC(exp)) == IOR
1283 || GET_CODE (SET_SRC(exp)) == XOR
1284 || GET_CODE (SET_SRC(exp)) == NOT
1285 || GET_CODE (SET_SRC(exp)) == NEG
1286 || GET_CODE (SET_SRC(exp)) == REG
1287 || GET_CODE (SET_SRC(exp)) == MEM))
1289 cc_status.flags = 0;
1290 cc_status.value1 = SET_SRC (exp);
1291 cc_status.value2 = SET_DEST (exp);
1293 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1295 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1296 cc_status.value2 = 0;
1297 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1299 && GET_CODE (cc_status.value2) == MEM)
1300 cc_status.value2 = 0;
1302 else if (GET_CODE (SET_SRC (exp)) == CALL)
1306 else if (GET_CODE (SET_DEST (exp)) == REG)
1309 if ((cc_status.value1
1310 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1311 cc_status.value1 = 0;
1312 if ((cc_status.value2
1313 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1314 cc_status.value2 = 0;
1316 else if (SET_DEST(exp) == pc_rtx)
1320 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1322 /* the last else is a bit paranoiac, but since nearly all instructions
1323 play with condition codes, it's reasonable! */
1325 CC_STATUS_INIT; /* paranoia*/
1331 simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1335 /* Eliminate non-memory operations */
1336 if (GET_CODE (op) != MEM)
1340 /* dword operations really put out 2 instructions, so eliminate them. */
1341 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1345 /* Decode the address now. */
1349 addr = XEXP (op, 0);
1351 switch (GET_CODE (addr))
1354 /* (R0) - no extra cost */
1359 /* -(R0), (R0)+ - cheap! */
1363 /* cheap - is encoded in addressing mode info!
1365 -- except for @(R0), which has to be @0(R0) !!! */
1367 if (GET_CODE (XEXP (addr, 0)) == REG)
1377 /* @#address - extra cost */
1381 /* X(R0) - extra cost */
1393 * output a block move:
1395 * operands[0] ... to
1396 * operands[1] ... from
1397 * operands[2] ... length
1398 * operands[3] ... alignment
1399 * operands[4] ... scratch register
1404 output_block_move(rtx *operands)
1406 static int count = 0;
1409 if (GET_CODE(operands[2]) == CONST_INT
1412 if (INTVAL(operands[2]) < 16
1413 && INTVAL(operands[3]) == 1)
1417 for (i = 1; i <= INTVAL(operands[2]); i++)
1418 output_asm_insn("movb (%1)+, (%0)+", operands);
1422 else if (INTVAL(operands[2]) < 32)
1426 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1427 output_asm_insn("mov (%1)+, (%0)+", operands);
1429 /* may I assume that moved quantity is
1430 multiple of alignment ???
1439 /* can do other clever things, maybe... */
1442 if (CONSTANT_P(operands[2]) )
1444 /* just move count to scratch */
1445 output_asm_insn("mov %2, %4", operands);
1449 /* just clobber the register */
1450 operands[4] = operands[2];
1454 /* switch over alignment */
1455 switch (INTVAL(operands[3]))
1471 sprintf(buf, "\nmovestrhi%d:", count);
1472 output_asm_insn(buf, NULL);
1474 output_asm_insn("movb (%1)+, (%0)+", operands);
1478 sprintf(buf, "sob %%4, movestrhi%d", count);
1479 output_asm_insn(buf, operands);
1483 output_asm_insn("dec %4", operands);
1485 sprintf(buf, "bgt movestrhi%d", count);
1486 output_asm_insn(buf, NULL);
1508 generate_compact_code:
1510 output_asm_insn("asr %4", operands);
1512 sprintf(buf, "\nmovestrhi%d:", count);
1513 output_asm_insn(buf, NULL);
1515 output_asm_insn("mov (%1)+, (%0)+", operands);
1519 sprintf(buf, "sob %%4, movestrhi%d", count);
1520 output_asm_insn(buf, operands);
1524 output_asm_insn("dec %4", operands);
1526 sprintf(buf, "bgt movestrhi%d", count);
1527 output_asm_insn(buf, NULL);
1553 goto generate_compact_code;
1555 output_asm_insn("asr %4", operands);
1556 output_asm_insn("asr %4", operands);
1558 sprintf(buf, "\nmovestrhi%d:", count);
1559 output_asm_insn(buf, NULL);
1561 output_asm_insn("mov (%1)+, (%0)+", operands);
1562 output_asm_insn("mov (%1)+, (%0)+", operands);
1566 sprintf(buf, "sob %%4, movestrhi%d", count);
1567 output_asm_insn(buf, operands);
1571 output_asm_insn("dec %4", operands);
1573 sprintf(buf, "bgt movestrhi%d", count);
1574 output_asm_insn(buf, NULL);
1604 goto generate_compact_code;
1606 output_asm_insn("asr %4", operands);
1607 output_asm_insn("asr %4", operands);
1608 output_asm_insn("asr %4", operands);
1610 sprintf(buf, "\nmovestrhi%d:", count);
1611 output_asm_insn(buf, NULL);
1613 output_asm_insn("mov (%1)+, (%0)+", operands);
1614 output_asm_insn("mov (%1)+, (%0)+", operands);
1615 output_asm_insn("mov (%1)+, (%0)+", operands);
1616 output_asm_insn("mov (%1)+, (%0)+", operands);
1620 sprintf(buf, "sob %%4, movestrhi%d", count);
1621 output_asm_insn(buf, operands);
1625 output_asm_insn("dec %4", operands);
1627 sprintf(buf, "bgt movestrhi%d", count);
1628 output_asm_insn(buf, NULL);
1641 /* This function checks whether a real value can be encoded as
1642 a literal, i.e., addressing mode 27. In that mode, real values
1643 are one word values, so the remaining 48 bits have to be zero. */
1645 legitimate_const_double_p (rtx address)
1649 REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1650 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1651 if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1656 /* A copy of output_addr_const modified for pdp11 expression syntax.
1657 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1658 use, and for debugging output, which we don't support with this port either.
1659 So this copy should get called whenever needed.
1662 output_addr_const_pdp11 (FILE *file, rtx x)
1667 switch (GET_CODE (x))
1670 gcc_assert (flag_pic);
1675 assemble_name (file, XSTR (x, 0));
1679 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1680 assemble_name (file, buf);
1684 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1685 assemble_name (file, buf);
1689 /* Should we check for constants which are too big? Maybe cutting
1690 them off to 16 bits is OK? */
1691 fprintf (file, "%#ho", (unsigned short) INTVAL (x));
1695 /* This used to output parentheses around the expression,
1696 but that does not work on the 386 (either ATT or BSD assembler). */
1697 output_addr_const_pdp11 (file, XEXP (x, 0));
1701 if (GET_MODE (x) == VOIDmode)
1703 /* We can use %o if the number is one word and positive. */
1704 gcc_assert (!CONST_DOUBLE_HIGH (x));
1705 fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
1708 /* We can't handle floating point constants;
1709 PRINT_OPERAND must handle them. */
1710 output_operand_lossage ("floating constant misused");
1714 /* Some assemblers need integer constants to appear last (e.g. masm). */
1715 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1717 output_addr_const_pdp11 (file, XEXP (x, 1));
1718 if (INTVAL (XEXP (x, 0)) >= 0)
1719 fprintf (file, "+");
1720 output_addr_const_pdp11 (file, XEXP (x, 0));
1724 output_addr_const_pdp11 (file, XEXP (x, 0));
1725 if (INTVAL (XEXP (x, 1)) >= 0)
1726 fprintf (file, "+");
1727 output_addr_const_pdp11 (file, XEXP (x, 1));
1732 /* Avoid outputting things like x-x or x+5-x,
1733 since some assemblers can't handle that. */
1734 x = simplify_subtraction (x);
1735 if (GET_CODE (x) != MINUS)
1738 output_addr_const_pdp11 (file, XEXP (x, 0));
1739 fprintf (file, "-");
1740 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1741 && INTVAL (XEXP (x, 1)) < 0)
1743 fprintf (file, targetm.asm_out.open_paren);
1744 output_addr_const_pdp11 (file, XEXP (x, 1));
1745 fprintf (file, targetm.asm_out.close_paren);
1748 output_addr_const_pdp11 (file, XEXP (x, 1));
1753 output_addr_const_pdp11 (file, XEXP (x, 0));
1757 output_operand_lossage ("invalid expression as operand");
1761 /* Worker function for TARGET_RETURN_IN_MEMORY. */
1764 pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1766 /* Should probably return DImode and DFmode in memory, lest
1767 we fill up all regs!
1769 have to, else we crash - exception: maybe return result in
1770 ac0 if DFmode and FPU present - compatibility problem with
1771 libraries for non-floating point.... */
1772 return (TYPE_MODE (type) == DImode
1773 || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
1776 /* Worker function for TARGET_FUNCTION_VALUE.
1778 On the pdp11 the value is found in R0 (or ac0??? not without FPU!!!! ) */
1781 pdp11_function_value (const_tree valtype,
1782 const_tree fntype_or_decl ATTRIBUTE_UNUSED,
1783 bool outgoing ATTRIBUTE_UNUSED)
1785 return gen_rtx_REG (TYPE_MODE (valtype),
1786 BASE_RETURN_VALUE_REG(TYPE_MODE(valtype)));
1789 /* Worker function for TARGET_LIBCALL_VALUE. */
1792 pdp11_libcall_value (enum machine_mode mode,
1793 const_rtx fun ATTRIBUTE_UNUSED)
1795 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode));
1798 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.
1800 On the pdp, the first "output" reg is the only register thus used.
1802 maybe ac0 ? - as option someday! */
1805 pdp11_function_value_regno_p (const unsigned int regno)
1807 return (regno == 0) || (TARGET_AC0 && (regno == 8));
1810 /* Worker function for TARGET_TRAMPOLINE_INIT.
1812 trampoline - how should i do it in separate i+d ?
1813 have some allocate_trampoline magic???
1815 the following should work for shared I/D:
1817 MV #STATIC, $4 0x940Y 0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
1818 JMP FUNCTION 0x0058 0x0000 <- FUNCTION
1822 pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1824 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
1827 gcc_assert (!TARGET_SPLIT);
1829 mem = adjust_address (m_tramp, HImode, 0);
1830 emit_move_insn (mem, GEN_INT (0x9400+STATIC_CHAIN_REGNUM));
1831 mem = adjust_address (m_tramp, HImode, 2);
1832 emit_move_insn (mem, chain_value);
1833 mem = adjust_address (m_tramp, HImode, 4);
1834 emit_move_insn (mem, GEN_INT (0x0058));
1835 emit_move_insn (mem, fnaddr);