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)
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. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
35 #include "insn-attr.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
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
=
84 const struct real_format pdp11_d_format
=
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);
111 decode_pdp11_f (const struct real_format
*fmt ATTRIBUTE_UNUSED
,
112 REAL_VALUE_TYPE
*r
, const long *buf
)
115 tbuf
= ((buf
[0] >> 16) & 0xffff) | ((buf
[0] & 0xffff) << 16);
116 (*vax_f_format
.decode
) (fmt
, r
, &tbuf
);
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);
129 decode_pdp11_d (const struct real_format
*fmt ATTRIBUTE_UNUSED
,
130 REAL_VALUE_TYPE
*r
, const long *buf
)
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
);
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.
217 pdp11_output_function_prologue (FILE *stream
, HOST_WIDE_INT size
)
219 fprintf (stream
, "\tjsr r5, csv\n");
222 fprintf (stream
, "\t/*abuse empty parameter slot for locals!*/\n");
224 fprintf(stream
, "\tsub $%#o, sp\n", size
- 2);
232 pdp11_output_function_prologue (FILE *stream
, HOST_WIDE_INT size
)
234 HOST_WIDE_INT fsize
= ((size
) + 1) & ~1;
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
)
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");
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 */
277 for (regno
= 8; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
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
]);
288 /* maybe make ac4, ac5 call used regs?? */
290 if (NO_LOAD_FPU_REG_P(regno
)
291 && regs_ever_live
[regno
]
292 && ! call_used_regs
[regno
])
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
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? */
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");
339 pdp11_output_function_epilogue (FILE *stream
, HOST_WIDE_INT size
)
341 HOST_WIDE_INT fsize
= ((size
) + 1) & ~1;
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
])
357 /* remember # of pushed bytes for CPU regs */
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
]);
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
])
375 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
377 if (LOAD_FPU_REG_P(i
)
379 && ! call_used_regs
[i
])
381 fprintf(stream
, "\tldd %#o(r5), %s\n", (-fsize
-k
)&0xffff, reg_names
[i
]);
385 if (NO_LOAD_FPU_REG_P(i
)
387 && ! call_used_regs
[i
])
389 if (! LOAD_FPU_REG_P(via_ac
))
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
]);
398 fprintf(stream
, "\tmov r5, sp\n");
399 fprintf (stream
, "\tmov (sp)+, r5\n");
403 via_ac
= FIRST_PSEUDO_REGISTER
-1;
406 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
407 if (regs_ever_live
[i
] && call_used_regs
[i
])
410 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
412 if (LOAD_FPU_REG_P(i
)
414 && ! call_used_regs
[i
])
415 fprintf(stream
, "\tldd (sp)+, %s\n", reg_names
[i
]);
417 if (NO_LOAD_FPU_REG_P(i
)
419 && ! call_used_regs
[i
])
421 if (! LOAD_FPU_REG_P(via_ac
))
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
]);
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. */
446 singlemove_string (rtx
*operands
)
448 if (operands
[1] != const0_rtx
)
455 /* Output assembler code to perform a doubleword move insn
456 with operands OPERANDS. */
459 output_move_double (rtx
*operands
)
461 enum { REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
463 rtx addreg0
= 0, addreg1
= 0;
465 /* First classify both operands. */
467 if (REG_P (operands
[0]))
469 else if (offsettable_memref_p (operands
[0]))
471 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
473 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
475 else if (GET_CODE (operands
[0]) == MEM
)
480 if (REG_P (operands
[1]))
482 else if (CONSTANT_P (operands
[1])
484 || GET_CODE (operands
[1]) == CONST_DOUBLE
488 else if (offsettable_memref_p (operands
[1]))
490 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
492 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
494 else if (GET_CODE (operands
[1]) == MEM
)
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
)
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]);
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]);
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);
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 */
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. */
595 output_asm_insn ("add $2,%0", &addreg0
);
597 output_asm_insn ("add $2,%0", &addreg1
);
600 output_asm_insn (singlemove_string (latehalf
), latehalf
);
602 /* Undo the adds we just did. */
604 output_asm_insn ("sub $2,%0", &addreg0
);
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. */
618 output_asm_insn ("add $2,%0", &addreg0
);
620 output_asm_insn ("add $2,%0", &addreg1
);
623 output_asm_insn (singlemove_string (latehalf
), latehalf
);
625 /* Undo the adds we just did. */
627 output_asm_insn ("sub $2,%0", &addreg0
);
629 output_asm_insn ("sub $2,%0", &addreg1
);
633 /* Output assembler code to perform a quadword move insn
634 with operands OPERANDS. */
637 output_move_quad (rtx
*operands
)
639 enum { REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
641 rtx addreg0
= 0, addreg1
= 0;
643 output_asm_insn(";/* movdi/df: %1 -> %0 */", operands
);
645 if (REG_P (operands
[0]))
647 else if (offsettable_memref_p (operands
[0]))
649 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
651 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
653 else if (GET_CODE (operands
[0]) == MEM
)
658 if (REG_P (operands
[1]))
660 else if (CONSTANT_P (operands
[1])
661 || GET_CODE (operands
[1]) == CONST_DOUBLE
)
663 else if (offsettable_memref_p (operands
[1]))
665 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
667 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
669 else if (GET_CODE (operands
[1]) == MEM
)
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
)
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])))
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
)
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]);
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]);
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);
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
)
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
;
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. */
807 output_asm_insn ("add $4,%0", &addreg0
);
809 output_asm_insn ("add $4,%0", &addreg1
);
812 output_asm_insn(output_move_double(latehalf
), latehalf
);
814 /* Undo the adds we just did. */
816 output_asm_insn ("sub $4,%0", &addreg0
);
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. */
830 output_asm_insn ("add $4,%0", &addreg0
);
832 output_asm_insn ("add $4,%0", &addreg1
);
835 output_asm_insn (output_move_double (latehalf
), latehalf
);
837 /* Undo the adds we just did. */
839 output_asm_insn ("sub $4,%0", &addreg0
);
841 output_asm_insn ("sub $4,%0", &addreg1
);
847 /* Return a REG that occurs in ADDR with coefficient 1.
848 ADDR can be effectively incremented by incrementing REG. */
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
)
869 /* Output an ascii string. */
871 output_ascii (FILE *file
, const char *p
, int size
)
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
];
884 fprintf (file
, "%#o", c
);
892 /* --- stole from out-vax, needs changes */
895 print_operand_address (FILE *file
, register rtx addr
)
897 register rtx reg1
, reg2
, breg
, ireg
;
902 switch (GET_CODE (addr
))
909 addr
= XEXP (addr
, 0);
913 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
918 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
923 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 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
)
974 if (addr
!= 0) abort ();
977 if (reg1
!= 0 && GET_CODE (reg1
) == MULT
)
982 else if (reg2
!= 0 && GET_CODE (reg2
) == MULT
)
987 else if (reg2
!= 0 || GET_CODE (addr
) == MEM
)
998 output_address (addr
);
1001 if (GET_CODE (breg
) != REG
)
1003 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
1007 if (GET_CODE (ireg
) == MULT
)
1008 ireg
= XEXP (ireg
, 0);
1009 if (GET_CODE (ireg
) != REG
)
1012 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
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. */
1025 pdp11_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
1031 fprintf (asm_out_file
, "\t.byte\t");
1032 output_addr_const_pdp11 (asm_out_file
, x
);
1033 fprintf (asm_out_file
, " /* char */\n");
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");
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 ? */
1068 register_move_cost(c1
, c2
)
1069 enum reg_class c1
, c2
;
1071 return move_costs
[(int)c1
][(int)c2
];
1075 pdp11_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int *total
)
1080 if (INTVAL (x
) == 0 || INTVAL (x
) == -1 || INTVAL (x
) == 1)
1090 /* Twice as expensive as REG. */
1095 /* Twice (or 4 times) as expensive as 16 bit. */
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. */
1105 *total
= COSTS_N_INSNS (2);
1107 *total
= COSTS_N_INSNS (11);
1112 *total
= COSTS_N_INSNS (2);
1114 *total
= COSTS_N_INSNS (25);
1119 *total
= COSTS_N_INSNS (2);
1121 *total
= COSTS_N_INSNS (26);
1125 /* Equivalent to length, so same for optimize_size. */
1126 *total
= COSTS_N_INSNS (3);
1130 /* Only used for qi->hi. */
1131 *total
= COSTS_N_INSNS (1);
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);
1140 *total
= COSTS_N_INSNS (2);
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 */
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);
1162 *total
= COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x
, 1)));
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);
1182 output_jump(const char *pos
, const char *neg
, int length
)
1186 static char buf
[1000];
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
1194 if (cc_status
.flags
& CC_IN_FPU
)
1195 output_asm_insn("cfcc", NULL
);
1203 strcat(buf
, " %l0");
1209 sprintf(buf
, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg
, x
, x
);
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
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
1261 && GET_CODE (cc_status
.value2
) == MEM
)
1262 cc_status
.value2
= 0;
1264 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1268 else if (GET_CODE (SET_DEST (exp
)) == REG
)
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
)
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
)
1297 /* Eliminate non-memory operations */
1298 if (GET_CODE (op
) != MEM
)
1302 /* dword operations really put out 2 instructions, so eliminate them. */
1303 if (GET_MODE_SIZE (GET_MODE (op
)) > (HAVE_64BIT_P () ? 8 : 4))
1307 /* Decode the address now. */
1311 addr
= XEXP (op
, 0);
1313 switch (GET_CODE (addr
))
1316 /* (R0) - no extra cost */
1321 /* -(R0), (R0)+ - cheap! */
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
)
1339 /* @#address - extra cost */
1343 /* X(R0) - extra cost */
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
1366 output_block_move(rtx
*operands
)
1368 static int count
= 0;
1371 if (GET_CODE(operands
[2]) == CONST_INT
1374 if (INTVAL(operands
[2]) < 16
1375 && INTVAL(operands
[3]) == 1)
1379 for (i
= 1; i
<= INTVAL(operands
[2]); i
++)
1380 output_asm_insn("movb (%1)+, (%0)+", operands
);
1384 else if (INTVAL(operands
[2]) < 32)
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 ???
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
);
1411 /* just clobber the register */
1412 operands
[4] = operands
[2];
1416 /* switch over alignment */
1417 switch (INTVAL(operands
[3]))
1433 sprintf(buf
, "\nmovestrhi%d:", count
);
1434 output_asm_insn(buf
, NULL
);
1436 output_asm_insn("movb (%1)+, (%0)+", operands
);
1440 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1441 output_asm_insn(buf
, operands
);
1445 output_asm_insn("dec %4", operands
);
1447 sprintf(buf
, "bgt movestrhi%d", count
);
1448 output_asm_insn(buf
, NULL
);
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
);
1481 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1482 output_asm_insn(buf
, operands
);
1486 output_asm_insn("dec %4", operands
);
1488 sprintf(buf
, "bgt movestrhi%d", count
);
1489 output_asm_insn(buf
, NULL
);
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
);
1528 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1529 output_asm_insn(buf
, operands
);
1533 output_asm_insn("dec %4", operands
);
1535 sprintf(buf
, "bgt movestrhi%d", count
);
1536 output_asm_insn(buf
, NULL
);
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
);
1582 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1583 output_asm_insn(buf
, operands
);
1587 output_asm_insn("dec %4", operands
);
1589 sprintf(buf
, "bgt movestrhi%d", count
);
1590 output_asm_insn(buf
, NULL
);
1604 legitimate_address_p (enum machine_mode mode
, rtx address
)
1606 /* #define REG_OK_STRICT */
1607 GO_IF_LEGITIMATE_ADDRESS(mode
, address
, win
);
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
)
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)
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.
1638 output_addr_const_pdp11 (FILE *file
, rtx x
)
1643 switch (GET_CODE (x
))
1653 assemble_name (file
, XSTR (x
, 0));
1657 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
1658 assemble_name (file
, buf
);
1662 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
1663 assemble_name (file
, buf
);
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
));
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));
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? */
1685 fprintf (file
, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x
));
1688 /* We can't handle floating point constants;
1689 PRINT_OPERAND must handle them. */
1690 output_operand_lossage ("floating constant misused");
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));
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));
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
)
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
);
1728 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1733 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1737 output_operand_lossage ("invalid expression as operand");
1741 /* Worker function for TARGET_RETURN_IN_MEMORY. */
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
));