1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994, 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
3 Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-flags.h"
33 #include "insn-attr.h"
38 #define FPU_REG_P(X) ((X)>=8 && (X)<14)
39 #define CPU_REG_P(X) ((X)>=0 && (X)<8)
42 /* this is the current value returned by the macro FIRST_PARM_OFFSET
44 int current_first_parm_offset
;
46 /* This is where the condition code register lives. */
47 /* rtx cc0_reg_rtx; - no longer needed? */
49 static rtx
find_addr_reg ();
51 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
54 arith_operand (op
, mode
)
56 enum machine_mode mode
;
58 return (register_operand (op
, mode
) || GET_CODE (op
) == CONST_INT
);
62 const_immediate_operand (op
, mode
)
64 enum machine_mode mode
;
66 return (GET_CODE (op
) == CONST_INT
);
70 immediate15_operand (op
, mode
)
72 enum machine_mode mode
;
74 return (GET_CODE (op
) == CONST_INT
&& ((INTVAL (op
) & 0x8000) == 0x0000));
78 expand_shift_operand (op
, mode
)
80 enum machine_mode mode
;
82 return (GET_CODE (op
) == CONST_INT
83 && abs (INTVAL(op
)) > 1
84 && abs (INTVAL(op
)) <= 4);
88 stream is a stdio stream to output the code to.
89 size is an int: how many units of temporary storage to allocate.
90 Refer to the array `regs_ever_live' to determine which registers
91 to save; `regs_ever_live[I]' is nonzero if register number I
92 is ever used in the function. This macro is responsible for
93 knowing which registers should not be saved even if used.
97 output_function_prologue(stream
, size
)
101 int fsize
= ((size
) + 1) & ~1;
106 fprintf (stream
, "\n\t; /* function prologue %s*/\n", current_function_name
);
108 /* if we are outputting code for main,
109 the switch FPU to right mode if TARGET_FPU */
110 if ( (strcmp ("main", current_function_name
) == 0)
113 fprintf(stream
, "\t;/* switch cpu to double float, single integer */\n");
114 fprintf(stream
, "\tsetd\n");
115 fprintf(stream
, "\tseti\n\n");
118 if (frame_pointer_needed
)
120 fprintf(stream
, "\tmov fp, -(sp)\n");
121 fprintf(stream
, "\tmov sp, fp\n");
130 fprintf (stream
, "\tsub $%o, sp\n", fsize
);
132 /* save CPU registers */
133 for (regno
= 0; regno
< 8; regno
++)
134 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
135 if (! ((regno
== FRAME_POINTER_REGNUM
)
136 && frame_pointer_needed
))
137 fprintf (stream
, "\tmov %s, -(sp)\n", reg_names
[regno
]);
138 /* fpu regs saving */
140 /* via_ac specifies the ac to use for saving ac4, ac5 */
143 for (regno
= 8; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
146 if (LOAD_FPU_REG_P(regno
)
147 && regs_ever_live
[regno
]
148 && ! call_used_regs
[regno
])
150 fprintf (stream
, "\tfstd %s, -(sp)\n", reg_names
[regno
]);
154 /* maybe make ac4, ac5 call used regs?? */
156 if (NO_LOAD_FPU_REG_P(regno
)
157 && regs_ever_live
[regno
]
158 && ! call_used_regs
[regno
])
163 fprintf (stream
, "\tfldd %s, %s\n", reg_names
[regno
], reg_names
[via_ac
]);
164 fprintf (stream
, "\tfstd %s, -(sp)\n", reg_names
[via_ac
]);
168 fprintf (stream
, "\t;/* end of prologue */\n\n");
172 The function epilogue should not depend on the current stack pointer!
173 It should use the frame pointer only. This is mandatory because
174 of alloca; we also take advantage of it to omit stack adjustments
177 /* maybe we can make leaf functions faster by switching to the
178 second register file - this way we don't have to save regs!
179 leaf functions are ~ 50% of all functions (dynamically!)
181 set/clear bit 11 (dec. 2048) of status word for switching register files -
182 but how can we do this? the pdp11/45 manual says bit may only
183 be set (p.24), but not cleared!
185 switching to kernel is probably more expensive, so we'll leave it
186 like this and not use the second set of registers...
188 maybe as option if you want to generate code for kernel mode? */
192 output_function_epilogue(stream
, size
)
196 int fsize
= ((size
) + 1) & ~1;
201 fprintf (stream
, "\n\t; /*function epilogue */\n");
203 if (frame_pointer_needed
)
205 /* hope this is safe - m68k does it also .... */
206 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
208 for (i
=7, j
= 0 ; i
>= 0 ; i
--)
209 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
212 /* remember # of pushed bytes for CPU regs */
215 for (i
=7 ; i
>= 0 ; i
--)
216 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
217 fprintf(stream
, "\tmov %o(fp), %s\n",-fsize
-2*j
--, reg_names
[i
]);
220 via_ac
= FIRST_PSEUDO_REGISTER
-1;
222 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
223 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
229 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
231 if (LOAD_FPU_REG_P(i
)
233 && ! call_used_regs
[i
])
235 fprintf(stream
, "\tfldd %o(fp), %s\n", -fsize
-k
, reg_names
[i
]);
239 if (NO_LOAD_FPU_REG_P(i
)
241 && ! call_used_regs
[i
])
243 if (! LOAD_FPU_REG_P(via_ac
))
246 fprintf(stream
, "\tfldd %o(fp), %s\n", -fsize
-k
, reg_names
[via_ac
]);
247 fprintf(stream
, "\tfstd %s, %s\n", reg_names
[via_ac
], reg_names
[i
]);
252 fprintf(stream
, "\tmov fp, sp\n");
253 fprintf (stream
, "\tmov (sp)+, fp\n");
257 via_ac
= FIRST_PSEUDO_REGISTER
-1;
260 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
261 if (regs_ever_live
[i
] && call_used_regs
[i
])
264 for (i
= FIRST_PSEUDO_REGISTER
; i
> 7; i
--)
266 if (LOAD_FPU_REG_P(i
)
268 && ! call_used_regs
[i
])
269 fprintf(stream
, "\tfldd (sp)+, %s\n", reg_names
[i
]);
271 if (NO_LOAD_FPU_REG_P(i
)
273 && ! call_used_regs
[i
])
275 if (! LOAD_FPU_REG_P(via_ac
))
278 fprintf(stream
, "\tfldd (sp)+, %s\n", reg_names
[via_ac
]);
279 fprintf(stream
, "\tfstd %s, %s\n", reg_names
[via_ac
], reg_names
[i
]);
283 for (i
=7; i
>= 0; i
--)
284 if (regs_ever_live
[i
] && !call_used_regs
[i
])
285 fprintf(stream
, "\tmov (sp)+, %s\n", reg_names
[i
]);
288 fprintf((stream
), "\tadd $%o, sp\n", fsize
);
291 fprintf (stream
, "\trts pc\n");
292 fprintf (stream
, "\t;/* end of epilogue*/\n\n\n");
295 /* Return the best assembler insn template
296 for moving operands[1] into operands[0] as a fullword. */
298 singlemove_string (operands
)
301 if (operands
[1] != const0_rtx
)
308 /* Output assembler code to perform a doubleword move insn
309 with operands OPERANDS. */
312 output_move_double (operands
)
315 enum { REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
317 rtx addreg0
= 0, addreg1
= 0;
319 /* First classify both operands. */
321 if (REG_P (operands
[0]))
323 else if (offsettable_memref_p (operands
[0]))
325 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
327 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
329 else if (GET_CODE (operands
[0]) == MEM
)
334 if (REG_P (operands
[1]))
336 else if (CONSTANT_P (operands
[1]))
338 || GET_CODE (operands
[1]) == CONST_DOUBLE
)
341 else if (offsettable_memref_p (operands
[1]))
343 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
345 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
347 else if (GET_CODE (operands
[1]) == MEM
)
352 /* Check for the cases that the operand constraints are not
353 supposed to allow to happen. Abort if we get one,
354 because generating code for these cases is painful. */
356 if (optype0
== RNDOP
|| optype1
== RNDOP
)
359 /* If one operand is decrementing and one is incrementing
360 decrement the former register explicitly
361 and change that operand into ordinary indexing. */
363 if (optype0
== PUSHOP
&& optype1
== POPOP
)
365 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
366 output_asm_insn ("sub $4,%0", operands
);
367 operands
[0] = gen_rtx (MEM
, SImode
, operands
[0]);
370 if (optype0
== POPOP
&& optype1
== PUSHOP
)
372 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
373 output_asm_insn ("sub $4,%1", operands
);
374 operands
[1] = gen_rtx (MEM
, SImode
, operands
[1]);
378 /* If an operand is an unoffsettable memory ref, find a register
379 we can increment temporarily to make it refer to the second word. */
381 if (optype0
== MEMOP
)
382 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
384 if (optype1
== MEMOP
)
385 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
387 /* Ok, we can do one word at a time.
388 Normally we do the low-numbered word first,
389 but if either operand is autodecrementing then we
390 do the high-numbered word first.
392 In either case, set up in LATEHALF the operands to use
393 for the high-numbered word and in some cases alter the
394 operands in OPERANDS to be suitable for the low-numbered word. */
396 if (optype0
== REGOP
)
397 latehalf
[0] = gen_rtx (REG
, HImode
, REGNO (operands
[0]) + 1);
398 else if (optype0
== OFFSOP
)
399 latehalf
[0] = adj_offsettable_operand (operands
[0], 2);
401 latehalf
[0] = operands
[0];
403 if (optype1
== REGOP
)
404 latehalf
[1] = gen_rtx (REG
, HImode
, REGNO (operands
[1]) + 1);
405 else if (optype1
== OFFSOP
)
406 latehalf
[1] = adj_offsettable_operand (operands
[1], 2);
407 else if (optype1
== CNSTOP
)
409 if (CONSTANT_P (operands
[1]))
411 /* now the mess begins, high word is in lower word???
413 that's what ashc makes me think, but I don't remember :-( */
414 latehalf
[1] = GEN_INT (INTVAL(operands
[1])>>16);
415 operands
[1] = GEN_INT (INTVAL(operands
[1])&0xff);
417 else if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
419 /* immediate 32 bit values not allowed */
424 latehalf
[1] = operands
[1];
426 /* If insn is effectively movd N(sp),-(sp) then we will do the
427 high word first. We should use the adjusted operand 1 (which is N+4(sp))
428 for the low word as well, to compensate for the first decrement of sp. */
429 if (optype0
== PUSHOP
430 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
431 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
432 operands
[1] = latehalf
[1];
434 /* If one or both operands autodecrementing,
435 do the two words, high-numbered first. */
437 /* Likewise, the first move would clobber the source of the second one,
438 do them in the other order. This happens only for registers;
439 such overlap can't happen in memory unless the user explicitly
440 sets it up, and that is an undefined circumstance. */
442 if (optype0
== PUSHOP
|| optype1
== PUSHOP
443 || (optype0
== REGOP
&& optype1
== REGOP
444 && REGNO (operands
[0]) == REGNO (latehalf
[1])))
446 /* Make any unoffsettable addresses point at high-numbered word. */
448 output_asm_insn ("add $2,%0", &addreg0
);
450 output_asm_insn ("add $2,%0", &addreg1
);
453 output_asm_insn (singlemove_string (latehalf
), latehalf
);
455 /* Undo the adds we just did. */
457 output_asm_insn ("sub $2,%0", &addreg0
);
459 output_asm_insn ("sub $2,%0", &addreg1
);
461 /* Do low-numbered word. */
462 return singlemove_string (operands
);
465 /* Normal case: do the two words, low-numbered first. */
467 output_asm_insn (singlemove_string (operands
), operands
);
469 /* Make any unoffsettable addresses point at high-numbered word. */
471 output_asm_insn ("add $2,%0", &addreg0
);
473 output_asm_insn ("add $2,%0", &addreg1
);
476 output_asm_insn (singlemove_string (latehalf
), latehalf
);
478 /* Undo the adds we just did. */
480 output_asm_insn ("sub $2,%0", &addreg0
);
482 output_asm_insn ("sub $2,%0", &addreg1
);
486 /* Output assembler code to perform a quadword move insn
487 with operands OPERANDS. */
490 output_move_quad (operands
)
493 enum { REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
495 rtx addreg0
= 0, addreg1
= 0;
497 output_asm_insn(";; movdi/df: %1 -> %0", operands
);
499 if (REG_P (operands
[0]))
501 else if (offsettable_memref_p (operands
[0]))
503 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
505 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
507 else if (GET_CODE (operands
[0]) == MEM
)
512 if (REG_P (operands
[1]))
514 else if (CONSTANT_P (operands
[1])
515 || GET_CODE (operands
[1]) == CONST_DOUBLE
)
517 else if (offsettable_memref_p (operands
[1]))
519 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
521 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
523 else if (GET_CODE (operands
[1]) == MEM
)
528 /* Check for the cases that the operand constraints are not
529 supposed to allow to happen. Abort if we get one,
530 because generating code for these cases is painful. */
532 if (optype0
== RNDOP
|| optype1
== RNDOP
)
535 /* check if we move a CPU reg to an FPU reg, or vice versa! */
536 if (optype0
== REGOP
&& optype1
== REGOP
)
537 /* bogus - 64 bit cannot reside in CPU! */
538 if (CPU_REG_P(REGNO(operands
[0]))
539 || CPU_REG_P (REGNO(operands
[1])))
542 if (optype0
== REGOP
|| optype1
== REGOP
)
544 /* check for use of clrd????
545 if you ever allow ac4 and ac5 (now we require secondary load)
546 you must check whether
547 you want to load into them or store from them -
548 then dump ac0 into $help$ movce ac4/5 to ac0, do the
549 store from ac0, and restore ac0 - if you can find
550 an unused ac[0-3], use that and you save a store and a load!*/
552 if (FPU_REG_P(REGNO(operands
[0])))
554 if (GET_CODE(operands
[1]) == CONST_DOUBLE
)
556 union { double d
; int i
[2]; } u
;
557 u
.i
[0] = CONST_DOUBLE_LOW (operands
[1]);
558 u
.i
[1] = CONST_DOUBLE_HIGH (operands
[1]);
561 return "{clrd|clrf} %0";
564 return "{ldd|movf} %1, %0";
567 if (FPU_REG_P(REGNO(operands
[1])))
568 return "{std|movf} %1, %0";
571 /* If one operand is decrementing and one is incrementing
572 decrement the former register explicitly
573 and change that operand into ordinary indexing. */
575 if (optype0
== PUSHOP
&& optype1
== POPOP
)
577 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
578 output_asm_insn ("sub $8,%0", operands
);
579 operands
[0] = gen_rtx (MEM
, DImode
, operands
[0]);
582 if (optype0
== POPOP
&& optype1
== PUSHOP
)
584 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
585 output_asm_insn ("sub $8,%1", operands
);
586 operands
[1] = gen_rtx (MEM
, SImode
, operands
[1]);
590 /* If an operand is an unoffsettable memory ref, find a register
591 we can increment temporarily to make it refer to the second word. */
593 if (optype0
== MEMOP
)
594 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
596 if (optype1
== MEMOP
)
597 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
599 /* Ok, we can do one word at a time.
600 Normally we do the low-numbered word first,
601 but if either operand is autodecrementing then we
602 do the high-numbered word first.
604 In either case, set up in LATEHALF the operands to use
605 for the high-numbered word and in some cases alter the
606 operands in OPERANDS to be suitable for the low-numbered word. */
608 if (optype0
== REGOP
)
609 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 2);
610 else if (optype0
== OFFSOP
)
611 latehalf
[0] = adj_offsettable_operand (operands
[0], 4);
613 latehalf
[0] = operands
[0];
615 if (optype1
== REGOP
)
616 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 2);
617 else if (optype1
== OFFSOP
)
618 latehalf
[1] = adj_offsettable_operand (operands
[1], 4);
619 else if (optype1
== CNSTOP
)
621 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
623 /* floats only. not yet supported!
625 -- compute it into PDP float format, - internally,
626 just use IEEE and ignore possible problems ;-)
628 we might get away with it !!!! */
632 #ifndef HOST_WORDS_BIG_ENDIAN
633 latehalf
[1] = GEN_INT (CONST_DOUBLE_LOW (operands
[1]));
634 operands
[1] = GEN_INT (CONST_DOUBLE_HIGH (operands
[1]));
635 #else /* HOST_WORDS_BIG_ENDIAN */
636 latehalf
[1] = GEN_INT (CONST_DOUBLE_HIGH (operands
[1]));
637 operands
[1] = GEN_INT (CONST_DOUBLE_LOW (operands
[1]));
638 #endif /* HOST_WORDS_BIG_ENDIAN */
640 else if (GET_CODE(operands
[1]) == CONST_INT
)
642 latehalf
[1] = GEN_INT (0);
649 latehalf
[1] = operands
[1];
651 /* If insn is effectively movd N(sp),-(sp) then we will do the
652 high word first. We should use the adjusted operand 1 (which is N+4(sp))
653 for the low word as well, to compensate for the first decrement of sp. */
654 if (optype0
== PUSHOP
655 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
656 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
657 operands
[1] = latehalf
[1];
659 /* If one or both operands autodecrementing,
660 do the two words, high-numbered first. */
662 /* Likewise, the first move would clobber the source of the second one,
663 do them in the other order. This happens only for registers;
664 such overlap can't happen in memory unless the user explicitly
665 sets it up, and that is an undefined circumstance. */
667 if (optype0
== PUSHOP
|| optype1
== PUSHOP
668 || (optype0
== REGOP
&& optype1
== REGOP
669 && REGNO (operands
[0]) == REGNO (latehalf
[1])))
671 /* Make any unoffsettable addresses point at high-numbered word. */
673 output_asm_insn ("add $4,%0", &addreg0
);
675 output_asm_insn ("add $4,%0", &addreg1
);
678 output_asm_insn(output_move_double(latehalf
), latehalf
);
680 /* Undo the adds we just did. */
682 output_asm_insn ("sub $4,%0", &addreg0
);
684 output_asm_insn ("sub $4,%0", &addreg1
);
686 /* Do low-numbered word. */
687 return output_move_double (operands
);
690 /* Normal case: do the two words, low-numbered first. */
692 output_asm_insn (output_move_double (operands
), operands
);
694 /* Make any unoffsettable addresses point at high-numbered word. */
696 output_asm_insn ("add $4,%0", &addreg0
);
698 output_asm_insn ("add $4,%0", &addreg1
);
701 output_asm_insn (output_move_double (latehalf
), latehalf
);
703 /* Undo the adds we just did. */
705 output_asm_insn ("sub $4,%0", &addreg0
);
707 output_asm_insn ("sub $4,%0", &addreg1
);
713 /* Return a REG that occurs in ADDR with coefficient 1.
714 ADDR can be effectively incremented by incrementing REG. */
720 while (GET_CODE (addr
) == PLUS
)
722 if (GET_CODE (XEXP (addr
, 0)) == REG
)
723 addr
= XEXP (addr
, 0);
724 if (GET_CODE (XEXP (addr
, 1)) == REG
)
725 addr
= XEXP (addr
, 1);
726 if (CONSTANT_P (XEXP (addr
, 0)))
727 addr
= XEXP (addr
, 1);
728 if (CONSTANT_P (XEXP (addr
, 1)))
729 addr
= XEXP (addr
, 0);
731 if (GET_CODE (addr
) == REG
)
736 /* Output an ascii string. */
738 output_ascii (file
, p
, size
)
745 /* This used to output .byte "string", which doesn't work with the UNIX
746 assembler and I think not with DEC ones either. */
747 fprintf (file
, "\t.byte ");
749 for (i
= 0; i
< size
; i
++)
751 register int c
= p
[i
];
754 fprintf (file
, "%o", c
);
762 /* --- stole from out-vax, needs changes */
765 print_operand_address (file
, addr
)
769 register rtx reg1
, reg2
, breg
, ireg
;
774 switch (GET_CODE (addr
))
781 addr
= XEXP (addr
, 0);
785 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
789 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
793 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
800 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
801 || GET_CODE (XEXP (addr
, 0)) == MEM
)
803 offset
= XEXP (addr
, 0);
804 addr
= XEXP (addr
, 1);
806 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
807 || GET_CODE (XEXP (addr
, 1)) == MEM
)
809 offset
= XEXP (addr
, 1);
810 addr
= XEXP (addr
, 0);
812 if (GET_CODE (addr
) != PLUS
)
814 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
816 reg1
= XEXP (addr
, 0);
817 addr
= XEXP (addr
, 1);
819 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
821 reg1
= XEXP (addr
, 1);
822 addr
= XEXP (addr
, 0);
824 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
826 reg1
= XEXP (addr
, 0);
827 addr
= XEXP (addr
, 1);
829 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
831 reg1
= XEXP (addr
, 1);
832 addr
= XEXP (addr
, 0);
834 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
)
844 if (addr
!= 0) abort ();
847 if (reg1
!= 0 && GET_CODE (reg1
) == MULT
)
852 else if (reg2
!= 0 && GET_CODE (reg2
) == MULT
)
857 else if (reg2
!= 0 || GET_CODE (addr
) == MEM
)
868 output_address (addr
);
871 if (GET_CODE (breg
) != REG
)
873 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
877 if (GET_CODE (ireg
) == MULT
)
878 ireg
= XEXP (ireg
, 0);
879 if (GET_CODE (ireg
) != REG
)
882 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
887 output_addr_const_pdp11 (file
, addr
);
891 /* register move costs, indexed by regs */
893 static int move_costs
[N_REG_CLASSES
][N_REG_CLASSES
] =
895 /* NO MUL GEN LFPU NLFPU FPU ALL */
897 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
898 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
899 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
900 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
901 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
902 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
903 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
907 /* -- note that some moves are tremendously expensive,
908 because they require lots of tricks! do we have to
909 charge the costs incurred by secondary reload class
910 -- as we do here with 22 -- or not ? */
913 register_move_cost(c1
, c2
)
914 enum reg_class c1
, c2
;
916 return move_costs
[(int)c1
][(int)c2
];
920 output_jump(pos
, neg
, length
)
926 static char buf
[1000];
929 /* currently we don't need this, because the tstdf and cmpdf
930 copy the condition code immediately, and other float operations are not
931 yet recognized as changing the FCC - if so, then the length-cost of all
932 jump insns increases by one, because we have to potentially copy the
934 if (cc_status
.flags
& CC_IN_FPU
)
935 output_asm_insn("cfcc", NULL
);
949 sprintf(buf
, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg
, x
, x
);
963 notice_update_cc_on_set(exp
, insn
)
967 if (GET_CODE (SET_DEST (exp
)) == CC0
)
970 cc_status
.value1
= SET_DEST (exp
);
971 cc_status
.value2
= SET_SRC (exp
);
974 if (GET_MODE(SET_SRC(exp)) == DFmode)
975 cc_status.flags |= CC_IN_FPU;
978 else if ((GET_CODE (SET_DEST (exp
)) == REG
979 || GET_CODE (SET_DEST (exp
)) == MEM
)
980 && GET_CODE (SET_SRC (exp
)) != PC
981 && (GET_MODE (SET_DEST(exp
)) == HImode
982 || GET_MODE (SET_DEST(exp
)) == QImode
)
983 && (GET_CODE (SET_SRC(exp
)) == PLUS
984 || GET_CODE (SET_SRC(exp
)) == MINUS
985 || GET_CODE (SET_SRC(exp
)) == AND
986 || GET_CODE (SET_SRC(exp
)) == IOR
987 || GET_CODE (SET_SRC(exp
)) == XOR
988 || GET_CODE (SET_SRC(exp
)) == NOT
989 || GET_CODE (SET_SRC(exp
)) == NEG
990 || GET_CODE (SET_SRC(exp
)) == REG
991 || GET_CODE (SET_SRC(exp
)) == MEM
))
994 cc_status
.value1
= SET_SRC (exp
);
995 cc_status
.value2
= SET_DEST (exp
);
997 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
999 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
1000 cc_status
.value2
= 0;
1001 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == MEM
1003 && GET_CODE (cc_status
.value2
) == MEM
)
1004 cc_status
.value2
= 0;
1006 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1010 else if (GET_CODE (SET_DEST (exp
)) == REG
)
1013 if ((cc_status
.value1
1014 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
)))
1015 cc_status
.value1
= 0;
1016 if ((cc_status
.value2
1017 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
)))
1018 cc_status
.value2
= 0;
1020 else if (SET_DEST(exp
) == pc_rtx
)
1024 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1026 /* the last else is a bit paranoiac, but since nearly all instructions
1027 play with condition codes, it's reasonable! */
1029 CC_STATUS_INIT
; /* paranoia*/
1034 int simple_memory_operand(op
, mode
)
1036 enum machine_mode mode
;
1040 /* Eliminate non-memory operations */
1041 if (GET_CODE (op
) != MEM
)
1045 /* dword operations really put out 2 instructions, so eliminate them. */
1046 if (GET_MODE_SIZE (GET_MODE (op
)) > (HAVE_64BIT_P () ? 8 : 4))
1050 /* Decode the address now. */
1054 addr
= XEXP (op
, 0);
1056 switch (GET_CODE (addr
))
1059 /* (R0) - no extra cost */
1064 /* -(R0), (R0)+ - cheap! */
1068 /* cheap - is encoded in addressing mode info!
1070 -- except for @(R0), which has to be @0(R0) !!! */
1072 if (GET_CODE (XEXP (addr
, 0)) == REG
)
1082 /* @#address - extra cost */
1086 /* X(R0) - extra cost */
1098 * output a block move:
1100 * operands[0] ... to
1101 * operands[1] ... from
1102 * operands[2] ... length
1103 * operands[3] ... alignment
1104 * operands[4] ... scratch register
1109 output_block_move(operands
)
1112 static int count
= 0;
1115 if (GET_CODE(operands
[2]) == CONST_INT
1118 if (INTVAL(operands
[2]) < 16
1119 && INTVAL(operands
[3]) == 1)
1123 for (i
= 1; i
<= INTVAL(operands
[2]); i
++)
1124 output_asm_insn("movb (%1)+, (%0)+", operands
);
1128 else if (INTVAL(operands
[2]) < 32)
1132 for (i
= 1; i
<= INTVAL(operands
[2])/2; i
++)
1133 output_asm_insn("mov (%1)+, (%0)+", operands
);
1135 /* may I assume that moved quantity is
1136 multiple of alignment ???
1145 /* can do other clever things, maybe... */
1148 if (CONSTANT_P(operands
[2]) )
1150 /* just move count to scratch */
1151 output_asm_insn("mov %2, %4", operands
);
1155 /* just clobber the register */
1156 operands
[4] = operands
[2];
1160 /* switch over alignment */
1161 switch (INTVAL(operands
[3]))
1177 sprintf(buf
, "\nmovestrhi%d:", count
);
1178 output_asm_insn(buf
, NULL
);
1180 output_asm_insn("movb (%1)+, (%0)+", operands
);
1184 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1185 output_asm_insn(buf
, operands
);
1189 output_asm_insn("dec %4", operands
);
1191 sprintf(buf
, "bgt movestrhi%d", count
);
1192 output_asm_insn(buf
, NULL
);
1214 generate_compact_code
:
1216 output_asm_insn("asr %4", operands
);
1218 sprintf(buf
, "\nmovestrhi%d:", count
);
1219 output_asm_insn(buf
, NULL
);
1221 output_asm_insn("mov (%1)+, (%0)+", operands
);
1225 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1226 output_asm_insn(buf
, operands
);
1230 output_asm_insn("dec %4", operands
);
1232 sprintf(buf
, "bgt movestrhi%d", count
);
1233 output_asm_insn(buf
, NULL
);
1259 goto generate_compact_code
;
1261 output_asm_insn("asr %4", operands
);
1262 output_asm_insn("asr %4", operands
);
1264 sprintf(buf
, "\nmovestrhi%d:", count
);
1265 output_asm_insn(buf
, NULL
);
1267 output_asm_insn("mov (%1)+, (%0)+", operands
);
1268 output_asm_insn("mov (%1)+, (%0)+", operands
);
1272 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1273 output_asm_insn(buf
, operands
);
1277 output_asm_insn("dec %4", operands
);
1279 sprintf(buf
, "bgt movestrhi%d", count
);
1280 output_asm_insn(buf
, NULL
);
1310 goto generate_compact_code
;
1312 output_asm_insn("asr %4", operands
);
1313 output_asm_insn("asr %4", operands
);
1314 output_asm_insn("asr %4", operands
);
1316 sprintf(buf
, "\nmovestrhi%d:", count
);
1317 output_asm_insn(buf
, NULL
);
1319 output_asm_insn("mov (%1)+, (%0)+", operands
);
1320 output_asm_insn("mov (%1)+, (%0)+", operands
);
1321 output_asm_insn("mov (%1)+, (%0)+", operands
);
1322 output_asm_insn("mov (%1)+, (%0)+", operands
);
1326 sprintf(buf
, "sob %%4, movestrhi%d", count
);
1327 output_asm_insn(buf
, operands
);
1331 output_asm_insn("dec %4", operands
);
1333 sprintf(buf
, "bgt movestrhi%d", count
);
1334 output_asm_insn(buf
, NULL
);
1347 /* for future use */
1349 comparison_operator_index(op
)
1352 switch (GET_CODE(op
))
1389 /* tests whether the rtx is a comparison operator */
1391 comp_operator (op
, mode
)
1393 enum machine_mode mode
;
1395 return comparison_operator_index(op
) >= 0;
1400 legitimate_address_p (mode
, address
)
1401 enum machine_mode mode
;
1404 /* #define REG_OK_STRICT */
1405 GO_IF_LEGITIMATE_ADDRESS(mode
, address
, win
);
1412 /* #undef REG_OK_STRICT */
1415 /* A copy of output_addr_const modified for pdp11 expression syntax.
1416 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1417 use, and for debugging output, which we don't support with this port either.
1418 So this copy should get called whenever needed.
1421 output_addr_const_pdp11 (file
, x
)
1428 switch (GET_CODE (x
))
1438 assemble_name (file
, XSTR (x
, 0));
1442 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
1443 assemble_name (file
, buf
);
1447 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
1448 assemble_name (file
, buf
);
1452 /* Should we check for constants which are too big? Maybe cutting
1453 them off to 16 bits is OK? */
1454 fprintf (file
, "%ho", (unsigned short) INTVAL (x
));
1458 /* This used to output parentheses around the expression,
1459 but that does not work on the 386 (either ATT or BSD assembler). */
1460 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1464 if (GET_MODE (x
) == VOIDmode
)
1466 /* We can use %o if the number is one word and positive. */
1467 if (CONST_DOUBLE_HIGH (x
))
1468 abort (); /* Should we just silently drop the high part? */
1470 fprintf (file
, "%ho", (unsigned short) CONST_DOUBLE_LOW (x
));
1473 /* We can't handle floating point constants;
1474 PRINT_OPERAND must handle them. */
1475 output_operand_lossage ("floating constant misused");
1479 /* Some assemblers need integer constants to appear last (eg masm). */
1480 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
1482 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1483 if (INTVAL (XEXP (x
, 0)) >= 0)
1484 fprintf (file
, "+");
1485 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1489 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1490 if (INTVAL (XEXP (x
, 1)) >= 0)
1491 fprintf (file
, "+");
1492 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1497 /* Avoid outputting things like x-x or x+5-x,
1498 since some assemblers can't handle that. */
1499 x
= simplify_subtraction (x
);
1500 if (GET_CODE (x
) != MINUS
)
1503 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1504 fprintf (file
, "-");
1505 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
1506 && INTVAL (XEXP (x
, 1)) < 0)
1508 fprintf (file
, ASM_OPEN_PAREN
);
1509 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1510 fprintf (file
, ASM_CLOSE_PAREN
);
1513 output_addr_const_pdp11 (file
, XEXP (x
, 1));
1518 output_addr_const_pdp11 (file
, XEXP (x
, 0));
1522 output_operand_lossage ("invalid expression as operand");