1 /* Subroutines for gcc2 for pdp11.
2 Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999
3 Free Software Foundation, Inc.
4 Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
34 #include "insn-attr.h"
40 #define FPU_REG_P(X) ((X)>=8 && (X)<14)
41 #define CPU_REG_P(X) ((X)>=0 && (X)<8)
44 /* this is the current value returned by the macro FIRST_PARM_OFFSET
46 int current_first_parm_offset;
48 /* This is where the condition code register lives. */
49 /* rtx cc0_reg_rtx; - no longer needed? */
51 static rtx find_addr_reg PARAMS ((rtx));
52 static const char *singlemove_string PARAMS ((rtx *));
54 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
57 arith_operand (op, mode)
59 enum machine_mode mode;
61 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
65 const_immediate_operand (op, mode)
67 enum machine_mode mode ATTRIBUTE_UNUSED;
69 return (GET_CODE (op) == CONST_INT);
73 immediate15_operand (op, mode)
75 enum machine_mode mode ATTRIBUTE_UNUSED;
77 return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
81 expand_shift_operand (op, mode)
83 enum machine_mode mode ATTRIBUTE_UNUSED;
85 return (GET_CODE (op) == CONST_INT
86 && abs (INTVAL(op)) > 1
87 && abs (INTVAL(op)) <= 4);
91 stream is a stdio stream to output the code to.
92 size is an int: how many units of temporary storage to allocate.
93 Refer to the array `regs_ever_live' to determine which registers
94 to save; `regs_ever_live[I]' is nonzero if register number I
95 is ever used in the function. This macro is responsible for
96 knowing which registers should not be saved even if used.
100 output_function_prologue(stream, size)
104 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 (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
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 $%o, 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 int fsize = ((size) + 1) & ~1;
203 fprintf (stream, "\n\t; /*function epilogue */\n");
205 if (frame_pointer_needed)
207 /* hope this is safe - m68k does it also .... */
208 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
210 for (i =7, j = 0 ; i >= 0 ; i--)
211 if (regs_ever_live[i] && ! call_used_regs[i])
214 /* remember # of pushed bytes for CPU regs */
217 for (i =7 ; i >= 0 ; i--)
218 if (regs_ever_live[i] && ! call_used_regs[i])
219 fprintf(stream, "\tmov %o(fp), %s\n",-fsize-2*j--, reg_names[i]);
222 via_ac = FIRST_PSEUDO_REGISTER -1;
224 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
225 if (regs_ever_live[i] && ! call_used_regs[i])
231 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
233 if (LOAD_FPU_REG_P(i)
235 && ! call_used_regs[i])
237 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[i]);
241 if (NO_LOAD_FPU_REG_P(i)
243 && ! call_used_regs[i])
245 if (! LOAD_FPU_REG_P(via_ac))
248 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[via_ac]);
249 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
254 fprintf(stream, "\tmov fp, sp\n");
255 fprintf (stream, "\tmov (sp)+, fp\n");
259 via_ac = FIRST_PSEUDO_REGISTER -1;
262 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
263 if (regs_ever_live[i] && call_used_regs[i])
266 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
268 if (LOAD_FPU_REG_P(i)
270 && ! call_used_regs[i])
271 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
273 if (NO_LOAD_FPU_REG_P(i)
275 && ! call_used_regs[i])
277 if (! LOAD_FPU_REG_P(via_ac))
280 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
281 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
285 for (i=7; i >= 0; i--)
286 if (regs_ever_live[i] && !call_used_regs[i])
287 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
290 fprintf((stream), "\tadd $%o, sp\n", fsize);
293 fprintf (stream, "\trts pc\n");
294 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
297 /* Return the best assembler insn template
298 for moving operands[1] into operands[0] as a fullword. */
300 singlemove_string (operands)
303 if (operands[1] != const0_rtx)
310 /* Output assembler code to perform a doubleword move insn
311 with operands OPERANDS. */
314 output_move_double (operands)
317 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
319 rtx addreg0 = 0, addreg1 = 0;
321 /* First classify both operands. */
323 if (REG_P (operands[0]))
325 else if (offsettable_memref_p (operands[0]))
327 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
329 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
331 else if (GET_CODE (operands[0]) == MEM)
336 if (REG_P (operands[1]))
338 else if (CONSTANT_P (operands[1]))
340 || GET_CODE (operands[1]) == CONST_DOUBLE)
343 else if (offsettable_memref_p (operands[1]))
345 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
347 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
349 else if (GET_CODE (operands[1]) == MEM)
354 /* Check for the cases that the operand constraints are not
355 supposed to allow to happen. Abort if we get one,
356 because generating code for these cases is painful. */
358 if (optype0 == RNDOP || optype1 == RNDOP)
361 /* If one operand is decrementing and one is incrementing
362 decrement the former register explicitly
363 and change that operand into ordinary indexing. */
365 if (optype0 == PUSHOP && optype1 == POPOP)
367 operands[0] = XEXP (XEXP (operands[0], 0), 0);
368 output_asm_insn ("sub $4,%0", operands);
369 operands[0] = gen_rtx_MEM (SImode, operands[0]);
372 if (optype0 == POPOP && optype1 == PUSHOP)
374 operands[1] = XEXP (XEXP (operands[1], 0), 0);
375 output_asm_insn ("sub $4,%1", operands);
376 operands[1] = gen_rtx_MEM (SImode, operands[1]);
380 /* If an operand is an unoffsettable memory ref, find a register
381 we can increment temporarily to make it refer to the second word. */
383 if (optype0 == MEMOP)
384 addreg0 = find_addr_reg (XEXP (operands[0], 0));
386 if (optype1 == MEMOP)
387 addreg1 = find_addr_reg (XEXP (operands[1], 0));
389 /* Ok, we can do one word at a time.
390 Normally we do the low-numbered word first,
391 but if either operand is autodecrementing then we
392 do the high-numbered word first.
394 In either case, set up in LATEHALF the operands to use
395 for the high-numbered word and in some cases alter the
396 operands in OPERANDS to be suitable for the low-numbered word. */
398 if (optype0 == REGOP)
399 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
400 else if (optype0 == OFFSOP)
401 latehalf[0] = adj_offsettable_operand (operands[0], 2);
403 latehalf[0] = operands[0];
405 if (optype1 == REGOP)
406 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
407 else if (optype1 == OFFSOP)
408 latehalf[1] = adj_offsettable_operand (operands[1], 2);
409 else if (optype1 == CNSTOP)
411 if (CONSTANT_P (operands[1]))
413 /* now the mess begins, high word is in lower word???
415 that's what ashc makes me think, but I don't remember :-( */
416 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
417 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
419 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
421 /* immediate 32 bit values not allowed */
426 latehalf[1] = operands[1];
428 /* If insn is effectively movd N(sp),-(sp) then we will do the
429 high word first. We should use the adjusted operand 1 (which is N+4(sp))
430 for the low word as well, to compensate for the first decrement of sp. */
431 if (optype0 == PUSHOP
432 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
433 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
434 operands[1] = latehalf[1];
436 /* If one or both operands autodecrementing,
437 do the two words, high-numbered first. */
439 /* Likewise, the first move would clobber the source of the second one,
440 do them in the other order. This happens only for registers;
441 such overlap can't happen in memory unless the user explicitly
442 sets it up, and that is an undefined circumstance. */
444 if (optype0 == PUSHOP || optype1 == PUSHOP
445 || (optype0 == REGOP && optype1 == REGOP
446 && REGNO (operands[0]) == REGNO (latehalf[1])))
448 /* Make any unoffsettable addresses point at high-numbered word. */
450 output_asm_insn ("add $2,%0", &addreg0);
452 output_asm_insn ("add $2,%0", &addreg1);
455 output_asm_insn (singlemove_string (latehalf), latehalf);
457 /* Undo the adds we just did. */
459 output_asm_insn ("sub $2,%0", &addreg0);
461 output_asm_insn ("sub $2,%0", &addreg1);
463 /* Do low-numbered word. */
464 return singlemove_string (operands);
467 /* Normal case: do the two words, low-numbered first. */
469 output_asm_insn (singlemove_string (operands), operands);
471 /* Make any unoffsettable addresses point at high-numbered word. */
473 output_asm_insn ("add $2,%0", &addreg0);
475 output_asm_insn ("add $2,%0", &addreg1);
478 output_asm_insn (singlemove_string (latehalf), latehalf);
480 /* Undo the adds we just did. */
482 output_asm_insn ("sub $2,%0", &addreg0);
484 output_asm_insn ("sub $2,%0", &addreg1);
488 /* Output assembler code to perform a quadword move insn
489 with operands OPERANDS. */
492 output_move_quad (operands)
495 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
497 rtx addreg0 = 0, addreg1 = 0;
499 output_asm_insn(";; movdi/df: %1 -> %0", operands);
501 if (REG_P (operands[0]))
503 else if (offsettable_memref_p (operands[0]))
505 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
507 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
509 else if (GET_CODE (operands[0]) == MEM)
514 if (REG_P (operands[1]))
516 else if (CONSTANT_P (operands[1])
517 || GET_CODE (operands[1]) == CONST_DOUBLE)
519 else if (offsettable_memref_p (operands[1]))
521 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
523 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
525 else if (GET_CODE (operands[1]) == MEM)
530 /* Check for the cases that the operand constraints are not
531 supposed to allow to happen. Abort if we get one,
532 because generating code for these cases is painful. */
534 if (optype0 == RNDOP || optype1 == RNDOP)
537 /* check if we move a CPU reg to an FPU reg, or vice versa! */
538 if (optype0 == REGOP && optype1 == REGOP)
539 /* bogus - 64 bit cannot reside in CPU! */
540 if (CPU_REG_P(REGNO(operands[0]))
541 || CPU_REG_P (REGNO(operands[1])))
544 if (optype0 == REGOP || optype1 == REGOP)
546 /* check for use of clrd????
547 if you ever allow ac4 and ac5 (now we require secondary load)
548 you must check whether
549 you want to load into them or store from them -
550 then dump ac0 into $help$ movce ac4/5 to ac0, do the
551 store from ac0, and restore ac0 - if you can find
552 an unused ac[0-3], use that and you save a store and a load!*/
554 if (FPU_REG_P(REGNO(operands[0])))
556 if (GET_CODE(operands[1]) == CONST_DOUBLE)
558 union { double d; int i[2]; } u;
559 u.i[0] = CONST_DOUBLE_LOW (operands[1]);
560 u.i[1] = CONST_DOUBLE_HIGH (operands[1]);
563 return "{clrd|clrf} %0";
566 return "{ldd|movf} %1, %0";
569 if (FPU_REG_P(REGNO(operands[1])))
570 return "{std|movf} %1, %0";
573 /* If one operand is decrementing and one is incrementing
574 decrement the former register explicitly
575 and change that operand into ordinary indexing. */
577 if (optype0 == PUSHOP && optype1 == POPOP)
579 operands[0] = XEXP (XEXP (operands[0], 0), 0);
580 output_asm_insn ("sub $8,%0", operands);
581 operands[0] = gen_rtx_MEM (DImode, operands[0]);
584 if (optype0 == POPOP && optype1 == PUSHOP)
586 operands[1] = XEXP (XEXP (operands[1], 0), 0);
587 output_asm_insn ("sub $8,%1", operands);
588 operands[1] = gen_rtx_MEM (SImode, operands[1]);
592 /* If an operand is an unoffsettable memory ref, find a register
593 we can increment temporarily to make it refer to the second word. */
595 if (optype0 == MEMOP)
596 addreg0 = find_addr_reg (XEXP (operands[0], 0));
598 if (optype1 == MEMOP)
599 addreg1 = find_addr_reg (XEXP (operands[1], 0));
601 /* Ok, we can do one word at a time.
602 Normally we do the low-numbered word first,
603 but if either operand is autodecrementing then we
604 do the high-numbered word first.
606 In either case, set up in LATEHALF the operands to use
607 for the high-numbered word and in some cases alter the
608 operands in OPERANDS to be suitable for the low-numbered word. */
610 if (optype0 == REGOP)
611 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
612 else if (optype0 == OFFSOP)
613 latehalf[0] = adj_offsettable_operand (operands[0], 4);
615 latehalf[0] = operands[0];
617 if (optype1 == REGOP)
618 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
619 else if (optype1 == OFFSOP)
620 latehalf[1] = adj_offsettable_operand (operands[1], 4);
621 else if (optype1 == CNSTOP)
623 if (GET_CODE (operands[1]) == CONST_DOUBLE)
625 /* floats only. not yet supported!
627 -- compute it into PDP float format, - internally,
628 just use IEEE and ignore possible problems ;-)
630 we might get away with it !!!! */
634 #ifndef HOST_WORDS_BIG_ENDIAN
635 latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
636 operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
637 #else /* HOST_WORDS_BIG_ENDIAN */
638 latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
639 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
640 #endif /* HOST_WORDS_BIG_ENDIAN */
642 else if (GET_CODE(operands[1]) == CONST_INT)
644 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. */
739 output_ascii (file, p, size)
746 /* This used to output .byte "string", which doesn't work with the UNIX
747 assembler and I think not with DEC ones either. */
748 fprintf (file, "\t.byte ");
750 for (i = 0; i < size; i++)
752 register int c = p[i];
755 fprintf (file, "%o", c);
763 /* --- stole from out-vax, needs changes */
766 print_operand_address (file, addr)
770 register rtx reg1, reg2, breg, ireg;
775 switch (GET_CODE (addr))
782 addr = XEXP (addr, 0);
786 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
790 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
794 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
801 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
802 || GET_CODE (XEXP (addr, 0)) == MEM)
804 offset = XEXP (addr, 0);
805 addr = XEXP (addr, 1);
807 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
808 || GET_CODE (XEXP (addr, 1)) == MEM)
810 offset = XEXP (addr, 1);
811 addr = XEXP (addr, 0);
813 if (GET_CODE (addr) != PLUS)
815 else if (GET_CODE (XEXP (addr, 0)) == MULT)
817 reg1 = XEXP (addr, 0);
818 addr = XEXP (addr, 1);
820 else if (GET_CODE (XEXP (addr, 1)) == MULT)
822 reg1 = XEXP (addr, 1);
823 addr = XEXP (addr, 0);
825 else if (GET_CODE (XEXP (addr, 0)) == REG)
827 reg1 = XEXP (addr, 0);
828 addr = XEXP (addr, 1);
830 else if (GET_CODE (XEXP (addr, 1)) == REG)
832 reg1 = XEXP (addr, 1);
833 addr = XEXP (addr, 0);
835 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
845 if (addr != 0) abort ();
848 if (reg1 != 0 && GET_CODE (reg1) == MULT)
853 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
858 else if (reg2 != 0 || GET_CODE (addr) == MEM)
869 output_address (addr);
872 if (GET_CODE (breg) != REG)
874 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
878 if (GET_CODE (ireg) == MULT)
879 ireg = XEXP (ireg, 0);
880 if (GET_CODE (ireg) != REG)
883 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
888 output_addr_const_pdp11 (file, addr);
892 /* register move costs, indexed by regs */
894 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
896 /* NO MUL GEN LFPU NLFPU FPU ALL */
898 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
899 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
900 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
901 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
902 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
903 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
904 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
908 /* -- note that some moves are tremendously expensive,
909 because they require lots of tricks! do we have to
910 charge the costs incurred by secondary reload class
911 -- as we do here with 22 -- or not ? */
914 register_move_cost(c1, c2)
915 enum reg_class c1, c2;
917 return move_costs[(int)c1][(int)c2];
921 output_jump(pos, neg, length)
922 const char *pos, *neg;
927 static char buf[1000];
930 /* currently we don't need this, because the tstdf and cmpdf
931 copy the condition code immediately, and other float operations are not
932 yet recognized as changing the FCC - if so, then the length-cost of all
933 jump insns increases by one, because we have to potentially copy the
935 if (cc_status.flags & CC_IN_FPU)
936 output_asm_insn("cfcc", NULL);
950 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
964 notice_update_cc_on_set(exp, insn)
966 rtx insn ATTRIBUTE_UNUSED;
968 if (GET_CODE (SET_DEST (exp)) == CC0)
971 cc_status.value1 = SET_DEST (exp);
972 cc_status.value2 = SET_SRC (exp);
975 if (GET_MODE(SET_SRC(exp)) == DFmode)
976 cc_status.flags |= CC_IN_FPU;
979 else if ((GET_CODE (SET_DEST (exp)) == REG
980 || GET_CODE (SET_DEST (exp)) == MEM)
981 && GET_CODE (SET_SRC (exp)) != PC
982 && (GET_MODE (SET_DEST(exp)) == HImode
983 || GET_MODE (SET_DEST(exp)) == QImode)
984 && (GET_CODE (SET_SRC(exp)) == PLUS
985 || GET_CODE (SET_SRC(exp)) == MINUS
986 || GET_CODE (SET_SRC(exp)) == AND
987 || GET_CODE (SET_SRC(exp)) == IOR
988 || GET_CODE (SET_SRC(exp)) == XOR
989 || GET_CODE (SET_SRC(exp)) == NOT
990 || GET_CODE (SET_SRC(exp)) == NEG
991 || GET_CODE (SET_SRC(exp)) == REG
992 || GET_CODE (SET_SRC(exp)) == MEM))
995 cc_status.value1 = SET_SRC (exp);
996 cc_status.value2 = SET_DEST (exp);
998 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1000 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1001 cc_status.value2 = 0;
1002 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1004 && GET_CODE (cc_status.value2) == MEM)
1005 cc_status.value2 = 0;
1007 else if (GET_CODE (SET_SRC (exp)) == CALL)
1011 else if (GET_CODE (SET_DEST (exp)) == REG)
1014 if ((cc_status.value1
1015 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1016 cc_status.value1 = 0;
1017 if ((cc_status.value2
1018 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1019 cc_status.value2 = 0;
1021 else if (SET_DEST(exp) == pc_rtx)
1025 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1027 /* the last else is a bit paranoiac, but since nearly all instructions
1028 play with condition codes, it's reasonable! */
1030 CC_STATUS_INIT; /* paranoia*/
1036 simple_memory_operand(op, mode)
1038 enum machine_mode mode ATTRIBUTE_UNUSED;
1042 /* Eliminate non-memory operations */
1043 if (GET_CODE (op) != MEM)
1047 /* dword operations really put out 2 instructions, so eliminate them. */
1048 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1052 /* Decode the address now. */
1056 addr = XEXP (op, 0);
1058 switch (GET_CODE (addr))
1061 /* (R0) - no extra cost */
1066 /* -(R0), (R0)+ - cheap! */
1070 /* cheap - is encoded in addressing mode info!
1072 -- except for @(R0), which has to be @0(R0) !!! */
1074 if (GET_CODE (XEXP (addr, 0)) == REG)
1084 /* @#address - extra cost */
1088 /* 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 ATTRIBUTE_UNUSED;
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 */
1417 /* A copy of output_addr_const modified for pdp11 expression syntax.
1418 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1419 use, and for debugging output, which we don't support with this port either.
1420 So this copy should get called whenever needed.
1423 output_addr_const_pdp11 (file, x)
1430 switch (GET_CODE (x))
1440 assemble_name (file, XSTR (x, 0));
1444 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1445 assemble_name (file, buf);
1449 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1450 assemble_name (file, buf);
1454 /* Should we check for constants which are too big? Maybe cutting
1455 them off to 16 bits is OK? */
1456 fprintf (file, "%ho", (unsigned short) INTVAL (x));
1460 /* This used to output parentheses around the expression,
1461 but that does not work on the 386 (either ATT or BSD assembler). */
1462 output_addr_const_pdp11 (file, XEXP (x, 0));
1466 if (GET_MODE (x) == VOIDmode)
1468 /* We can use %o if the number is one word and positive. */
1469 if (CONST_DOUBLE_HIGH (x))
1470 abort (); /* Should we just silently drop the high part? */
1472 fprintf (file, "%ho", (unsigned short) CONST_DOUBLE_LOW (x));
1475 /* We can't handle floating point constants;
1476 PRINT_OPERAND must handle them. */
1477 output_operand_lossage ("floating constant misused");
1481 /* Some assemblers need integer constants to appear last (eg masm). */
1482 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1484 output_addr_const_pdp11 (file, XEXP (x, 1));
1485 if (INTVAL (XEXP (x, 0)) >= 0)
1486 fprintf (file, "+");
1487 output_addr_const_pdp11 (file, XEXP (x, 0));
1491 output_addr_const_pdp11 (file, XEXP (x, 0));
1492 if (INTVAL (XEXP (x, 1)) >= 0)
1493 fprintf (file, "+");
1494 output_addr_const_pdp11 (file, XEXP (x, 1));
1499 /* Avoid outputting things like x-x or x+5-x,
1500 since some assemblers can't handle that. */
1501 x = simplify_subtraction (x);
1502 if (GET_CODE (x) != MINUS)
1505 output_addr_const_pdp11 (file, XEXP (x, 0));
1506 fprintf (file, "-");
1507 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1508 && INTVAL (XEXP (x, 1)) < 0)
1510 fprintf (file, ASM_OPEN_PAREN);
1511 output_addr_const_pdp11 (file, XEXP (x, 1));
1512 fprintf (file, ASM_CLOSE_PAREN);
1515 output_addr_const_pdp11 (file, XEXP (x, 1));
1520 output_addr_const_pdp11 (file, XEXP (x, 0));
1524 output_operand_lossage ("invalid expression as operand");