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"
32 #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 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 int fsize = ((size) + 1) & ~1;
200 fprintf (stream, "\n\t; /*function epilogue */\n");
202 if (frame_pointer_needed)
204 /* hope this is safe - m68k does it also .... */
205 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
207 for (i =7, j = 0 ; i >= 0 ; i--)
208 if (regs_ever_live[i] && ! call_used_regs[i])
211 /* remember # of pushed bytes for CPU regs */
214 for (i =7 ; i >= 0 ; i--)
215 if (regs_ever_live[i] && ! call_used_regs[i])
216 fprintf(stream, "\tmov %d(fp), %s\n",-fsize-2*j--, reg_names[i]);
219 via_ac = FIRST_PSEUDO_REGISTER -1;
221 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
222 if (regs_ever_live[i] && ! call_used_regs[i])
228 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
230 if (LOAD_FPU_REG_P(i)
232 && ! call_used_regs[i])
234 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[i]);
238 if (NO_LOAD_FPU_REG_P(i)
240 && ! call_used_regs[i])
242 if (! LOAD_FPU_REG_P(via_ac))
245 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[via_ac]);
246 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
251 fprintf(stream, "\tmov fp, sp\n");
252 fprintf (stream, "\tmov (sp)+, fp\n");
256 via_ac = FIRST_PSEUDO_REGISTER -1;
259 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
260 if (regs_ever_live[i] && call_used_regs[i])
263 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
265 if (LOAD_FPU_REG_P(i)
267 && ! call_used_regs[i])
268 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
270 if (NO_LOAD_FPU_REG_P(i)
272 && ! call_used_regs[i])
274 if (! LOAD_FPU_REG_P(via_ac))
277 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
278 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
282 for (i=7; i >= 0; i--)
283 if (regs_ever_live[i] && !call_used_regs[i])
284 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
287 fprintf((stream), "\tadd $%d, sp\n", fsize);
290 fprintf (stream, "\trts pc\n");
291 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
294 /* Return the best assembler insn template
295 for moving operands[1] into operands[0] as a fullword. */
297 singlemove_string (operands)
300 if (operands[1] != const0_rtx)
307 /* Output assembler code to perform a doubleword move insn
308 with operands OPERANDS. */
311 output_move_double (operands)
314 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
316 rtx addreg0 = 0, addreg1 = 0;
318 /* First classify both operands. */
320 if (REG_P (operands[0]))
322 else if (offsettable_memref_p (operands[0]))
324 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
326 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
328 else if (GET_CODE (operands[0]) == MEM)
333 if (REG_P (operands[1]))
335 else if (CONSTANT_P (operands[1]))
337 || GET_CODE (operands[1]) == CONST_DOUBLE)
340 else if (offsettable_memref_p (operands[1]))
342 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
344 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
346 else if (GET_CODE (operands[1]) == MEM)
351 /* Check for the cases that the operand constraints are not
352 supposed to allow to happen. Abort if we get one,
353 because generating code for these cases is painful. */
355 if (optype0 == RNDOP || optype1 == RNDOP)
358 /* If one operand is decrementing and one is incrementing
359 decrement the former register explicitly
360 and change that operand into ordinary indexing. */
362 if (optype0 == PUSHOP && optype1 == POPOP)
364 operands[0] = XEXP (XEXP (operands[0], 0), 0);
365 output_asm_insn ("sub $4,%0", operands);
366 operands[0] = gen_rtx (MEM, SImode, operands[0]);
369 if (optype0 == POPOP && optype1 == PUSHOP)
371 operands[1] = XEXP (XEXP (operands[1], 0), 0);
372 output_asm_insn ("sub $4,%1", operands);
373 operands[1] = gen_rtx (MEM, SImode, operands[1]);
377 /* If an operand is an unoffsettable memory ref, find a register
378 we can increment temporarily to make it refer to the second word. */
380 if (optype0 == MEMOP)
381 addreg0 = find_addr_reg (XEXP (operands[0], 0));
383 if (optype1 == MEMOP)
384 addreg1 = find_addr_reg (XEXP (operands[1], 0));
386 /* Ok, we can do one word at a time.
387 Normally we do the low-numbered word first,
388 but if either operand is autodecrementing then we
389 do the high-numbered word first.
391 In either case, set up in LATEHALF the operands to use
392 for the high-numbered word and in some cases alter the
393 operands in OPERANDS to be suitable for the low-numbered word. */
395 if (optype0 == REGOP)
396 latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
397 else if (optype0 == OFFSOP)
398 latehalf[0] = adj_offsettable_operand (operands[0], 2);
400 latehalf[0] = operands[0];
402 if (optype1 == REGOP)
403 latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
404 else if (optype1 == OFFSOP)
405 latehalf[1] = adj_offsettable_operand (operands[1], 2);
406 else if (optype1 == CNSTOP)
408 if (CONSTANT_P (operands[1]))
410 /* now the mess begins, high word is in lower word???
412 that's what ashc makes me think, but I don't remember :-( */
413 latehalf[1] = GEN_INT (INTVAL(operands[1])>>16);
414 operands[1] = GEN_INT (INTVAL(operands[1])&0xff);
416 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
418 /* immediate 32 bit values not allowed */
423 latehalf[1] = operands[1];
425 /* If insn is effectively movd N(sp),-(sp) then we will do the
426 high word first. We should use the adjusted operand 1 (which is N+4(sp))
427 for the low word as well, to compensate for the first decrement of sp. */
428 if (optype0 == PUSHOP
429 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
430 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
431 operands[1] = latehalf[1];
433 /* If one or both operands autodecrementing,
434 do the two words, high-numbered first. */
436 /* Likewise, the first move would clobber the source of the second one,
437 do them in the other order. This happens only for registers;
438 such overlap can't happen in memory unless the user explicitly
439 sets it up, and that is an undefined circumstance. */
441 if (optype0 == PUSHOP || optype1 == PUSHOP
442 || (optype0 == REGOP && optype1 == REGOP
443 && REGNO (operands[0]) == REGNO (latehalf[1])))
445 /* Make any unoffsettable addresses point at high-numbered word. */
447 output_asm_insn ("add $2,%0", &addreg0);
449 output_asm_insn ("add $2,%0", &addreg1);
452 output_asm_insn (singlemove_string (latehalf), latehalf);
454 /* Undo the adds we just did. */
456 output_asm_insn ("sub $2,%0", &addreg0);
458 output_asm_insn ("sub $2,%0", &addreg1);
460 /* Do low-numbered word. */
461 return singlemove_string (operands);
464 /* Normal case: do the two words, low-numbered first. */
466 output_asm_insn (singlemove_string (operands), operands);
468 /* Make any unoffsettable addresses point at high-numbered word. */
470 output_asm_insn ("add $2,%0", &addreg0);
472 output_asm_insn ("add $2,%0", &addreg1);
475 output_asm_insn (singlemove_string (latehalf), latehalf);
477 /* Undo the adds we just did. */
479 output_asm_insn ("sub $2,%0", &addreg0);
481 output_asm_insn ("sub $2,%0", &addreg1);
485 /* Output assembler code to perform a quadword move insn
486 with operands OPERANDS. */
489 output_move_quad (operands)
492 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
494 rtx addreg0 = 0, addreg1 = 0;
496 output_asm_insn(";; movdi/df: %1 -> %0", operands);
498 if (REG_P (operands[0]))
500 else if (offsettable_memref_p (operands[0]))
502 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
504 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
506 else if (GET_CODE (operands[0]) == MEM)
511 if (REG_P (operands[1]))
513 else if (CONSTANT_P (operands[1])
514 || GET_CODE (operands[1]) == CONST_DOUBLE)
516 else if (offsettable_memref_p (operands[1]))
518 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
520 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
522 else if (GET_CODE (operands[1]) == MEM)
527 /* Check for the cases that the operand constraints are not
528 supposed to allow to happen. Abort if we get one,
529 because generating code for these cases is painful. */
531 if (optype0 == RNDOP || optype1 == RNDOP)
534 /* check if we move a CPU reg to an FPU reg, or vice versa! */
535 if (optype0 == REGOP && optype1 == REGOP)
536 /* bogus - 64 bit cannot reside in CPU! */
537 if (CPU_REG_P(REGNO(operands[0]))
538 || CPU_REG_P (REGNO(operands[1])))
541 if (optype0 == REGOP || optype1 == REGOP)
543 /* check for use of clrd????
544 if you ever allow ac4 and ac5 (now we require secondary load)
545 you must check whether
546 you want to load into them or store from them -
547 then dump ac0 into $help$ movce ac4/5 to ac0, do the
548 store from ac0, and restore ac0 - if you can find
549 an unused ac[0-3], use that and you save a store and a load!*/
551 if (FPU_REG_P(REGNO(operands[0])))
553 if (GET_CODE(operands[1]) == CONST_DOUBLE)
555 union { double d; int i[2]; } u;
556 u.i[0] = CONST_DOUBLE_LOW (operands[1]);
557 u.i[1] = CONST_DOUBLE_HIGH (operands[1]);
566 if (FPU_REG_P(REGNO(operands[1])))
570 /* If one operand is decrementing and one is incrementing
571 decrement the former register explicitly
572 and change that operand into ordinary indexing. */
574 if (optype0 == PUSHOP && optype1 == POPOP)
576 operands[0] = XEXP (XEXP (operands[0], 0), 0);
577 output_asm_insn ("sub $8,%0", operands);
578 operands[0] = gen_rtx (MEM, DImode, operands[0]);
581 if (optype0 == POPOP && optype1 == PUSHOP)
583 operands[1] = XEXP (XEXP (operands[1], 0), 0);
584 output_asm_insn ("sub $8,%1", operands);
585 operands[1] = gen_rtx (MEM, SImode, operands[1]);
589 /* If an operand is an unoffsettable memory ref, find a register
590 we can increment temporarily to make it refer to the second word. */
592 if (optype0 == MEMOP)
593 addreg0 = find_addr_reg (XEXP (operands[0], 0));
595 if (optype1 == MEMOP)
596 addreg1 = find_addr_reg (XEXP (operands[1], 0));
598 /* Ok, we can do one word at a time.
599 Normally we do the low-numbered word first,
600 but if either operand is autodecrementing then we
601 do the high-numbered word first.
603 In either case, set up in LATEHALF the operands to use
604 for the high-numbered word and in some cases alter the
605 operands in OPERANDS to be suitable for the low-numbered word. */
607 if (optype0 == REGOP)
608 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
609 else if (optype0 == OFFSOP)
610 latehalf[0] = adj_offsettable_operand (operands[0], 4);
612 latehalf[0] = operands[0];
614 if (optype1 == REGOP)
615 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
616 else if (optype1 == OFFSOP)
617 latehalf[1] = adj_offsettable_operand (operands[1], 4);
618 else if (optype1 == CNSTOP)
620 if (GET_CODE (operands[1]) == CONST_DOUBLE)
622 /* floats only. not yet supported!
624 -- compute it into PDP float format, - internally,
625 just use IEEE and ignore possible problems ;-)
627 we might get away with it !!!! */
631 #ifndef HOST_WORDS_BIG_ENDIAN
632 latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
633 operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
634 #else /* HOST_WORDS_BIG_ENDIAN */
635 latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
636 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
637 #endif /* HOST_WORDS_BIG_ENDIAN */
639 else if (GET_CODE(operands[1]) == CONST_INT)
641 latehalf[1] = GEN_INT (0);
648 latehalf[1] = operands[1];
650 /* If insn is effectively movd N(sp),-(sp) then we will do the
651 high word first. We should use the adjusted operand 1 (which is N+4(sp))
652 for the low word as well, to compensate for the first decrement of sp. */
653 if (optype0 == PUSHOP
654 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
655 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
656 operands[1] = latehalf[1];
658 /* If one or both operands autodecrementing,
659 do the two words, high-numbered first. */
661 /* Likewise, the first move would clobber the source of the second one,
662 do them in the other order. This happens only for registers;
663 such overlap can't happen in memory unless the user explicitly
664 sets it up, and that is an undefined circumstance. */
666 if (optype0 == PUSHOP || optype1 == PUSHOP
667 || (optype0 == REGOP && optype1 == REGOP
668 && REGNO (operands[0]) == REGNO (latehalf[1])))
670 /* Make any unoffsettable addresses point at high-numbered word. */
672 output_asm_insn ("add $4,%0", &addreg0);
674 output_asm_insn ("add $4,%0", &addreg1);
677 output_asm_insn(output_move_double(latehalf), latehalf);
679 /* Undo the adds we just did. */
681 output_asm_insn ("sub $4,%0", &addreg0);
683 output_asm_insn ("sub $4,%0", &addreg1);
685 /* Do low-numbered word. */
686 return output_move_double (operands);
689 /* Normal case: do the two words, low-numbered first. */
691 output_asm_insn (output_move_double (operands), operands);
693 /* Make any unoffsettable addresses point at high-numbered word. */
695 output_asm_insn ("add $4,%0", &addreg0);
697 output_asm_insn ("add $4,%0", &addreg1);
700 output_asm_insn (output_move_double (latehalf), latehalf);
702 /* Undo the adds we just did. */
704 output_asm_insn ("sub $4,%0", &addreg0);
706 output_asm_insn ("sub $4,%0", &addreg1);
712 /* Return a REG that occurs in ADDR with coefficient 1.
713 ADDR can be effectively incremented by incrementing REG. */
719 while (GET_CODE (addr) == PLUS)
721 if (GET_CODE (XEXP (addr, 0)) == REG)
722 addr = XEXP (addr, 0);
723 if (GET_CODE (XEXP (addr, 1)) == REG)
724 addr = XEXP (addr, 1);
725 if (CONSTANT_P (XEXP (addr, 0)))
726 addr = XEXP (addr, 1);
727 if (CONSTANT_P (XEXP (addr, 1)))
728 addr = XEXP (addr, 0);
730 if (GET_CODE (addr) == REG)
735 /* Output an ascii string. */
737 output_ascii (file, p, size)
744 fprintf (file, "\t.byte \"");
746 for (i = 0; i < size; i++)
748 register int c = p[i];
749 if (c == '\"' || c == '\\')
751 if (c >= ' ' && c < 0177)
755 fprintf (file, "\\%03o", c);
756 /* After an octal-escape, if a digit follows,
757 terminate one string constant and start another.
758 The Vax assembler fails to stop reading the escape
759 after three digits, so this is the only way we
760 can get it to parse the data properly. */
761 if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
762 fprintf (file, "\"\n\tstring \"");
765 fprintf (file, "\"\n");
769 /* --- 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;
1044 /* Eliminate non-memory operations */
1045 if (GET_CODE (op) != MEM)
1049 /* dword operations really put out 2 instructions, so eliminate them. */
1050 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1054 /* Decode the address now. */
1058 addr = XEXP (op, 0);
1060 switch (GET_CODE (addr))
1063 /* (R0) - no extra cost */
1068 /* -(R0), (R0)+ - cheap! */
1072 /* cheap - is encoded in addressing mode info!
1074 -- except for @(R0), which has to be @0(R0) !!! */
1076 if (GET_CODE (XEXP (addr, 0)) == REG)
1086 /* @#address - extra cost */
1090 /* X(R0) - extra cost */
1102 * output a block move:
1104 * operands[0] ... to
1105 * operands[1] ... from
1106 * operands[2] ... length
1107 * operands[3] ... alignment
1108 * operands[4] ... scratch register
1113 output_block_move(operands)
1116 static int count = 0;
1119 if (GET_CODE(operands[2]) == CONST_INT
1122 if (INTVAL(operands[2]) < 16
1123 && INTVAL(operands[3]) == 1)
1127 for (i = 1; i <= INTVAL(operands[2]); i++)
1128 output_asm_insn("movb (%1)+, (%0)+", operands);
1132 else if (INTVAL(operands[2]) < 32)
1136 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1137 output_asm_insn("mov (%1)+, (%0)+", operands);
1139 /* may I assume that moved quantity is
1140 multiple of alignment ???
1149 /* can do other clever things, maybe... */
1152 if (CONSTANT_P(operands[2]) )
1154 /* just move count to scratch */
1155 output_asm_insn("mov %2, %4", operands);
1159 /* just clobber the register */
1160 operands[4] = operands[2];
1164 /* switch over alignment */
1165 switch (INTVAL(operands[3]))
1181 sprintf(buf, "\nmovestrhi%d:", count);
1182 output_asm_insn(buf, NULL);
1184 output_asm_insn("movb (%1)+, (%0)+", operands);
1188 sprintf(buf, "sob %%4, movestrhi%d", count);
1189 output_asm_insn(buf, operands);
1193 output_asm_insn("dec %4", operands);
1195 sprintf(buf, "bgt movestrhi%d", count);
1196 output_asm_insn(buf, NULL);
1218 generate_compact_code:
1220 output_asm_insn("asr %4", operands);
1222 sprintf(buf, "\nmovestrhi%d:", count);
1223 output_asm_insn(buf, NULL);
1225 output_asm_insn("mov (%1)+, (%0)+", operands);
1229 sprintf(buf, "sob %%4, movestrhi%d", count);
1230 output_asm_insn(buf, operands);
1234 output_asm_insn("dec %4", operands);
1236 sprintf(buf, "bgt movestrhi%d", count);
1237 output_asm_insn(buf, NULL);
1263 goto generate_compact_code;
1265 output_asm_insn("asr %4", operands);
1266 output_asm_insn("asr %4", operands);
1268 sprintf(buf, "\nmovestrhi%d:", count);
1269 output_asm_insn(buf, NULL);
1271 output_asm_insn("mov (%1)+, (%0)+", operands);
1272 output_asm_insn("mov (%1)+, (%0)+", operands);
1276 sprintf(buf, "sob %%4, movestrhi%d", count);
1277 output_asm_insn(buf, operands);
1281 output_asm_insn("dec %4", operands);
1283 sprintf(buf, "bgt movestrhi%d", count);
1284 output_asm_insn(buf, NULL);
1314 goto generate_compact_code;
1316 output_asm_insn("asr %4", operands);
1317 output_asm_insn("asr %4", operands);
1318 output_asm_insn("asr %4", operands);
1320 sprintf(buf, "\nmovestrhi%d:", count);
1321 output_asm_insn(buf, NULL);
1323 output_asm_insn("mov (%1)+, (%0)+", operands);
1324 output_asm_insn("mov (%1)+, (%0)+", operands);
1325 output_asm_insn("mov (%1)+, (%0)+", operands);
1326 output_asm_insn("mov (%1)+, (%0)+", operands);
1330 sprintf(buf, "sob %%4, movestrhi%d", count);
1331 output_asm_insn(buf, operands);
1335 output_asm_insn("dec %4", operands);
1337 sprintf(buf, "bgt movestrhi%d", count);
1338 output_asm_insn(buf, NULL);
1351 /* for future use */
1353 comparison_operator_index(op)
1356 switch (GET_CODE(op))
1393 /* tests whether the rtx is a comparison operator */
1395 comp_operator (op, mode)
1397 enum machine_mode mode;
1399 return comparison_operator_index(op) >= 0;
1404 legitimate_address_p (mode, address)
1405 enum machine_mode mode;
1408 /* #define REG_OK_STRICT */
1409 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1416 /* #undef REG_OK_STRICT */