* target.def (target_option.init_struct): New hook.
[official-gcc.git] / gcc / config / pdp11 / pdp11.c
blobe6b41596c13b3d7037aef0da6f6196cc20abd633
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)
11 any later version.
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/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "function.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "recog.h"
36 #include "tree.h"
37 #include "expr.h"
38 #include "diagnostic-core.h"
39 #include "toplev.h"
40 #include "tm_p.h"
41 #include "target.h"
42 #include "target-def.h"
43 #include "df.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
51 defined in tm.h */
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 =
68 encode_pdp11_f,
69 decode_pdp11_f,
72 24,
73 24,
74 -127,
75 127,
76 15,
77 false,
78 false,
79 false,
80 false,
81 false,
82 false,
83 false,
84 false
87 const struct real_format pdp11_d_format =
89 encode_pdp11_d,
90 decode_pdp11_d,
93 56,
94 56,
95 -127,
96 127,
97 15,
98 false,
99 false,
100 false,
101 false,
102 false,
103 false,
104 false,
105 false
108 static void
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);
116 static void
117 decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
118 REAL_VALUE_TYPE *r, const long *buf)
120 long tbuf;
121 tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
122 (*vax_f_format.decode) (fmt, r, &tbuf);
125 static void
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);
134 static void
135 decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
136 REAL_VALUE_TYPE *r, const long *buf)
138 long tbuf[2];
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 void pdp11_option_init_struct (struct gcc_options *);
150 static rtx find_addr_reg (rtx);
151 static const char *singlemove_string (rtx *);
152 static bool pdp11_assemble_integer (rtx, unsigned int, int);
153 static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT);
154 static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT);
155 static bool pdp11_rtx_costs (rtx, int, int, int *, bool);
156 static bool pdp11_return_in_memory (const_tree, const_tree);
157 static rtx pdp11_function_value (const_tree, const_tree, bool);
158 static rtx pdp11_libcall_value (enum machine_mode, const_rtx);
159 static bool pdp11_function_value_regno_p (const unsigned int);
160 static void pdp11_trampoline_init (rtx, tree, rtx);
161 static rtx pdp11_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
162 const_tree, bool);
163 static void pdp11_function_arg_advance (CUMULATIVE_ARGS *,
164 enum machine_mode, const_tree, bool);
166 /* Initialize the GCC target structure. */
167 #undef TARGET_ASM_BYTE_OP
168 #define TARGET_ASM_BYTE_OP NULL
169 #undef TARGET_ASM_ALIGNED_HI_OP
170 #define TARGET_ASM_ALIGNED_HI_OP NULL
171 #undef TARGET_ASM_ALIGNED_SI_OP
172 #define TARGET_ASM_ALIGNED_SI_OP NULL
173 #undef TARGET_ASM_INTEGER
174 #define TARGET_ASM_INTEGER pdp11_assemble_integer
176 #undef TARGET_ASM_FUNCTION_PROLOGUE
177 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
178 #undef TARGET_ASM_FUNCTION_EPILOGUE
179 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
181 #undef TARGET_ASM_OPEN_PAREN
182 #define TARGET_ASM_OPEN_PAREN "["
183 #undef TARGET_ASM_CLOSE_PAREN
184 #define TARGET_ASM_CLOSE_PAREN "]"
186 #undef TARGET_DEFAULT_TARGET_FLAGS
187 #define TARGET_DEFAULT_TARGET_FLAGS \
188 (MASK_FPU | MASK_45 | MASK_ABSHI_BUILTIN | TARGET_UNIX_ASM_DEFAULT)
189 #undef TARGET_HANDLE_OPTION
190 #define TARGET_HANDLE_OPTION pdp11_handle_option
191 #undef TARGET_OPTION_OPTIMIZATION
192 #define TARGET_OPTION_OPTIMIZATION pdp11_option_optimization
193 #undef TARGET_OPTION_INIT_STRUCT
194 #define TARGET_OPTION_INIT_STRUCT pdp11_option_init_struct
196 #undef TARGET_RTX_COSTS
197 #define TARGET_RTX_COSTS pdp11_rtx_costs
199 #undef TARGET_FUNCTION_ARG
200 #define TARGET_FUNCTION_ARG pdp11_function_arg
201 #undef TARGET_FUNCTION_ARG_ADVANCE
202 #define TARGET_FUNCTION_ARG_ADVANCE pdp11_function_arg_advance
204 #undef TARGET_RETURN_IN_MEMORY
205 #define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
207 #undef TARGET_FUNCTION_VALUE
208 #define TARGET_FUNCTION_VALUE pdp11_function_value
209 #undef TARGET_LIBCALL_VALUE
210 #define TARGET_LIBCALL_VALUE pdp11_libcall_value
211 #undef TARGET_FUNCTION_VALUE_REGNO_P
212 #define TARGET_FUNCTION_VALUE_REGNO_P pdp11_function_value_regno_p
214 #undef TARGET_TRAMPOLINE_INIT
215 #define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
217 struct gcc_target targetm = TARGET_INITIALIZER;
219 /* Implement TARGET_HANDLE_OPTION. */
221 static bool
222 pdp11_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED,
223 int value ATTRIBUTE_UNUSED)
225 switch (code)
227 case OPT_m10:
228 target_flags &= ~(MASK_40 | MASK_45);
229 return true;
231 default:
232 return true;
236 /* Implement TARGET_OPTION_OPTIMIZATION. */
238 static void
239 pdp11_option_optimization (int level, int size ATTRIBUTE_UNUSED)
241 if (level >= 3)
243 flag_omit_frame_pointer = 1;
244 /* flag_unroll_loops = 1; */
248 /* Implement TARGET_OPTION_INIT_STRUCT. */
250 static void
251 pdp11_option_init_struct (struct gcc_options *opts)
253 opts->x_flag_finite_math_only = 0;
254 opts->x_flag_trapping_math = 0;
255 opts->x_flag_signaling_nans = 0;
258 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
261 arith_operand (rtx op, enum machine_mode mode)
263 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
267 const_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
269 return (GET_CODE (op) == CONST_INT);
272 int
273 immediate15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
275 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
279 expand_shift_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
281 return (GET_CODE (op) == CONST_INT
282 && abs (INTVAL(op)) > 1
283 && abs (INTVAL(op)) <= 4);
287 stream is a stdio stream to output the code to.
288 size is an int: how many units of temporary storage to allocate.
289 Refer to the array `regs_ever_live' to determine which registers
290 to save; `regs_ever_live[I]' is nonzero if register number I
291 is ever used in the function. This macro is responsible for
292 knowing which registers should not be saved even if used.
295 static void
296 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
298 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
299 int regno;
300 int via_ac = -1;
302 fprintf (stream,
303 "\n\t; /* function prologue %s*/\n",
304 current_function_name ());
306 /* if we are outputting code for main,
307 the switch FPU to right mode if TARGET_FPU */
308 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
310 fprintf(stream,
311 "\t;/* switch cpu to double float, single integer */\n");
312 fprintf(stream, "\tsetd\n");
313 fprintf(stream, "\tseti\n\n");
316 if (frame_pointer_needed)
318 fprintf(stream, "\tmov r5, -(sp)\n");
319 fprintf(stream, "\tmov sp, r5\n");
321 else
323 /* DON'T SAVE FP */
326 /* make frame */
327 if (fsize)
328 asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
330 /* save CPU registers */
331 for (regno = 0; regno < 8; regno++)
332 if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
333 if (! ((regno == FRAME_POINTER_REGNUM)
334 && frame_pointer_needed))
335 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
336 /* fpu regs saving */
338 /* via_ac specifies the ac to use for saving ac4, ac5 */
339 via_ac = -1;
341 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
343 /* ac0 - ac3 */
344 if (LOAD_FPU_REG_P(regno)
345 && df_regs_ever_live_p (regno)
346 && ! call_used_regs[regno])
348 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
349 via_ac = regno;
352 /* maybe make ac4, ac5 call used regs?? */
353 /* ac4 - ac5 */
354 if (NO_LOAD_FPU_REG_P(regno)
355 && df_regs_ever_live_p (regno)
356 && ! call_used_regs[regno])
358 gcc_assert (via_ac != -1);
359 fprintf (stream, "\tldd %s, %s\n",
360 reg_names[regno], reg_names[via_ac]);
361 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
365 fprintf (stream, "\t;/* end of prologue */\n\n");
369 The function epilogue should not depend on the current stack pointer!
370 It should use the frame pointer only. This is mandatory because
371 of alloca; we also take advantage of it to omit stack adjustments
372 before returning. */
374 /* maybe we can make leaf functions faster by switching to the
375 second register file - this way we don't have to save regs!
376 leaf functions are ~ 50% of all functions (dynamically!)
378 set/clear bit 11 (dec. 2048) of status word for switching register files -
379 but how can we do this? the pdp11/45 manual says bit may only
380 be set (p.24), but not cleared!
382 switching to kernel is probably more expensive, so we'll leave it
383 like this and not use the second set of registers...
385 maybe as option if you want to generate code for kernel mode? */
387 static void
388 pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
390 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
391 int i, j, k;
393 int via_ac;
395 fprintf (stream, "\n\t; /*function epilogue */\n");
397 if (frame_pointer_needed)
399 /* hope this is safe - m68k does it also .... */
400 df_set_regs_ever_live (FRAME_POINTER_REGNUM, false);
402 for (i =7, j = 0 ; i >= 0 ; i--)
403 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
404 j++;
406 /* remember # of pushed bytes for CPU regs */
407 k = 2*j;
409 /* change fp -> r5 due to the compile error on libgcc2.c */
410 for (i =7 ; i >= 0 ; i--)
411 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
412 fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
413 (-fsize-2*j--)&0xffff, reg_names[i]);
415 /* get ACs */
416 via_ac = FIRST_PSEUDO_REGISTER -1;
418 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
419 if (df_regs_ever_live_p (i) && ! call_used_regs[i])
421 via_ac = i;
422 k += 8;
425 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
427 if (LOAD_FPU_REG_P(i)
428 && df_regs_ever_live_p (i)
429 && ! call_used_regs[i])
431 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
432 (-fsize-k)&0xffff, reg_names[i]);
433 k -= 8;
436 if (NO_LOAD_FPU_REG_P(i)
437 && df_regs_ever_live_p (i)
438 && ! call_used_regs[i])
440 gcc_assert (LOAD_FPU_REG_P(via_ac));
442 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
443 (-fsize-k)&0xffff, reg_names[via_ac]);
444 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
445 k -= 8;
449 fprintf(stream, "\tmov r5, sp\n");
450 fprintf (stream, "\tmov (sp)+, r5\n");
452 else
454 via_ac = FIRST_PSEUDO_REGISTER -1;
456 /* get ACs */
457 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
458 if (df_regs_ever_live_p (i) && call_used_regs[i])
459 via_ac = i;
461 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
463 if (LOAD_FPU_REG_P(i)
464 && df_regs_ever_live_p (i)
465 && ! call_used_regs[i])
466 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
468 if (NO_LOAD_FPU_REG_P(i)
469 && df_regs_ever_live_p (i)
470 && ! call_used_regs[i])
472 gcc_assert (LOAD_FPU_REG_P(via_ac));
474 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
475 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
479 for (i=7; i >= 0; i--)
480 if (df_regs_ever_live_p (i) && !call_used_regs[i])
481 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
483 if (fsize)
484 fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n",
485 (fsize)&0xffff);
488 fprintf (stream, "\trts pc\n");
489 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
492 /* Return the best assembler insn template
493 for moving operands[1] into operands[0] as a fullword. */
494 static const char *
495 singlemove_string (rtx *operands)
497 if (operands[1] != const0_rtx)
498 return "mov %1,%0";
500 return "clr %0";
504 /* Output assembler code to perform a doubleword move insn
505 with operands OPERANDS. */
507 const char *
508 output_move_double (rtx *operands)
510 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
511 rtx latehalf[2];
512 rtx addreg0 = 0, addreg1 = 0;
514 /* First classify both operands. */
516 if (REG_P (operands[0]))
517 optype0 = REGOP;
518 else if (offsettable_memref_p (operands[0]))
519 optype0 = OFFSOP;
520 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
521 optype0 = POPOP;
522 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
523 optype0 = PUSHOP;
524 else if (GET_CODE (operands[0]) == MEM)
525 optype0 = MEMOP;
526 else
527 optype0 = RNDOP;
529 if (REG_P (operands[1]))
530 optype1 = REGOP;
531 else if (CONSTANT_P (operands[1])
532 #if 0
533 || GET_CODE (operands[1]) == CONST_DOUBLE
534 #endif
536 optype1 = CNSTOP;
537 else if (offsettable_memref_p (operands[1]))
538 optype1 = OFFSOP;
539 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
540 optype1 = POPOP;
541 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
542 optype1 = PUSHOP;
543 else if (GET_CODE (operands[1]) == MEM)
544 optype1 = MEMOP;
545 else
546 optype1 = RNDOP;
548 /* Check for the cases that the operand constraints are not
549 supposed to allow to happen. Abort if we get one,
550 because generating code for these cases is painful. */
552 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
554 /* If one operand is decrementing and one is incrementing
555 decrement the former register explicitly
556 and change that operand into ordinary indexing. */
558 if (optype0 == PUSHOP && optype1 == POPOP)
560 operands[0] = XEXP (XEXP (operands[0], 0), 0);
561 output_asm_insn ("sub $4,%0", operands);
562 operands[0] = gen_rtx_MEM (SImode, operands[0]);
563 optype0 = OFFSOP;
565 if (optype0 == POPOP && optype1 == PUSHOP)
567 operands[1] = XEXP (XEXP (operands[1], 0), 0);
568 output_asm_insn ("sub $4,%1", operands);
569 operands[1] = gen_rtx_MEM (SImode, operands[1]);
570 optype1 = OFFSOP;
573 /* If an operand is an unoffsettable memory ref, find a register
574 we can increment temporarily to make it refer to the second word. */
576 if (optype0 == MEMOP)
577 addreg0 = find_addr_reg (XEXP (operands[0], 0));
579 if (optype1 == MEMOP)
580 addreg1 = find_addr_reg (XEXP (operands[1], 0));
582 /* Ok, we can do one word at a time.
583 Normally we do the low-numbered word first,
584 but if either operand is autodecrementing then we
585 do the high-numbered word first.
587 In either case, set up in LATEHALF the operands to use
588 for the high-numbered word and in some cases alter the
589 operands in OPERANDS to be suitable for the low-numbered word. */
591 if (optype0 == REGOP)
592 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
593 else if (optype0 == OFFSOP)
594 latehalf[0] = adjust_address (operands[0], HImode, 2);
595 else
596 latehalf[0] = operands[0];
598 if (optype1 == REGOP)
599 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
600 else if (optype1 == OFFSOP)
601 latehalf[1] = adjust_address (operands[1], HImode, 2);
602 else if (optype1 == CNSTOP)
604 if (CONSTANT_P (operands[1]))
606 /* now the mess begins, high word is in lower word???
608 that's what ashc makes me think, but I don't remember :-( */
609 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
610 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
612 else
613 /* immediate 32-bit values not allowed */
614 gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE);
616 else
617 latehalf[1] = operands[1];
619 /* If insn is effectively movd N(sp),-(sp) then we will do the
620 high word first. We should use the adjusted operand 1 (which is N+4(sp))
621 for the low word as well, to compensate for the first decrement of sp. */
622 if (optype0 == PUSHOP
623 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
624 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
625 operands[1] = latehalf[1];
627 /* If one or both operands autodecrementing,
628 do the two words, high-numbered first. */
630 /* Likewise, the first move would clobber the source of the second one,
631 do them in the other order. This happens only for registers;
632 such overlap can't happen in memory unless the user explicitly
633 sets it up, and that is an undefined circumstance. */
635 if (optype0 == PUSHOP || optype1 == PUSHOP
636 || (optype0 == REGOP && optype1 == REGOP
637 && REGNO (operands[0]) == REGNO (latehalf[1])))
639 /* Make any unoffsettable addresses point at high-numbered word. */
640 if (addreg0)
641 output_asm_insn ("add $2,%0", &addreg0);
642 if (addreg1)
643 output_asm_insn ("add $2,%0", &addreg1);
645 /* Do that word. */
646 output_asm_insn (singlemove_string (latehalf), latehalf);
648 /* Undo the adds we just did. */
649 if (addreg0)
650 output_asm_insn ("sub $2,%0", &addreg0);
651 if (addreg1)
652 output_asm_insn ("sub $2,%0", &addreg1);
654 /* Do low-numbered word. */
655 return singlemove_string (operands);
658 /* Normal case: do the two words, low-numbered first. */
660 output_asm_insn (singlemove_string (operands), operands);
662 /* Make any unoffsettable addresses point at high-numbered word. */
663 if (addreg0)
664 output_asm_insn ("add $2,%0", &addreg0);
665 if (addreg1)
666 output_asm_insn ("add $2,%0", &addreg1);
668 /* Do that word. */
669 output_asm_insn (singlemove_string (latehalf), latehalf);
671 /* Undo the adds we just did. */
672 if (addreg0)
673 output_asm_insn ("sub $2,%0", &addreg0);
674 if (addreg1)
675 output_asm_insn ("sub $2,%0", &addreg1);
677 return "";
679 /* Output assembler code to perform a quadword move insn
680 with operands OPERANDS. */
682 const char *
683 output_move_quad (rtx *operands)
685 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
686 rtx latehalf[2];
687 rtx addreg0 = 0, addreg1 = 0;
689 output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);
691 if (REG_P (operands[0]))
692 optype0 = REGOP;
693 else if (offsettable_memref_p (operands[0]))
694 optype0 = OFFSOP;
695 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
696 optype0 = POPOP;
697 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
698 optype0 = PUSHOP;
699 else if (GET_CODE (operands[0]) == MEM)
700 optype0 = MEMOP;
701 else
702 optype0 = RNDOP;
704 if (REG_P (operands[1]))
705 optype1 = REGOP;
706 else if (CONSTANT_P (operands[1])
707 || GET_CODE (operands[1]) == CONST_DOUBLE)
708 optype1 = CNSTOP;
709 else if (offsettable_memref_p (operands[1]))
710 optype1 = OFFSOP;
711 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
712 optype1 = POPOP;
713 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
714 optype1 = PUSHOP;
715 else if (GET_CODE (operands[1]) == MEM)
716 optype1 = MEMOP;
717 else
718 optype1 = RNDOP;
720 /* Check for the cases that the operand constraints are not
721 supposed to allow to happen. Abort if we get one,
722 because generating code for these cases is painful. */
724 gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
726 /* check if we move a CPU reg to an FPU reg, or vice versa! */
727 if (optype0 == REGOP && optype1 == REGOP)
728 /* bogus - 64 bit cannot reside in CPU! */
729 gcc_assert (!CPU_REG_P(REGNO(operands[0]))
730 && !CPU_REG_P (REGNO(operands[1])));
732 if (optype0 == REGOP || optype1 == REGOP)
734 /* check for use of clrd????
735 if you ever allow ac4 and ac5 (now we require secondary load)
736 you must check whether
737 you want to load into them or store from them -
738 then dump ac0 into $help$ movce ac4/5 to ac0, do the
739 store from ac0, and restore ac0 - if you can find
740 an unused ac[0-3], use that and you save a store and a load!*/
742 if (FPU_REG_P(REGNO(operands[0])))
744 if (GET_CODE(operands[1]) == CONST_DOUBLE)
746 REAL_VALUE_TYPE r;
747 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
749 if (REAL_VALUES_EQUAL (r, dconst0))
750 return "{clrd|clrf} %0";
753 return "{ldd|movf} %1, %0";
756 if (FPU_REG_P(REGNO(operands[1])))
757 return "{std|movf} %1, %0";
760 /* If one operand is decrementing and one is incrementing
761 decrement the former register explicitly
762 and change that operand into ordinary indexing. */
764 if (optype0 == PUSHOP && optype1 == POPOP)
766 operands[0] = XEXP (XEXP (operands[0], 0), 0);
767 output_asm_insn ("sub $8,%0", operands);
768 operands[0] = gen_rtx_MEM (DImode, operands[0]);
769 optype0 = OFFSOP;
771 if (optype0 == POPOP && optype1 == PUSHOP)
773 operands[1] = XEXP (XEXP (operands[1], 0), 0);
774 output_asm_insn ("sub $8,%1", operands);
775 operands[1] = gen_rtx_MEM (SImode, operands[1]);
776 optype1 = OFFSOP;
779 /* If an operand is an unoffsettable memory ref, find a register
780 we can increment temporarily to make it refer to the second word. */
782 if (optype0 == MEMOP)
783 addreg0 = find_addr_reg (XEXP (operands[0], 0));
785 if (optype1 == MEMOP)
786 addreg1 = find_addr_reg (XEXP (operands[1], 0));
788 /* Ok, we can do one word at a time.
789 Normally we do the low-numbered word first,
790 but if either operand is autodecrementing then we
791 do the high-numbered word first.
793 In either case, set up in LATEHALF the operands to use
794 for the high-numbered word and in some cases alter the
795 operands in OPERANDS to be suitable for the low-numbered word. */
797 if (optype0 == REGOP)
798 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
799 else if (optype0 == OFFSOP)
800 latehalf[0] = adjust_address (operands[0], SImode, 4);
801 else
802 latehalf[0] = operands[0];
804 if (optype1 == REGOP)
805 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
806 else if (optype1 == OFFSOP)
807 latehalf[1] = adjust_address (operands[1], SImode, 4);
808 else if (optype1 == CNSTOP)
810 if (GET_CODE (operands[1]) == CONST_DOUBLE)
812 REAL_VALUE_TYPE r;
813 long dval[2];
814 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
815 REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
816 latehalf[1] = GEN_INT (dval[1]);
817 operands[1] = GEN_INT (dval[0]);
819 else if (GET_CODE(operands[1]) == CONST_INT)
821 latehalf[1] = const0_rtx;
823 else
824 gcc_unreachable ();
826 else
827 latehalf[1] = operands[1];
829 /* If insn is effectively movd N(sp),-(sp) then we will do the
830 high word first. We should use the adjusted operand 1 (which is N+4(sp))
831 for the low word as well, to compensate for the first decrement of sp. */
832 if (optype0 == PUSHOP
833 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
834 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
835 operands[1] = latehalf[1];
837 /* If one or both operands autodecrementing,
838 do the two words, high-numbered first. */
840 /* Likewise, the first move would clobber the source of the second one,
841 do them in the other order. This happens only for registers;
842 such overlap can't happen in memory unless the user explicitly
843 sets it up, and that is an undefined circumstance. */
845 if (optype0 == PUSHOP || optype1 == PUSHOP
846 || (optype0 == REGOP && optype1 == REGOP
847 && REGNO (operands[0]) == REGNO (latehalf[1])))
849 /* Make any unoffsettable addresses point at high-numbered word. */
850 if (addreg0)
851 output_asm_insn ("add $4,%0", &addreg0);
852 if (addreg1)
853 output_asm_insn ("add $4,%0", &addreg1);
855 /* Do that word. */
856 output_asm_insn(output_move_double(latehalf), latehalf);
858 /* Undo the adds we just did. */
859 if (addreg0)
860 output_asm_insn ("sub $4,%0", &addreg0);
861 if (addreg1)
862 output_asm_insn ("sub $4,%0", &addreg1);
864 /* Do low-numbered word. */
865 return output_move_double (operands);
868 /* Normal case: do the two words, low-numbered first. */
870 output_asm_insn (output_move_double (operands), operands);
872 /* Make any unoffsettable addresses point at high-numbered word. */
873 if (addreg0)
874 output_asm_insn ("add $4,%0", &addreg0);
875 if (addreg1)
876 output_asm_insn ("add $4,%0", &addreg1);
878 /* Do that word. */
879 output_asm_insn (output_move_double (latehalf), latehalf);
881 /* Undo the adds we just did. */
882 if (addreg0)
883 output_asm_insn ("sub $4,%0", &addreg0);
884 if (addreg1)
885 output_asm_insn ("sub $4,%0", &addreg1);
887 return "";
891 /* Return a REG that occurs in ADDR with coefficient 1.
892 ADDR can be effectively incremented by incrementing REG. */
894 static rtx
895 find_addr_reg (rtx addr)
897 while (GET_CODE (addr) == PLUS)
899 if (GET_CODE (XEXP (addr, 0)) == REG)
900 addr = XEXP (addr, 0);
901 if (GET_CODE (XEXP (addr, 1)) == REG)
902 addr = XEXP (addr, 1);
903 if (CONSTANT_P (XEXP (addr, 0)))
904 addr = XEXP (addr, 1);
905 if (CONSTANT_P (XEXP (addr, 1)))
906 addr = XEXP (addr, 0);
908 if (GET_CODE (addr) == REG)
909 return addr;
910 return 0;
913 /* Output an ascii string. */
914 void
915 output_ascii (FILE *file, const char *p, int size)
917 int i;
919 /* This used to output .byte "string", which doesn't work with the UNIX
920 assembler and I think not with DEC ones either. */
921 fprintf (file, "\t.byte ");
923 for (i = 0; i < size; i++)
925 register int c = p[i];
926 if (c < 0)
927 c += 256;
928 fprintf (file, "%#o", c);
929 if (i < size - 1)
930 putc (',', file);
932 putc ('\n', file);
936 /* --- stole from out-vax, needs changes */
938 void
939 print_operand_address (FILE *file, register rtx addr)
941 register rtx reg1, reg2, breg, ireg;
942 rtx offset;
944 retry:
946 switch (GET_CODE (addr))
948 case MEM:
949 if (TARGET_UNIX_ASM)
950 fprintf (file, "*");
951 else
952 fprintf (file, "@");
953 addr = XEXP (addr, 0);
954 goto retry;
956 case REG:
957 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
958 break;
960 case PRE_MODIFY:
961 case PRE_DEC:
962 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
963 break;
965 case POST_MODIFY:
966 case POST_INC:
967 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
968 break;
970 case PLUS:
971 reg1 = 0; reg2 = 0;
972 ireg = 0; breg = 0;
973 offset = 0;
974 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
975 || GET_CODE (XEXP (addr, 0)) == MEM)
977 offset = XEXP (addr, 0);
978 addr = XEXP (addr, 1);
980 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
981 || GET_CODE (XEXP (addr, 1)) == MEM)
983 offset = XEXP (addr, 1);
984 addr = XEXP (addr, 0);
986 if (GET_CODE (addr) != PLUS)
988 else if (GET_CODE (XEXP (addr, 0)) == MULT)
990 reg1 = XEXP (addr, 0);
991 addr = XEXP (addr, 1);
993 else if (GET_CODE (XEXP (addr, 1)) == MULT)
995 reg1 = XEXP (addr, 1);
996 addr = XEXP (addr, 0);
998 else if (GET_CODE (XEXP (addr, 0)) == REG)
1000 reg1 = XEXP (addr, 0);
1001 addr = XEXP (addr, 1);
1003 else if (GET_CODE (XEXP (addr, 1)) == REG)
1005 reg1 = XEXP (addr, 1);
1006 addr = XEXP (addr, 0);
1008 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
1010 if (reg1 == 0)
1011 reg1 = addr;
1012 else
1013 reg2 = addr;
1014 addr = 0;
1016 if (offset != 0)
1018 gcc_assert (addr == 0);
1019 addr = offset;
1021 if (reg1 != 0 && GET_CODE (reg1) == MULT)
1023 breg = reg2;
1024 ireg = reg1;
1026 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
1028 breg = reg1;
1029 ireg = reg2;
1031 else if (reg2 != 0 || GET_CODE (addr) == MEM)
1033 breg = reg2;
1034 ireg = reg1;
1036 else
1038 breg = reg1;
1039 ireg = reg2;
1041 if (addr != 0)
1042 output_address (addr);
1043 if (breg != 0)
1045 gcc_assert (GET_CODE (breg) == REG);
1046 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
1048 if (ireg != 0)
1050 if (GET_CODE (ireg) == MULT)
1051 ireg = XEXP (ireg, 0);
1052 gcc_assert (GET_CODE (ireg) == REG);
1053 gcc_unreachable(); /* ??? */
1054 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
1056 break;
1058 default:
1059 output_addr_const_pdp11 (file, addr);
1063 /* Target hook to assemble integer objects. We need to use the
1064 pdp-specific version of output_addr_const. */
1066 static bool
1067 pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
1069 if (aligned_p)
1070 switch (size)
1072 case 1:
1073 fprintf (asm_out_file, "\t.byte\t");
1074 output_addr_const_pdp11 (asm_out_file, x);
1075 fprintf (asm_out_file, " /* char */\n");
1076 return true;
1078 case 2:
1079 fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
1080 output_addr_const_pdp11 (asm_out_file, x);
1081 fprintf (asm_out_file, " /* short */\n");
1082 return true;
1084 return default_assemble_integer (x, size, aligned_p);
1088 /* register move costs, indexed by regs */
1090 static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
1092 /* NO MUL GEN LFPU NLFPU FPU ALL */
1094 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
1095 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
1096 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
1097 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
1098 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
1099 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
1100 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
1104 /* -- note that some moves are tremendously expensive,
1105 because they require lots of tricks! do we have to
1106 charge the costs incurred by secondary reload class
1107 -- as we do here with 22 -- or not ? */
1109 int
1110 pdp11_register_move_cost (enum reg_class c1, enum reg_class c2)
1112 return move_costs[(int)c1][(int)c2];
1115 static bool
1116 pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
1117 bool speed ATTRIBUTE_UNUSED)
1119 switch (code)
1121 case CONST_INT:
1122 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
1124 *total = 0;
1125 return true;
1127 /* FALLTHRU */
1129 case CONST:
1130 case LABEL_REF:
1131 case SYMBOL_REF:
1132 /* Twice as expensive as REG. */
1133 *total = 2;
1134 return true;
1136 case CONST_DOUBLE:
1137 /* Twice (or 4 times) as expensive as 16 bit. */
1138 *total = 4;
1139 return true;
1141 case MULT:
1142 /* ??? There is something wrong in MULT because MULT is not
1143 as cheap as total = 2 even if we can shift! */
1144 /* If optimizing for size make mult etc cheap, but not 1, so when
1145 in doubt the faster insn is chosen. */
1146 if (optimize_size)
1147 *total = COSTS_N_INSNS (2);
1148 else
1149 *total = COSTS_N_INSNS (11);
1150 return false;
1152 case DIV:
1153 if (optimize_size)
1154 *total = COSTS_N_INSNS (2);
1155 else
1156 *total = COSTS_N_INSNS (25);
1157 return false;
1159 case MOD:
1160 if (optimize_size)
1161 *total = COSTS_N_INSNS (2);
1162 else
1163 *total = COSTS_N_INSNS (26);
1164 return false;
1166 case ABS:
1167 /* Equivalent to length, so same for optimize_size. */
1168 *total = COSTS_N_INSNS (3);
1169 return false;
1171 case ZERO_EXTEND:
1172 /* Only used for qi->hi. */
1173 *total = COSTS_N_INSNS (1);
1174 return false;
1176 case SIGN_EXTEND:
1177 if (GET_MODE (x) == HImode)
1178 *total = COSTS_N_INSNS (1);
1179 else if (GET_MODE (x) == SImode)
1180 *total = COSTS_N_INSNS (6);
1181 else
1182 *total = COSTS_N_INSNS (2);
1183 return false;
1185 case ASHIFT:
1186 case LSHIFTRT:
1187 case ASHIFTRT:
1188 if (optimize_size)
1189 *total = COSTS_N_INSNS (1);
1190 else if (GET_MODE (x) == QImode)
1192 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
1193 *total = COSTS_N_INSNS (8); /* worst case */
1194 else
1195 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
1197 else if (GET_MODE (x) == HImode)
1199 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1201 if (abs (INTVAL (XEXP (x, 1))) == 1)
1202 *total = COSTS_N_INSNS (1);
1203 else
1204 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1206 else
1207 *total = COSTS_N_INSNS (10); /* worst case */
1209 else if (GET_MODE (x) == SImode)
1211 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1212 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1213 else /* worst case */
1214 *total = COSTS_N_INSNS (18);
1216 return false;
1218 default:
1219 return false;
1223 const char *
1224 output_jump (enum rtx_code code, int inv, int length)
1226 static int x = 0;
1228 static char buf[1000];
1229 const char *pos, *neg;
1231 switch (code)
1233 case EQ: pos = "beq", neg = "bne"; break;
1234 case NE: pos = "bne", neg = "beq"; break;
1235 case GT: pos = "bgt", neg = "ble"; break;
1236 case GTU: pos = "bhi", neg = "blos"; break;
1237 case LT: pos = "blt", neg = "bge"; break;
1238 case LTU: pos = "blo", neg = "bhis"; break;
1239 case GE: pos = "bge", neg = "blt"; break;
1240 case GEU: pos = "bhis", neg = "blo"; break;
1241 case LE: pos = "ble", neg = "bgt"; break;
1242 case LEU: pos = "blos", neg = "bhi"; break;
1243 default: gcc_unreachable ();
1246 #if 0
1247 /* currently we don't need this, because the tstdf and cmpdf
1248 copy the condition code immediately, and other float operations are not
1249 yet recognized as changing the FCC - if so, then the length-cost of all
1250 jump insns increases by one, because we have to potentially copy the
1251 FCC! */
1252 if (cc_status.flags & CC_IN_FPU)
1253 output_asm_insn("cfcc", NULL);
1254 #endif
1256 switch (length)
1258 case 1:
1260 sprintf(buf, "%s %%l1", inv ? neg : pos);
1262 return buf;
1264 case 3:
1266 sprintf(buf, "%s JMP_%d\n\tjmp %%l1\nJMP_%d:", inv ? pos : neg, x, x);
1268 x++;
1270 return buf;
1272 default:
1274 gcc_unreachable ();
1279 void
1280 notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
1282 if (GET_CODE (SET_DEST (exp)) == CC0)
1284 cc_status.flags = 0;
1285 cc_status.value1 = SET_DEST (exp);
1286 cc_status.value2 = SET_SRC (exp);
1289 if (GET_MODE(SET_SRC(exp)) == DFmode)
1290 cc_status.flags |= CC_IN_FPU;
1293 else if ((GET_CODE (SET_DEST (exp)) == REG
1294 || GET_CODE (SET_DEST (exp)) == MEM)
1295 && GET_CODE (SET_SRC (exp)) != PC
1296 && (GET_MODE (SET_DEST(exp)) == HImode
1297 || GET_MODE (SET_DEST(exp)) == QImode)
1298 && (GET_CODE (SET_SRC(exp)) == PLUS
1299 || GET_CODE (SET_SRC(exp)) == MINUS
1300 || GET_CODE (SET_SRC(exp)) == AND
1301 || GET_CODE (SET_SRC(exp)) == IOR
1302 || GET_CODE (SET_SRC(exp)) == XOR
1303 || GET_CODE (SET_SRC(exp)) == NOT
1304 || GET_CODE (SET_SRC(exp)) == NEG
1305 || GET_CODE (SET_SRC(exp)) == REG
1306 || GET_CODE (SET_SRC(exp)) == MEM))
1308 cc_status.flags = 0;
1309 cc_status.value1 = SET_SRC (exp);
1310 cc_status.value2 = SET_DEST (exp);
1312 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1313 && cc_status.value2
1314 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1315 cc_status.value2 = 0;
1316 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1317 && cc_status.value2
1318 && GET_CODE (cc_status.value2) == MEM)
1319 cc_status.value2 = 0;
1321 else if (GET_CODE (SET_SRC (exp)) == CALL)
1323 CC_STATUS_INIT;
1325 else if (GET_CODE (SET_DEST (exp)) == REG)
1326 /* what's this ? */
1328 if ((cc_status.value1
1329 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1330 cc_status.value1 = 0;
1331 if ((cc_status.value2
1332 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1333 cc_status.value2 = 0;
1335 else if (SET_DEST(exp) == pc_rtx)
1337 /* jump */
1339 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1341 /* the last else is a bit paranoiac, but since nearly all instructions
1342 play with condition codes, it's reasonable! */
1344 CC_STATUS_INIT; /* paranoia*/
1350 simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1352 rtx addr;
1354 /* Eliminate non-memory operations */
1355 if (GET_CODE (op) != MEM)
1356 return FALSE;
1358 #if 0
1359 /* dword operations really put out 2 instructions, so eliminate them. */
1360 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1361 return FALSE;
1362 #endif
1364 /* Decode the address now. */
1366 indirection:
1368 addr = XEXP (op, 0);
1370 switch (GET_CODE (addr))
1372 case REG:
1373 /* (R0) - no extra cost */
1374 return 1;
1376 case PRE_DEC:
1377 case POST_INC:
1378 /* -(R0), (R0)+ - cheap! */
1379 return 0;
1381 case MEM:
1382 /* cheap - is encoded in addressing mode info!
1384 -- except for @(R0), which has to be @0(R0) !!! */
1386 if (GET_CODE (XEXP (addr, 0)) == REG)
1387 return 0;
1389 op=addr;
1390 goto indirection;
1392 case CONST_INT:
1393 case LABEL_REF:
1394 case CONST:
1395 case SYMBOL_REF:
1396 /* @#address - extra cost */
1397 return 0;
1399 case PLUS:
1400 /* X(R0) - extra cost */
1401 return 0;
1403 default:
1404 break;
1407 return FALSE;
1412 * output a block move:
1414 * operands[0] ... to
1415 * operands[1] ... from
1416 * operands[2] ... length
1417 * operands[3] ... alignment
1418 * operands[4] ... scratch register
1422 const char *
1423 output_block_move(rtx *operands)
1425 static int count = 0;
1426 char buf[200];
1428 if (GET_CODE(operands[2]) == CONST_INT
1429 && ! optimize_size)
1431 if (INTVAL(operands[2]) < 16
1432 && INTVAL(operands[3]) == 1)
1434 register int i;
1436 for (i = 1; i <= INTVAL(operands[2]); i++)
1437 output_asm_insn("movb (%1)+, (%0)+", operands);
1439 return "";
1441 else if (INTVAL(operands[2]) < 32)
1443 register int i;
1445 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1446 output_asm_insn("mov (%1)+, (%0)+", operands);
1448 /* may I assume that moved quantity is
1449 multiple of alignment ???
1451 I HOPE SO !
1454 return "";
1458 /* can do other clever things, maybe... */
1461 if (CONSTANT_P(operands[2]) )
1463 /* just move count to scratch */
1464 output_asm_insn("mov %2, %4", operands);
1466 else
1468 /* just clobber the register */
1469 operands[4] = operands[2];
1473 /* switch over alignment */
1474 switch (INTVAL(operands[3]))
1476 case 1:
1480 movb (%1)+, (%0)+
1482 if (TARGET_45)
1483 sob %4,x
1484 else
1485 dec %4
1486 bgt x
1490 sprintf(buf, "\nmovestrhi%d:", count);
1491 output_asm_insn(buf, NULL);
1493 output_asm_insn("movb (%1)+, (%0)+", operands);
1495 if (TARGET_45)
1497 sprintf(buf, "sob %%4, movestrhi%d", count);
1498 output_asm_insn(buf, operands);
1500 else
1502 output_asm_insn("dec %4", operands);
1504 sprintf(buf, "bgt movestrhi%d", count);
1505 output_asm_insn(buf, NULL);
1508 count ++;
1509 break;
1511 case 2:
1514 asr %4
1518 mov (%1)+, (%0)+
1520 if (TARGET_45)
1521 sob %4, x
1522 else
1523 dec %4
1524 bgt x
1527 generate_compact_code:
1529 output_asm_insn("asr %4", operands);
1531 sprintf(buf, "\nmovestrhi%d:", count);
1532 output_asm_insn(buf, NULL);
1534 output_asm_insn("mov (%1)+, (%0)+", operands);
1536 if (TARGET_45)
1538 sprintf(buf, "sob %%4, movestrhi%d", count);
1539 output_asm_insn(buf, operands);
1541 else
1543 output_asm_insn("dec %4", operands);
1545 sprintf(buf, "bgt movestrhi%d", count);
1546 output_asm_insn(buf, NULL);
1549 count ++;
1550 break;
1552 case 4:
1556 asr %4
1557 asr %4
1561 mov (%1)+, (%0)+
1562 mov (%1)+, (%0)+
1564 if (TARGET_45)
1565 sob %4, x
1566 else
1567 dec %4
1568 bgt x
1571 if (optimize_size)
1572 goto generate_compact_code;
1574 output_asm_insn("asr %4", operands);
1575 output_asm_insn("asr %4", operands);
1577 sprintf(buf, "\nmovestrhi%d:", count);
1578 output_asm_insn(buf, NULL);
1580 output_asm_insn("mov (%1)+, (%0)+", operands);
1581 output_asm_insn("mov (%1)+, (%0)+", operands);
1583 if (TARGET_45)
1585 sprintf(buf, "sob %%4, movestrhi%d", count);
1586 output_asm_insn(buf, operands);
1588 else
1590 output_asm_insn("dec %4", operands);
1592 sprintf(buf, "bgt movestrhi%d", count);
1593 output_asm_insn(buf, NULL);
1596 count ++;
1597 break;
1599 default:
1603 asr %4
1604 asr %4
1605 asr %4
1609 mov (%1)+, (%0)+
1610 mov (%1)+, (%0)+
1611 mov (%1)+, (%0)+
1612 mov (%1)+, (%0)+
1614 if (TARGET_45)
1615 sob %4, x
1616 else
1617 dec %4
1618 bgt x
1622 if (optimize_size)
1623 goto generate_compact_code;
1625 output_asm_insn("asr %4", operands);
1626 output_asm_insn("asr %4", operands);
1627 output_asm_insn("asr %4", operands);
1629 sprintf(buf, "\nmovestrhi%d:", count);
1630 output_asm_insn(buf, NULL);
1632 output_asm_insn("mov (%1)+, (%0)+", operands);
1633 output_asm_insn("mov (%1)+, (%0)+", operands);
1634 output_asm_insn("mov (%1)+, (%0)+", operands);
1635 output_asm_insn("mov (%1)+, (%0)+", operands);
1637 if (TARGET_45)
1639 sprintf(buf, "sob %%4, movestrhi%d", count);
1640 output_asm_insn(buf, operands);
1642 else
1644 output_asm_insn("dec %4", operands);
1646 sprintf(buf, "bgt movestrhi%d", count);
1647 output_asm_insn(buf, NULL);
1650 count ++;
1651 break;
1657 return "";
1660 /* This function checks whether a real value can be encoded as
1661 a literal, i.e., addressing mode 27. In that mode, real values
1662 are one word values, so the remaining 48 bits have to be zero. */
1664 legitimate_const_double_p (rtx address)
1666 REAL_VALUE_TYPE r;
1667 long sval[2];
1668 REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1669 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1670 if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1671 return 1;
1672 return 0;
1675 /* A copy of output_addr_const modified for pdp11 expression syntax.
1676 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1677 use, and for debugging output, which we don't support with this port either.
1678 So this copy should get called whenever needed.
1680 void
1681 output_addr_const_pdp11 (FILE *file, rtx x)
1683 char buf[256];
1685 restart:
1686 switch (GET_CODE (x))
1688 case PC:
1689 gcc_assert (flag_pic);
1690 putc ('.', file);
1691 break;
1693 case SYMBOL_REF:
1694 assemble_name (file, XSTR (x, 0));
1695 break;
1697 case LABEL_REF:
1698 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1699 assemble_name (file, buf);
1700 break;
1702 case CODE_LABEL:
1703 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1704 assemble_name (file, buf);
1705 break;
1707 case CONST_INT:
1708 /* Should we check for constants which are too big? Maybe cutting
1709 them off to 16 bits is OK? */
1710 fprintf (file, "%#ho", (unsigned short) INTVAL (x));
1711 break;
1713 case CONST:
1714 /* This used to output parentheses around the expression,
1715 but that does not work on the 386 (either ATT or BSD assembler). */
1716 output_addr_const_pdp11 (file, XEXP (x, 0));
1717 break;
1719 case CONST_DOUBLE:
1720 if (GET_MODE (x) == VOIDmode)
1722 /* We can use %o if the number is one word and positive. */
1723 gcc_assert (!CONST_DOUBLE_HIGH (x));
1724 fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
1726 else
1727 /* We can't handle floating point constants;
1728 PRINT_OPERAND must handle them. */
1729 output_operand_lossage ("floating constant misused");
1730 break;
1732 case PLUS:
1733 /* Some assemblers need integer constants to appear last (e.g. masm). */
1734 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1736 output_addr_const_pdp11 (file, XEXP (x, 1));
1737 if (INTVAL (XEXP (x, 0)) >= 0)
1738 fprintf (file, "+");
1739 output_addr_const_pdp11 (file, XEXP (x, 0));
1741 else
1743 output_addr_const_pdp11 (file, XEXP (x, 0));
1744 if (INTVAL (XEXP (x, 1)) >= 0)
1745 fprintf (file, "+");
1746 output_addr_const_pdp11 (file, XEXP (x, 1));
1748 break;
1750 case MINUS:
1751 /* Avoid outputting things like x-x or x+5-x,
1752 since some assemblers can't handle that. */
1753 x = simplify_subtraction (x);
1754 if (GET_CODE (x) != MINUS)
1755 goto restart;
1757 output_addr_const_pdp11 (file, XEXP (x, 0));
1758 fprintf (file, "-");
1759 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1760 && INTVAL (XEXP (x, 1)) < 0)
1762 fprintf (file, targetm.asm_out.open_paren);
1763 output_addr_const_pdp11 (file, XEXP (x, 1));
1764 fprintf (file, targetm.asm_out.close_paren);
1766 else
1767 output_addr_const_pdp11 (file, XEXP (x, 1));
1768 break;
1770 case ZERO_EXTEND:
1771 case SIGN_EXTEND:
1772 output_addr_const_pdp11 (file, XEXP (x, 0));
1773 break;
1775 default:
1776 output_operand_lossage ("invalid expression as operand");
1780 /* Worker function for TARGET_RETURN_IN_MEMORY. */
1782 static bool
1783 pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1785 /* Should probably return DImode and DFmode in memory, lest
1786 we fill up all regs!
1788 have to, else we crash - exception: maybe return result in
1789 ac0 if DFmode and FPU present - compatibility problem with
1790 libraries for non-floating point.... */
1791 return (TYPE_MODE (type) == DImode
1792 || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
1795 /* Worker function for TARGET_FUNCTION_VALUE.
1797 On the pdp11 the value is found in R0 (or ac0??? not without FPU!!!! ) */
1799 static rtx
1800 pdp11_function_value (const_tree valtype,
1801 const_tree fntype_or_decl ATTRIBUTE_UNUSED,
1802 bool outgoing ATTRIBUTE_UNUSED)
1804 return gen_rtx_REG (TYPE_MODE (valtype),
1805 BASE_RETURN_VALUE_REG(TYPE_MODE(valtype)));
1808 /* Worker function for TARGET_LIBCALL_VALUE. */
1810 static rtx
1811 pdp11_libcall_value (enum machine_mode mode,
1812 const_rtx fun ATTRIBUTE_UNUSED)
1814 return gen_rtx_REG (mode, BASE_RETURN_VALUE_REG(mode));
1817 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.
1819 On the pdp, the first "output" reg is the only register thus used.
1821 maybe ac0 ? - as option someday! */
1823 static bool
1824 pdp11_function_value_regno_p (const unsigned int regno)
1826 return (regno == 0) || (TARGET_AC0 && (regno == 8));
1829 /* Worker function for TARGET_TRAMPOLINE_INIT.
1831 trampoline - how should i do it in separate i+d ?
1832 have some allocate_trampoline magic???
1834 the following should work for shared I/D:
1836 MV #STATIC, $4 0x940Y 0x0000 <- STATIC; Y = STATIC_CHAIN_REGNUM
1837 JMP FUNCTION 0x0058 0x0000 <- FUNCTION
1840 static void
1841 pdp11_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1843 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
1844 rtx mem;
1846 gcc_assert (!TARGET_SPLIT);
1848 mem = adjust_address (m_tramp, HImode, 0);
1849 emit_move_insn (mem, GEN_INT (0x9400+STATIC_CHAIN_REGNUM));
1850 mem = adjust_address (m_tramp, HImode, 2);
1851 emit_move_insn (mem, chain_value);
1852 mem = adjust_address (m_tramp, HImode, 4);
1853 emit_move_insn (mem, GEN_INT (0x0058));
1854 emit_move_insn (mem, fnaddr);
1857 /* Worker function for TARGET_FUNCTION_ARG.
1859 Determine where to put an argument to a function.
1860 Value is zero to push the argument on the stack,
1861 or a hard register in which to store the argument.
1863 MODE is the argument's machine mode.
1864 TYPE is the data type of the argument (as a tree).
1865 This is null for libcalls where that information may
1866 not be available.
1867 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1868 the preceding args and about the function being called.
1869 NAMED is nonzero if this argument is a named parameter
1870 (otherwise it is an extra parameter matching an ellipsis). */
1872 static rtx
1873 pdp11_function_arg (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1874 enum machine_mode mode ATTRIBUTE_UNUSED,
1875 const_tree type ATTRIBUTE_UNUSED,
1876 bool named ATTRIBUTE_UNUSED)
1878 return NULL_RTX;
1881 /* Worker function for TARGET_FUNCTION_ARG_ADVANCE.
1883 Update the data in CUM to advance over an argument of mode MODE and
1884 data type TYPE. (TYPE is null for libcalls where that information
1885 may not be available.) */
1887 static void
1888 pdp11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1889 const_tree type, bool named ATTRIBUTE_UNUSED)
1891 *cum += (mode != BLKmode
1892 ? GET_MODE_SIZE (mode)
1893 : int_size_in_bytes (type));