* config/darwin-c.c, config/arc/arc.c, config/arc/arc.md,
[official-gcc.git] / gcc / config / pdp11 / pdp11.c
blobb0f6e3de3917c3ce518fb74ce0515d5d762c68b3
1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2004
3 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 2, 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 COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "function.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "recog.h"
38 #include "tree.h"
39 #include "expr.h"
40 #include "toplev.h"
41 #include "tm_p.h"
42 #include "target.h"
43 #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
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
84 const struct real_format pdp11_d_format =
86 encode_pdp11_d,
87 decode_pdp11_d,
90 56,
91 56,
92 -127,
93 127,
94 15,
95 false,
96 false,
97 false,
98 false,
99 false
102 static void
103 encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
104 const REAL_VALUE_TYPE *r)
106 (*vax_f_format.encode) (fmt, buf, r);
107 buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
110 static void
111 decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
112 REAL_VALUE_TYPE *r, const long *buf)
114 long tbuf;
115 tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
116 (*vax_f_format.decode) (fmt, r, &tbuf);
119 static void
120 encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
121 const REAL_VALUE_TYPE *r)
123 (*vax_d_format.encode) (fmt, buf, r);
124 buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
125 buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
128 static void
129 decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
130 REAL_VALUE_TYPE *r, const long *buf)
132 long tbuf[2];
133 tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
134 tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
135 (*vax_d_format.decode) (fmt, r, tbuf);
138 /* This is where the condition code register lives. */
139 /* rtx cc0_reg_rtx; - no longer needed? */
141 static rtx find_addr_reg (rtx);
142 static const char *singlemove_string (rtx *);
143 static bool pdp11_assemble_integer (rtx, unsigned int, int);
144 static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT);
145 static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT);
146 static bool pdp11_rtx_costs (rtx, int, int, int *);
147 static bool pdp11_return_in_memory (tree, tree);
149 /* Initialize the GCC target structure. */
150 #undef TARGET_ASM_BYTE_OP
151 #define TARGET_ASM_BYTE_OP NULL
152 #undef TARGET_ASM_ALIGNED_HI_OP
153 #define TARGET_ASM_ALIGNED_HI_OP NULL
154 #undef TARGET_ASM_ALIGNED_SI_OP
155 #define TARGET_ASM_ALIGNED_SI_OP NULL
156 #undef TARGET_ASM_INTEGER
157 #define TARGET_ASM_INTEGER pdp11_assemble_integer
159 #undef TARGET_ASM_FUNCTION_PROLOGUE
160 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
161 #undef TARGET_ASM_FUNCTION_EPILOGUE
162 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
164 #undef TARGET_ASM_OPEN_PAREN
165 #define TARGET_ASM_OPEN_PAREN "["
166 #undef TARGET_ASM_CLOSE_PAREN
167 #define TARGET_ASM_CLOSE_PAREN "]"
169 #undef TARGET_RTX_COSTS
170 #define TARGET_RTX_COSTS pdp11_rtx_costs
172 #undef TARGET_RETURN_IN_MEMORY
173 #define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
175 struct gcc_target targetm = TARGET_INITIALIZER;
177 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
180 arith_operand (rtx op, enum machine_mode mode)
182 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
186 const_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
188 return (GET_CODE (op) == CONST_INT);
191 int
192 immediate15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
194 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
198 expand_shift_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
200 return (GET_CODE (op) == CONST_INT
201 && abs (INTVAL(op)) > 1
202 && abs (INTVAL(op)) <= 4);
206 stream is a stdio stream to output the code to.
207 size is an int: how many units of temporary storage to allocate.
208 Refer to the array `regs_ever_live' to determine which registers
209 to save; `regs_ever_live[I]' is nonzero if register number I
210 is ever used in the function. This macro is responsible for
211 knowing which registers should not be saved even if used.
214 #ifdef TWO_BSD
216 static void
217 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
219 fprintf (stream, "\tjsr r5, csv\n");
220 if (size)
222 fprintf (stream, "\t/*abuse empty parameter slot for locals!*/\n");
223 if (size > 2)
224 fprintf(stream, "\tsub $%#o, sp\n", size - 2);
229 #else /* !TWO_BSD */
231 static void
232 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
234 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
235 int regno;
236 int via_ac = -1;
238 fprintf (stream,
239 "\n\t; /* function prologue %s*/\n",
240 current_function_name ());
242 /* if we are outputting code for main,
243 the switch FPU to right mode if TARGET_FPU */
244 if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
246 fprintf(stream,
247 "\t;/* switch cpu to double float, single integer */\n");
248 fprintf(stream, "\tsetd\n");
249 fprintf(stream, "\tseti\n\n");
252 if (frame_pointer_needed)
254 fprintf(stream, "\tmov r5, -(sp)\n");
255 fprintf(stream, "\tmov sp, r5\n");
257 else
259 /* DON'T SAVE FP */
262 /* make frame */
263 if (fsize)
264 fprintf (stream, "\tsub $%#o, sp\n", fsize);
266 /* save CPU registers */
267 for (regno = 0; regno < 8; regno++)
268 if (regs_ever_live[regno] && ! call_used_regs[regno])
269 if (! ((regno == FRAME_POINTER_REGNUM)
270 && frame_pointer_needed))
271 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
272 /* fpu regs saving */
274 /* via_ac specifies the ac to use for saving ac4, ac5 */
275 via_ac = -1;
277 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
279 /* ac0 - ac3 */
280 if (LOAD_FPU_REG_P(regno)
281 && regs_ever_live[regno]
282 && ! call_used_regs[regno])
284 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
285 via_ac = regno;
288 /* maybe make ac4, ac5 call used regs?? */
289 /* ac4 - ac5 */
290 if (NO_LOAD_FPU_REG_P(regno)
291 && regs_ever_live[regno]
292 && ! call_used_regs[regno])
294 if (via_ac == -1)
295 abort();
297 fprintf (stream, "\tldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
298 fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
302 fprintf (stream, "\t;/* end of prologue */\n\n");
305 #endif /* !TWO_BSD */
308 The function epilogue should not depend on the current stack pointer!
309 It should use the frame pointer only. This is mandatory because
310 of alloca; we also take advantage of it to omit stack adjustments
311 before returning. */
313 /* maybe we can make leaf functions faster by switching to the
314 second register file - this way we don't have to save regs!
315 leaf functions are ~ 50% of all functions (dynamically!)
317 set/clear bit 11 (dec. 2048) of status word for switching register files -
318 but how can we do this? the pdp11/45 manual says bit may only
319 be set (p.24), but not cleared!
321 switching to kernel is probably more expensive, so we'll leave it
322 like this and not use the second set of registers...
324 maybe as option if you want to generate code for kernel mode? */
326 #ifdef TWO_BSD
328 static void
329 pdp11_output_function_epilogue (FILE *stream,
330 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
332 fprintf (stream, "\t/* SP ignored by cret? */\n");
333 fprintf (stream, "\tjmp cret\n");
336 #else /* !TWO_BSD */
338 static void
339 pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
341 HOST_WIDE_INT fsize = ((size) + 1) & ~1;
342 int i, j, k;
344 int via_ac;
346 fprintf (stream, "\n\t; /*function epilogue */\n");
348 if (frame_pointer_needed)
350 /* hope this is safe - m68k does it also .... */
351 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
353 for (i =7, j = 0 ; i >= 0 ; i--)
354 if (regs_ever_live[i] && ! call_used_regs[i])
355 j++;
357 /* remember # of pushed bytes for CPU regs */
358 k = 2*j;
360 /* change fp -> r5 due to the compile error on libgcc2.c */
361 for (i =7 ; i >= 0 ; i--)
362 if (regs_ever_live[i] && ! call_used_regs[i])
363 fprintf(stream, "\tmov %#o(r5), %s\n",(-fsize-2*j--)&0xffff, reg_names[i]);
365 /* get ACs */
366 via_ac = FIRST_PSEUDO_REGISTER -1;
368 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
369 if (regs_ever_live[i] && ! call_used_regs[i])
371 via_ac = i;
372 k += 8;
375 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
377 if (LOAD_FPU_REG_P(i)
378 && regs_ever_live[i]
379 && ! call_used_regs[i])
381 fprintf(stream, "\tldd %#o(r5), %s\n", (-fsize-k)&0xffff, reg_names[i]);
382 k -= 8;
385 if (NO_LOAD_FPU_REG_P(i)
386 && regs_ever_live[i]
387 && ! call_used_regs[i])
389 if (! LOAD_FPU_REG_P(via_ac))
390 abort();
392 fprintf(stream, "\tldd %#o(r5), %s\n", (-fsize-k)&0xffff, reg_names[via_ac]);
393 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
394 k -= 8;
398 fprintf(stream, "\tmov r5, sp\n");
399 fprintf (stream, "\tmov (sp)+, r5\n");
401 else
403 via_ac = FIRST_PSEUDO_REGISTER -1;
405 /* get ACs */
406 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
407 if (regs_ever_live[i] && call_used_regs[i])
408 via_ac = i;
410 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
412 if (LOAD_FPU_REG_P(i)
413 && regs_ever_live[i]
414 && ! call_used_regs[i])
415 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
417 if (NO_LOAD_FPU_REG_P(i)
418 && regs_ever_live[i]
419 && ! call_used_regs[i])
421 if (! LOAD_FPU_REG_P(via_ac))
422 abort();
424 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
425 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
429 for (i=7; i >= 0; i--)
430 if (regs_ever_live[i] && !call_used_regs[i])
431 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
433 if (fsize)
434 fprintf((stream), "\tadd $%#o, sp\n", (fsize)&0xffff);
437 fprintf (stream, "\trts pc\n");
438 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
441 #endif /* !TWO_BSD */
443 /* Return the best assembler insn template
444 for moving operands[1] into operands[0] as a fullword. */
445 static const char *
446 singlemove_string (rtx *operands)
448 if (operands[1] != const0_rtx)
449 return "mov %1,%0";
451 return "clr %0";
455 /* Output assembler code to perform a doubleword move insn
456 with operands OPERANDS. */
458 const char *
459 output_move_double (rtx *operands)
461 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
462 rtx latehalf[2];
463 rtx addreg0 = 0, addreg1 = 0;
465 /* First classify both operands. */
467 if (REG_P (operands[0]))
468 optype0 = REGOP;
469 else if (offsettable_memref_p (operands[0]))
470 optype0 = OFFSOP;
471 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
472 optype0 = POPOP;
473 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
474 optype0 = PUSHOP;
475 else if (GET_CODE (operands[0]) == MEM)
476 optype0 = MEMOP;
477 else
478 optype0 = RNDOP;
480 if (REG_P (operands[1]))
481 optype1 = REGOP;
482 else if (CONSTANT_P (operands[1])
483 #if 0
484 || GET_CODE (operands[1]) == CONST_DOUBLE
485 #endif
487 optype1 = CNSTOP;
488 else if (offsettable_memref_p (operands[1]))
489 optype1 = OFFSOP;
490 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
491 optype1 = POPOP;
492 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
493 optype1 = PUSHOP;
494 else if (GET_CODE (operands[1]) == MEM)
495 optype1 = MEMOP;
496 else
497 optype1 = RNDOP;
499 /* Check for the cases that the operand constraints are not
500 supposed to allow to happen. Abort if we get one,
501 because generating code for these cases is painful. */
503 if (optype0 == RNDOP || optype1 == RNDOP)
504 abort ();
506 /* If one operand is decrementing and one is incrementing
507 decrement the former register explicitly
508 and change that operand into ordinary indexing. */
510 if (optype0 == PUSHOP && optype1 == POPOP)
512 operands[0] = XEXP (XEXP (operands[0], 0), 0);
513 output_asm_insn ("sub $4,%0", operands);
514 operands[0] = gen_rtx_MEM (SImode, operands[0]);
515 optype0 = OFFSOP;
517 if (optype0 == POPOP && optype1 == PUSHOP)
519 operands[1] = XEXP (XEXP (operands[1], 0), 0);
520 output_asm_insn ("sub $4,%1", operands);
521 operands[1] = gen_rtx_MEM (SImode, operands[1]);
522 optype1 = OFFSOP;
525 /* If an operand is an unoffsettable memory ref, find a register
526 we can increment temporarily to make it refer to the second word. */
528 if (optype0 == MEMOP)
529 addreg0 = find_addr_reg (XEXP (operands[0], 0));
531 if (optype1 == MEMOP)
532 addreg1 = find_addr_reg (XEXP (operands[1], 0));
534 /* Ok, we can do one word at a time.
535 Normally we do the low-numbered word first,
536 but if either operand is autodecrementing then we
537 do the high-numbered word first.
539 In either case, set up in LATEHALF the operands to use
540 for the high-numbered word and in some cases alter the
541 operands in OPERANDS to be suitable for the low-numbered word. */
543 if (optype0 == REGOP)
544 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
545 else if (optype0 == OFFSOP)
546 latehalf[0] = adjust_address (operands[0], HImode, 2);
547 else
548 latehalf[0] = operands[0];
550 if (optype1 == REGOP)
551 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
552 else if (optype1 == OFFSOP)
553 latehalf[1] = adjust_address (operands[1], HImode, 2);
554 else if (optype1 == CNSTOP)
556 if (CONSTANT_P (operands[1]))
558 /* now the mess begins, high word is in lower word???
560 that's what ashc makes me think, but I don't remember :-( */
561 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
562 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
564 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
566 /* immediate 32 bit values not allowed */
567 abort();
570 else
571 latehalf[1] = operands[1];
573 /* If insn is effectively movd N(sp),-(sp) then we will do the
574 high word first. We should use the adjusted operand 1 (which is N+4(sp))
575 for the low word as well, to compensate for the first decrement of sp. */
576 if (optype0 == PUSHOP
577 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
578 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
579 operands[1] = latehalf[1];
581 /* If one or both operands autodecrementing,
582 do the two words, high-numbered first. */
584 /* Likewise, the first move would clobber the source of the second one,
585 do them in the other order. This happens only for registers;
586 such overlap can't happen in memory unless the user explicitly
587 sets it up, and that is an undefined circumstance. */
589 if (optype0 == PUSHOP || optype1 == PUSHOP
590 || (optype0 == REGOP && optype1 == REGOP
591 && REGNO (operands[0]) == REGNO (latehalf[1])))
593 /* Make any unoffsettable addresses point at high-numbered word. */
594 if (addreg0)
595 output_asm_insn ("add $2,%0", &addreg0);
596 if (addreg1)
597 output_asm_insn ("add $2,%0", &addreg1);
599 /* Do that word. */
600 output_asm_insn (singlemove_string (latehalf), latehalf);
602 /* Undo the adds we just did. */
603 if (addreg0)
604 output_asm_insn ("sub $2,%0", &addreg0);
605 if (addreg1)
606 output_asm_insn ("sub $2,%0", &addreg1);
608 /* Do low-numbered word. */
609 return singlemove_string (operands);
612 /* Normal case: do the two words, low-numbered first. */
614 output_asm_insn (singlemove_string (operands), operands);
616 /* Make any unoffsettable addresses point at high-numbered word. */
617 if (addreg0)
618 output_asm_insn ("add $2,%0", &addreg0);
619 if (addreg1)
620 output_asm_insn ("add $2,%0", &addreg1);
622 /* Do that word. */
623 output_asm_insn (singlemove_string (latehalf), latehalf);
625 /* Undo the adds we just did. */
626 if (addreg0)
627 output_asm_insn ("sub $2,%0", &addreg0);
628 if (addreg1)
629 output_asm_insn ("sub $2,%0", &addreg1);
631 return "";
633 /* Output assembler code to perform a quadword move insn
634 with operands OPERANDS. */
636 const char *
637 output_move_quad (rtx *operands)
639 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
640 rtx latehalf[2];
641 rtx addreg0 = 0, addreg1 = 0;
643 output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);
645 if (REG_P (operands[0]))
646 optype0 = REGOP;
647 else if (offsettable_memref_p (operands[0]))
648 optype0 = OFFSOP;
649 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
650 optype0 = POPOP;
651 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
652 optype0 = PUSHOP;
653 else if (GET_CODE (operands[0]) == MEM)
654 optype0 = MEMOP;
655 else
656 optype0 = RNDOP;
658 if (REG_P (operands[1]))
659 optype1 = REGOP;
660 else if (CONSTANT_P (operands[1])
661 || GET_CODE (operands[1]) == CONST_DOUBLE)
662 optype1 = CNSTOP;
663 else if (offsettable_memref_p (operands[1]))
664 optype1 = OFFSOP;
665 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
666 optype1 = POPOP;
667 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
668 optype1 = PUSHOP;
669 else if (GET_CODE (operands[1]) == MEM)
670 optype1 = MEMOP;
671 else
672 optype1 = RNDOP;
674 /* Check for the cases that the operand constraints are not
675 supposed to allow to happen. Abort if we get one,
676 because generating code for these cases is painful. */
678 if (optype0 == RNDOP || optype1 == RNDOP)
679 abort ();
681 /* check if we move a CPU reg to an FPU reg, or vice versa! */
682 if (optype0 == REGOP && optype1 == REGOP)
683 /* bogus - 64 bit cannot reside in CPU! */
684 if (CPU_REG_P(REGNO(operands[0]))
685 || CPU_REG_P (REGNO(operands[1])))
686 abort();
688 if (optype0 == REGOP || optype1 == REGOP)
690 /* check for use of clrd????
691 if you ever allow ac4 and ac5 (now we require secondary load)
692 you must check whether
693 you want to load into them or store from them -
694 then dump ac0 into $help$ movce ac4/5 to ac0, do the
695 store from ac0, and restore ac0 - if you can find
696 an unused ac[0-3], use that and you save a store and a load!*/
698 if (FPU_REG_P(REGNO(operands[0])))
700 if (GET_CODE(operands[1]) == CONST_DOUBLE)
702 REAL_VALUE_TYPE r;
703 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
705 if (REAL_VALUES_EQUAL (r, dconst0))
706 return "{clrd|clrf} %0";
709 return "{ldd|movf} %1, %0";
712 if (FPU_REG_P(REGNO(operands[1])))
713 return "{std|movf} %1, %0";
716 /* If one operand is decrementing and one is incrementing
717 decrement the former register explicitly
718 and change that operand into ordinary indexing. */
720 if (optype0 == PUSHOP && optype1 == POPOP)
722 operands[0] = XEXP (XEXP (operands[0], 0), 0);
723 output_asm_insn ("sub $8,%0", operands);
724 operands[0] = gen_rtx_MEM (DImode, operands[0]);
725 optype0 = OFFSOP;
727 if (optype0 == POPOP && optype1 == PUSHOP)
729 operands[1] = XEXP (XEXP (operands[1], 0), 0);
730 output_asm_insn ("sub $8,%1", operands);
731 operands[1] = gen_rtx_MEM (SImode, operands[1]);
732 optype1 = OFFSOP;
735 /* If an operand is an unoffsettable memory ref, find a register
736 we can increment temporarily to make it refer to the second word. */
738 if (optype0 == MEMOP)
739 addreg0 = find_addr_reg (XEXP (operands[0], 0));
741 if (optype1 == MEMOP)
742 addreg1 = find_addr_reg (XEXP (operands[1], 0));
744 /* Ok, we can do one word at a time.
745 Normally we do the low-numbered word first,
746 but if either operand is autodecrementing then we
747 do the high-numbered word first.
749 In either case, set up in LATEHALF the operands to use
750 for the high-numbered word and in some cases alter the
751 operands in OPERANDS to be suitable for the low-numbered word. */
753 if (optype0 == REGOP)
754 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
755 else if (optype0 == OFFSOP)
756 latehalf[0] = adjust_address (operands[0], SImode, 4);
757 else
758 latehalf[0] = operands[0];
760 if (optype1 == REGOP)
761 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
762 else if (optype1 == OFFSOP)
763 latehalf[1] = adjust_address (operands[1], SImode, 4);
764 else if (optype1 == CNSTOP)
766 if (GET_CODE (operands[1]) == CONST_DOUBLE)
768 REAL_VALUE_TYPE r;
769 long dval[2];
770 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
771 REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
772 latehalf[1] = GEN_INT (dval[1]);
773 operands[1] = GEN_INT (dval[0]);
775 else if (GET_CODE(operands[1]) == CONST_INT)
777 latehalf[1] = const0_rtx;
779 else
780 abort();
782 else
783 latehalf[1] = operands[1];
785 /* If insn is effectively movd N(sp),-(sp) then we will do the
786 high word first. We should use the adjusted operand 1 (which is N+4(sp))
787 for the low word as well, to compensate for the first decrement of sp. */
788 if (optype0 == PUSHOP
789 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
790 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
791 operands[1] = latehalf[1];
793 /* If one or both operands autodecrementing,
794 do the two words, high-numbered first. */
796 /* Likewise, the first move would clobber the source of the second one,
797 do them in the other order. This happens only for registers;
798 such overlap can't happen in memory unless the user explicitly
799 sets it up, and that is an undefined circumstance. */
801 if (optype0 == PUSHOP || optype1 == PUSHOP
802 || (optype0 == REGOP && optype1 == REGOP
803 && REGNO (operands[0]) == REGNO (latehalf[1])))
805 /* Make any unoffsettable addresses point at high-numbered word. */
806 if (addreg0)
807 output_asm_insn ("add $4,%0", &addreg0);
808 if (addreg1)
809 output_asm_insn ("add $4,%0", &addreg1);
811 /* Do that word. */
812 output_asm_insn(output_move_double(latehalf), latehalf);
814 /* Undo the adds we just did. */
815 if (addreg0)
816 output_asm_insn ("sub $4,%0", &addreg0);
817 if (addreg1)
818 output_asm_insn ("sub $4,%0", &addreg1);
820 /* Do low-numbered word. */
821 return output_move_double (operands);
824 /* Normal case: do the two words, low-numbered first. */
826 output_asm_insn (output_move_double (operands), operands);
828 /* Make any unoffsettable addresses point at high-numbered word. */
829 if (addreg0)
830 output_asm_insn ("add $4,%0", &addreg0);
831 if (addreg1)
832 output_asm_insn ("add $4,%0", &addreg1);
834 /* Do that word. */
835 output_asm_insn (output_move_double (latehalf), latehalf);
837 /* Undo the adds we just did. */
838 if (addreg0)
839 output_asm_insn ("sub $4,%0", &addreg0);
840 if (addreg1)
841 output_asm_insn ("sub $4,%0", &addreg1);
843 return "";
847 /* Return a REG that occurs in ADDR with coefficient 1.
848 ADDR can be effectively incremented by incrementing REG. */
850 static rtx
851 find_addr_reg (rtx addr)
853 while (GET_CODE (addr) == PLUS)
855 if (GET_CODE (XEXP (addr, 0)) == REG)
856 addr = XEXP (addr, 0);
857 if (GET_CODE (XEXP (addr, 1)) == REG)
858 addr = XEXP (addr, 1);
859 if (CONSTANT_P (XEXP (addr, 0)))
860 addr = XEXP (addr, 1);
861 if (CONSTANT_P (XEXP (addr, 1)))
862 addr = XEXP (addr, 0);
864 if (GET_CODE (addr) == REG)
865 return addr;
866 return 0;
869 /* Output an ascii string. */
870 void
871 output_ascii (FILE *file, const char *p, int size)
873 int i;
875 /* This used to output .byte "string", which doesn't work with the UNIX
876 assembler and I think not with DEC ones either. */
877 fprintf (file, "\t.byte ");
879 for (i = 0; i < size; i++)
881 register int c = p[i];
882 if (c < 0)
883 c += 256;
884 fprintf (file, "%#o", c);
885 if (i < size - 1)
886 putc (',', file);
888 putc ('\n', file);
892 /* --- stole from out-vax, needs changes */
894 void
895 print_operand_address (FILE *file, register rtx addr)
897 register rtx reg1, reg2, breg, ireg;
898 rtx offset;
900 retry:
902 switch (GET_CODE (addr))
904 case MEM:
905 if (TARGET_UNIX_ASM)
906 fprintf (file, "*");
907 else
908 fprintf (file, "@");
909 addr = XEXP (addr, 0);
910 goto retry;
912 case REG:
913 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
914 break;
916 case PRE_MODIFY:
917 case PRE_DEC:
918 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
919 break;
921 case POST_MODIFY:
922 case POST_INC:
923 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
924 break;
926 case PLUS:
927 reg1 = 0; reg2 = 0;
928 ireg = 0; breg = 0;
929 offset = 0;
930 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
931 || GET_CODE (XEXP (addr, 0)) == MEM)
933 offset = XEXP (addr, 0);
934 addr = XEXP (addr, 1);
936 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
937 || GET_CODE (XEXP (addr, 1)) == MEM)
939 offset = XEXP (addr, 1);
940 addr = XEXP (addr, 0);
942 if (GET_CODE (addr) != PLUS)
944 else if (GET_CODE (XEXP (addr, 0)) == MULT)
946 reg1 = XEXP (addr, 0);
947 addr = XEXP (addr, 1);
949 else if (GET_CODE (XEXP (addr, 1)) == MULT)
951 reg1 = XEXP (addr, 1);
952 addr = XEXP (addr, 0);
954 else if (GET_CODE (XEXP (addr, 0)) == REG)
956 reg1 = XEXP (addr, 0);
957 addr = XEXP (addr, 1);
959 else if (GET_CODE (XEXP (addr, 1)) == REG)
961 reg1 = XEXP (addr, 1);
962 addr = XEXP (addr, 0);
964 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
966 if (reg1 == 0)
967 reg1 = addr;
968 else
969 reg2 = addr;
970 addr = 0;
972 if (offset != 0)
974 if (addr != 0) abort ();
975 addr = offset;
977 if (reg1 != 0 && GET_CODE (reg1) == MULT)
979 breg = reg2;
980 ireg = reg1;
982 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
984 breg = reg1;
985 ireg = reg2;
987 else if (reg2 != 0 || GET_CODE (addr) == MEM)
989 breg = reg2;
990 ireg = reg1;
992 else
994 breg = reg1;
995 ireg = reg2;
997 if (addr != 0)
998 output_address (addr);
999 if (breg != 0)
1001 if (GET_CODE (breg) != REG)
1002 abort ();
1003 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
1005 if (ireg != 0)
1007 if (GET_CODE (ireg) == MULT)
1008 ireg = XEXP (ireg, 0);
1009 if (GET_CODE (ireg) != REG)
1010 abort ();
1011 abort();
1012 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
1014 break;
1016 default:
1017 output_addr_const_pdp11 (file, addr);
1021 /* Target hook to assemble integer objects. We need to use the
1022 pdp-specific version of output_addr_const. */
1024 static bool
1025 pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
1027 if (aligned_p)
1028 switch (size)
1030 case 1:
1031 fprintf (asm_out_file, "\t.byte\t");
1032 output_addr_const_pdp11 (asm_out_file, x);
1033 fprintf (asm_out_file, " /* char */\n");
1034 return true;
1036 case 2:
1037 fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
1038 output_addr_const_pdp11 (asm_out_file, x);
1039 fprintf (asm_out_file, " /* short */\n");
1040 return true;
1042 return default_assemble_integer (x, size, aligned_p);
1046 /* register move costs, indexed by regs */
1048 static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
1050 /* NO MUL GEN LFPU NLFPU FPU ALL */
1052 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
1053 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
1054 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
1055 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
1056 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
1057 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
1058 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
1062 /* -- note that some moves are tremendously expensive,
1063 because they require lots of tricks! do we have to
1064 charge the costs incurred by secondary reload class
1065 -- as we do here with 22 -- or not ? */
1067 int
1068 register_move_cost(c1, c2)
1069 enum reg_class c1, c2;
1071 return move_costs[(int)c1][(int)c2];
1074 static bool
1075 pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
1077 switch (code)
1079 case CONST_INT:
1080 if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
1082 *total = 0;
1083 return true;
1085 /* FALLTHRU */
1087 case CONST:
1088 case LABEL_REF:
1089 case SYMBOL_REF:
1090 /* Twice as expensive as REG. */
1091 *total = 2;
1092 return true;
1094 case CONST_DOUBLE:
1095 /* Twice (or 4 times) as expensive as 16 bit. */
1096 *total = 4;
1097 return true;
1099 case MULT:
1100 /* ??? There is something wrong in MULT because MULT is not
1101 as cheap as total = 2 even if we can shift! */
1102 /* If optimizing for size make mult etc cheap, but not 1, so when
1103 in doubt the faster insn is chosen. */
1104 if (optimize_size)
1105 *total = COSTS_N_INSNS (2);
1106 else
1107 *total = COSTS_N_INSNS (11);
1108 return false;
1110 case DIV:
1111 if (optimize_size)
1112 *total = COSTS_N_INSNS (2);
1113 else
1114 *total = COSTS_N_INSNS (25);
1115 return false;
1117 case MOD:
1118 if (optimize_size)
1119 *total = COSTS_N_INSNS (2);
1120 else
1121 *total = COSTS_N_INSNS (26);
1122 return false;
1124 case ABS:
1125 /* Equivalent to length, so same for optimize_size. */
1126 *total = COSTS_N_INSNS (3);
1127 return false;
1129 case ZERO_EXTEND:
1130 /* Only used for qi->hi. */
1131 *total = COSTS_N_INSNS (1);
1132 return false;
1134 case SIGN_EXTEND:
1135 if (GET_MODE (x) == HImode)
1136 *total = COSTS_N_INSNS (1);
1137 else if (GET_MODE (x) == SImode)
1138 *total = COSTS_N_INSNS (6);
1139 else
1140 *total = COSTS_N_INSNS (2);
1141 return false;
1143 case ASHIFT:
1144 case LSHIFTRT:
1145 case ASHIFTRT:
1146 if (optimize_size)
1147 *total = COSTS_N_INSNS (1);
1148 else if (GET_MODE (x) == QImode)
1150 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
1151 *total = COSTS_N_INSNS (8); /* worst case */
1152 else
1153 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
1155 else if (GET_MODE (x) == HImode)
1157 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1159 if (abs (INTVAL (XEXP (x, 1))) == 1)
1160 *total = COSTS_N_INSNS (1);
1161 else
1162 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1164 else
1165 *total = COSTS_N_INSNS (10); /* worst case */
1167 else if (GET_MODE (x) == SImode)
1169 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1170 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1171 else /* worst case */
1172 *total = COSTS_N_INSNS (18);
1174 return false;
1176 default:
1177 return false;
1181 const char *
1182 output_jump(const char *pos, const char *neg, int length)
1184 static int x = 0;
1186 static char buf[1000];
1188 #if 0
1189 /* currently we don't need this, because the tstdf and cmpdf
1190 copy the condition code immediately, and other float operations are not
1191 yet recognized as changing the FCC - if so, then the length-cost of all
1192 jump insns increases by one, because we have to potentially copy the
1193 FCC! */
1194 if (cc_status.flags & CC_IN_FPU)
1195 output_asm_insn("cfcc", NULL);
1196 #endif
1198 switch (length)
1200 case 1:
1202 strcpy(buf, pos);
1203 strcat(buf, " %l0");
1205 return buf;
1207 case 3:
1209 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
1211 x++;
1213 return buf;
1215 default:
1217 abort();
1222 void
1223 notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
1225 if (GET_CODE (SET_DEST (exp)) == CC0)
1227 cc_status.flags = 0;
1228 cc_status.value1 = SET_DEST (exp);
1229 cc_status.value2 = SET_SRC (exp);
1232 if (GET_MODE(SET_SRC(exp)) == DFmode)
1233 cc_status.flags |= CC_IN_FPU;
1236 else if ((GET_CODE (SET_DEST (exp)) == REG
1237 || GET_CODE (SET_DEST (exp)) == MEM)
1238 && GET_CODE (SET_SRC (exp)) != PC
1239 && (GET_MODE (SET_DEST(exp)) == HImode
1240 || GET_MODE (SET_DEST(exp)) == QImode)
1241 && (GET_CODE (SET_SRC(exp)) == PLUS
1242 || GET_CODE (SET_SRC(exp)) == MINUS
1243 || GET_CODE (SET_SRC(exp)) == AND
1244 || GET_CODE (SET_SRC(exp)) == IOR
1245 || GET_CODE (SET_SRC(exp)) == XOR
1246 || GET_CODE (SET_SRC(exp)) == NOT
1247 || GET_CODE (SET_SRC(exp)) == NEG
1248 || GET_CODE (SET_SRC(exp)) == REG
1249 || GET_CODE (SET_SRC(exp)) == MEM))
1251 cc_status.flags = 0;
1252 cc_status.value1 = SET_SRC (exp);
1253 cc_status.value2 = SET_DEST (exp);
1255 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1256 && cc_status.value2
1257 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1258 cc_status.value2 = 0;
1259 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1260 && cc_status.value2
1261 && GET_CODE (cc_status.value2) == MEM)
1262 cc_status.value2 = 0;
1264 else if (GET_CODE (SET_SRC (exp)) == CALL)
1266 CC_STATUS_INIT;
1268 else if (GET_CODE (SET_DEST (exp)) == REG)
1269 /* what's this ? */
1271 if ((cc_status.value1
1272 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1273 cc_status.value1 = 0;
1274 if ((cc_status.value2
1275 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1276 cc_status.value2 = 0;
1278 else if (SET_DEST(exp) == pc_rtx)
1280 /* jump */
1282 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1284 /* the last else is a bit paranoiac, but since nearly all instructions
1285 play with condition codes, it's reasonable! */
1287 CC_STATUS_INIT; /* paranoia*/
1293 simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1295 rtx addr;
1297 /* Eliminate non-memory operations */
1298 if (GET_CODE (op) != MEM)
1299 return FALSE;
1301 #if 0
1302 /* dword operations really put out 2 instructions, so eliminate them. */
1303 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1304 return FALSE;
1305 #endif
1307 /* Decode the address now. */
1309 indirection:
1311 addr = XEXP (op, 0);
1313 switch (GET_CODE (addr))
1315 case REG:
1316 /* (R0) - no extra cost */
1317 return 1;
1319 case PRE_DEC:
1320 case POST_INC:
1321 /* -(R0), (R0)+ - cheap! */
1322 return 0;
1324 case MEM:
1325 /* cheap - is encoded in addressing mode info!
1327 -- except for @(R0), which has to be @0(R0) !!! */
1329 if (GET_CODE (XEXP (addr, 0)) == REG)
1330 return 0;
1332 op=addr;
1333 goto indirection;
1335 case CONST_INT:
1336 case LABEL_REF:
1337 case CONST:
1338 case SYMBOL_REF:
1339 /* @#address - extra cost */
1340 return 0;
1342 case PLUS:
1343 /* X(R0) - extra cost */
1344 return 0;
1346 default:
1347 break;
1350 return FALSE;
1355 * output a block move:
1357 * operands[0] ... to
1358 * operands[1] ... from
1359 * operands[2] ... length
1360 * operands[3] ... alignment
1361 * operands[4] ... scratch register
1365 const char *
1366 output_block_move(rtx *operands)
1368 static int count = 0;
1369 char buf[200];
1371 if (GET_CODE(operands[2]) == CONST_INT
1372 && ! optimize_size)
1374 if (INTVAL(operands[2]) < 16
1375 && INTVAL(operands[3]) == 1)
1377 register int i;
1379 for (i = 1; i <= INTVAL(operands[2]); i++)
1380 output_asm_insn("movb (%1)+, (%0)+", operands);
1382 return "";
1384 else if (INTVAL(operands[2]) < 32)
1386 register int i;
1388 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1389 output_asm_insn("mov (%1)+, (%0)+", operands);
1391 /* may I assume that moved quantity is
1392 multiple of alignment ???
1394 I HOPE SO !
1397 return "";
1401 /* can do other clever things, maybe... */
1404 if (CONSTANT_P(operands[2]) )
1406 /* just move count to scratch */
1407 output_asm_insn("mov %2, %4", operands);
1409 else
1411 /* just clobber the register */
1412 operands[4] = operands[2];
1416 /* switch over alignment */
1417 switch (INTVAL(operands[3]))
1419 case 1:
1423 movb (%1)+, (%0)+
1425 if (TARGET_45)
1426 sob %4,x
1427 else
1428 dec %4
1429 bgt x
1433 sprintf(buf, "\nmovestrhi%d:", count);
1434 output_asm_insn(buf, NULL);
1436 output_asm_insn("movb (%1)+, (%0)+", operands);
1438 if (TARGET_45)
1440 sprintf(buf, "sob %%4, movestrhi%d", count);
1441 output_asm_insn(buf, operands);
1443 else
1445 output_asm_insn("dec %4", operands);
1447 sprintf(buf, "bgt movestrhi%d", count);
1448 output_asm_insn(buf, NULL);
1451 count ++;
1452 break;
1454 case 2:
1457 asr %4
1461 mov (%1)+, (%0)+
1463 if (TARGET_45)
1464 sob %4, x
1465 else
1466 dec %4
1467 bgt x
1470 generate_compact_code:
1472 output_asm_insn("asr %4", operands);
1474 sprintf(buf, "\nmovestrhi%d:", count);
1475 output_asm_insn(buf, NULL);
1477 output_asm_insn("mov (%1)+, (%0)+", operands);
1479 if (TARGET_45)
1481 sprintf(buf, "sob %%4, movestrhi%d", count);
1482 output_asm_insn(buf, operands);
1484 else
1486 output_asm_insn("dec %4", operands);
1488 sprintf(buf, "bgt movestrhi%d", count);
1489 output_asm_insn(buf, NULL);
1492 count ++;
1493 break;
1495 case 4:
1499 asr %4
1500 asr %4
1504 mov (%1)+, (%0)+
1505 mov (%1)+, (%0)+
1507 if (TARGET_45)
1508 sob %4, x
1509 else
1510 dec %4
1511 bgt x
1514 if (optimize_size)
1515 goto generate_compact_code;
1517 output_asm_insn("asr %4", operands);
1518 output_asm_insn("asr %4", operands);
1520 sprintf(buf, "\nmovestrhi%d:", count);
1521 output_asm_insn(buf, NULL);
1523 output_asm_insn("mov (%1)+, (%0)+", operands);
1524 output_asm_insn("mov (%1)+, (%0)+", operands);
1526 if (TARGET_45)
1528 sprintf(buf, "sob %%4, movestrhi%d", count);
1529 output_asm_insn(buf, operands);
1531 else
1533 output_asm_insn("dec %4", operands);
1535 sprintf(buf, "bgt movestrhi%d", count);
1536 output_asm_insn(buf, NULL);
1539 count ++;
1540 break;
1542 default:
1546 asr %4
1547 asr %4
1548 asr %4
1552 mov (%1)+, (%0)+
1553 mov (%1)+, (%0)+
1554 mov (%1)+, (%0)+
1555 mov (%1)+, (%0)+
1557 if (TARGET_45)
1558 sob %4, x
1559 else
1560 dec %4
1561 bgt x
1565 if (optimize_size)
1566 goto generate_compact_code;
1568 output_asm_insn("asr %4", operands);
1569 output_asm_insn("asr %4", operands);
1570 output_asm_insn("asr %4", operands);
1572 sprintf(buf, "\nmovestrhi%d:", count);
1573 output_asm_insn(buf, NULL);
1575 output_asm_insn("mov (%1)+, (%0)+", operands);
1576 output_asm_insn("mov (%1)+, (%0)+", operands);
1577 output_asm_insn("mov (%1)+, (%0)+", operands);
1578 output_asm_insn("mov (%1)+, (%0)+", operands);
1580 if (TARGET_45)
1582 sprintf(buf, "sob %%4, movestrhi%d", count);
1583 output_asm_insn(buf, operands);
1585 else
1587 output_asm_insn("dec %4", operands);
1589 sprintf(buf, "bgt movestrhi%d", count);
1590 output_asm_insn(buf, NULL);
1593 count ++;
1594 break;
1600 return "";
1604 legitimate_address_p (enum machine_mode mode, rtx address)
1606 /* #define REG_OK_STRICT */
1607 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1609 return 0;
1611 win:
1612 return 1;
1614 /* #undef REG_OK_STRICT */
1617 /* This function checks whether a real value can be encoded as
1618 a literal, i.e., addressing mode 27. In that mode, real values
1619 are one word values, so the remaining 48 bits have to be zero. */
1621 legitimate_const_double_p (rtx address)
1623 REAL_VALUE_TYPE r;
1624 long sval[2];
1625 REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1626 REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1627 if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1628 return 1;
1629 return 0;
1632 /* A copy of output_addr_const modified for pdp11 expression syntax.
1633 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1634 use, and for debugging output, which we don't support with this port either.
1635 So this copy should get called whenever needed.
1637 void
1638 output_addr_const_pdp11 (FILE *file, rtx x)
1640 char buf[256];
1642 restart:
1643 switch (GET_CODE (x))
1645 case PC:
1646 if (flag_pic)
1647 putc ('.', file);
1648 else
1649 abort ();
1650 break;
1652 case SYMBOL_REF:
1653 assemble_name (file, XSTR (x, 0));
1654 break;
1656 case LABEL_REF:
1657 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1658 assemble_name (file, buf);
1659 break;
1661 case CODE_LABEL:
1662 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1663 assemble_name (file, buf);
1664 break;
1666 case CONST_INT:
1667 /* Should we check for constants which are too big? Maybe cutting
1668 them off to 16 bits is OK? */
1669 fprintf (file, "%#ho", (unsigned short) INTVAL (x));
1670 break;
1672 case CONST:
1673 /* This used to output parentheses around the expression,
1674 but that does not work on the 386 (either ATT or BSD assembler). */
1675 output_addr_const_pdp11 (file, XEXP (x, 0));
1676 break;
1678 case CONST_DOUBLE:
1679 if (GET_MODE (x) == VOIDmode)
1681 /* We can use %o if the number is one word and positive. */
1682 if (CONST_DOUBLE_HIGH (x))
1683 abort (); /* Should we just silently drop the high part? */
1684 else
1685 fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
1687 else
1688 /* We can't handle floating point constants;
1689 PRINT_OPERAND must handle them. */
1690 output_operand_lossage ("floating constant misused");
1691 break;
1693 case PLUS:
1694 /* Some assemblers need integer constants to appear last (e.g. masm). */
1695 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1697 output_addr_const_pdp11 (file, XEXP (x, 1));
1698 if (INTVAL (XEXP (x, 0)) >= 0)
1699 fprintf (file, "+");
1700 output_addr_const_pdp11 (file, XEXP (x, 0));
1702 else
1704 output_addr_const_pdp11 (file, XEXP (x, 0));
1705 if (INTVAL (XEXP (x, 1)) >= 0)
1706 fprintf (file, "+");
1707 output_addr_const_pdp11 (file, XEXP (x, 1));
1709 break;
1711 case MINUS:
1712 /* Avoid outputting things like x-x or x+5-x,
1713 since some assemblers can't handle that. */
1714 x = simplify_subtraction (x);
1715 if (GET_CODE (x) != MINUS)
1716 goto restart;
1718 output_addr_const_pdp11 (file, XEXP (x, 0));
1719 fprintf (file, "-");
1720 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1721 && INTVAL (XEXP (x, 1)) < 0)
1723 fprintf (file, targetm.asm_out.open_paren);
1724 output_addr_const_pdp11 (file, XEXP (x, 1));
1725 fprintf (file, targetm.asm_out.close_paren);
1727 else
1728 output_addr_const_pdp11 (file, XEXP (x, 1));
1729 break;
1731 case ZERO_EXTEND:
1732 case SIGN_EXTEND:
1733 output_addr_const_pdp11 (file, XEXP (x, 0));
1734 break;
1736 default:
1737 output_operand_lossage ("invalid expression as operand");
1741 /* Worker function for TARGET_RETURN_IN_MEMORY. */
1743 static bool
1744 pdp11_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
1746 /* Should probably return DImode and DFmode in memory, lest
1747 we fill up all regs!
1749 have to, else we crash - exception: maybe return result in
1750 ac0 if DFmode and FPU present - compatibility problem with
1751 libraries for non-floating point.... */
1752 return (TYPE_MODE (type) == DImode
1753 || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));