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 $%o, 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 %o(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 %o(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 %o(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 $%o, 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]);
560 return "{clrd|clrf} %0";
563 return "{ldd|movf} %1, %0";
566 if (FPU_REG_P(REGNO(operands[1])))
567 return "{std|movf} %1, %0";
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 /* This used to output .byte "string", which doesn't work with the UNIX
745 assembler and I think not with DEC ones either. */
746 fprintf (file, "\t.byte ");
748 for (i = 0; i < size; i++)
750 register int c = p[i];
753 fprintf (file, "%o", c);
761 /* --- stole from out-vax, needs changes */
764 print_operand_address (file, addr)
768 register rtx reg1, reg2, breg, ireg;
773 switch (GET_CODE (addr))
780 addr = XEXP (addr, 0);
784 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
788 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
792 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
799 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
800 || GET_CODE (XEXP (addr, 0)) == MEM)
802 offset = XEXP (addr, 0);
803 addr = XEXP (addr, 1);
805 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
806 || GET_CODE (XEXP (addr, 1)) == MEM)
808 offset = XEXP (addr, 1);
809 addr = XEXP (addr, 0);
811 if (GET_CODE (addr) != PLUS)
813 else if (GET_CODE (XEXP (addr, 0)) == MULT)
815 reg1 = XEXP (addr, 0);
816 addr = XEXP (addr, 1);
818 else if (GET_CODE (XEXP (addr, 1)) == MULT)
820 reg1 = XEXP (addr, 1);
821 addr = XEXP (addr, 0);
823 else if (GET_CODE (XEXP (addr, 0)) == REG)
825 reg1 = XEXP (addr, 0);
826 addr = XEXP (addr, 1);
828 else if (GET_CODE (XEXP (addr, 1)) == REG)
830 reg1 = XEXP (addr, 1);
831 addr = XEXP (addr, 0);
833 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
843 if (addr != 0) abort ();
846 if (reg1 != 0 && GET_CODE (reg1) == MULT)
851 else if (reg2 != 0 && GET_CODE (reg2) == MULT)
856 else if (reg2 != 0 || GET_CODE (addr) == MEM)
867 output_address (addr);
870 if (GET_CODE (breg) != REG)
872 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
876 if (GET_CODE (ireg) == MULT)
877 ireg = XEXP (ireg, 0);
878 if (GET_CODE (ireg) != REG)
881 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
886 output_addr_const_pdp11 (file, addr);
890 /* register move costs, indexed by regs */
892 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
894 /* NO MUL GEN LFPU NLFPU FPU ALL */
896 /* NO */ { 0, 0, 0, 0, 0, 0, 0},
897 /* MUL */ { 0, 2, 2, 10, 22, 22, 22},
898 /* GEN */ { 0, 2, 2, 10, 22, 22, 22},
899 /* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
900 /* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
901 /* FPU */ { 0, 22, 22, 2, 2, 2, 22},
902 /* ALL */ { 0, 22, 22, 10, 22, 22, 22}
906 /* -- note that some moves are tremendously expensive,
907 because they require lots of tricks! do we have to
908 charge the costs incurred by secondary reload class
909 -- as we do here with 22 -- or not ? */
912 register_move_cost(c1, c2)
913 enum reg_class c1, c2;
915 return move_costs[(int)c1][(int)c2];
919 output_jump(pos, neg, length)
925 static char buf[1000];
928 /* currently we don't need this, because the tstdf and cmpdf
929 copy the condition code immediately, and other float operations are not
930 yet recognized as changing the FCC - if so, then the length-cost of all
931 jump insns increases by one, because we have to potentially copy the
933 if (cc_status.flags & CC_IN_FPU)
934 output_asm_insn("cfcc", NULL);
948 sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
962 notice_update_cc_on_set(exp, insn)
966 if (GET_CODE (SET_DEST (exp)) == CC0)
969 cc_status.value1 = SET_DEST (exp);
970 cc_status.value2 = SET_SRC (exp);
973 if (GET_MODE(SET_SRC(exp)) == DFmode)
974 cc_status.flags |= CC_IN_FPU;
977 else if ((GET_CODE (SET_DEST (exp)) == REG
978 || GET_CODE (SET_DEST (exp)) == MEM)
979 && GET_CODE (SET_SRC (exp)) != PC
980 && (GET_MODE (SET_DEST(exp)) == HImode
981 || GET_MODE (SET_DEST(exp)) == QImode)
982 && (GET_CODE (SET_SRC(exp)) == PLUS
983 || GET_CODE (SET_SRC(exp)) == MINUS
984 || GET_CODE (SET_SRC(exp)) == AND
985 || GET_CODE (SET_SRC(exp)) == IOR
986 || GET_CODE (SET_SRC(exp)) == XOR
987 || GET_CODE (SET_SRC(exp)) == NOT
988 || GET_CODE (SET_SRC(exp)) == NEG
989 || GET_CODE (SET_SRC(exp)) == REG
990 || GET_CODE (SET_SRC(exp)) == MEM))
993 cc_status.value1 = SET_SRC (exp);
994 cc_status.value2 = SET_DEST (exp);
996 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
998 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
999 cc_status.value2 = 0;
1000 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
1002 && GET_CODE (cc_status.value2) == MEM)
1003 cc_status.value2 = 0;
1005 else if (GET_CODE (SET_SRC (exp)) == CALL)
1009 else if (GET_CODE (SET_DEST (exp)) == REG)
1012 if ((cc_status.value1
1013 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1014 cc_status.value1 = 0;
1015 if ((cc_status.value2
1016 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1017 cc_status.value2 = 0;
1019 else if (SET_DEST(exp) == pc_rtx)
1023 else /* if (GET_CODE (SET_DEST (exp)) == MEM) */
1025 /* the last else is a bit paranoiac, but since nearly all instructions
1026 play with condition codes, it's reasonable! */
1028 CC_STATUS_INIT; /* paranoia*/
1033 int simple_memory_operand(op, mode)
1035 enum machine_mode mode;
1039 /* Eliminate non-memory operations */
1040 if (GET_CODE (op) != MEM)
1044 /* dword operations really put out 2 instructions, so eliminate them. */
1045 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1049 /* Decode the address now. */
1053 addr = XEXP (op, 0);
1055 switch (GET_CODE (addr))
1058 /* (R0) - no extra cost */
1063 /* -(R0), (R0)+ - cheap! */
1067 /* cheap - is encoded in addressing mode info!
1069 -- except for @(R0), which has to be @0(R0) !!! */
1071 if (GET_CODE (XEXP (addr, 0)) == REG)
1081 /* @#address - extra cost */
1085 /* X(R0) - extra cost */
1097 * output a block move:
1099 * operands[0] ... to
1100 * operands[1] ... from
1101 * operands[2] ... length
1102 * operands[3] ... alignment
1103 * operands[4] ... scratch register
1108 output_block_move(operands)
1111 static int count = 0;
1114 if (GET_CODE(operands[2]) == CONST_INT
1117 if (INTVAL(operands[2]) < 16
1118 && INTVAL(operands[3]) == 1)
1122 for (i = 1; i <= INTVAL(operands[2]); i++)
1123 output_asm_insn("movb (%1)+, (%0)+", operands);
1127 else if (INTVAL(operands[2]) < 32)
1131 for (i = 1; i <= INTVAL(operands[2])/2; i++)
1132 output_asm_insn("mov (%1)+, (%0)+", operands);
1134 /* may I assume that moved quantity is
1135 multiple of alignment ???
1144 /* can do other clever things, maybe... */
1147 if (CONSTANT_P(operands[2]) )
1149 /* just move count to scratch */
1150 output_asm_insn("mov %2, %4", operands);
1154 /* just clobber the register */
1155 operands[4] = operands[2];
1159 /* switch over alignment */
1160 switch (INTVAL(operands[3]))
1176 sprintf(buf, "\nmovestrhi%d:", count);
1177 output_asm_insn(buf, NULL);
1179 output_asm_insn("movb (%1)+, (%0)+", operands);
1183 sprintf(buf, "sob %%4, movestrhi%d", count);
1184 output_asm_insn(buf, operands);
1188 output_asm_insn("dec %4", operands);
1190 sprintf(buf, "bgt movestrhi%d", count);
1191 output_asm_insn(buf, NULL);
1213 generate_compact_code:
1215 output_asm_insn("asr %4", operands);
1217 sprintf(buf, "\nmovestrhi%d:", count);
1218 output_asm_insn(buf, NULL);
1220 output_asm_insn("mov (%1)+, (%0)+", operands);
1224 sprintf(buf, "sob %%4, movestrhi%d", count);
1225 output_asm_insn(buf, operands);
1229 output_asm_insn("dec %4", operands);
1231 sprintf(buf, "bgt movestrhi%d", count);
1232 output_asm_insn(buf, NULL);
1258 goto generate_compact_code;
1260 output_asm_insn("asr %4", operands);
1261 output_asm_insn("asr %4", operands);
1263 sprintf(buf, "\nmovestrhi%d:", count);
1264 output_asm_insn(buf, NULL);
1266 output_asm_insn("mov (%1)+, (%0)+", operands);
1267 output_asm_insn("mov (%1)+, (%0)+", operands);
1271 sprintf(buf, "sob %%4, movestrhi%d", count);
1272 output_asm_insn(buf, operands);
1276 output_asm_insn("dec %4", operands);
1278 sprintf(buf, "bgt movestrhi%d", count);
1279 output_asm_insn(buf, NULL);
1309 goto generate_compact_code;
1311 output_asm_insn("asr %4", operands);
1312 output_asm_insn("asr %4", operands);
1313 output_asm_insn("asr %4", operands);
1315 sprintf(buf, "\nmovestrhi%d:", count);
1316 output_asm_insn(buf, NULL);
1318 output_asm_insn("mov (%1)+, (%0)+", operands);
1319 output_asm_insn("mov (%1)+, (%0)+", operands);
1320 output_asm_insn("mov (%1)+, (%0)+", operands);
1321 output_asm_insn("mov (%1)+, (%0)+", operands);
1325 sprintf(buf, "sob %%4, movestrhi%d", count);
1326 output_asm_insn(buf, operands);
1330 output_asm_insn("dec %4", operands);
1332 sprintf(buf, "bgt movestrhi%d", count);
1333 output_asm_insn(buf, NULL);
1346 /* for future use */
1348 comparison_operator_index(op)
1351 switch (GET_CODE(op))
1388 /* tests whether the rtx is a comparison operator */
1390 comp_operator (op, mode)
1392 enum machine_mode mode;
1394 return comparison_operator_index(op) >= 0;
1399 legitimate_address_p (mode, address)
1400 enum machine_mode mode;
1403 /* #define REG_OK_STRICT */
1404 GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1411 /* #undef REG_OK_STRICT */
1414 /* A copy of output_addr_const modified for pdp11 expression syntax.
1415 output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1416 use, and for debugging output, which we don't support with this port either.
1417 So this copy should get called whenever needed.
1420 output_addr_const_pdp11 (file, x)
1427 switch (GET_CODE (x))
1437 assemble_name (file, XSTR (x, 0));
1441 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1442 assemble_name (file, buf);
1446 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1447 assemble_name (file, buf);
1451 /* Should we check for constants which are too big? Maybe cutting
1452 them off to 16 bits is OK? */
1453 fprintf (file, "%ho", (unsigned short) INTVAL (x));
1457 /* This used to output parentheses around the expression,
1458 but that does not work on the 386 (either ATT or BSD assembler). */
1459 output_addr_const_pdp11 (file, XEXP (x, 0));
1463 if (GET_MODE (x) == VOIDmode)
1465 /* We can use %o if the number is one word and positive. */
1466 if (CONST_DOUBLE_HIGH (x))
1467 abort (); /* Should we just silently drop the high part? */
1469 fprintf (file, "%ho", (unsigned short) CONST_DOUBLE_LOW (x));
1472 /* We can't handle floating point constants;
1473 PRINT_OPERAND must handle them. */
1474 output_operand_lossage ("floating constant misused");
1478 /* Some assemblers need integer constants to appear last (eg masm). */
1479 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1481 output_addr_const_pdp11 (file, XEXP (x, 1));
1482 if (INTVAL (XEXP (x, 0)) >= 0)
1483 fprintf (file, "+");
1484 output_addr_const_pdp11 (file, XEXP (x, 0));
1488 output_addr_const_pdp11 (file, XEXP (x, 0));
1489 if (INTVAL (XEXP (x, 1)) >= 0)
1490 fprintf (file, "+");
1491 output_addr_const_pdp11 (file, XEXP (x, 1));
1496 /* Avoid outputting things like x-x or x+5-x,
1497 since some assemblers can't handle that. */
1498 x = simplify_subtraction (x);
1499 if (GET_CODE (x) != MINUS)
1502 output_addr_const_pdp11 (file, XEXP (x, 0));
1503 fprintf (file, "-");
1504 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1505 && INTVAL (XEXP (x, 1)) < 0)
1507 fprintf (file, ASM_OPEN_PAREN);
1508 output_addr_const_pdp11 (file, XEXP (x, 1));
1509 fprintf (file, ASM_CLOSE_PAREN);
1512 output_addr_const_pdp11 (file, XEXP (x, 1));
1517 output_addr_const_pdp11 (file, XEXP (x, 0));
1521 output_operand_lossage ("invalid expression as operand");