1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994, 1995, 1996, 1997 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"
32 #include "insn-attr.h"
36 #define FPU_REG_P(X) ((X)>=8 && (X)<14)
37 #define CPU_REG_P(X) ((X)>=0 && (X)<8)
40 /* this is the current value returned by the macro FIRST_PARM_OFFSET
42 int current_first_parm_offset;
44 /* This is where the condition code register lives. */
45 /* rtx cc0_reg_rtx; - no longer needed? */
47 static rtx find_addr_reg ();
49 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
52 arith_operand (op, mode)
54 enum machine_mode mode;
56 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
60 const_immediate_operand (op, mode)
62 enum machine_mode mode;
64 return (GET_CODE (op) == CONST_INT);
68 immediate15_operand (op, mode)
70 enum machine_mode mode;
72 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
76 expand_shift_operand (op, mode)
78 enum machine_mode mode;
80 return (GET_CODE (op) == CONST_INT
81 && abs (INTVAL(op)) > 1
82 && abs (INTVAL(op)) <= 4);
86 stream is a stdio stream to output the code to.
87 size is an int: how many units of temporary storage to allocate.
88 Refer to the array `regs_ever_live' to determine which registers
89 to save; `regs_ever_live[I]' is nonzero if register number I
90 is ever used in the function. This macro is responsible for
91 knowing which registers should not be saved even if used.
95 output_function_prologue(stream, size)
99 int fsize = ((size) + 1) & ~1;
105 fprintf (stream, "\n\t; /* function prologue %s*/\n", current_function_name);
107 /* if we are outputting code for main,
108 the switch FPU to right mode if TARGET_FPU */
109 if ( (strcmp ("main", current_function_name) == 0)
112 fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
113 fprintf(stream, "\tsetd\n");
114 fprintf(stream, "\tseti\n\n");
117 if (frame_pointer_needed)
119 fprintf(stream, "\tmov fp, -(sp)\n");
120 fprintf(stream, "\tmov sp, fp\n");
129 fprintf (stream, "\tsub $%d, sp\n", fsize);
131 /* save CPU registers */
132 for (regno = 0; regno < 8; regno++)
133 if (regs_ever_live[regno] && ! call_used_regs[regno])
134 if (! ((regno == FRAME_POINTER_REGNUM)
135 && frame_pointer_needed))
136 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
137 /* fpu regs saving */
139 /* via_ac specifies the ac to use for saving ac4, ac5 */
142 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
145 if (LOAD_FPU_REG_P(regno)
146 && regs_ever_live[regno]
147 && ! call_used_regs[regno])
149 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
153 /* maybe make ac4, ac5 call used regs?? */
155 if (NO_LOAD_FPU_REG_P(regno)
156 && regs_ever_live[regno]
157 && ! call_used_regs[regno])
162 fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
163 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
167 fprintf (stream, "\t;/* end of prologue */\n\n");
171 The function epilogue should not depend on the current stack pointer!
172 It should use the frame pointer only. This is mandatory because
173 of alloca; we also take advantage of it to omit stack adjustments
176 /* maybe we can make leaf functions faster by switching to the
177 second register file - this way we don't have to save regs!
178 leaf functions are ~ 50% of all functions (dynamically!)
180 set/clear bit 11 (dec. 2048) of status word for switching register files -
181 but how can we do this? the pdp11/45 manual says bit may only
182 be set (p.24), but not cleared!
184 switching to kernel is probably more expensive, so we'll leave it
185 like this and not use the second set of registers...
187 maybe as option if you want to generate code for kernel mode? */
191 output_function_epilogue(stream, size)
195 extern int may_call_alloca;
197 int fsize = ((size) + 1) & ~1;
198 int nregs, regno, i, j, k, adjust_fp;
202 fprintf (stream, "\n\t; /*function epilogue */\n");
204 if (frame_pointer_needed)
206 /* hope this is safe - m68k does it also .... */
207 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
209 for (i =7, j = 0 ; i >= 0 ; i--)
210 if (regs_ever_live[i] && ! call_used_regs[i])
213 /* remember # of pushed bytes for CPU regs */
216 for (i =7 ; i >= 0 ; i--)
217 if (regs_ever_live[i] && ! call_used_regs[i])
218 fprintf(stream, "\tmov %d(fp), %s\n",-fsize-2*j--, reg_names[i]);
221 via_ac = FIRST_PSEUDO_REGISTER -1;
223 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
224 if (regs_ever_live[i] && ! call_used_regs[i])
230 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
232 if (LOAD_FPU_REG_P(i)
234 && ! call_used_regs[i])
236 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[i]);
240 if (NO_LOAD_FPU_REG_P(i)
242 && ! call_used_regs[i])
244 if (! LOAD_FPU_REG_P(via_ac))
247 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[via_ac]);
248 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
253 fprintf(stream, "\tmov fp, sp\n");
254 fprintf (stream, "\tmov (sp)+, fp\n");
258 via_ac = FIRST_PSEUDO_REGISTER -1;
261 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
262 if (regs_ever_live[i] && call_used_regs[i])
265 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
267 if (LOAD_FPU_REG_P(i)
269 && ! call_used_regs[i])
270 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
272 if (NO_LOAD_FPU_REG_P(i)
274 && ! call_used_regs[i])
276 if (! LOAD_FPU_REG_P(via_ac))
279 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
280 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
284 for (i=7; i >= 0; i--)
285 if (regs_ever_live[i] && !call_used_regs[i])
286 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
289 fprintf((stream), "\tadd $%d, sp\n", fsize);
292 fprintf (stream, "\trts pc\n");
293 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
296 /* Return the best assembler insn template
297 for moving operands[1] into operands[0] as a fullword. */
299 singlemove_string (operands)
302 if (operands[1] != const0_rtx)
309 /* Output assembler code to perform a doubleword move insn
310 with operands OPERANDS. */
313 output_move_double (operands)
316 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
318 rtx addreg0 = 0, addreg1 = 0;
320 /* First classify both operands. */
322 if (REG_P (operands[0]))
324 else if (offsettable_memref_p (operands[0]))
326 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
328 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
330 else if (GET_CODE (operands[0]) == MEM)
335 if (REG_P (operands[1]))
337 else if (CONSTANT_P (operands[1]))
339 || GET_CODE (operands[1]) == CONST_DOUBLE)
342 else if (offsettable_memref_p (operands[1]))
344 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
346 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
348 else if (GET_CODE (operands[1]) == MEM)
353 /* Check for the cases that the operand constraints are not
354 supposed to allow to happen. Abort if we get one,
355 because generating code for these cases is painful. */
357 if (optype0 == RNDOP || optype1 == RNDOP)
360 /* If one operand is decrementing and one is incrementing
361 decrement the former register explicitly
362 and change that operand into ordinary indexing. */
364 if (optype0 == PUSHOP && optype1 == POPOP)
366 operands[0] = XEXP (XEXP (operands[0], 0), 0);
367 output_asm_insn ("sub $4,%0", operands);
368 operands[0] = gen_rtx (MEM, SImode, operands[0]);
371 if (optype0 == POPOP && optype1 == PUSHOP)
373 operands[1] = XEXP (XEXP (operands[1], 0), 0);
374 output_asm_insn ("sub $4,%1", operands);
375 operands[1] = gen_rtx (MEM, SImode, operands[1]);
379 /* If an operand is an unoffsettable memory ref, find a register
380 we can increment temporarily to make it refer to the second word. */
382 if (optype0 == MEMOP)
383 addreg0 = find_addr_reg (XEXP (operands[0], 0));
385 if (optype1 == MEMOP)
386 addreg1 = find_addr_reg (XEXP (operands[1], 0));
388 /* Ok, we can do one word at a time.
389 Normally we do the low-numbered word first,
390 but if either operand is autodecrementing then we
391 do the high-numbered word first.
393 In either case, set up in LATEHALF the operands to use
394 for the high-numbered word and in some cases alter the
395 operands in OPERANDS to be suitable for the low-numbered word. */
397 if (optype0 == REGOP)
398 latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
399 else if (optype0 == OFFSOP)
400 latehalf[0] = adj_offsettable_operand (operands[0], 2);
402 latehalf[0] = operands[0];
404 if (optype1 == REGOP)
405 latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
406 else if (optype1 == OFFSOP)
407 latehalf[1] = adj_offsettable_operand (operands[1], 2);
408 else if (optype1 == CNSTOP)
410 if (CONSTANT_P (operands[1]))
412 /* now the mess begins, high word is in lower word???
414 that's what ashc makes me think, but I don't remember :-( */
415 latehalf[1] = GEN_INT (INTVAL(operands[1])>>16);
416 operands[1] = GEN_INT (INTVAL(operands[1])&0xff);
418 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
420 /* immediate 32 bit values not allowed */
425 latehalf[1] = operands[1];
427 /* If insn is effectively movd N(sp),-(sp) then we will do the
428 high word first. We should use the adjusted operand 1 (which is N+4(sp))
429 for the low word as well, to compensate for the first decrement of sp. */
430 if (optype0 == PUSHOP
431 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
432 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
433 operands[1] = latehalf[1];
435 /* If one or both operands autodecrementing,
436 do the two words, high-numbered first. */
438 /* Likewise, the first move would clobber the source of the second one,
439 do them in the other order. This happens only for registers;
440 such overlap can't happen in memory unless the user explicitly
441 sets it up, and that is an undefined circumstance. */
443 if (optype0 == PUSHOP || optype1 == PUSHOP
444 || (optype0 == REGOP && optype1 == REGOP
445 && REGNO (operands[0]) == REGNO (latehalf[1])))
447 /* Make any unoffsettable addresses point at high-numbered word. */
449 output_asm_insn ("add $2,%0", &addreg0);
451 output_asm_insn ("add $2,%0", &addreg1);
454 output_asm_insn (singlemove_string (latehalf), latehalf);
456 /* Undo the adds we just did. */
458 output_asm_insn ("sub $2,%0", &addreg0);
460 output_asm_insn ("sub $2,%0", &addreg1);
462 /* Do low-numbered word. */
463 return singlemove_string (operands);
466 /* Normal case: do the two words, low-numbered first. */
468 output_asm_insn (singlemove_string (operands), operands);
470 /* Make any unoffsettable addresses point at high-numbered word. */
472 output_asm_insn ("add $2,%0", &addreg0);
474 output_asm_insn ("add $2,%0", &addreg1);
477 output_asm_insn (singlemove_string (latehalf), latehalf);
479 /* Undo the adds we just did. */
481 output_asm_insn ("sub $2,%0", &addreg0);
483 output_asm_insn ("sub $2,%0", &addreg1);
487 /* Output assembler code to perform a quadword move insn
488 with operands OPERANDS. */
491 output_move_quad (operands)
494 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
496 rtx addreg0 = 0, addreg1 = 0;
498 output_asm_insn(";; movdi/df: %1 -> %0", operands);
500 if (REG_P (operands[0]))
502 else if (offsettable_memref_p (operands[0]))
504 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
506 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
508 else if (GET_CODE (operands[0]) == MEM)
513 if (REG_P (operands[1]))
515 else if (CONSTANT_P (operands[1])
516 || GET_CODE (operands[1]) == CONST_DOUBLE)
518 else if (offsettable_memref_p (operands[1]))
520 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
522 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
524 else if (GET_CODE (operands[1]) == MEM)
529 /* Check for the cases that the operand constraints are not
530 supposed to allow to happen. Abort if we get one,
531 because generating code for these cases is painful. */
533 if (optype0 == RNDOP || optype1 == RNDOP)
536 /* check if we move a CPU reg to an FPU reg, or vice versa! */
537 if (optype0 == REGOP && optype1 == REGOP)
538 /* bogus - 64 bit cannot reside in CPU! */
539 if (CPU_REG_P(REGNO(operands[0]))
540 || CPU_REG_P (REGNO(operands[1])))
543 if (optype0 == REGOP || optype1 == REGOP)
545 /* check for use of clrd????
546 if you ever allow ac4 and ac5 (now we require secondary load)
547 you must check whether
548 you want to load into them or store from them -
549 then dump ac0 into $help$ movce ac4/5 to ac0, do the
550 store from ac0, and restore ac0 - if you can find
551 an unused ac[0-3], use that and you save a store and a load!*/
553 if (FPU_REG_P(REGNO(operands[0])))
555 if (GET_CODE(operands[1]) == CONST_DOUBLE)
557 union { double d; int i[2]; } u;
558 u.i[0] = CONST_DOUBLE_LOW (operands[1]);
559 u.i[1] = CONST_DOUBLE_HIGH (operands[1]);
568 if (FPU_REG_P(REGNO(operands[1])))
572 /* If one operand is decrementing and one is incrementing
573 decrement the former register explicitly
574 and change that operand into ordinary indexing. */
576 if (optype0 == PUSHOP && optype1 == POPOP)
578 operands[0] = XEXP (XEXP (operands[0], 0), 0);
579 output_asm_insn ("sub $8,%0", operands);
580 operands[0] = gen_rtx (MEM, DImode, operands[0]);
583 if (optype0 == POPOP && optype1 == PUSHOP)
585 operands[1] = XEXP (XEXP (operands[1], 0), 0);
586 output_asm_insn ("sub $8,%1", operands);
587 operands[1] = gen_rtx (MEM, SImode, operands[1]);
591 /* If an operand is an unoffsettable memory ref, find a register
592 we can increment temporarily to make it refer to the second word. */
594 if (optype0 == MEMOP)
595 addreg0 = find_addr_reg (XEXP (operands[0], 0));
597 if (optype1 == MEMOP)
598 addreg1 = find_addr_reg (XEXP (operands[1], 0));
600 /* Ok, we can do one word at a time.
601 Normally we do the low-numbered word first,
602 but if either operand is autodecrementing then we
603 do the high-numbered word first.
605 In either case, set up in LATEHALF the operands to use
606 for the high-numbered word and in some cases alter the
607 operands in OPERANDS to be suitable for the low-numbered word. */
609 if (optype0 == REGOP)
610 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
611 else if (optype0 == OFFSOP)
612 latehalf[0] = adj_offsettable_operand (operands[0], 4);
614 latehalf[0] = operands[0];
616 if (optype1 == REGOP)
617 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
618 else if (optype1 == OFFSOP)
619 latehalf[1] = adj_offsettable_operand (operands[1], 4);
620 else if (optype1 == CNSTOP)
622 if (GET_CODE (operands[1]) == CONST_DOUBLE)
624 /* floats only. not yet supported!
626 -- compute it into PDP float format, - internally,
627 just use IEEE and ignore possible problems ;-)
629 we might get away with it !!!! */
633 #ifndef HOST_WORDS_BIG_ENDIAN
634 latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
635 operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
636 #else /* HOST_WORDS_BIG_ENDIAN */
637 latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
638 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
639 #endif /* HOST_WORDS_BIG_ENDIAN */
641 else if (GET_CODE(operands[1]) == CONST_INT)
643 latehalf[1] = GEN_INT (0);
650 latehalf[1] = operands[1];
652 /* If insn is effectively movd N(sp),-(sp) then we will do the
653 high word first. We should use the adjusted operand 1 (which is N+4(sp))
654 for the low word as well, to compensate for the first decrement of sp. */
655 if (optype0 == PUSHOP
656 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
657 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
658 operands[1] = latehalf[1];
660 /* If one or both operands autodecrementing,
661 do the two words, high-numbered first. */
663 /* Likewise, the first move would clobber the source of the second one,
664 do them in the other order. This happens only for registers;
665 such overlap can't happen in memory unless the user explicitly
666 sets it up, and that is an undefined circumstance. */
668 if (optype0 == PUSHOP || optype1 == PUSHOP
669 || (optype0 == REGOP && optype1 == REGOP
670 && REGNO (operands[0]) == REGNO (latehalf[1])))
672 /* Make any unoffsettable addresses point at high-numbered word. */
674 output_asm_insn ("add $4,%0", &addreg0);
676 output_asm_insn ("add $4,%0", &addreg1);
679 output_asm_insn(output_move_double(latehalf), latehalf);
681 /* Undo the adds we just did. */
683 output_asm_insn ("sub $4,%0", &addreg0);
685 output_asm_insn ("sub $4,%0", &addreg1);
687 /* Do low-numbered word. */
688 return output_move_double (operands);
691 /* Normal case: do the two words, low-numbered first. */
693 output_asm_insn (output_move_double (operands), operands);
695 /* Make any unoffsettable addresses point at high-numbered word. */
697 output_asm_insn ("add $4,%0", &addreg0);
699 output_asm_insn ("add $4,%0", &addreg1);
702 output_asm_insn (output_move_double (latehalf), latehalf);
704 /* Undo the adds we just did. */
706 output_asm_insn ("sub $4,%0", &addreg0);
708 output_asm_insn ("sub $4,%0", &addreg1);
714 /* Return a REG that occurs in ADDR with coefficient 1.
715 ADDR can be effectively incremented by incrementing REG. */
721 while (GET_CODE (addr) == PLUS)
723 if (GET_CODE (XEXP (addr, 0)) == REG)
724 addr = XEXP (addr, 0);
725 if (GET_CODE (XEXP (addr, 1)) == REG)
726 addr = XEXP (addr, 1);
727 if (CONSTANT_P (XEXP (addr, 0)))
728 addr = XEXP (addr, 1);
729 if (CONSTANT_P (XEXP (addr, 1)))
730 addr = XEXP (addr, 0);
732 if (GET_CODE (addr) == REG)
737 /* Output an ascii string. */
738 output_ascii (file, p, size)
745 fprintf (file, "\t.byte \"");
747 for (i = 0; i < size; i++)
749 register int c = p[i];
750 if (c == '\"' || c == '\\')
752 if (c >= ' ' && c < 0177)
756 fprintf (file, "\\%03o", c);
757 /* After an octal-escape, if a digit follows,
758 terminate one string constant and start another.
759 The Vax assembler fails to stop reading the escape
760 after three digits, so this is the only way we
761 can get it to parse the data properly. */
762 if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
763 fprintf (file, "\"\n\tstring \"");
766 fprintf (file, "\"\n");
770 /* --- stole from out-vax, needs changes */
772 print_operand_address (file, addr)
776 register rtx reg1, reg2, breg, ireg;
781 switch (GET_CODE (addr))
785 addr = XEXP (addr, 0);
789 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
793 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
797 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
804 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
805 || GET_CODE (XEXP (addr, 0)) == MEM)
807 offset = XEXP (addr, 0);
808 addr = XEXP (addr, 1);
810 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
811 || GET_CODE (XEXP (addr, 1)) == MEM)
813 offset = XEXP (addr, 1);
814 addr = XEXP (addr, 0);
816 if (GET_CODE (addr) != PLUS)
818 else if (GET_CODE (XEXP (addr, 0)) == MULT)
820 reg1 = XEXP (addr, 0);
821 addr = XEXP (addr, 1);
823 else if (GET_CODE (XEXP (addr, 1)) == MULT)
825 reg1 = XEXP (addr, 1);
826 addr = XEXP (addr, 0);
828 else if (GET_CODE (XEXP (addr, 0)) == REG)
830 reg1 = XEXP (addr, 0);
831 addr = XEXP (addr, 1);
833 else if (GET_CODE (XEXP (addr, 1)) == REG)
835 reg1 = XEXP (addr, 1);
836 addr = XEXP (addr, 0);
838 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
848 if (addr != 0) abort ();
851 if (reg1 != 0 && GET_CODE (reg1) == MULT)
856 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
861 else if (reg2 != 0 || GET_CODE (addr) == MEM)
872 output_address (addr);
875 if (GET_CODE (breg) != REG)
877 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
881 if (GET_CODE (ireg) == MULT)
882 ireg = XEXP (ireg, 0);
883 if (GET_CODE (ireg) != REG)
886 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
891 output_addr_const (file, addr);
895 /* register move costs, indexed by regs */
897 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
899 /* NO MUL GEN LFPU NLFPU FPU ALL */
901 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
902 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
903 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
904 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
905 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
906 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
907 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
911 /* -- note that some moves are tremendously expensive,
912 because they require lots of tricks! do we have to
913 charge the costs incurred by secondary reload class
914 -- as we do here with 22 -- or not ? */
917 register_move_cost(c1, c2)
918 enum reg_class c1, c2;
920 return move_costs[(int)c1][(int)c2];
924 output_jump(pos, neg, length)
930 static char buf[1000];
933 /* currently we don't need this, because the tstdf and cmpdf
934 copy the condition code immediately, and other float operations are not
935 yet recognized as changing the FCC - if so, then the length-cost of all
936 jump insns increases by one, because we have to potentially copy the
938 if (cc_status.flags & CC_IN_FPU)
939 output_asm_insn("cfcc", NULL);
953 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
967 notice_update_cc_on_set(exp, insn)
971 if (GET_CODE (SET_DEST (exp)) == CC0)
974 cc_status.value1 = SET_DEST (exp);
975 cc_status.value2 = SET_SRC (exp);
978 if (GET_MODE(SET_SRC(exp)) == DFmode)
979 cc_status.flags |= CC_IN_FPU;
982 else if ((GET_CODE (SET_DEST (exp)) == REG
983 || GET_CODE (SET_DEST (exp)) == MEM)
984 && GET_CODE (SET_SRC (exp)) != PC
985 && (GET_MODE (SET_DEST(exp)) == HImode
986 || GET_MODE (SET_DEST(exp)) == QImode)
987 && (GET_CODE (SET_SRC(exp)) == PLUS
988 || GET_CODE (SET_SRC(exp)) == MINUS
989 || GET_CODE (SET_SRC(exp)) == AND
990 || GET_CODE (SET_SRC(exp)) == IOR
991 || GET_CODE (SET_SRC(exp)) == XOR
992 || GET_CODE (SET_SRC(exp)) == NOT
993 || GET_CODE (SET_SRC(exp)) == NEG
994 || GET_CODE (SET_SRC(exp)) == REG
995 || GET_CODE (SET_SRC(exp)) == MEM))
998 cc_status.value1 = SET_SRC (exp);
999 cc_status.value2 = SET_DEST (exp);
1001 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1003 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1004 cc_status.value2 = 0;
1005 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1007 && GET_CODE (cc_status.value2) == MEM)
1008 cc_status.value2 = 0;
1010 else if (GET_CODE (SET_SRC (exp)) == CALL)
1014 else if (GET_CODE (SET_DEST (exp)) == REG)
1017 if ((cc_status.value1
1018 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1019 cc_status.value1 = 0;
1020 if ((cc_status.value2
1021 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1022 cc_status.value2 = 0;
1024 else if (SET_DEST(exp) == pc_rtx)
1028 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1030 /* the last else is a bit paranoiac, but since nearly all instructions
1031 play with condition codes, it's reasonable! */
1033 CC_STATUS_INIT; /* paranoia*/
1038 int simple_memory_operand(op, mode)
1040 enum machine_mode mode;
1042 rtx addr, plus0, plus1;
1045 /* Eliminate non-memory operations */
1046 if (GET_CODE (op) != MEM)
1050 /* dword operations really put out 2 instructions, so eliminate them. */
1051 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1055 /* Decode the address now. */
1059 addr = XEXP (op, 0);
1061 switch (GET_CODE (addr))
1064 /* (R0) - no extra cost */
1069 /* -(R0), (R0)+ - cheap! */
1073 /* cheap - is encoded in addressing mode info!
1075 -- except for @(R0), which has to be @0(R0) !!! */
1077 if (GET_CODE (XEXP (addr, 0)) == REG)
1087 /* @#address - extra cost */
1091 /* X(R0) - extra cost */
1100 * output a block move:
1102 * operands[0] ... to
1103 * operands[1] ... from
1104 * operands[2] ... length
1105 * operands[3] ... alignment
1106 * operands[4] ... scratch register
1111 output_block_move(operands)
1114 static int count = 0;
1117 if (GET_CODE(operands[2]) == CONST_INT
1120 if (INTVAL(operands[2]) < 16
1121 && INTVAL(operands[3]) == 1)
1125 for (i = 1; i <= INTVAL(operands[2]); i++)
1126 output_asm_insn("movb (%1)+, (%0)+", operands);
1130 else if (INTVAL(operands[2]) < 32)
1134 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1135 output_asm_insn("mov (%1)+, (%0)+", operands);
1137 /* may I assume that moved quantity is
1138 multiple of alignment ???
1147 /* can do other clever things, maybe... */
1150 if (CONSTANT_P(operands[2]) )
1152 /* just move count to scratch */
1153 output_asm_insn("mov %2, %4", operands);
1157 /* just clobber the register */
1158 operands[4] = operands[2];
1162 /* switch over alignment */
1163 switch (INTVAL(operands[3]))
1179 sprintf(buf, "\nmovestrhi%d:", count);
1180 output_asm_insn(buf, NULL);
1182 output_asm_insn("movb (%1)+, (%0)+", operands);
1186 sprintf(buf, "sob %%4, movestrhi%d", count);
1187 output_asm_insn(buf, operands);
1191 output_asm_insn("dec %4", operands);
1193 sprintf(buf, "bgt movestrhi%d", count);
1194 output_asm_insn(buf, NULL);
1216 generate_compact_code:
1218 output_asm_insn("asr %4", operands);
1220 sprintf(buf, "\nmovestrhi%d:", count);
1221 output_asm_insn(buf, NULL);
1223 output_asm_insn("mov (%1)+, (%0)+", operands);
1227 sprintf(buf, "sob %%4, movestrhi%d", count);
1228 output_asm_insn(buf, operands);
1232 output_asm_insn("dec %4", operands);
1234 sprintf(buf, "bgt movestrhi%d", count);
1235 output_asm_insn(buf, NULL);
1261 goto generate_compact_code;
1263 output_asm_insn("asr %4", operands);
1264 output_asm_insn("asr %4", operands);
1266 sprintf(buf, "\nmovestrhi%d:", count);
1267 output_asm_insn(buf, NULL);
1269 output_asm_insn("mov (%1)+, (%0)+", operands);
1270 output_asm_insn("mov (%1)+, (%0)+", operands);
1274 sprintf(buf, "sob %%4, movestrhi%d", count);
1275 output_asm_insn(buf, operands);
1279 output_asm_insn("dec %4", operands);
1281 sprintf(buf, "bgt movestrhi%d", count);
1282 output_asm_insn(buf, NULL);
1312 goto generate_compact_code;
1314 output_asm_insn("asr %4", operands);
1315 output_asm_insn("asr %4", operands);
1316 output_asm_insn("asr %4", operands);
1318 sprintf(buf, "\nmovestrhi%d:", count);
1319 output_asm_insn(buf, NULL);
1321 output_asm_insn("mov (%1)+, (%0)+", operands);
1322 output_asm_insn("mov (%1)+, (%0)+", operands);
1323 output_asm_insn("mov (%1)+, (%0)+", operands);
1324 output_asm_insn("mov (%1)+, (%0)+", operands);
1328 sprintf(buf, "sob %%4, movestrhi%d", count);
1329 output_asm_insn(buf, operands);
1333 output_asm_insn("dec %4", operands);
1335 sprintf(buf, "bgt movestrhi%d", count);
1336 output_asm_insn(buf, NULL);
1349 /* for future use */
1351 comparison_operator_index(op)
1354 switch (GET_CODE(op))
1391 /* tests whether the rtx is a comparison operator */
1393 comp_operator (op, mode)
1395 enum machine_mode mode;
1397 return comparison_operator_index(op) >= 0;
1402 legitimate_address_p (mode, address)
1403 enum machine_mode mode;
1406 /* #define REG_OK_STRICT */
1407 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1414 /* #undef REG_OK_STRICT */