1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001
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 /* This is where the condition code register lives. */
55 /* rtx cc0_reg_rtx; - no longer needed? */
57 static rtx find_addr_reg
PARAMS ((rtx
));
58 static const char *singlemove_string
PARAMS ((rtx
*));
59 static bool pdp11_assemble_integer
PARAMS ((rtx
, unsigned int, int));
60 static void pdp11_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
61 static void pdp11_output_function_epilogue
PARAMS ((FILE *, HOST_WIDE_INT
));
62 static bool pdp11_rtx_costs
PARAMS ((rtx
, int, int, int *));
64 /* Initialize the GCC target structure. */
65 #undef TARGET_ASM_BYTE_OP
66 #define TARGET_ASM_BYTE_OP NULL
67 #undef TARGET_ASM_ALIGNED_HI_OP
68 #define TARGET_ASM_ALIGNED_HI_OP NULL
69 #undef TARGET_ASM_ALIGNED_SI_OP
70 #define TARGET_ASM_ALIGNED_SI_OP NULL
71 #undef TARGET_ASM_INTEGER
72 #define TARGET_ASM_INTEGER pdp11_assemble_integer
74 #undef TARGET_ASM_FUNCTION_PROLOGUE
75 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
76 #undef TARGET_ASM_FUNCTION_EPILOGUE
77 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
79 #undef TARGET_ASM_OPEN_PAREN
80 #define TARGET_ASM_OPEN_PAREN "["
81 #undef TARGET_ASM_CLOSE_PAREN
82 #define TARGET_ASM_CLOSE_PAREN "]"
84 #undef TARGET_RTX_COSTS
85 #define TARGET_RTX_COSTS pdp11_rtx_costs
87 struct gcc_target targetm
= TARGET_INITIALIZER
;
89 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
92 arith_operand (op
, mode
)
94 enum machine_mode mode
;
96 return (register_operand (op
, mode
) || GET_CODE (op
) == CONST_INT
);
100 const_immediate_operand (op
, mode
)
102 enum machine_mode mode ATTRIBUTE_UNUSED
;
104 return (GET_CODE (op
) == CONST_INT
);
108 immediate15_operand (op
, mode
)
110 enum machine_mode mode ATTRIBUTE_UNUSED
;
112 return (GET_CODE (op
) == CONST_INT
&& ((INTVAL (op
) & 0x8000) == 0x0000));
116 expand_shift_operand (op
, mode
)
118 enum machine_mode mode ATTRIBUTE_UNUSED
;
120 return (GET_CODE (op
) == CONST_INT
121 && abs (INTVAL(op
)) > 1
122 && abs (INTVAL(op
)) <= 4);
126 stream is a stdio stream to output the code to.
127 size is an int: how many units of temporary storage to allocate.
128 Refer to the array `regs_ever_live' to determine which registers
129 to save; `regs_ever_live[I]' is nonzero if register number I
130 is ever used in the function. This macro is responsible for
131 knowing which registers should not be saved even if used.
137 pdp11_output_function_prologue (stream
, size
)
141 fprintf (stream
, "\tjsr r5, csv\n");
144 fprintf (stream
, "\t/*abuse empty parameter slot for locals!*/\n");
146 fprintf(stream
, "\tsub $%#o, sp\n", size
- 2);
154 pdp11_output_function_prologue (stream
, size
)
158 HOST_WIDE_INT fsize
= ((size
) + 1) & ~1;
163 "\n\t; /* function prologue %s*/\n", current_function_name
);
165 /* if we are outputting code for main,
166 the switch FPU to right mode if TARGET_FPU */
167 if (MAIN_NAME_P (DECL_NAME (current_function_decl
)) && TARGET_FPU
)
170 "\t;/* switch cpu to double float, single integer */\n");
171 fprintf(stream
, "\tsetd\n");
172 fprintf(stream
, "\tseti\n\n");
175 if (frame_pointer_needed
)
177 fprintf(stream
, "\tmov r5, -(sp)\n");
178 fprintf(stream
, "\tmov sp, r5\n");
187 fprintf (stream
, "\tsub $%#o, sp\n", fsize
);
189 /* save CPU registers */
190 for (regno
= 0; regno
< 8; regno
++)
191 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
192 if (! ((regno
== FRAME_POINTER_REGNUM
)
193 && frame_pointer_needed
))
194 fprintf (stream
, "\tmov %s, -(sp)\n", reg_names
[regno
]);
195 /* fpu regs saving */
197 /* via_ac specifies the ac to use for saving ac4, ac5 */
200 for (regno
= 8; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
203 if (LOAD_FPU_REG_P(regno
)
204 && regs_ever_live
[regno
]
205 && ! call_used_regs
[regno
])
207 fprintf (stream
, "\tstd %s, -(sp)\n", reg_names
[regno
]);
211 /* maybe make ac4, ac5 call used regs?? */
213 if (NO_LOAD_FPU_REG_P(regno
)
214 && regs_ever_live
[regno
]
215 && ! call_used_regs
[regno
])
220 fprintf (stream
, "\tldd %s, %s\n", reg_names
[regno
], reg_names
[via_ac
]);
221 fprintf (stream
, "\tstd %s, -(sp)\n", reg_names
[via_ac
]);
225 fprintf (stream
, "\t;/* end of prologue */\n\n");
228 #endif /* !TWO_BSD */
231 The function epilogue should not depend on the current stack pointer!
232 It should use the frame pointer only. This is mandatory because
233 of alloca; we also take advantage of it to omit stack adjustments
236 /* maybe we can make leaf functions faster by switching to the
237 second register file - this way we don't have to save regs!
238 leaf functions are ~ 50% of all functions (dynamically!)
240 set/clear bit 11 (dec. 2048) of status word for switching register files -
241 but how can we do this? the pdp11/45 manual says bit may only
242 be set (p.24), but not cleared!
244 switching to kernel is probably more expensive, so we'll leave it
245 like this and not use the second set of registers...
247 maybe as option if you want to generate code for kernel mode? */
252 pdp11_output_function_epilogue (stream
, size
)
254 HOST_WIDE_INT size ATTRIBUTE_UNUSED
;
256 fprintf (stream
, "\t/* SP ignored by cret? */\n");
257 fprintf (stream
, "\tjmp cret\n");
263 pdp11_output_function_epilogue (stream
, size
)
267 HOST_WIDE_INT fsize
= ((size
) + 1) & ~1;
272 fprintf (stream
, "\n\t; /*function epilogue */\n");
274 if (frame_pointer_needed
)
276 /* hope this is safe - m68k does it also .... */
277 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
279 for (i
=7, j
= 0 ; i
>= 0 ; i
--)
280 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
283 /* remember # of pushed bytes for CPU regs */
286 /* change fp -> r5 due to the compile error on libgcc2.c */
287 for (i
=7 ; i
>= 0 ; i
--)
288 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
289 fprintf(stream
, "\tmov %#o(r5), %s\n",(-fsize
-2*j
--)&0xffff, reg_names
[i
]);
292 via_ac
= FIRST_PSEUDO_REGISTER
-1;
294 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
295 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
301 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
303 if (LOAD_FPU_REG_P(i
)
305 && ! call_used_regs
[i
])
307 fprintf(stream
, "\tldd %#o(r5), %s\n", (-fsize
-k
)&0xffff, reg_names
[i
]);
311 if (NO_LOAD_FPU_REG_P(i
)
313 && ! call_used_regs
[i
])
315 if (! LOAD_FPU_REG_P(via_ac
))
318 fprintf(stream
, "\tldd %#o(r5), %s\n", (-fsize
-k
)&0xffff, reg_names
[via_ac
]);
319 fprintf(stream
, "\tstd %s, %s\n", reg_names
[via_ac
], reg_names
[i
]);
324 fprintf(stream
, "\tmov r5, sp\n");
325 fprintf (stream
, "\tmov (sp)+, r5\n");
329 via_ac
= FIRST_PSEUDO_REGISTER
-1;
332 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
333 if (regs_ever_live
[i
] && call_used_regs
[i
])
336 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
338 if (LOAD_FPU_REG_P(i
)
340 && ! call_used_regs
[i
])
341 fprintf(stream
, "\tldd (sp)+, %s\n", reg_names
[i
]);
343 if (NO_LOAD_FPU_REG_P(i
)
345 && ! call_used_regs
[i
])
347 if (! LOAD_FPU_REG_P(via_ac
))
350 fprintf(stream
, "\tldd (sp)+, %s\n", reg_names
[via_ac
]);
351 fprintf(stream
, "\tstd %s, %s\n", reg_names
[via_ac
], reg_names
[i
]);
355 for (i
=7; i
>= 0; i
--)
356 if (regs_ever_live
[i
] && !call_used_regs
[i
])
357 fprintf(stream
, "\tmov (sp)+, %s\n", reg_names
[i
]);
360 fprintf((stream
), "\tadd $%#o, sp\n", (fsize
)&0xffff);
363 fprintf (stream
, "\trts pc\n");
364 fprintf (stream
, "\t;/* end of epilogue*/\n\n\n");
367 #endif /* !TWO_BSD */
369 /* Return the best assembler insn template
370 for moving operands[1] into operands[0] as a fullword. */
372 singlemove_string (operands
)
375 if (operands
[1] != const0_rtx
)
382 /* Output assembler code to perform a doubleword move insn
383 with operands OPERANDS. */
386 output_move_double (operands
)
389 enum { REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
391 rtx addreg0
= 0, addreg1
= 0;
393 /* First classify both operands. */
395 if (REG_P (operands
[0]))
397 else if (offsettable_memref_p (operands
[0]))
399 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
401 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
403 else if (GET_CODE (operands
[0]) == MEM
)
408 if (REG_P (operands
[1]))
410 else if (CONSTANT_P (operands
[1])
412 || GET_CODE (operands
[1]) == CONST_DOUBLE
416 else if (offsettable_memref_p (operands
[1]))
418 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
420 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
422 else if (GET_CODE (operands
[1]) == MEM
)
427 /* Check for the cases that the operand constraints are not
428 supposed to allow to happen. Abort if we get one,
429 because generating code for these cases is painful. */
431 if (optype0
== RNDOP
|| optype1
== RNDOP
)
434 /* If one operand is decrementing and one is incrementing
435 decrement the former register explicitly
436 and change that operand into ordinary indexing. */
438 if (optype0
== PUSHOP
&& optype1
== POPOP
)
440 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
441 output_asm_insn ("sub $4,%0", operands
);
442 operands
[0] = gen_rtx_MEM (SImode
, operands
[0]);
445 if (optype0
== POPOP
&& optype1
== PUSHOP
)
447 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
448 output_asm_insn ("sub $4,%1", operands
);
449 operands
[1] = gen_rtx_MEM (SImode
, operands
[1]);
453 /* If an operand is an unoffsettable memory ref, find a register
454 we can increment temporarily to make it refer to the second word. */
456 if (optype0
== MEMOP
)
457 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
459 if (optype1
== MEMOP
)
460 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
462 /* Ok, we can do one word at a time.
463 Normally we do the low-numbered word first,
464 but if either operand is autodecrementing then we
465 do the high-numbered word first.
467 In either case, set up in LATEHALF the operands to use
468 for the high-numbered word and in some cases alter the
469 operands in OPERANDS to be suitable for the low-numbered word. */
471 if (optype0
== REGOP
)
472 latehalf
[0] = gen_rtx_REG (HImode
, REGNO (operands
[0]) + 1);
473 else if (optype0
== OFFSOP
)
474 latehalf
[0] = adjust_address (operands
[0], HImode
, 2);
476 latehalf
[0] = operands
[0];
478 if (optype1
== REGOP
)
479 latehalf
[1] = gen_rtx_REG (HImode
, REGNO (operands
[1]) + 1);
480 else if (optype1
== OFFSOP
)
481 latehalf
[1] = adjust_address (operands
[1], HImode
, 2);
482 else if (optype1
== CNSTOP
)
484 if (CONSTANT_P (operands
[1]))
486 /* now the mess begins, high word is in lower word???
488 that's what ashc makes me think, but I don't remember :-( */
489 latehalf
[1] = GEN_INT (INTVAL(operands
[1]) >> 16);
490 operands
[1] = GEN_INT (INTVAL(operands
[1]) & 0xff);
492 else if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
494 /* immediate 32 bit values not allowed */
499 latehalf
[1] = operands
[1];
501 /* If insn is effectively movd N(sp),-(sp) then we will do the
502 high word first. We should use the adjusted operand 1 (which is N+4(sp))
503 for the low word as well, to compensate for the first decrement of sp. */
504 if (optype0
== PUSHOP
505 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
506 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
507 operands
[1] = latehalf
[1];
509 /* If one or both operands autodecrementing,
510 do the two words, high-numbered first. */
512 /* Likewise, the first move would clobber the source of the second one,
513 do them in the other order. This happens only for registers;
514 such overlap can't happen in memory unless the user explicitly
515 sets it up, and that is an undefined circumstance. */
517 if (optype0
== PUSHOP
|| optype1
== PUSHOP
518 || (optype0
== REGOP
&& optype1
== REGOP
519 && REGNO (operands
[0]) == REGNO (latehalf
[1])))
521 /* Make any unoffsettable addresses point at high-numbered word. */
523 output_asm_insn ("add $2,%0", &addreg0
);
525 output_asm_insn ("add $2,%0", &addreg1
);
528 output_asm_insn (singlemove_string (latehalf
), latehalf
);
530 /* Undo the adds we just did. */
532 output_asm_insn ("sub $2,%0", &addreg0
);
534 output_asm_insn ("sub $2,%0", &addreg1
);
536 /* Do low-numbered word. */
537 return singlemove_string (operands
);
540 /* Normal case: do the two words, low-numbered first. */
542 output_asm_insn (singlemove_string (operands
), operands
);
544 /* Make any unoffsettable addresses point at high-numbered word. */
546 output_asm_insn ("add $2,%0", &addreg0
);
548 output_asm_insn ("add $2,%0", &addreg1
);
551 output_asm_insn (singlemove_string (latehalf
), latehalf
);
553 /* Undo the adds we just did. */
555 output_asm_insn ("sub $2,%0", &addreg0
);
557 output_asm_insn ("sub $2,%0", &addreg1
);
561 /* Output assembler code to perform a quadword move insn
562 with operands OPERANDS. */
565 output_move_quad (operands
)
568 enum { REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
570 rtx addreg0
= 0, addreg1
= 0;
572 output_asm_insn(";/* movdi/df: %1 -> %0 */", operands
);
574 if (REG_P (operands
[0]))
576 else if (offsettable_memref_p (operands
[0]))
578 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
580 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
582 else if (GET_CODE (operands
[0]) == MEM
)
587 if (REG_P (operands
[1]))
589 else if (CONSTANT_P (operands
[1])
590 || GET_CODE (operands
[1]) == CONST_DOUBLE
)
592 else if (offsettable_memref_p (operands
[1]))
594 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
596 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
598 else if (GET_CODE (operands
[1]) == MEM
)
603 /* Check for the cases that the operand constraints are not
604 supposed to allow to happen. Abort if we get one,
605 because generating code for these cases is painful. */
607 if (optype0
== RNDOP
|| optype1
== RNDOP
)
610 /* check if we move a CPU reg to an FPU reg, or vice versa! */
611 if (optype0
== REGOP
&& optype1
== REGOP
)
612 /* bogus - 64 bit cannot reside in CPU! */
613 if (CPU_REG_P(REGNO(operands
[0]))
614 || CPU_REG_P (REGNO(operands
[1])))
617 if (optype0
== REGOP
|| optype1
== REGOP
)
619 /* check for use of clrd????
620 if you ever allow ac4 and ac5 (now we require secondary load)
621 you must check whether
622 you want to load into them or store from them -
623 then dump ac0 into $help$ movce ac4/5 to ac0, do the
624 store from ac0, and restore ac0 - if you can find
625 an unused ac[0-3], use that and you save a store and a load!*/
627 if (FPU_REG_P(REGNO(operands
[0])))
629 if (GET_CODE(operands
[1]) == CONST_DOUBLE
)
632 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
634 if (REAL_VALUES_EQUAL (r
, dconst0
))
635 return "{clrd|clrf} %0";
638 return "{ldd|movf} %1, %0";
641 if (FPU_REG_P(REGNO(operands
[1])))
642 return "{std|movf} %1, %0";
645 /* If one operand is decrementing and one is incrementing
646 decrement the former register explicitly
647 and change that operand into ordinary indexing. */
649 if (optype0
== PUSHOP
&& optype1
== POPOP
)
651 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
652 output_asm_insn ("sub $8,%0", operands
);
653 operands
[0] = gen_rtx_MEM (DImode
, operands
[0]);
656 if (optype0
== POPOP
&& optype1
== PUSHOP
)
658 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
659 output_asm_insn ("sub $8,%1", operands
);
660 operands
[1] = gen_rtx_MEM (SImode
, operands
[1]);
664 /* If an operand is an unoffsettable memory ref, find a register
665 we can increment temporarily to make it refer to the second word. */
667 if (optype0
== MEMOP
)
668 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
670 if (optype1
== MEMOP
)
671 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
673 /* Ok, we can do one word at a time.
674 Normally we do the low-numbered word first,
675 but if either operand is autodecrementing then we
676 do the high-numbered word first.
678 In either case, set up in LATEHALF the operands to use
679 for the high-numbered word and in some cases alter the
680 operands in OPERANDS to be suitable for the low-numbered word. */
682 if (optype0
== REGOP
)
683 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 2);
684 else if (optype0
== OFFSOP
)
685 latehalf
[0] = adjust_address (operands
[0], SImode
, 4);
687 latehalf
[0] = operands
[0];
689 if (optype1
== REGOP
)
690 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 2);
691 else if (optype1
== OFFSOP
)
692 latehalf
[1] = adjust_address (operands
[1], SImode
, 4);
693 else if (optype1
== CNSTOP
)
695 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
697 /* floats only. not yet supported!
699 -- compute it into PDP float format, - internally,
700 just use IEEE and ignore possible problems ;-)
702 we might get away with it !!!! */
706 #ifndef HOST_WORDS_BIG_ENDIAN
707 latehalf
[1] = GEN_INT (CONST_DOUBLE_LOW (operands
[1]));
708 operands
[1] = GEN_INT (CONST_DOUBLE_HIGH (operands
[1]));
709 #else /* HOST_WORDS_BIG_ENDIAN */
710 latehalf
[1] = GEN_INT (CONST_DOUBLE_HIGH (operands
[1]));
711 operands
[1] = GEN_INT (CONST_DOUBLE_LOW (operands
[1]));
712 #endif /* HOST_WORDS_BIG_ENDIAN */
714 else if (GET_CODE(operands
[1]) == CONST_INT
)
716 latehalf
[1] = GEN_INT (0);
722 latehalf
[1] = operands
[1];
724 /* If insn is effectively movd N(sp),-(sp) then we will do the
725 high word first. We should use the adjusted operand 1 (which is N+4(sp))
726 for the low word as well, to compensate for the first decrement of sp. */
727 if (optype0
== PUSHOP
728 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
729 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
730 operands
[1] = latehalf
[1];
732 /* If one or both operands autodecrementing,
733 do the two words, high-numbered first. */
735 /* Likewise, the first move would clobber the source of the second one,
736 do them in the other order. This happens only for registers;
737 such overlap can't happen in memory unless the user explicitly
738 sets it up, and that is an undefined circumstance. */
740 if (optype0
== PUSHOP
|| optype1
== PUSHOP
741 || (optype0
== REGOP
&& optype1
== REGOP
742 && REGNO (operands
[0]) == REGNO (latehalf
[1])))
744 /* Make any unoffsettable addresses point at high-numbered word. */
746 output_asm_insn ("add $4,%0", &addreg0
);
748 output_asm_insn ("add $4,%0", &addreg1
);
751 output_asm_insn(output_move_double(latehalf
), latehalf
);
753 /* Undo the adds we just did. */
755 output_asm_insn ("sub $4,%0", &addreg0
);
757 output_asm_insn ("sub $4,%0", &addreg1
);
759 /* Do low-numbered word. */
760 return output_move_double (operands
);
763 /* Normal case: do the two words, low-numbered first. */
765 output_asm_insn (output_move_double (operands
), operands
);
767 /* Make any unoffsettable addresses point at high-numbered word. */
769 output_asm_insn ("add $4,%0", &addreg0
);
771 output_asm_insn ("add $4,%0", &addreg1
);
774 output_asm_insn (output_move_double (latehalf
), latehalf
);
776 /* Undo the adds we just did. */
778 output_asm_insn ("sub $4,%0", &addreg0
);
780 output_asm_insn ("sub $4,%0", &addreg1
);
786 /* Return a REG that occurs in ADDR with coefficient 1.
787 ADDR can be effectively incremented by incrementing REG. */
793 while (GET_CODE (addr
) == PLUS
)
795 if (GET_CODE (XEXP (addr
, 0)) == REG
)
796 addr
= XEXP (addr
, 0);
797 if (GET_CODE (XEXP (addr
, 1)) == REG
)
798 addr
= XEXP (addr
, 1);
799 if (CONSTANT_P (XEXP (addr
, 0)))
800 addr
= XEXP (addr
, 1);
801 if (CONSTANT_P (XEXP (addr
, 1)))
802 addr
= XEXP (addr
, 0);
804 if (GET_CODE (addr
) == REG
)
809 /* Output an ascii string. */
811 output_ascii (file
, p
, size
)
818 /* This used to output .byte "string", which doesn't work with the UNIX
819 assembler and I think not with DEC ones either. */
820 fprintf (file
, "\t.byte ");
822 for (i
= 0; i
< size
; i
++)
824 register int c
= p
[i
];
827 fprintf (file
, "%#o", c
);
835 /* --- stole from out-vax, needs changes */
838 print_operand_address (file
, addr
)
842 register rtx reg1
, reg2
, breg
, ireg
;
847 switch (GET_CODE (addr
))
854 addr
= XEXP (addr
, 0);
858 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
863 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
868 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
875 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
876 || GET_CODE (XEXP (addr
, 0)) == MEM
)
878 offset
= XEXP (addr
, 0);
879 addr
= XEXP (addr
, 1);
881 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
882 || GET_CODE (XEXP (addr
, 1)) == MEM
)
884 offset
= XEXP (addr
, 1);
885 addr
= XEXP (addr
, 0);
887 if (GET_CODE (addr
) != PLUS
)
889 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
891 reg1
= XEXP (addr
, 0);
892 addr
= XEXP (addr
, 1);
894 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
896 reg1
= XEXP (addr
, 1);
897 addr
= XEXP (addr
, 0);
899 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
901 reg1
= XEXP (addr
, 0);
902 addr
= XEXP (addr
, 1);
904 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
906 reg1
= XEXP (addr
, 1);
907 addr
= XEXP (addr
, 0);
909 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
)
919 if (addr
!= 0) abort ();
922 if (reg1
!= 0 && GET_CODE (reg1
) == MULT
)
927 else if (reg2
!= 0 && GET_CODE (reg2
) == MULT
)
932 else if (reg2
!= 0 || GET_CODE (addr
) == MEM
)
943 output_address (addr
);
946 if (GET_CODE (breg
) != REG
)
948 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
952 if (GET_CODE (ireg
) == MULT
)
953 ireg
= XEXP (ireg
, 0);
954 if (GET_CODE (ireg
) != REG
)
957 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
962 output_addr_const_pdp11 (file
, addr
);
966 /* Target hook to assemble integer objects. We need to use the
967 pdp-specific version of output_addr_const. */
970 pdp11_assemble_integer (x
, size
, aligned_p
)
979 fprintf (asm_out_file
, "\t.byte\t");
980 output_addr_const_pdp11 (asm_out_file
, x
);
981 fprintf (asm_out_file
, " /* char */\n");
985 fprintf (asm_out_file
, TARGET_UNIX_ASM
? "\t" : "\t.word\t");
986 output_addr_const_pdp11 (asm_out_file
, x
);
987 fprintf (asm_out_file
, " /* short */\n");
990 return default_assemble_integer (x
, size
, aligned_p
);
994 /* register move costs, indexed by regs */
996 static const int move_costs
[N_REG_CLASSES
][N_REG_CLASSES
] =
998 /* NO MUL GEN LFPU NLFPU FPU ALL */
1000 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
1001 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
1002 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
1003 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
1004 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
1005 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
1006 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
1010 /* -- note that some moves are tremendously expensive,
1011 because they require lots of tricks! do we have to
1012 charge the costs incurred by secondary reload class
1013 -- as we do here with 22 -- or not ? */
1016 register_move_cost(c1
, c2
)
1017 enum reg_class c1
, c2
;
1019 return move_costs
[(int)c1
][(int)c2
];
1023 pdp11_rtx_costs (x
, code
, outer_code
, total
)
1025 int code
, outer_code ATTRIBUTE_UNUSED
;
1031 if (INTVAL (x
) == 0 || INTVAL (x
) == -1 || INTVAL (x
) == 1)
1041 /* Twice as expensive as REG. */
1046 /* Twice (or 4 times) as expensive as 16 bit. */
1051 /* ??? There is something wrong in MULT because MULT is not
1052 as cheap as total = 2 even if we can shift! */
1053 /* If optimizing for size make mult etc cheap, but not 1, so when
1054 in doubt the faster insn is chosen. */
1056 *total
= COSTS_N_INSNS (2);
1058 *total
= COSTS_N_INSNS (11);
1063 *total
= COSTS_N_INSNS (2);
1065 *total
= COSTS_N_INSNS (25);
1070 *total
= COSTS_N_INSNS (2);
1072 *total
= COSTS_N_INSNS (26);
1076 /* Equivalent to length, so same for optimize_size. */
1077 *total
= COSTS_N_INSNS (3);
1081 /* Only used for qi->hi. */
1082 *total
= COSTS_N_INSNS (1);
1086 if (GET_MODE (x
) == HImode
)
1087 *total
= COSTS_N_INSNS (1);
1088 else if (GET_MODE (x
) == SImode
)
1089 *total
= COSTS_N_INSNS (6);
1091 *total
= COSTS_N_INSNS (2);
1098 *total
= COSTS_N_INSNS (1);
1099 else if (GET_MODE (x
) == QImode
)
1101 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
1102 *total
= COSTS_N_INSNS (8); /* worst case */
1104 *total
= COSTS_N_INSNS (INTVAL (XEXP (x
, 1)));
1106 else if (GET_MODE (x
) == HImode
)
1108 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
1110 if (abs (INTVAL (XEXP (x
, 1))) == 1)
1111 *total
= COSTS_N_INSNS (1);
1113 *total
= COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x
, 1)));
1116 *total
= COSTS_N_INSNS (10); /* worst case */
1118 else if (GET_MODE (x
) == SImode
)
1120 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
1121 *total
= COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x
, 1)));
1122 else /* worst case */
1123 *total
= COSTS_N_INSNS (18);
1133 output_jump(pos
, neg
, length
)
1134 const char *pos
, *neg
;
1139 static char buf
[1000];
1142 /* currently we don't need this, because the tstdf and cmpdf
1143 copy the condition code immediately, and other float operations are not
1144 yet recognized as changing the FCC - if so, then the length-cost of all
1145 jump insns increases by one, because we have to potentially copy the
1147 if (cc_status
.flags
& CC_IN_FPU
)
1148 output_asm_insn("cfcc", NULL
);
1156 strcat(buf
, " %l0");
1162 sprintf(buf
, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg
, x
, x
);
1176 notice_update_cc_on_set(exp
, insn
)
1178 rtx insn ATTRIBUTE_UNUSED
;
1180 if (GET_CODE (SET_DEST (exp
)) == CC0
)
1182 cc_status
.flags
= 0;
1183 cc_status
.value1
= SET_DEST (exp
);
1184 cc_status
.value2
= SET_SRC (exp
);
1187 if (GET_MODE(SET_SRC(exp)) == DFmode)
1188 cc_status.flags |= CC_IN_FPU;
1191 else if ((GET_CODE (SET_DEST (exp
)) == REG
1192 || GET_CODE (SET_DEST (exp
)) == MEM
)
1193 && GET_CODE (SET_SRC (exp
)) != PC
1194 && (GET_MODE (SET_DEST(exp
)) == HImode
1195 || GET_MODE (SET_DEST(exp
)) == QImode
)
1196 && (GET_CODE (SET_SRC(exp
)) == PLUS
1197 || GET_CODE (SET_SRC(exp
)) == MINUS
1198 || GET_CODE (SET_SRC(exp
)) == AND
1199 || GET_CODE (SET_SRC(exp
)) == IOR
1200 || GET_CODE (SET_SRC(exp
)) == XOR
1201 || GET_CODE (SET_SRC(exp
)) == NOT
1202 || GET_CODE (SET_SRC(exp
)) == NEG
1203 || GET_CODE (SET_SRC(exp
)) == REG
1204 || GET_CODE (SET_SRC(exp
)) == MEM
))
1206 cc_status
.flags
= 0;
1207 cc_status
.value1
= SET_SRC (exp
);
1208 cc_status
.value2
= SET_DEST (exp
);
1210 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
1212 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
1213 cc_status
.value2
= 0;
1214 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == MEM
1216 && GET_CODE (cc_status
.value2
) == MEM
)
1217 cc_status
.value2
= 0;
1219 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1223 else if (GET_CODE (SET_DEST (exp
)) == REG
)
1226 if ((cc_status
.value1
1227 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
)))
1228 cc_status
.value1
= 0;
1229 if ((cc_status
.value2
1230 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
)))
1231 cc_status
.value2
= 0;
1233 else if (SET_DEST(exp
) == pc_rtx
)
1237 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1239 /* the last else is a bit paranoiac, but since nearly all instructions
1240 play with condition codes, it's reasonable! */
1242 CC_STATUS_INIT
; /* paranoia*/
1248 simple_memory_operand(op
, mode
)
1250 enum machine_mode mode ATTRIBUTE_UNUSED
;
1254 /* Eliminate non-memory operations */
1255 if (GET_CODE (op
) != MEM
)
1259 /* dword operations really put out 2 instructions, so eliminate them. */
1260 if (GET_MODE_SIZE (GET_MODE (op
)) > (HAVE_64BIT_P () ? 8 : 4))
1264 /* Decode the address now. */
1268 addr
= XEXP (op
, 0);
1270 switch (GET_CODE (addr
))
1273 /* (R0) - no extra cost */
1278 /* -(R0), (R0)+ - cheap! */
1282 /* cheap - is encoded in addressing mode info!
1284 -- except for @(R0), which has to be @0(R0) !!! */
1286 if (GET_CODE (XEXP (addr
, 0)) == REG
)
1296 /* @#address - extra cost */
1300 /* X(R0) - extra cost */
1312 * output a block move:
1314 * operands[0] ... to
1315 * operands[1] ... from
1316 * operands[2] ... length
1317 * operands[3] ... alignment
1318 * operands[4] ... scratch register
1323 output_block_move(operands
)
1326 static int count
= 0;
1329 if (GET_CODE(operands
[2]) == CONST_INT
1332 if (INTVAL(operands
[2]) < 16
1333 && INTVAL(operands
[3]) == 1)
1337 for (i
= 1; i
<= INTVAL(operands
[2]); i
++)
1338 output_asm_insn("movb (%1)+, (%0)+", operands
);
1342 else if (INTVAL(operands
[2]) < 32)
1346 for (i
= 1; i
<= INTVAL(operands
[2])/2; i
++)
1347 output_asm_insn("mov (%1)+, (%0)+", operands
);
1349 /* may I assume that moved quantity is
1350 multiple of alignment ???
1359 /* can do other clever things, maybe... */
1362 if (CONSTANT_P(operands
[2]) )
1364 /* just move count to scratch */
1365 output_asm_insn("mov %2, %4", operands
);
1369 /* just clobber the register */
1370 operands
[4] = operands
[2];
1374 /* switch over alignment */
1375 switch (INTVAL(operands
[3]))
1391 sprintf(buf
, "\nmovestrhi%d:", count
);
1392 output_asm_insn(buf
, NULL
);
1394 output_asm_insn("movb (%1)+, (%0)+", operands
);
1398 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1399 output_asm_insn(buf
, operands
);
1403 output_asm_insn("dec %4", operands
);
1405 sprintf(buf
, "bgt movestrhi%d", count
);
1406 output_asm_insn(buf
, NULL
);
1428 generate_compact_code
:
1430 output_asm_insn("asr %4", operands
);
1432 sprintf(buf
, "\nmovestrhi%d:", count
);
1433 output_asm_insn(buf
, NULL
);
1435 output_asm_insn("mov (%1)+, (%0)+", operands
);
1439 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1440 output_asm_insn(buf
, operands
);
1444 output_asm_insn("dec %4", operands
);
1446 sprintf(buf
, "bgt movestrhi%d", count
);
1447 output_asm_insn(buf
, NULL
);
1473 goto generate_compact_code
;
1475 output_asm_insn("asr %4", operands
);
1476 output_asm_insn("asr %4", operands
);
1478 sprintf(buf
, "\nmovestrhi%d:", count
);
1479 output_asm_insn(buf
, NULL
);
1481 output_asm_insn("mov (%1)+, (%0)+", operands
);
1482 output_asm_insn("mov (%1)+, (%0)+", operands
);
1486 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1487 output_asm_insn(buf
, operands
);
1491 output_asm_insn("dec %4", operands
);
1493 sprintf(buf
, "bgt movestrhi%d", count
);
1494 output_asm_insn(buf
, NULL
);
1524 goto generate_compact_code
;
1526 output_asm_insn("asr %4", operands
);
1527 output_asm_insn("asr %4", operands
);
1528 output_asm_insn("asr %4", operands
);
1530 sprintf(buf
, "\nmovestrhi%d:", count
);
1531 output_asm_insn(buf
, NULL
);
1533 output_asm_insn("mov (%1)+, (%0)+", operands
);
1534 output_asm_insn("mov (%1)+, (%0)+", operands
);
1535 output_asm_insn("mov (%1)+, (%0)+", operands
);
1536 output_asm_insn("mov (%1)+, (%0)+", operands
);
1540 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1541 output_asm_insn(buf
, operands
);
1545 output_asm_insn("dec %4", operands
);
1547 sprintf(buf
, "bgt movestrhi%d", count
);
1548 output_asm_insn(buf
, NULL
);
1561 /* for future use */
1563 comparison_operator_index(op
)
1566 switch (GET_CODE(op
))
1603 /* tests whether the rtx is a comparison operator */
1605 comp_operator (op
, mode
)
1607 enum machine_mode mode ATTRIBUTE_UNUSED
;
1609 return comparison_operator_index(op
) >= 0;
1614 legitimate_address_p (mode
, address
)
1615 enum machine_mode mode
;
1618 /* #define REG_OK_STRICT */
1619 GO_IF_LEGITIMATE_ADDRESS(mode
, address
, win
);
1626 /* #undef REG_OK_STRICT */
1629 /* A copy of output_addr_const modified for pdp11 expression syntax.
1630 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1631 use, and for debugging output, which we don't support with this port either.
1632 So this copy should get called whenever needed.
1635 output_addr_const_pdp11 (file
, x
)
1642 switch (GET_CODE (x
))
1652 assemble_name (file
, XSTR (x
, 0));
1656 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
1657 assemble_name (file
, buf
);
1661 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
1662 assemble_name (file
, buf
);
1666 /* Should we check for constants which are too big? Maybe cutting
1667 them off to 16 bits is OK? */
1668 fprintf (file
, "%#ho", (unsigned short) INTVAL (x
));
1672 /* This used to output parentheses around the expression,
1673 but that does not work on the 386 (either ATT or BSD assembler). */
1674 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1678 if (GET_MODE (x
) == VOIDmode
)
1680 /* We can use %o if the number is one word and positive. */
1681 if (CONST_DOUBLE_HIGH (x
))
1682 abort (); /* Should we just silently drop the high part? */
1684 fprintf (file
, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x
));
1687 /* We can't handle floating point constants;
1688 PRINT_OPERAND must handle them. */
1689 output_operand_lossage ("floating constant misused");
1693 /* Some assemblers need integer constants to appear last (eg masm). */
1694 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
1696 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1697 if (INTVAL (XEXP (x
, 0)) >= 0)
1698 fprintf (file
, "+");
1699 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1703 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1704 if (INTVAL (XEXP (x
, 1)) >= 0)
1705 fprintf (file
, "+");
1706 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1711 /* Avoid outputting things like x-x or x+5-x,
1712 since some assemblers can't handle that. */
1713 x
= simplify_subtraction (x
);
1714 if (GET_CODE (x
) != MINUS
)
1717 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1718 fprintf (file
, "-");
1719 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
1720 && INTVAL (XEXP (x
, 1)) < 0)
1722 fprintf (file
, targetm
.asm_out
.open_paren
);
1723 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1724 fprintf (file
, targetm
.asm_out
.close_paren
);
1727 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1732 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1736 output_operand_lossage ("invalid expression as operand");