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 1, 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 ( (strcmp ("main", current_function_name) == 0)
116 fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
117 fprintf(stream, "\tsetd\n");
118 fprintf(stream, "\tseti\n\n");
121 if (frame_pointer_needed)
123 fprintf(stream, "\tmov fp, -(sp)\n");
124 fprintf(stream, "\tmov sp, fp\n");
133 fprintf (stream, "\tsub $%o, sp\n", fsize);
135 /* save CPU registers */
136 for (regno = 0; regno < 8; regno++)
137 if (regs_ever_live[regno] && ! call_used_regs[regno])
138 if (! ((regno == FRAME_POINTER_REGNUM)
139 && frame_pointer_needed))
140 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);
141 /* fpu regs saving */
143 /* via_ac specifies the ac to use for saving ac4, ac5 */
146 for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++)
149 if (LOAD_FPU_REG_P(regno)
150 && regs_ever_live[regno]
151 && ! call_used_regs[regno])
153 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
157 /* maybe make ac4, ac5 call used regs?? */
159 if (NO_LOAD_FPU_REG_P(regno)
160 && regs_ever_live[regno]
161 && ! call_used_regs[regno])
166 fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
167 fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
171 fprintf (stream, "\t;/* end of prologue */\n\n");
175 The function epilogue should not depend on the current stack pointer!
176 It should use the frame pointer only. This is mandatory because
177 of alloca; we also take advantage of it to omit stack adjustments
180 /* maybe we can make leaf functions faster by switching to the
181 second register file - this way we don't have to save regs!
182 leaf functions are ~ 50% of all functions (dynamically!)
184 set/clear bit 11 (dec. 2048) of status word for switching register files -
185 but how can we do this? the pdp11/45 manual says bit may only
186 be set (p.24), but not cleared!
188 switching to kernel is probably more expensive, so we'll leave it
189 like this and not use the second set of registers...
191 maybe as option if you want to generate code for kernel mode? */
195 output_function_epilogue(stream, size)
199 int fsize = ((size) + 1) & ~1;
204 fprintf (stream, "\n\t; /*function epilogue */\n");
206 if (frame_pointer_needed)
208 /* hope this is safe - m68k does it also .... */
209 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
211 for (i =7, j = 0 ; i >= 0 ; i--)
212 if (regs_ever_live[i] && ! call_used_regs[i])
215 /* remember # of pushed bytes for CPU regs */
218 for (i =7 ; i >= 0 ; i--)
219 if (regs_ever_live[i] && ! call_used_regs[i])
220 fprintf(stream, "\tmov %o(fp), %s\n",-fsize-2*j--, reg_names[i]);
223 via_ac = FIRST_PSEUDO_REGISTER -1;
225 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
226 if (regs_ever_live[i] && ! call_used_regs[i])
232 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
234 if (LOAD_FPU_REG_P(i)
236 && ! call_used_regs[i])
238 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[i]);
242 if (NO_LOAD_FPU_REG_P(i)
244 && ! call_used_regs[i])
246 if (! LOAD_FPU_REG_P(via_ac))
249 fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[via_ac]);
250 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
255 fprintf(stream, "\tmov fp, sp\n");
256 fprintf (stream, "\tmov (sp)+, fp\n");
260 via_ac = FIRST_PSEUDO_REGISTER -1;
263 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
264 if (regs_ever_live[i] && call_used_regs[i])
267 for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
269 if (LOAD_FPU_REG_P(i)
271 && ! call_used_regs[i])
272 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
274 if (NO_LOAD_FPU_REG_P(i)
276 && ! call_used_regs[i])
278 if (! LOAD_FPU_REG_P(via_ac))
281 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
282 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
286 for (i=7; i >= 0; i--)
287 if (regs_ever_live[i] && !call_used_regs[i])
288 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);
291 fprintf((stream), "\tadd $%o, sp\n", fsize);
294 fprintf (stream, "\trts pc\n");
295 fprintf (stream, "\t;/* end of epilogue*/\n\n\n");
298 /* Return the best assembler insn template
299 for moving operands[1] into operands[0] as a fullword. */
301 singlemove_string (operands)
304 if (operands[1] != const0_rtx)
311 /* Output assembler code to perform a doubleword move insn
312 with operands OPERANDS. */
315 output_move_double (operands)
318 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
320 rtx addreg0 = 0, addreg1 = 0;
322 /* First classify both operands. */
324 if (REG_P (operands[0]))
326 else if (offsettable_memref_p (operands[0]))
328 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
330 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
332 else if (GET_CODE (operands[0]) == MEM)
337 if (REG_P (operands[1]))
339 else if (CONSTANT_P (operands[1]))
341 || GET_CODE (operands[1]) == CONST_DOUBLE)
344 else if (offsettable_memref_p (operands[1]))
346 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
348 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
350 else if (GET_CODE (operands[1]) == MEM)
355 /* Check for the cases that the operand constraints are not
356 supposed to allow to happen. Abort if we get one,
357 because generating code for these cases is painful. */
359 if (optype0 == RNDOP || optype1 == RNDOP)
362 /* If one operand is decrementing and one is incrementing
363 decrement the former register explicitly
364 and change that operand into ordinary indexing. */
366 if (optype0 == PUSHOP && optype1 == POPOP)
368 operands[0] = XEXP (XEXP (operands[0], 0), 0);
369 output_asm_insn ("sub $4,%0", operands);
370 operands[0] = gen_rtx_MEM (SImode, operands[0]);
373 if (optype0 == POPOP && optype1 == PUSHOP)
375 operands[1] = XEXP (XEXP (operands[1], 0), 0);
376 output_asm_insn ("sub $4,%1", operands);
377 operands[1] = gen_rtx_MEM (SImode, operands[1]);
381 /* If an operand is an unoffsettable memory ref, find a register
382 we can increment temporarily to make it refer to the second word. */
384 if (optype0 == MEMOP)
385 addreg0 = find_addr_reg (XEXP (operands[0], 0));
387 if (optype1 == MEMOP)
388 addreg1 = find_addr_reg (XEXP (operands[1], 0));
390 /* Ok, we can do one word at a time.
391 Normally we do the low-numbered word first,
392 but if either operand is autodecrementing then we
393 do the high-numbered word first.
395 In either case, set up in LATEHALF the operands to use
396 for the high-numbered word and in some cases alter the
397 operands in OPERANDS to be suitable for the low-numbered word. */
399 if (optype0 == REGOP)
400 latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
401 else if (optype0 == OFFSOP)
402 latehalf[0] = adj_offsettable_operand (operands[0], 2);
404 latehalf[0] = operands[0];
406 if (optype1 == REGOP)
407 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
408 else if (optype1 == OFFSOP)
409 latehalf[1] = adj_offsettable_operand (operands[1], 2);
410 else if (optype1 == CNSTOP)
412 if (CONSTANT_P (operands[1]))
414 /* now the mess begins, high word is in lower word???
416 that's what ashc makes me think, but I don't remember :-( */
417 latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
418 operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
420 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
422 /* immediate 32 bit values not allowed */
427 latehalf[1] = operands[1];
429 /* If insn is effectively movd N(sp),-(sp) then we will do the
430 high word first. We should use the adjusted operand 1 (which is N+4(sp))
431 for the low word as well, to compensate for the first decrement of sp. */
432 if (optype0 == PUSHOP
433 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
434 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
435 operands[1] = latehalf[1];
437 /* If one or both operands autodecrementing,
438 do the two words, high-numbered first. */
440 /* Likewise, the first move would clobber the source of the second one,
441 do them in the other order. This happens only for registers;
442 such overlap can't happen in memory unless the user explicitly
443 sets it up, and that is an undefined circumstance. */
445 if (optype0 == PUSHOP || optype1 == PUSHOP
446 || (optype0 == REGOP && optype1 == REGOP
447 && REGNO (operands[0]) == REGNO (latehalf[1])))
449 /* Make any unoffsettable addresses point at high-numbered word. */
451 output_asm_insn ("add $2,%0", &addreg0);
453 output_asm_insn ("add $2,%0", &addreg1);
456 output_asm_insn (singlemove_string (latehalf), latehalf);
458 /* Undo the adds we just did. */
460 output_asm_insn ("sub $2,%0", &addreg0);
462 output_asm_insn ("sub $2,%0", &addreg1);
464 /* Do low-numbered word. */
465 return singlemove_string (operands);
468 /* Normal case: do the two words, low-numbered first. */
470 output_asm_insn (singlemove_string (operands), operands);
472 /* Make any unoffsettable addresses point at high-numbered word. */
474 output_asm_insn ("add $2,%0", &addreg0);
476 output_asm_insn ("add $2,%0", &addreg1);
479 output_asm_insn (singlemove_string (latehalf), latehalf);
481 /* Undo the adds we just did. */
483 output_asm_insn ("sub $2,%0", &addreg0);
485 output_asm_insn ("sub $2,%0", &addreg1);
489 /* Output assembler code to perform a quadword move insn
490 with operands OPERANDS. */
493 output_move_quad (operands)
496 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
498 rtx addreg0 = 0, addreg1 = 0;
500 output_asm_insn(";; movdi/df: %1 -> %0", operands);
502 if (REG_P (operands[0]))
504 else if (offsettable_memref_p (operands[0]))
506 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
508 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
510 else if (GET_CODE (operands[0]) == MEM)
515 if (REG_P (operands[1]))
517 else if (CONSTANT_P (operands[1])
518 || GET_CODE (operands[1]) == CONST_DOUBLE)
520 else if (offsettable_memref_p (operands[1]))
522 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
524 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
526 else if (GET_CODE (operands[1]) == MEM)
531 /* Check for the cases that the operand constraints are not
532 supposed to allow to happen. Abort if we get one,
533 because generating code for these cases is painful. */
535 if (optype0 == RNDOP || optype1 == RNDOP)
538 /* check if we move a CPU reg to an FPU reg, or vice versa! */
539 if (optype0 == REGOP && optype1 == REGOP)
540 /* bogus - 64 bit cannot reside in CPU! */
541 if (CPU_REG_P(REGNO(operands[0]))
542 || CPU_REG_P (REGNO(operands[1])))
545 if (optype0 == REGOP || optype1 == REGOP)
547 /* check for use of clrd????
548 if you ever allow ac4 and ac5 (now we require secondary load)
549 you must check whether
550 you want to load into them or store from them -
551 then dump ac0 into $help$ movce ac4/5 to ac0, do the
552 store from ac0, and restore ac0 - if you can find
553 an unused ac[0-3], use that and you save a store and a load!*/
555 if (FPU_REG_P(REGNO(operands[0])))
557 if (GET_CODE(operands[1]) == CONST_DOUBLE)
559 union { double d; int i[2]; } u;
560 u.i[0] = CONST_DOUBLE_LOW (operands[1]);
561 u.i[1] = CONST_DOUBLE_HIGH (operands[1]);
564 return "{clrd|clrf} %0";
567 return "{ldd|movf} %1, %0";
570 if (FPU_REG_P(REGNO(operands[1])))
571 return "{std|movf} %1, %0";
574 /* If one operand is decrementing and one is incrementing
575 decrement the former register explicitly
576 and change that operand into ordinary indexing. */
578 if (optype0 == PUSHOP && optype1 == POPOP)
580 operands[0] = XEXP (XEXP (operands[0], 0), 0);
581 output_asm_insn ("sub $8,%0", operands);
582 operands[0] = gen_rtx_MEM (DImode, operands[0]);
585 if (optype0 == POPOP && optype1 == PUSHOP)
587 operands[1] = XEXP (XEXP (operands[1], 0), 0);
588 output_asm_insn ("sub $8,%1", operands);
589 operands[1] = gen_rtx_MEM (SImode, operands[1]);
593 /* If an operand is an unoffsettable memory ref, find a register
594 we can increment temporarily to make it refer to the second word. */
596 if (optype0 == MEMOP)
597 addreg0 = find_addr_reg (XEXP (operands[0], 0));
599 if (optype1 == MEMOP)
600 addreg1 = find_addr_reg (XEXP (operands[1], 0));
602 /* Ok, we can do one word at a time.
603 Normally we do the low-numbered word first,
604 but if either operand is autodecrementing then we
605 do the high-numbered word first.
607 In either case, set up in LATEHALF the operands to use
608 for the high-numbered word and in some cases alter the
609 operands in OPERANDS to be suitable for the low-numbered word. */
611 if (optype0 == REGOP)
612 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
613 else if (optype0 == OFFSOP)
614 latehalf[0] = adj_offsettable_operand (operands[0], 4);
616 latehalf[0] = operands[0];
618 if (optype1 == REGOP)
619 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
620 else if (optype1 == OFFSOP)
621 latehalf[1] = adj_offsettable_operand (operands[1], 4);
622 else if (optype1 == CNSTOP)
624 if (GET_CODE (operands[1]) == CONST_DOUBLE)
626 /* floats only. not yet supported!
628 -- compute it into PDP float format, - internally,
629 just use IEEE and ignore possible problems ;-)
631 we might get away with it !!!! */
635 #ifndef HOST_WORDS_BIG_ENDIAN
636 latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
637 operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
638 #else /* HOST_WORDS_BIG_ENDIAN */
639 latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
640 operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
641 #endif /* HOST_WORDS_BIG_ENDIAN */
643 else if (GET_CODE(operands[1]) == CONST_INT)
645 latehalf[1] = GEN_INT (0);
651 latehalf[1] = operands[1];
653 /* If insn is effectively movd N(sp),-(sp) then we will do the
654 high word first. We should use the adjusted operand 1 (which is N+4(sp))
655 for the low word as well, to compensate for the first decrement of sp. */
656 if (optype0 == PUSHOP
657 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
658 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
659 operands[1] = latehalf[1];
661 /* If one or both operands autodecrementing,
662 do the two words, high-numbered first. */
664 /* Likewise, the first move would clobber the source of the second one,
665 do them in the other order. This happens only for registers;
666 such overlap can't happen in memory unless the user explicitly
667 sets it up, and that is an undefined circumstance. */
669 if (optype0 == PUSHOP || optype1 == PUSHOP
670 || (optype0 == REGOP && optype1 == REGOP
671 && REGNO (operands[0]) == REGNO (latehalf[1])))
673 /* Make any unoffsettable addresses point at high-numbered word. */
675 output_asm_insn ("add $4,%0", &addreg0);
677 output_asm_insn ("add $4,%0", &addreg1);
680 output_asm_insn(output_move_double(latehalf), latehalf);
682 /* Undo the adds we just did. */
684 output_asm_insn ("sub $4,%0", &addreg0);
686 output_asm_insn ("sub $4,%0", &addreg1);
688 /* Do low-numbered word. */
689 return output_move_double (operands);
692 /* Normal case: do the two words, low-numbered first. */
694 output_asm_insn (output_move_double (operands), operands);
696 /* Make any unoffsettable addresses point at high-numbered word. */
698 output_asm_insn ("add $4,%0", &addreg0);
700 output_asm_insn ("add $4,%0", &addreg1);
703 output_asm_insn (output_move_double (latehalf), latehalf);
705 /* Undo the adds we just did. */
707 output_asm_insn ("sub $4,%0", &addreg0);
709 output_asm_insn ("sub $4,%0", &addreg1);
715 /* Return a REG that occurs in ADDR with coefficient 1.
716 ADDR can be effectively incremented by incrementing REG. */
722 while (GET_CODE (addr) == PLUS)
724 if (GET_CODE (XEXP (addr, 0)) == REG)
725 addr = XEXP (addr, 0);
726 if (GET_CODE (XEXP (addr, 1)) == REG)
727 addr = XEXP (addr, 1);
728 if (CONSTANT_P (XEXP (addr, 0)))
729 addr = XEXP (addr, 1);
730 if (CONSTANT_P (XEXP (addr, 1)))
731 addr = XEXP (addr, 0);
733 if (GET_CODE (addr) == REG)
738 /* Output an ascii string. */
740 output_ascii (file, p, size)
747 /* This used to output .byte "string", which doesn't work with the UNIX
748 assembler and I think not with DEC ones either. */
749 fprintf (file, "\t.byte ");
751 for (i = 0; i < size; i++)
753 register int c = p[i];
756 fprintf (file, "%o", c);
764 /* --- stole from out-vax, needs changes */
767 print_operand_address (file, addr)
771 register rtx reg1, reg2, breg, ireg;
776 switch (GET_CODE (addr))
783 addr = XEXP (addr, 0);
787 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
791 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
795 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
802 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
803 || GET_CODE (XEXP (addr, 0)) == MEM)
805 offset = XEXP (addr, 0);
806 addr = XEXP (addr, 1);
808 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
809 || GET_CODE (XEXP (addr, 1)) == MEM)
811 offset = XEXP (addr, 1);
812 addr = XEXP (addr, 0);
814 if (GET_CODE (addr) != PLUS)
816 else if (GET_CODE (XEXP (addr, 0)) == MULT)
818 reg1 = XEXP (addr, 0);
819 addr = XEXP (addr, 1);
821 else if (GET_CODE (XEXP (addr, 1)) == MULT)
823 reg1 = XEXP (addr, 1);
824 addr = XEXP (addr, 0);
826 else if (GET_CODE (XEXP (addr, 0)) == REG)
828 reg1 = XEXP (addr, 0);
829 addr = XEXP (addr, 1);
831 else if (GET_CODE (XEXP (addr, 1)) == REG)
833 reg1 = XEXP (addr, 1);
834 addr = XEXP (addr, 0);
836 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
846 if (addr != 0) abort ();
849 if (reg1 != 0 && GET_CODE (reg1) == MULT)
854 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
859 else if (reg2 != 0 || GET_CODE (addr) == MEM)
870 output_address (addr);
873 if (GET_CODE (breg) != REG)
875 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
879 if (GET_CODE (ireg) == MULT)
880 ireg = XEXP (ireg, 0);
881 if (GET_CODE (ireg) != REG)
884 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
889 output_addr_const_pdp11 (file, addr);
893 /* register move costs, indexed by regs */
895 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
897 /* NO MUL GEN LFPU NLFPU FPU ALL */
899 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
900 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
901 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
902 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
903 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
904 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
905 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
909 /* -- note that some moves are tremendously expensive,
910 because they require lots of tricks! do we have to
911 charge the costs incurred by secondary reload class
912 -- as we do here with 22 -- or not ? */
915 register_move_cost(c1, c2)
916 enum reg_class c1, c2;
918 return move_costs[(int)c1][(int)c2];
922 output_jump(pos, neg, length)
923 const char *pos, *neg;
928 static char buf[1000];
931 /* currently we don't need this, because the tstdf and cmpdf
932 copy the condition code immediately, and other float operations are not
933 yet recognized as changing the FCC - if so, then the length-cost of all
934 jump insns increases by one, because we have to potentially copy the
936 if (cc_status.flags & CC_IN_FPU)
937 output_asm_insn("cfcc", NULL);
951 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
965 notice_update_cc_on_set(exp, insn)
967 rtx insn ATTRIBUTE_UNUSED;
969 if (GET_CODE (SET_DEST (exp)) == CC0)
972 cc_status.value1 = SET_DEST (exp);
973 cc_status.value2 = SET_SRC (exp);
976 if (GET_MODE(SET_SRC(exp)) == DFmode)
977 cc_status.flags |= CC_IN_FPU;
980 else if ((GET_CODE (SET_DEST (exp)) == REG
981 || GET_CODE (SET_DEST (exp)) == MEM)
982 && GET_CODE (SET_SRC (exp)) != PC
983 && (GET_MODE (SET_DEST(exp)) == HImode
984 || GET_MODE (SET_DEST(exp)) == QImode)
985 && (GET_CODE (SET_SRC(exp)) == PLUS
986 || GET_CODE (SET_SRC(exp)) == MINUS
987 || GET_CODE (SET_SRC(exp)) == AND
988 || GET_CODE (SET_SRC(exp)) == IOR
989 || GET_CODE (SET_SRC(exp)) == XOR
990 || GET_CODE (SET_SRC(exp)) == NOT
991 || GET_CODE (SET_SRC(exp)) == NEG
992 || GET_CODE (SET_SRC(exp)) == REG
993 || GET_CODE (SET_SRC(exp)) == MEM))
996 cc_status.value1 = SET_SRC (exp);
997 cc_status.value2 = SET_DEST (exp);
999 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1001 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1002 cc_status.value2 = 0;
1003 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1005 && GET_CODE (cc_status.value2) == MEM)
1006 cc_status.value2 = 0;
1008 else if (GET_CODE (SET_SRC (exp)) == CALL)
1012 else if (GET_CODE (SET_DEST (exp)) == REG)
1015 if ((cc_status.value1
1016 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1017 cc_status.value1 = 0;
1018 if ((cc_status.value2
1019 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1020 cc_status.value2 = 0;
1022 else if (SET_DEST(exp) == pc_rtx)
1026 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1028 /* the last else is a bit paranoiac, but since nearly all instructions
1029 play with condition codes, it's reasonable! */
1031 CC_STATUS_INIT; /* paranoia*/
1037 simple_memory_operand(op, mode)
1039 enum machine_mode mode ATTRIBUTE_UNUSED;
1043 /* Eliminate non-memory operations */
1044 if (GET_CODE (op) != MEM)
1048 /* dword operations really put out 2 instructions, so eliminate them. */
1049 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1053 /* Decode the address now. */
1057 addr = XEXP (op, 0);
1059 switch (GET_CODE (addr))
1062 /* (R0) - no extra cost */
1067 /* -(R0), (R0)+ - cheap! */
1071 /* cheap - is encoded in addressing mode info!
1073 -- except for @(R0), which has to be @0(R0) !!! */
1075 if (GET_CODE (XEXP (addr, 0)) == REG)
1085 /* @#address - extra cost */
1089 /* X(R0) - extra cost */
1101 * output a block move:
1103 * operands[0] ... to
1104 * operands[1] ... from
1105 * operands[2] ... length
1106 * operands[3] ... alignment
1107 * operands[4] ... scratch register
1112 output_block_move(operands)
1115 static int count = 0;
1118 if (GET_CODE(operands[2]) == CONST_INT
1121 if (INTVAL(operands[2]) < 16
1122 && INTVAL(operands[3]) == 1)
1126 for (i = 1; i <= INTVAL(operands[2]); i++)
1127 output_asm_insn("movb (%1)+, (%0)+", operands);
1131 else if (INTVAL(operands[2]) < 32)
1135 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1136 output_asm_insn("mov (%1)+, (%0)+", operands);
1138 /* may I assume that moved quantity is
1139 multiple of alignment ???
1148 /* can do other clever things, maybe... */
1151 if (CONSTANT_P(operands[2]) )
1153 /* just move count to scratch */
1154 output_asm_insn("mov %2, %4", operands);
1158 /* just clobber the register */
1159 operands[4] = operands[2];
1163 /* switch over alignment */
1164 switch (INTVAL(operands[3]))
1180 sprintf(buf, "\nmovestrhi%d:", count);
1181 output_asm_insn(buf, NULL);
1183 output_asm_insn("movb (%1)+, (%0)+", operands);
1187 sprintf(buf, "sob %%4, movestrhi%d", count);
1188 output_asm_insn(buf, operands);
1192 output_asm_insn("dec %4", operands);
1194 sprintf(buf, "bgt movestrhi%d", count);
1195 output_asm_insn(buf, NULL);
1217 generate_compact_code:
1219 output_asm_insn("asr %4", operands);
1221 sprintf(buf, "\nmovestrhi%d:", count);
1222 output_asm_insn(buf, NULL);
1224 output_asm_insn("mov (%1)+, (%0)+", operands);
1228 sprintf(buf, "sob %%4, movestrhi%d", count);
1229 output_asm_insn(buf, operands);
1233 output_asm_insn("dec %4", operands);
1235 sprintf(buf, "bgt movestrhi%d", count);
1236 output_asm_insn(buf, NULL);
1262 goto generate_compact_code;
1264 output_asm_insn("asr %4", operands);
1265 output_asm_insn("asr %4", operands);
1267 sprintf(buf, "\nmovestrhi%d:", count);
1268 output_asm_insn(buf, NULL);
1270 output_asm_insn("mov (%1)+, (%0)+", operands);
1271 output_asm_insn("mov (%1)+, (%0)+", operands);
1275 sprintf(buf, "sob %%4, movestrhi%d", count);
1276 output_asm_insn(buf, operands);
1280 output_asm_insn("dec %4", operands);
1282 sprintf(buf, "bgt movestrhi%d", count);
1283 output_asm_insn(buf, NULL);
1313 goto generate_compact_code;
1315 output_asm_insn("asr %4", operands);
1316 output_asm_insn("asr %4", operands);
1317 output_asm_insn("asr %4", operands);
1319 sprintf(buf, "\nmovestrhi%d:", count);
1320 output_asm_insn(buf, NULL);
1322 output_asm_insn("mov (%1)+, (%0)+", operands);
1323 output_asm_insn("mov (%1)+, (%0)+", operands);
1324 output_asm_insn("mov (%1)+, (%0)+", operands);
1325 output_asm_insn("mov (%1)+, (%0)+", operands);
1329 sprintf(buf, "sob %%4, movestrhi%d", count);
1330 output_asm_insn(buf, operands);
1334 output_asm_insn("dec %4", operands);
1336 sprintf(buf, "bgt movestrhi%d", count);
1337 output_asm_insn(buf, NULL);
1350 /* for future use */
1352 comparison_operator_index(op)
1355 switch (GET_CODE(op))
1392 /* tests whether the rtx is a comparison operator */
1394 comp_operator (op, mode)
1396 enum machine_mode mode ATTRIBUTE_UNUSED;
1398 return comparison_operator_index(op) >= 0;
1403 legitimate_address_p (mode, address)
1404 enum machine_mode mode;
1407 /* #define REG_OK_STRICT */
1408 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1415 /* #undef REG_OK_STRICT */
1418 /* A copy of output_addr_const modified for pdp11 expression syntax.
1419 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1420 use, and for debugging output, which we don't support with this port either.
1421 So this copy should get called whenever needed.
1424 output_addr_const_pdp11 (file, x)
1431 switch (GET_CODE (x))
1441 assemble_name (file, XSTR (x, 0));
1445 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1446 assemble_name (file, buf);
1450 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1451 assemble_name (file, buf);
1455 /* Should we check for constants which are too big? Maybe cutting
1456 them off to 16 bits is OK? */
1457 fprintf (file, "%ho", (unsigned short) INTVAL (x));
1461 /* This used to output parentheses around the expression,
1462 but that does not work on the 386 (either ATT or BSD assembler). */
1463 output_addr_const_pdp11 (file, XEXP (x, 0));
1467 if (GET_MODE (x) == VOIDmode)
1469 /* We can use %o if the number is one word and positive. */
1470 if (CONST_DOUBLE_HIGH (x))
1471 abort (); /* Should we just silently drop the high part? */
1473 fprintf (file, "%ho", (unsigned short) CONST_DOUBLE_LOW (x));
1476 /* We can't handle floating point constants;
1477 PRINT_OPERAND must handle them. */
1478 output_operand_lossage ("floating constant misused");
1482 /* Some assemblers need integer constants to appear last (eg masm). */
1483 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1485 output_addr_const_pdp11 (file, XEXP (x, 1));
1486 if (INTVAL (XEXP (x, 0)) >= 0)
1487 fprintf (file, "+");
1488 output_addr_const_pdp11 (file, XEXP (x, 0));
1492 output_addr_const_pdp11 (file, XEXP (x, 0));
1493 if (INTVAL (XEXP (x, 1)) >= 0)
1494 fprintf (file, "+");
1495 output_addr_const_pdp11 (file, XEXP (x, 1));
1500 /* Avoid outputting things like x-x or x+5-x,
1501 since some assemblers can't handle that. */
1502 x = simplify_subtraction (x);
1503 if (GET_CODE (x) != MINUS)
1506 output_addr_const_pdp11 (file, XEXP (x, 0));
1507 fprintf (file, "-");
1508 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1509 && INTVAL (XEXP (x, 1)) < 0)
1511 fprintf (file, ASM_OPEN_PAREN);
1512 output_addr_const_pdp11 (file, XEXP (x, 1));
1513 fprintf (file, ASM_CLOSE_PAREN);
1516 output_addr_const_pdp11 (file, XEXP (x, 1));
1521 output_addr_const_pdp11 (file, XEXP (x, 0));
1525 output_operand_lossage ("invalid expression as operand");