1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
33 #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 extern char call_used_regs[];
100 extern int frame_pointer_needed;
102 int fsize = ((size) + 1) & ~1;
108 fprintf (stream, "\n\t; /* function prologue %s*/\n", current_function_name);
110 /* if we are outputting code for main,
111 the switch FPU to right mode if TARGET_FPU */
112 if ( (strcmp ("main", current_function_name) == 0)
115 fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
116 fprintf(stream, "\tsetd\n");
117 fprintf(stream, "\tseti\n\n");
120 if (frame_pointer_needed)
122 fprintf(stream, "\tmov fp, -(sp)\n");
123 fprintf(stream, "\tmov sp, fp\n");
132 fprintf (stream, "\tsub $%d, sp\n", fsize);
134 /* save CPU registers */
135 for (regno = 0; regno < 8; regno++)
136 if (regs_ever_live[regno] && ! call_used_regs[regno])
137 if (! ((regno == FRAME_POINTER_REGNUM)
138 && frame_pointer_needed))
139 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
140 /* fpu regs saving */
142 /* via_ac specifies the ac to use for saving ac4, ac5 */
145 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
148 if (LOAD_FPU_REG_P(regno)
149 && regs_ever_live[regno]
150 && ! call_used_regs[regno])
152 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
156 /* maybe make ac4, ac5 call used regs?? */
158 if (NO_LOAD_FPU_REG_P(regno)
159 && regs_ever_live[regno]
160 && ! call_used_regs[regno])
165 fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
166 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
170 fprintf (stream, "\t;/* end of prologue */\n\n");
174 The function epilogue should not depend on the current stack pointer!
175 It should use the frame pointer only. This is mandatory because
176 of alloca; we also take advantage of it to omit stack adjustments
179 /* maybe we can make leaf functions faster by switching to the
180 second register file - this way we don't have to save regs!
181 leaf functions are ~ 50% of all functions (dynamically!)
183 set/clear bit 11 (dec. 2048) of status word for switching register files -
184 but how can we do this? the pdp11/45 manual says bit may only
185 be set (p.24), but not cleared!
187 switching to kernel is probably more expensive, so we'll leave it
188 like this and not use the second set of registers...
190 maybe as option if you want to generate code for kernel mode? */
194 output_function_epilogue(stream, size)
198 extern char call_used_regs[];
199 extern int may_call_alloca;
201 int fsize = ((size) + 1) & ~1;
202 int nregs, regno, i, j, k, adjust_fp;
206 fprintf (stream, "\n\t; /*function epilogue */\n");
208 if (frame_pointer_needed)
210 /* hope this is safe - m68k does it also .... */
211 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
213 for (i =7, j = 0 ; i >= 0 ; i--)
214 if (regs_ever_live[i] && ! call_used_regs[i])
217 /* remember # of pushed bytes for CPU regs */
220 for (i =7 ; i >= 0 ; i--)
221 if (regs_ever_live[i] && ! call_used_regs[i])
222 fprintf(stream, "\tmov %d(fp), %s\n",-fsize-2*j--, reg_names[i]);
225 via_ac = FIRST_PSEUDO_REGISTER -1;
227 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
228 if (regs_ever_live[i] && ! call_used_regs[i])
234 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
236 if (LOAD_FPU_REG_P(i)
238 && ! call_used_regs[i])
240 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[i]);
244 if (NO_LOAD_FPU_REG_P(i)
246 && ! call_used_regs[i])
248 if (! LOAD_FPU_REG_P(via_ac))
251 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[via_ac]);
252 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
257 fprintf(stream, "\tmov fp, sp\n");
258 fprintf (stream, "\tmov (sp)+, fp\n");
262 via_ac = FIRST_PSEUDO_REGISTER -1;
265 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
266 if (regs_ever_live[i] && call_used_regs[i])
269 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
271 if (LOAD_FPU_REG_P(i)
273 && ! call_used_regs[i])
274 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
276 if (NO_LOAD_FPU_REG_P(i)
278 && ! call_used_regs[i])
280 if (! LOAD_FPU_REG_P(via_ac))
283 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
284 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
288 for (i=7; i >= 0; i--)
289 if (regs_ever_live[i] && !call_used_regs[i])
290 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
293 fprintf((stream), "\tadd $%d, sp\n", fsize);
296 fprintf (stream, "\trts pc\n");
297 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
300 /* Return the best assembler insn template
301 for moving operands[1] into operands[0] as a fullword. */
303 singlemove_string (operands)
306 if (operands[1] != const0_rtx)
313 /* Output assembler code to perform a doubleword move insn
314 with operands OPERANDS. */
317 output_move_double (operands)
320 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
322 rtx addreg0 = 0, addreg1 = 0;
324 /* First classify both operands. */
326 if (REG_P (operands[0]))
328 else if (offsettable_memref_p (operands[0]))
330 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
332 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
334 else if (GET_CODE (operands[0]) == MEM)
339 if (REG_P (operands[1]))
341 else if (CONSTANT_P (operands[1]))
343 || GET_CODE (operands[1]) == CONST_DOUBLE)
346 else if (offsettable_memref_p (operands[1]))
348 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
350 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
352 else if (GET_CODE (operands[1]) == MEM)
357 /* Check for the cases that the operand constraints are not
358 supposed to allow to happen. Abort if we get one,
359 because generating code for these cases is painful. */
361 if (optype0 == RNDOP || optype1 == RNDOP)
364 /* If one operand is decrementing and one is incrementing
365 decrement the former register explicitly
366 and change that operand into ordinary indexing. */
368 if (optype0 == PUSHOP && optype1 == POPOP)
370 operands[0] = XEXP (XEXP (operands[0], 0), 0);
371 output_asm_insn ("sub $4,%0", operands);
372 operands[0] = gen_rtx (MEM, SImode, operands[0]);
375 if (optype0 == POPOP && optype1 == PUSHOP)
377 operands[1] = XEXP (XEXP (operands[1], 0), 0);
378 output_asm_insn ("sub $4,%1", operands);
379 operands[1] = gen_rtx (MEM, SImode, operands[1]);
383 /* If an operand is an unoffsettable memory ref, find a register
384 we can increment temporarily to make it refer to the second word. */
386 if (optype0 == MEMOP)
387 addreg0 = find_addr_reg (XEXP (operands[0], 0));
389 if (optype1 == MEMOP)
390 addreg1 = find_addr_reg (XEXP (operands[1], 0));
392 /* Ok, we can do one word at a time.
393 Normally we do the low-numbered word first,
394 but if either operand is autodecrementing then we
395 do the high-numbered word first.
397 In either case, set up in LATEHALF the operands to use
398 for the high-numbered word and in some cases alter the
399 operands in OPERANDS to be suitable for the low-numbered word. */
401 if (optype0 == REGOP)
402 latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
403 else if (optype0 == OFFSOP)
404 latehalf[0] = adj_offsettable_operand (operands[0], 2);
406 latehalf[0] = operands[0];
408 if (optype1 == REGOP)
409 latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
410 else if (optype1 == OFFSOP)
411 latehalf[1] = adj_offsettable_operand (operands[1], 2);
412 else if (optype1 == CNSTOP)
414 if (CONSTANT_P (operands[1]))
416 /* now the mess begins, high word is in lower word???
418 that's what ashc makes me think, but I don't remember :-( */
419 latehalf[1] = gen_rtx(CONST_INT, VOIDmode,
420 INTVAL(operands[1])>>16);
421 operands[1] = gen_rtx(CONST_INT, VOIDmode,
422 INTVAL(operands[1])&0xff);
424 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
426 /* immediate 32 bit values not allowed */
431 latehalf[1] = operands[1];
433 /* If insn is effectively movd N(sp),-(sp) then we will do the
434 high word first. We should use the adjusted operand 1 (which is N+4(sp))
435 for the low word as well, to compensate for the first decrement of sp. */
436 if (optype0 == PUSHOP
437 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
438 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
439 operands[1] = latehalf[1];
441 /* If one or both operands autodecrementing,
442 do the two words, high-numbered first. */
444 /* Likewise, the first move would clobber the source of the second one,
445 do them in the other order. This happens only for registers;
446 such overlap can't happen in memory unless the user explicitly
447 sets it up, and that is an undefined circumstance. */
449 if (optype0 == PUSHOP || optype1 == PUSHOP
450 || (optype0 == REGOP && optype1 == REGOP
451 && REGNO (operands[0]) == REGNO (latehalf[1])))
453 /* Make any unoffsettable addresses point at high-numbered word. */
455 output_asm_insn ("add $2,%0", &addreg0);
457 output_asm_insn ("add $2,%0", &addreg1);
460 output_asm_insn (singlemove_string (latehalf), latehalf);
462 /* Undo the adds we just did. */
464 output_asm_insn ("sub $2,%0", &addreg0);
466 output_asm_insn ("sub $2,%0", &addreg1);
468 /* Do low-numbered word. */
469 return singlemove_string (operands);
472 /* Normal case: do the two words, low-numbered first. */
474 output_asm_insn (singlemove_string (operands), operands);
476 /* Make any unoffsettable addresses point at high-numbered word. */
478 output_asm_insn ("add $2,%0", &addreg0);
480 output_asm_insn ("add $2,%0", &addreg1);
483 output_asm_insn (singlemove_string (latehalf), latehalf);
485 /* Undo the adds we just did. */
487 output_asm_insn ("sub $2,%0", &addreg0);
489 output_asm_insn ("sub $2,%0", &addreg1);
493 /* Output assembler code to perform a quadword move insn
494 with operands OPERANDS. */
497 output_move_quad (operands)
500 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
502 rtx addreg0 = 0, addreg1 = 0;
504 output_asm_insn(";; movdi/df: %1 -> %0", operands);
506 if (REG_P (operands[0]))
508 else if (offsettable_memref_p (operands[0]))
510 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
512 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
514 else if (GET_CODE (operands[0]) == MEM)
519 if (REG_P (operands[1]))
521 else if (CONSTANT_P (operands[1])
522 || GET_CODE (operands[1]) == CONST_DOUBLE)
524 else if (offsettable_memref_p (operands[1]))
526 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
528 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
530 else if (GET_CODE (operands[1]) == MEM)
535 /* Check for the cases that the operand constraints are not
536 supposed to allow to happen. Abort if we get one,
537 because generating code for these cases is painful. */
539 if (optype0 == RNDOP || optype1 == RNDOP)
542 /* check if we move a CPU reg to an FPU reg, or vice versa! */
543 if (optype0 == REGOP && optype1 == REGOP)
544 /* bogus - 64 bit cannot reside in CPU! */
545 if (CPU_REG_P(REGNO(operands[0]))
546 || CPU_REG_P (REGNO(operands[1])))
549 if (optype0 == REGOP || optype1 == REGOP)
551 /* check for use of clrd????
552 if you ever allow ac4 and ac5 (now we require secondary load)
553 you must check whether
554 you want to load into them or store from them -
555 then dump ac0 into $help$ movce ac4/5 to ac0, do the
556 store from ac0, and restore ac0 - if you can find
557 an unused ac[0-3], use that and you save a store and a load!*/
559 if (FPU_REG_P(REGNO(operands[0])))
561 if (GET_CODE(operands[1]) == CONST_DOUBLE)
563 union { double d; int i[2]; } u;
564 u.i[0] = CONST_DOUBLE_LOW (operands[1]);
565 u.i[1] = CONST_DOUBLE_HIGH (operands[1]);
574 if (FPU_REG_P(REGNO(operands[1])))
578 /* If one operand is decrementing and one is incrementing
579 decrement the former register explicitly
580 and change that operand into ordinary indexing. */
582 if (optype0 == PUSHOP && optype1 == POPOP)
584 operands[0] = XEXP (XEXP (operands[0], 0), 0);
585 output_asm_insn ("sub $8,%0", operands);
586 operands[0] = gen_rtx (MEM, DImode, operands[0]);
589 if (optype0 == POPOP && optype1 == PUSHOP)
591 operands[1] = XEXP (XEXP (operands[1], 0), 0);
592 output_asm_insn ("sub $8,%1", operands);
593 operands[1] = gen_rtx (MEM, SImode, operands[1]);
597 /* If an operand is an unoffsettable memory ref, find a register
598 we can increment temporarily to make it refer to the second word. */
600 if (optype0 == MEMOP)
601 addreg0 = find_addr_reg (XEXP (operands[0], 0));
603 if (optype1 == MEMOP)
604 addreg1 = find_addr_reg (XEXP (operands[1], 0));
606 /* Ok, we can do one word at a time.
607 Normally we do the low-numbered word first,
608 but if either operand is autodecrementing then we
609 do the high-numbered word first.
611 In either case, set up in LATEHALF the operands to use
612 for the high-numbered word and in some cases alter the
613 operands in OPERANDS to be suitable for the low-numbered word. */
615 if (optype0 == REGOP)
616 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
617 else if (optype0 == OFFSOP)
618 latehalf[0] = adj_offsettable_operand (operands[0], 4);
620 latehalf[0] = operands[0];
622 if (optype1 == REGOP)
623 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
624 else if (optype1 == OFFSOP)
625 latehalf[1] = adj_offsettable_operand (operands[1], 4);
626 else if (optype1 == CNSTOP)
628 if (GET_CODE (operands[1]) == CONST_DOUBLE)
630 /* floats only. not yet supported!
632 -- compute it into PDP float format, - internally,
633 just use IEEE and ignore possible problems ;-)
635 we might get away with it !!!! */
639 #ifndef HOST_WORDS_BIG_ENDIAN
640 latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
641 CONST_DOUBLE_LOW (operands[1]));
642 operands[1] = gen_rtx (CONST_INT, VOIDmode,
643 CONST_DOUBLE_HIGH (operands[1]));
644 #else /* HOST_WORDS_BIG_ENDIAN */
645 latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
646 CONST_DOUBLE_HIGH (operands[1]));
647 operands[1] = gen_rtx (CONST_INT, VOIDmode,
648 CONST_DOUBLE_LOW (operands[1]));
649 #endif /* HOST_WORDS_BIG_ENDIAN */
653 latehalf[1] = operands[1];
655 /* If insn is effectively movd N(sp),-(sp) then we will do the
656 high word first. We should use the adjusted operand 1 (which is N+4(sp))
657 for the low word as well, to compensate for the first decrement of sp. */
658 if (optype0 == PUSHOP
659 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
660 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
661 operands[1] = latehalf[1];
663 /* If one or both operands autodecrementing,
664 do the two words, high-numbered first. */
666 /* Likewise, the first move would clobber the source of the second one,
667 do them in the other order. This happens only for registers;
668 such overlap can't happen in memory unless the user explicitly
669 sets it up, and that is an undefined circumstance. */
671 if (optype0 == PUSHOP || optype1 == PUSHOP
672 || (optype0 == REGOP && optype1 == REGOP
673 && REGNO (operands[0]) == REGNO (latehalf[1])))
675 /* Make any unoffsettable addresses point at high-numbered word. */
677 output_asm_insn ("add $4,%0", &addreg0);
679 output_asm_insn ("add $4,%0", &addreg1);
682 output_asm_insn(output_move_double(latehalf), latehalf);
684 /* Undo the adds we just did. */
686 output_asm_insn ("sub $4,%0", &addreg0);
688 output_asm_insn ("sub $4,%0", &addreg1);
690 /* Do low-numbered word. */
691 return output_move_double (operands);
694 /* Normal case: do the two words, low-numbered first. */
696 output_asm_insn (output_move_double (operands), operands);
698 /* Make any unoffsettable addresses point at high-numbered word. */
700 output_asm_insn ("add $4,%0", &addreg0);
702 output_asm_insn ("add $4,%0", &addreg1);
705 output_asm_insn (output_move_double (latehalf), latehalf);
707 /* Undo the adds we just did. */
709 output_asm_insn ("sub $4,%0", &addreg0);
711 output_asm_insn ("sub $4,%0", &addreg1);
717 /* Return a REG that occurs in ADDR with coefficient 1.
718 ADDR can be effectively incremented by incrementing REG. */
724 while (GET_CODE (addr) == PLUS)
726 if (GET_CODE (XEXP (addr, 0)) == REG)
727 addr = XEXP (addr, 0);
728 if (GET_CODE (XEXP (addr, 1)) == REG)
729 addr = XEXP (addr, 1);
730 if (CONSTANT_P (XEXP (addr, 0)))
731 addr = XEXP (addr, 1);
732 if (CONSTANT_P (XEXP (addr, 1)))
733 addr = XEXP (addr, 0);
735 if (GET_CODE (addr) == REG)
740 /* Output an ascii string. */
741 output_ascii (file, p, size)
748 fprintf (file, "\t.byte \"");
750 for (i = 0; i < size; i++)
752 register int c = p[i];
753 if (c == '\"' || c == '\\')
755 if (c >= ' ' && c < 0177)
759 fprintf (file, "\\%03o", c);
760 /* After an octal-escape, if a digit follows,
761 terminate one string constant and start another.
762 The Vax assembler fails to stop reading the escape
763 after three digits, so this is the only way we
764 can get it to parse the data properly. */
765 if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
766 fprintf (file, "\"\n\tstring \"");
769 fprintf (file, "\"\n");
773 /* --- stole from out-vax, needs changes */
775 print_operand_address (file, addr)
779 register rtx reg1, reg2, breg, ireg;
784 switch (GET_CODE (addr))
788 addr = XEXP (addr, 0);
792 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
796 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
800 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
807 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
808 || GET_CODE (XEXP (addr, 0)) == MEM)
810 offset = XEXP (addr, 0);
811 addr = XEXP (addr, 1);
813 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
814 || GET_CODE (XEXP (addr, 1)) == MEM)
816 offset = XEXP (addr, 1);
817 addr = XEXP (addr, 0);
819 if (GET_CODE (addr) != PLUS)
821 else if (GET_CODE (XEXP (addr, 0)) == MULT)
823 reg1 = XEXP (addr, 0);
824 addr = XEXP (addr, 1);
826 else if (GET_CODE (XEXP (addr, 1)) == MULT)
828 reg1 = XEXP (addr, 1);
829 addr = XEXP (addr, 0);
831 else if (GET_CODE (XEXP (addr, 0)) == REG)
833 reg1 = XEXP (addr, 0);
834 addr = XEXP (addr, 1);
836 else if (GET_CODE (XEXP (addr, 1)) == REG)
838 reg1 = XEXP (addr, 1);
839 addr = XEXP (addr, 0);
841 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
851 if (addr != 0) abort ();
854 if (reg1 != 0 && GET_CODE (reg1) == MULT)
859 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
864 else if (reg2 != 0 || GET_CODE (addr) == MEM)
875 output_address (addr);
878 if (GET_CODE (breg) != REG)
880 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
884 if (GET_CODE (ireg) == MULT)
885 ireg = XEXP (ireg, 0);
886 if (GET_CODE (ireg) != REG)
889 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
894 output_addr_const (file, addr);
898 /* register move costs, indexed by regs */
900 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
902 /* NO MUL GEN LFPU NLFPU FPU ALL */
904 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
905 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
906 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
907 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
908 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
909 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
910 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
914 /* -- note that some moves are tremendously expensive,
915 because they require lots of tricks! do we have to
916 charge the costs incurred by secondary reload class
917 -- as we do here with 22 -- or not ? */
920 register_move_cost(c1, c2)
921 enum reg_class c1, c2;
923 return move_costs[(int)c1][(int)c2];
927 output_jump(pos, neg, length)
933 static char buf[1000];
936 /* currently we don't need this, because the tstdf and cmpdf
937 copy the condition code immediately, and other float operations are not
938 yet recognized as changing the FCC - if so, then the length-cost of all
939 jump insns increases by one, because we have to potentially copy the
941 if (cc_status.flags & CC_IN_FPU)
942 output_asm_insn("cfcc", NULL);
956 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
970 notice_update_cc_on_set(exp, insn)
974 if (GET_CODE (SET_DEST (exp)) == CC0)
977 cc_status.value1 = SET_DEST (exp);
978 cc_status.value2 = SET_SRC (exp);
981 if (GET_MODE(SET_SRC(exp)) == DFmode)
982 cc_status.flags |= CC_IN_FPU;
985 else if ((GET_CODE (SET_DEST (exp)) == REG
986 || GET_CODE (SET_DEST (exp)) == MEM)
987 && GET_CODE (SET_SRC (exp)) != PC
988 && (GET_MODE (SET_DEST(exp)) == HImode
989 || GET_MODE (SET_DEST(exp)) == QImode)
990 && (GET_CODE (SET_SRC(exp)) == PLUS
991 || GET_CODE (SET_SRC(exp)) == MINUS
992 || GET_CODE (SET_SRC(exp)) == AND
993 || GET_CODE (SET_SRC(exp)) == IOR
994 || GET_CODE (SET_SRC(exp)) == XOR
995 || GET_CODE (SET_SRC(exp)) == NOT
996 || GET_CODE (SET_SRC(exp)) == NEG
997 || GET_CODE (SET_SRC(exp)) == REG
998 || GET_CODE (SET_SRC(exp)) == MEM))
1000 cc_status.flags = 0;
1001 cc_status.value1 = SET_SRC (exp);
1002 cc_status.value2 = SET_DEST (exp);
1004 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1006 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1007 cc_status.value2 = 0;
1008 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1010 && GET_CODE (cc_status.value2) == MEM)
1011 cc_status.value2 = 0;
1013 else if (GET_CODE (SET_SRC (exp)) == CALL)
1017 else if (GET_CODE (SET_DEST (exp)) == REG)
1020 if ((cc_status.value1
1021 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1022 cc_status.value1 = 0;
1023 if ((cc_status.value2
1024 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1025 cc_status.value2 = 0;
1027 else if (SET_DEST(exp) == pc_rtx)
1031 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1033 /* the last else is a bit paranoiac, but since nearly all instructions
1034 play with condition codes, it's reasonable! */
1036 CC_STATUS_INIT; /* paranoia*/
1041 int simple_memory_operand(op, mode)
1043 enum machine_mode mode;
1045 rtx addr, plus0, plus1;
1048 /* Eliminate non-memory operations */
1049 if (GET_CODE (op) != MEM)
1053 /* dword operations really put out 2 instructions, so eliminate them. */
1054 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1058 /* Decode the address now. */
1062 addr = XEXP (op, 0);
1064 switch (GET_CODE (addr))
1067 /* (R0) - no extra cost */
1072 /* -(R0), (R0)+ - cheap! */
1076 /* cheap - is encoded in addressing mode info!
1078 -- except for @(R0), which has to be @0(R0) !!! */
1080 if (GET_CODE (XEXP (addr, 0)) == REG)
1090 /* @#address - extra cost */
1094 /* X(R0) - extra cost */
1103 * output a block move:
1105 * operands[0] ... to
1106 * operands[1] ... from
1107 * operands[2] ... length
1108 * operands[3] ... alignment
1109 * operands[4] ... scratch register
1114 output_block_move(operands)
1117 static int count = 0;
1120 if (GET_CODE(operands[2]) == CONST_INT
1123 if (INTVAL(operands[2]) < 16
1124 && INTVAL(operands[3]) == 1)
1128 for (i = 1; i <= INTVAL(operands[2]); i++)
1129 output_asm_insn("movb (%1)+, (%0)+", operands);
1133 else if (INTVAL(operands[2]) < 32)
1137 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1138 output_asm_insn("mov (%1)+, (%0)+", operands);
1140 /* may I assume that moved quantity is
1141 multiple of alignment ???
1150 /* can do other clever things, maybe... */
1153 if (CONSTANT_P(operands[2]) )
1155 /* just move count to scratch */
1156 output_asm_insn("mov %2, %4", operands);
1160 /* just clobber the register */
1161 operands[4] = operands[2];
1165 /* switch over alignment */
1166 switch (INTVAL(operands[3]))
1182 sprintf(buf, "\nmovestrhi%d:", count);
1183 output_asm_insn(buf, NULL);
1185 output_asm_insn("movb (%1)+, (%0)+", operands);
1189 sprintf(buf, "sob %%4, movestrhi%d", count);
1190 output_asm_insn(buf, operands);
1194 output_asm_insn("dec %4", operands);
1196 sprintf(buf, "bgt movestrhi%d", count);
1197 output_asm_insn(buf, NULL);
1219 generate_compact_code:
1221 output_asm_insn("asr %4", operands);
1223 sprintf(buf, "\nmovestrhi%d:", count);
1224 output_asm_insn(buf, NULL);
1226 output_asm_insn("mov (%1)+, (%0)+", operands);
1230 sprintf(buf, "sob %%4, movestrhi%d", count);
1231 output_asm_insn(buf, operands);
1235 output_asm_insn("dec %4", operands);
1237 sprintf(buf, "bgt movestrhi%d", count);
1238 output_asm_insn(buf, NULL);
1264 goto generate_compact_code;
1266 output_asm_insn("asr %4", operands);
1267 output_asm_insn("asr %4", operands);
1269 sprintf(buf, "\nmovestrhi%d:", count);
1270 output_asm_insn(buf, NULL);
1272 output_asm_insn("mov (%1)+, (%0)+", operands);
1273 output_asm_insn("mov (%1)+, (%0)+", operands);
1277 sprintf(buf, "sob %%4, movestrhi%d", count);
1278 output_asm_insn(buf, operands);
1282 output_asm_insn("dec %4", operands);
1284 sprintf(buf, "bgt movestrhi%d", count);
1285 output_asm_insn(buf, NULL);
1315 goto generate_compact_code;
1317 output_asm_insn("asr %4", operands);
1318 output_asm_insn("asr %4", operands);
1319 output_asm_insn("asr %4", operands);
1321 sprintf(buf, "\nmovestrhi%d:", count);
1322 output_asm_insn(buf, NULL);
1324 output_asm_insn("mov (%1)+, (%0)+", operands);
1325 output_asm_insn("mov (%1)+, (%0)+", operands);
1326 output_asm_insn("mov (%1)+, (%0)+", operands);
1327 output_asm_insn("mov (%1)+, (%0)+", operands);
1331 sprintf(buf, "sob %%4, movestrhi%d", count);
1332 output_asm_insn(buf, operands);
1336 output_asm_insn("dec %4", operands);
1338 sprintf(buf, "bgt movestrhi%d", count);
1339 output_asm_insn(buf, NULL);
1352 /* for future use */
1354 comparison_operator_index(op)
1357 switch (GET_CODE(op))
1394 /* tests whether the rtx is a comparison operator */
1396 comp_operator (op, mode)
1398 enum machine_mode mode;
1400 return comparison_operator_index(op) >= 0;
1405 legitimate_address_p (mode, address)
1406 enum machine_mode mode;
1409 /* #define REG_OK_STRICT */
1410 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1417 /* #undef REG_OK_STRICT */