1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994, 1995 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. */
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
34 #include "insn-attr.h"
37 #define FPU_REG_P(X) ((X)>=8 && (X)<14)
38 #define CPU_REG_P(X) ((X)>=0 && (X)<8)
41 /* this is the current value returned by the macro FIRST_PARM_OFFSET
43 int current_first_parm_offset;
45 /* This is where the condition code register lives. */
46 /* rtx cc0_reg_rtx; - no longer needed? */
48 static rtx find_addr_reg ();
50 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
53 arith_operand (op, mode)
55 enum machine_mode mode;
57 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
61 const_immediate_operand (op, mode)
63 enum machine_mode mode;
65 return (GET_CODE (op) == CONST_INT);
69 immediate15_operand (op, mode)
71 enum machine_mode mode;
73 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
77 expand_shift_operand (op, mode)
79 enum machine_mode mode;
81 return (GET_CODE (op) == CONST_INT
82 && abs (INTVAL(op)) > 1
83 && abs (INTVAL(op)) <= 4);
87 stream is a stdio stream to output the code to.
88 size is an int: how many units of temporary storage to allocate.
89 Refer to the array `regs_ever_live' to determine which registers
90 to save; `regs_ever_live[I]' is nonzero if register number I
91 is ever used in the function. This macro is responsible for
92 knowing which registers should not be saved even if used.
96 output_function_prologue(stream, size)
100 extern char call_used_regs[];
101 extern int frame_pointer_needed;
103 int fsize = ((size) + 1) & ~1;
109 fprintf (stream, "\n\t; /* function prologue %s*/\n", current_function_name);
111 /* if we are outputting code for main,
112 the switch FPU to right mode if TARGET_FPU */
113 if ( (strcmp ("main", current_function_name) == 0)
116 fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
117 fprintf(stream, "\tsetd\n");
118 fprintf(stream, "\tseti\n\n");
121 if (frame_pointer_needed)
123 fprintf(stream, "\tmov fp, -(sp)\n");
124 fprintf(stream, "\tmov sp, fp\n");
133 fprintf (stream, "\tsub $%d, sp\n", fsize);
135 /* save CPU registers */
136 for (regno = 0; regno < 8; regno++)
137 if (regs_ever_live[regno] && ! call_used_regs[regno])
138 if (! ((regno == FRAME_POINTER_REGNUM)
139 && frame_pointer_needed))
140 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
141 /* fpu regs saving */
143 /* via_ac specifies the ac to use for saving ac4, ac5 */
146 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
149 if (LOAD_FPU_REG_P(regno)
150 && regs_ever_live[regno]
151 && ! call_used_regs[regno])
153 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
157 /* maybe make ac4, ac5 call used regs?? */
159 if (NO_LOAD_FPU_REG_P(regno)
160 && regs_ever_live[regno]
161 && ! call_used_regs[regno])
166 fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
167 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
171 fprintf (stream, "\t;/* end of prologue */\n\n");
175 The function epilogue should not depend on the current stack pointer!
176 It should use the frame pointer only. This is mandatory because
177 of alloca; we also take advantage of it to omit stack adjustments
180 /* maybe we can make leaf functions faster by switching to the
181 second register file - this way we don't have to save regs!
182 leaf functions are ~ 50% of all functions (dynamically!)
184 set/clear bit 11 (dec. 2048) of status word for switching register files -
185 but how can we do this? the pdp11/45 manual says bit may only
186 be set (p.24), but not cleared!
188 switching to kernel is probably more expensive, so we'll leave it
189 like this and not use the second set of registers...
191 maybe as option if you want to generate code for kernel mode? */
195 output_function_epilogue(stream, size)
199 extern char call_used_regs[];
200 extern int may_call_alloca;
202 int fsize = ((size) + 1) & ~1;
203 int nregs, regno, i, j, k, adjust_fp;
207 fprintf (stream, "\n\t; /*function epilogue */\n");
209 if (frame_pointer_needed)
211 /* hope this is safe - m68k does it also .... */
212 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
214 for (i =7, j = 0 ; i >= 0 ; i--)
215 if (regs_ever_live[i] && ! call_used_regs[i])
218 /* remember # of pushed bytes for CPU regs */
221 for (i =7 ; i >= 0 ; i--)
222 if (regs_ever_live[i] && ! call_used_regs[i])
223 fprintf(stream, "\tmov %d(fp), %s\n",-fsize-2*j--, reg_names[i]);
226 via_ac = FIRST_PSEUDO_REGISTER -1;
228 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
229 if (regs_ever_live[i] && ! call_used_regs[i])
235 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
237 if (LOAD_FPU_REG_P(i)
239 && ! call_used_regs[i])
241 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[i]);
245 if (NO_LOAD_FPU_REG_P(i)
247 && ! call_used_regs[i])
249 if (! LOAD_FPU_REG_P(via_ac))
252 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[via_ac]);
253 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
258 fprintf(stream, "\tmov fp, sp\n");
259 fprintf (stream, "\tmov (sp)+, fp\n");
263 via_ac = FIRST_PSEUDO_REGISTER -1;
266 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
267 if (regs_ever_live[i] && call_used_regs[i])
270 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
272 if (LOAD_FPU_REG_P(i)
274 && ! call_used_regs[i])
275 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
277 if (NO_LOAD_FPU_REG_P(i)
279 && ! call_used_regs[i])
281 if (! LOAD_FPU_REG_P(via_ac))
284 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
285 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
289 for (i=7; i >= 0; i--)
290 if (regs_ever_live[i] && !call_used_regs[i])
291 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
294 fprintf((stream), "\tadd $%d, sp\n", fsize);
297 fprintf (stream, "\trts pc\n");
298 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
301 /* Return the best assembler insn template
302 for moving operands[1] into operands[0] as a fullword. */
304 singlemove_string (operands)
307 if (operands[1] != const0_rtx)
314 /* Output assembler code to perform a doubleword move insn
315 with operands OPERANDS. */
318 output_move_double (operands)
321 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
323 rtx addreg0 = 0, addreg1 = 0;
325 /* First classify both operands. */
327 if (REG_P (operands[0]))
329 else if (offsettable_memref_p (operands[0]))
331 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
333 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
335 else if (GET_CODE (operands[0]) == MEM)
340 if (REG_P (operands[1]))
342 else if (CONSTANT_P (operands[1]))
344 || GET_CODE (operands[1]) == CONST_DOUBLE)
347 else if (offsettable_memref_p (operands[1]))
349 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
351 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
353 else if (GET_CODE (operands[1]) == MEM)
358 /* Check for the cases that the operand constraints are not
359 supposed to allow to happen. Abort if we get one,
360 because generating code for these cases is painful. */
362 if (optype0 == RNDOP || optype1 == RNDOP)
365 /* If one operand is decrementing and one is incrementing
366 decrement the former register explicitly
367 and change that operand into ordinary indexing. */
369 if (optype0 == PUSHOP && optype1 == POPOP)
371 operands[0] = XEXP (XEXP (operands[0], 0), 0);
372 output_asm_insn ("sub $4,%0", operands);
373 operands[0] = gen_rtx (MEM, SImode, operands[0]);
376 if (optype0 == POPOP && optype1 == PUSHOP)
378 operands[1] = XEXP (XEXP (operands[1], 0), 0);
379 output_asm_insn ("sub $4,%1", operands);
380 operands[1] = gen_rtx (MEM, SImode, operands[1]);
384 /* If an operand is an unoffsettable memory ref, find a register
385 we can increment temporarily to make it refer to the second word. */
387 if (optype0 == MEMOP)
388 addreg0 = find_addr_reg (XEXP (operands[0], 0));
390 if (optype1 == MEMOP)
391 addreg1 = find_addr_reg (XEXP (operands[1], 0));
393 /* Ok, we can do one word at a time.
394 Normally we do the low-numbered word first,
395 but if either operand is autodecrementing then we
396 do the high-numbered word first.
398 In either case, set up in LATEHALF the operands to use
399 for the high-numbered word and in some cases alter the
400 operands in OPERANDS to be suitable for the low-numbered word. */
402 if (optype0 == REGOP)
403 latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
404 else if (optype0 == OFFSOP)
405 latehalf[0] = adj_offsettable_operand (operands[0], 2);
407 latehalf[0] = operands[0];
409 if (optype1 == REGOP)
410 latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
411 else if (optype1 == OFFSOP)
412 latehalf[1] = adj_offsettable_operand (operands[1], 2);
413 else if (optype1 == CNSTOP)
415 if (CONSTANT_P (operands[1]))
417 /* now the mess begins, high word is in lower word???
419 that's what ashc makes me think, but I don't remember :-( */
420 latehalf[1] = gen_rtx(CONST_INT, VOIDmode,
421 INTVAL(operands[1])>>16);
422 operands[1] = gen_rtx(CONST_INT, VOIDmode,
423 INTVAL(operands[1])&0xff);
425 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
427 /* immediate 32 bit values not allowed */
432 latehalf[1] = operands[1];
434 /* If insn is effectively movd N(sp),-(sp) then we will do the
435 high word first. We should use the adjusted operand 1 (which is N+4(sp))
436 for the low word as well, to compensate for the first decrement of sp. */
437 if (optype0 == PUSHOP
438 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
439 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
440 operands[1] = latehalf[1];
442 /* If one or both operands autodecrementing,
443 do the two words, high-numbered first. */
445 /* Likewise, the first move would clobber the source of the second one,
446 do them in the other order. This happens only for registers;
447 such overlap can't happen in memory unless the user explicitly
448 sets it up, and that is an undefined circumstance. */
450 if (optype0 == PUSHOP || optype1 == PUSHOP
451 || (optype0 == REGOP && optype1 == REGOP
452 && REGNO (operands[0]) == REGNO (latehalf[1])))
454 /* Make any unoffsettable addresses point at high-numbered word. */
456 output_asm_insn ("add $2,%0", &addreg0);
458 output_asm_insn ("add $2,%0", &addreg1);
461 output_asm_insn (singlemove_string (latehalf), latehalf);
463 /* Undo the adds we just did. */
465 output_asm_insn ("sub $2,%0", &addreg0);
467 output_asm_insn ("sub $2,%0", &addreg1);
469 /* Do low-numbered word. */
470 return singlemove_string (operands);
473 /* Normal case: do the two words, low-numbered first. */
475 output_asm_insn (singlemove_string (operands), operands);
477 /* Make any unoffsettable addresses point at high-numbered word. */
479 output_asm_insn ("add $2,%0", &addreg0);
481 output_asm_insn ("add $2,%0", &addreg1);
484 output_asm_insn (singlemove_string (latehalf), latehalf);
486 /* Undo the adds we just did. */
488 output_asm_insn ("sub $2,%0", &addreg0);
490 output_asm_insn ("sub $2,%0", &addreg1);
494 /* Output assembler code to perform a quadword move insn
495 with operands OPERANDS. */
498 output_move_quad (operands)
501 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
503 rtx addreg0 = 0, addreg1 = 0;
505 output_asm_insn(";; movdi/df: %1 -> %0", operands);
507 if (REG_P (operands[0]))
509 else if (offsettable_memref_p (operands[0]))
511 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
513 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
515 else if (GET_CODE (operands[0]) == MEM)
520 if (REG_P (operands[1]))
522 else if (CONSTANT_P (operands[1])
523 || GET_CODE (operands[1]) == CONST_DOUBLE)
525 else if (offsettable_memref_p (operands[1]))
527 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
529 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
531 else if (GET_CODE (operands[1]) == MEM)
536 /* Check for the cases that the operand constraints are not
537 supposed to allow to happen. Abort if we get one,
538 because generating code for these cases is painful. */
540 if (optype0 == RNDOP || optype1 == RNDOP)
543 /* check if we move a CPU reg to an FPU reg, or vice versa! */
544 if (optype0 == REGOP && optype1 == REGOP)
545 /* bogus - 64 bit cannot reside in CPU! */
546 if (CPU_REG_P(REGNO(operands[0]))
547 || CPU_REG_P (REGNO(operands[1])))
550 if (optype0 == REGOP || optype1 == REGOP)
552 /* check for use of clrd????
553 if you ever allow ac4 and ac5 (now we require secondary load)
554 you must check whether
555 you want to load into them or store from them -
556 then dump ac0 into $help$ movce ac4/5 to ac0, do the
557 store from ac0, and restore ac0 - if you can find
558 an unused ac[0-3], use that and you save a store and a load!*/
560 if (FPU_REG_P(REGNO(operands[0])))
562 if (GET_CODE(operands[1]) == CONST_DOUBLE)
564 union { double d; int i[2]; } u;
565 u.i[0] = CONST_DOUBLE_LOW (operands[1]);
566 u.i[1] = CONST_DOUBLE_HIGH (operands[1]);
575 if (FPU_REG_P(REGNO(operands[1])))
579 /* If one operand is decrementing and one is incrementing
580 decrement the former register explicitly
581 and change that operand into ordinary indexing. */
583 if (optype0 == PUSHOP && optype1 == POPOP)
585 operands[0] = XEXP (XEXP (operands[0], 0), 0);
586 output_asm_insn ("sub $8,%0", operands);
587 operands[0] = gen_rtx (MEM, DImode, operands[0]);
590 if (optype0 == POPOP && optype1 == PUSHOP)
592 operands[1] = XEXP (XEXP (operands[1], 0), 0);
593 output_asm_insn ("sub $8,%1", operands);
594 operands[1] = gen_rtx (MEM, SImode, operands[1]);
598 /* If an operand is an unoffsettable memory ref, find a register
599 we can increment temporarily to make it refer to the second word. */
601 if (optype0 == MEMOP)
602 addreg0 = find_addr_reg (XEXP (operands[0], 0));
604 if (optype1 == MEMOP)
605 addreg1 = find_addr_reg (XEXP (operands[1], 0));
607 /* Ok, we can do one word at a time.
608 Normally we do the low-numbered word first,
609 but if either operand is autodecrementing then we
610 do the high-numbered word first.
612 In either case, set up in LATEHALF the operands to use
613 for the high-numbered word and in some cases alter the
614 operands in OPERANDS to be suitable for the low-numbered word. */
616 if (optype0 == REGOP)
617 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
618 else if (optype0 == OFFSOP)
619 latehalf[0] = adj_offsettable_operand (operands[0], 4);
621 latehalf[0] = operands[0];
623 if (optype1 == REGOP)
624 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
625 else if (optype1 == OFFSOP)
626 latehalf[1] = adj_offsettable_operand (operands[1], 4);
627 else if (optype1 == CNSTOP)
629 if (GET_CODE (operands[1]) == CONST_DOUBLE)
631 /* floats only. not yet supported!
633 -- compute it into PDP float format, - internally,
634 just use IEEE and ignore possible problems ;-)
636 we might get away with it !!!! */
640 #ifndef HOST_WORDS_BIG_ENDIAN
641 latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
642 CONST_DOUBLE_LOW (operands[1]));
643 operands[1] = gen_rtx (CONST_INT, VOIDmode,
644 CONST_DOUBLE_HIGH (operands[1]));
645 #else /* HOST_WORDS_BIG_ENDIAN */
646 latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
647 CONST_DOUBLE_HIGH (operands[1]));
648 operands[1] = gen_rtx (CONST_INT, VOIDmode,
649 CONST_DOUBLE_LOW (operands[1]));
650 #endif /* HOST_WORDS_BIG_ENDIAN */
652 else if (GET_CODE(operands[1]) == CONST_INT)
654 latehalf[1] = gen_rtx (CONST_INT, VOIDmode, 0);
661 latehalf[1] = operands[1];
663 /* If insn is effectively movd N(sp),-(sp) then we will do the
664 high word first. We should use the adjusted operand 1 (which is N+4(sp))
665 for the low word as well, to compensate for the first decrement of sp. */
666 if (optype0 == PUSHOP
667 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
668 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
669 operands[1] = latehalf[1];
671 /* If one or both operands autodecrementing,
672 do the two words, high-numbered first. */
674 /* Likewise, the first move would clobber the source of the second one,
675 do them in the other order. This happens only for registers;
676 such overlap can't happen in memory unless the user explicitly
677 sets it up, and that is an undefined circumstance. */
679 if (optype0 == PUSHOP || optype1 == PUSHOP
680 || (optype0 == REGOP && optype1 == REGOP
681 && REGNO (operands[0]) == REGNO (latehalf[1])))
683 /* Make any unoffsettable addresses point at high-numbered word. */
685 output_asm_insn ("add $4,%0", &addreg0);
687 output_asm_insn ("add $4,%0", &addreg1);
690 output_asm_insn(output_move_double(latehalf), latehalf);
692 /* Undo the adds we just did. */
694 output_asm_insn ("sub $4,%0", &addreg0);
696 output_asm_insn ("sub $4,%0", &addreg1);
698 /* Do low-numbered word. */
699 return output_move_double (operands);
702 /* Normal case: do the two words, low-numbered first. */
704 output_asm_insn (output_move_double (operands), operands);
706 /* Make any unoffsettable addresses point at high-numbered word. */
708 output_asm_insn ("add $4,%0", &addreg0);
710 output_asm_insn ("add $4,%0", &addreg1);
713 output_asm_insn (output_move_double (latehalf), latehalf);
715 /* Undo the adds we just did. */
717 output_asm_insn ("sub $4,%0", &addreg0);
719 output_asm_insn ("sub $4,%0", &addreg1);
725 /* Return a REG that occurs in ADDR with coefficient 1.
726 ADDR can be effectively incremented by incrementing REG. */
732 while (GET_CODE (addr) == PLUS)
734 if (GET_CODE (XEXP (addr, 0)) == REG)
735 addr = XEXP (addr, 0);
736 if (GET_CODE (XEXP (addr, 1)) == REG)
737 addr = XEXP (addr, 1);
738 if (CONSTANT_P (XEXP (addr, 0)))
739 addr = XEXP (addr, 1);
740 if (CONSTANT_P (XEXP (addr, 1)))
741 addr = XEXP (addr, 0);
743 if (GET_CODE (addr) == REG)
748 /* Output an ascii string. */
749 output_ascii (file, p, size)
756 fprintf (file, "\t.byte \"");
758 for (i = 0; i < size; i++)
760 register int c = p[i];
761 if (c == '\"' || c == '\\')
763 if (c >= ' ' && c < 0177)
767 fprintf (file, "\\%03o", c);
768 /* After an octal-escape, if a digit follows,
769 terminate one string constant and start another.
770 The Vax assembler fails to stop reading the escape
771 after three digits, so this is the only way we
772 can get it to parse the data properly. */
773 if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
774 fprintf (file, "\"\n\tstring \"");
777 fprintf (file, "\"\n");
781 /* --- stole from out-vax, needs changes */
783 print_operand_address (file, addr)
787 register rtx reg1, reg2, breg, ireg;
792 switch (GET_CODE (addr))
796 addr = XEXP (addr, 0);
800 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
804 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
808 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
815 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
816 || GET_CODE (XEXP (addr, 0)) == MEM)
818 offset = XEXP (addr, 0);
819 addr = XEXP (addr, 1);
821 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
822 || GET_CODE (XEXP (addr, 1)) == MEM)
824 offset = XEXP (addr, 1);
825 addr = XEXP (addr, 0);
827 if (GET_CODE (addr) != PLUS)
829 else if (GET_CODE (XEXP (addr, 0)) == MULT)
831 reg1 = XEXP (addr, 0);
832 addr = XEXP (addr, 1);
834 else if (GET_CODE (XEXP (addr, 1)) == MULT)
836 reg1 = XEXP (addr, 1);
837 addr = XEXP (addr, 0);
839 else if (GET_CODE (XEXP (addr, 0)) == REG)
841 reg1 = XEXP (addr, 0);
842 addr = XEXP (addr, 1);
844 else if (GET_CODE (XEXP (addr, 1)) == REG)
846 reg1 = XEXP (addr, 1);
847 addr = XEXP (addr, 0);
849 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
859 if (addr != 0) abort ();
862 if (reg1 != 0 && GET_CODE (reg1) == MULT)
867 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
872 else if (reg2 != 0 || GET_CODE (addr) == MEM)
883 output_address (addr);
886 if (GET_CODE (breg) != REG)
888 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
892 if (GET_CODE (ireg) == MULT)
893 ireg = XEXP (ireg, 0);
894 if (GET_CODE (ireg) != REG)
897 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
902 output_addr_const (file, addr);
906 /* register move costs, indexed by regs */
908 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
910 /* NO MUL GEN LFPU NLFPU FPU ALL */
912 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
913 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
914 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
915 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
916 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
917 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
918 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
922 /* -- note that some moves are tremendously expensive,
923 because they require lots of tricks! do we have to
924 charge the costs incurred by secondary reload class
925 -- as we do here with 22 -- or not ? */
928 register_move_cost(c1, c2)
929 enum reg_class c1, c2;
931 return move_costs[(int)c1][(int)c2];
935 output_jump(pos, neg, length)
941 static char buf[1000];
944 /* currently we don't need this, because the tstdf and cmpdf
945 copy the condition code immediately, and other float operations are not
946 yet recognized as changing the FCC - if so, then the length-cost of all
947 jump insns increases by one, because we have to potentially copy the
949 if (cc_status.flags & CC_IN_FPU)
950 output_asm_insn("cfcc", NULL);
964 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
978 notice_update_cc_on_set(exp, insn)
982 if (GET_CODE (SET_DEST (exp)) == CC0)
985 cc_status.value1 = SET_DEST (exp);
986 cc_status.value2 = SET_SRC (exp);
989 if (GET_MODE(SET_SRC(exp)) == DFmode)
990 cc_status.flags |= CC_IN_FPU;
993 else if ((GET_CODE (SET_DEST (exp)) == REG
994 || GET_CODE (SET_DEST (exp)) == MEM)
995 && GET_CODE (SET_SRC (exp)) != PC
996 && (GET_MODE (SET_DEST(exp)) == HImode
997 || GET_MODE (SET_DEST(exp)) == QImode)
998 && (GET_CODE (SET_SRC(exp)) == PLUS
999 || GET_CODE (SET_SRC(exp)) == MINUS
1000 || GET_CODE (SET_SRC(exp)) == AND
1001 || GET_CODE (SET_SRC(exp)) == IOR
1002 || GET_CODE (SET_SRC(exp)) == XOR
1003 || GET_CODE (SET_SRC(exp)) == NOT
1004 || GET_CODE (SET_SRC(exp)) == NEG
1005 || GET_CODE (SET_SRC(exp)) == REG
1006 || GET_CODE (SET_SRC(exp)) == MEM))
1008 cc_status.flags = 0;
1009 cc_status.value1 = SET_SRC (exp);
1010 cc_status.value2 = SET_DEST (exp);
1012 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1014 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1015 cc_status.value2 = 0;
1016 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1018 && GET_CODE (cc_status.value2) == MEM)
1019 cc_status.value2 = 0;
1021 else if (GET_CODE (SET_SRC (exp)) == CALL)
1025 else if (GET_CODE (SET_DEST (exp)) == REG)
1028 if ((cc_status.value1
1029 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1030 cc_status.value1 = 0;
1031 if ((cc_status.value2
1032 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1033 cc_status.value2 = 0;
1035 else if (SET_DEST(exp) == pc_rtx)
1039 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1041 /* the last else is a bit paranoiac, but since nearly all instructions
1042 play with condition codes, it's reasonable! */
1044 CC_STATUS_INIT; /* paranoia*/
1049 int simple_memory_operand(op, mode)
1051 enum machine_mode mode;
1053 rtx addr, plus0, plus1;
1056 /* Eliminate non-memory operations */
1057 if (GET_CODE (op) != MEM)
1061 /* dword operations really put out 2 instructions, so eliminate them. */
1062 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1066 /* Decode the address now. */
1070 addr = XEXP (op, 0);
1072 switch (GET_CODE (addr))
1075 /* (R0) - no extra cost */
1080 /* -(R0), (R0)+ - cheap! */
1084 /* cheap - is encoded in addressing mode info!
1086 -- except for @(R0), which has to be @0(R0) !!! */
1088 if (GET_CODE (XEXP (addr, 0)) == REG)
1098 /* @#address - extra cost */
1102 /* X(R0) - extra cost */
1111 * output a block move:
1113 * operands[0] ... to
1114 * operands[1] ... from
1115 * operands[2] ... length
1116 * operands[3] ... alignment
1117 * operands[4] ... scratch register
1122 output_block_move(operands)
1125 static int count = 0;
1128 if (GET_CODE(operands[2]) == CONST_INT
1131 if (INTVAL(operands[2]) < 16
1132 && INTVAL(operands[3]) == 1)
1136 for (i = 1; i <= INTVAL(operands[2]); i++)
1137 output_asm_insn("movb (%1)+, (%0)+", operands);
1141 else if (INTVAL(operands[2]) < 32)
1145 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1146 output_asm_insn("mov (%1)+, (%0)+", operands);
1148 /* may I assume that moved quantity is
1149 multiple of alignment ???
1158 /* can do other clever things, maybe... */
1161 if (CONSTANT_P(operands[2]) )
1163 /* just move count to scratch */
1164 output_asm_insn("mov %2, %4", operands);
1168 /* just clobber the register */
1169 operands[4] = operands[2];
1173 /* switch over alignment */
1174 switch (INTVAL(operands[3]))
1190 sprintf(buf, "\nmovestrhi%d:", count);
1191 output_asm_insn(buf, NULL);
1193 output_asm_insn("movb (%1)+, (%0)+", operands);
1197 sprintf(buf, "sob %%4, movestrhi%d", count);
1198 output_asm_insn(buf, operands);
1202 output_asm_insn("dec %4", operands);
1204 sprintf(buf, "bgt movestrhi%d", count);
1205 output_asm_insn(buf, NULL);
1227 generate_compact_code:
1229 output_asm_insn("asr %4", operands);
1231 sprintf(buf, "\nmovestrhi%d:", count);
1232 output_asm_insn(buf, NULL);
1234 output_asm_insn("mov (%1)+, (%0)+", operands);
1238 sprintf(buf, "sob %%4, movestrhi%d", count);
1239 output_asm_insn(buf, operands);
1243 output_asm_insn("dec %4", operands);
1245 sprintf(buf, "bgt movestrhi%d", count);
1246 output_asm_insn(buf, NULL);
1272 goto generate_compact_code;
1274 output_asm_insn("asr %4", operands);
1275 output_asm_insn("asr %4", operands);
1277 sprintf(buf, "\nmovestrhi%d:", count);
1278 output_asm_insn(buf, NULL);
1280 output_asm_insn("mov (%1)+, (%0)+", operands);
1281 output_asm_insn("mov (%1)+, (%0)+", operands);
1285 sprintf(buf, "sob %%4, movestrhi%d", count);
1286 output_asm_insn(buf, operands);
1290 output_asm_insn("dec %4", operands);
1292 sprintf(buf, "bgt movestrhi%d", count);
1293 output_asm_insn(buf, NULL);
1323 goto generate_compact_code;
1325 output_asm_insn("asr %4", operands);
1326 output_asm_insn("asr %4", operands);
1327 output_asm_insn("asr %4", operands);
1329 sprintf(buf, "\nmovestrhi%d:", count);
1330 output_asm_insn(buf, NULL);
1332 output_asm_insn("mov (%1)+, (%0)+", operands);
1333 output_asm_insn("mov (%1)+, (%0)+", operands);
1334 output_asm_insn("mov (%1)+, (%0)+", operands);
1335 output_asm_insn("mov (%1)+, (%0)+", operands);
1339 sprintf(buf, "sob %%4, movestrhi%d", count);
1340 output_asm_insn(buf, operands);
1344 output_asm_insn("dec %4", operands);
1346 sprintf(buf, "bgt movestrhi%d", count);
1347 output_asm_insn(buf, NULL);
1360 /* for future use */
1362 comparison_operator_index(op)
1365 switch (GET_CODE(op))
1402 /* tests whether the rtx is a comparison operator */
1404 comp_operator (op, mode)
1406 enum machine_mode mode;
1408 return comparison_operator_index(op) >= 0;
1413 legitimate_address_p (mode, address)
1414 enum machine_mode mode;
1417 /* #define REG_OK_STRICT */
1418 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1425 /* #undef REG_OK_STRICT */