1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 1993 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* Some output-actions in m68k.md need these. */
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"
34 /* Needed for use_return_insn. */
37 #ifdef SUPPORT_SUN_FPA
39 /* Index into this array by (register number >> 3) to find the
40 smallest class which contains that register. */
41 enum reg_class regno_reg_class
[]
42 = { DATA_REGS
, ADDR_REGS
, FP_REGS
,
43 LO_FPA_REGS
, LO_FPA_REGS
, FPA_REGS
, FPA_REGS
};
45 #endif /* defined SUPPORT_SUN_FPA */
47 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
48 if SGS_SWITCH_TABLE. */
49 int switch_table_difference_label_flag
;
51 static rtx
find_addr_reg ();
52 rtx
legitimize_pic_address ();
55 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
56 function at any time during the compilation process. In the future
57 we should try and eliminate the USE if we can easily determine that
58 all PIC references were deleted from the current function. That would
59 save an address register */
63 if (flag_pic
&& current_function_uses_pic_offset_table
)
64 emit_insn (gen_rtx (USE
, VOIDmode
, pic_offset_table_rtx
));
68 /* This function generates the assembly code for function entry.
69 STREAM is a stdio stream to output the code to.
70 SIZE is an int: how many units of temporary storage to allocate.
71 Refer to the array `regs_ever_live' to determine which registers
72 to save; `regs_ever_live[I]' is nonzero if register number I
73 is ever used in the function. This function is responsible for
74 knowing which registers should not be saved even if used. */
77 /* Note that the order of the bit mask for fmovem is the opposite
78 of the order for movem! */
82 output_function_prologue (stream
, size
)
87 register int mask
= 0;
88 int num_saved_regs
= 0;
89 extern char call_used_regs
[];
90 int fsize
= (size
+ 3) & -4;
93 if (frame_pointer_needed
)
95 /* Adding negative number is faster on the 68040. */
96 if (fsize
< 0x8000 && !TARGET_68040
)
99 asm_fprintf (stream
, "\tlink.w %s,%0I%d\n",
100 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
102 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
103 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
106 else if (TARGET_68020
)
109 asm_fprintf (stream
, "\tlink.l %s,%0I%d\n",
110 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
112 asm_fprintf (stream
, "\tlink %s,%0I%d\n",
113 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
119 asm_fprintf (stream
, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
120 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
122 asm_fprintf (stream
, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
123 reg_names
[FRAME_POINTER_REGNUM
], -fsize
);
129 /* Adding negative number is faster on the 68040. */
130 if (fsize
+ 4 < 0x8000)
133 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", - (fsize
+ 4));
135 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", - (fsize
+ 4));
141 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", - (fsize
+ 4));
143 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", - (fsize
+ 4));
147 #ifdef SUPPORT_SUN_FPA
148 for (regno
= 24; regno
< 56; regno
++)
149 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
152 asm_fprintf (stream
, "\tfpmovd %s,-(%Rsp)\n",
155 asm_fprintf (stream
, "\tfpmoved %s,%Rsp@-\n",
160 for (regno
= 16; regno
< 24; regno
++)
161 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
162 mask
|= 1 << (regno
- 16);
163 if ((mask
& 0xff) != 0)
166 asm_fprintf (stream
, "\tfmovm %0I0x%x,-(%Rsp)\n", mask
& 0xff);
168 asm_fprintf (stream
, "\tfmovem %0I0x%x,%Rsp@-\n", mask
& 0xff);
172 for (regno
= 0; regno
< 16; regno
++)
173 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
175 mask
|= 1 << (15 - regno
);
178 if (frame_pointer_needed
)
180 mask
&= ~ (1 << (15 - FRAME_POINTER_REGNUM
));
185 fprintf (stream
, "\ttstl sp@(%d)\n", NEED_PROBE
- num_saved_regs
* 4);
188 if (num_saved_regs
<= 2)
190 /* Store each separately in the same order moveml uses.
191 Using two movel instructions instead of a single moveml
192 is about 15% faster for the 68020 and 68030 at no expense
197 /* Undo the work from above. */
198 for (i
= 0; i
< 16; i
++)
202 "\t%Omove.l %s,-(%Rsp)\n",
204 "\tmovel %s,%Rsp@-\n",
211 asm_fprintf (stream
, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask
);
213 asm_fprintf (stream
, "\tmoveml %0I0x%x,%Rsp@-\n", mask
);
216 if (flag_pic
&& current_function_uses_pic_offset_table
)
219 asm_fprintf (stream
, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
220 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
222 asm_fprintf (stream
, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
223 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
224 asm_fprintf (stream
, "\tlea %Rpc@(0,%s:l),%s\n",
225 reg_names
[PIC_OFFSET_TABLE_REGNUM
],
226 reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
231 /* Return true if this function's epilogue can be output as RTL. */
238 if (!reload_completed
|| frame_pointer_needed
|| get_frame_size () != 0)
241 /* Copied from output_function_epilogue (). We should probably create a
242 separate layout routine to perform the common work. */
244 for (regno
= 0 ; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
245 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
251 /* This function generates the assembly code for function exit,
252 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
254 The function epilogue should not depend on the current stack pointer!
255 It should use the frame pointer only, if there is a frame pointer.
256 This is mandatory because of alloca; we also take advantage of it to
257 omit stack adjustments before returning. */
260 output_function_epilogue (stream
, size
)
265 register int mask
, fmask
;
267 int offset
, foffset
, fpoffset
;
268 extern char call_used_regs
[];
269 int fsize
= (size
+ 3) & -4;
271 rtx insn
= get_last_insn ();
273 /* If the last insn was a BARRIER, we don't have to write any code. */
274 if (GET_CODE (insn
) == NOTE
)
275 insn
= prev_nonnote_insn (insn
);
276 if (insn
&& GET_CODE (insn
) == BARRIER
)
278 /* Output just a no-op so that debuggers don't get confused
279 about which function the pc is in at this address. */
280 asm_fprintf (stream
, "\tnop\n");
284 #ifdef FUNCTION_EXTRA_EPILOGUE
285 FUNCTION_EXTRA_EPILOGUE (stream
, size
);
287 nregs
= 0; fmask
= 0; fpoffset
= 0;
288 #ifdef SUPPORT_SUN_FPA
289 for (regno
= 24 ; regno
< 56 ; regno
++)
290 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
292 fpoffset
= nregs
* 8;
295 for (regno
= 16; regno
< 24; regno
++)
296 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
299 fmask
|= 1 << (23 - regno
);
301 foffset
= fpoffset
+ nregs
* 12;
303 if (frame_pointer_needed
)
304 regs_ever_live
[FRAME_POINTER_REGNUM
] = 0;
305 for (regno
= 0; regno
< 16; regno
++)
306 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
311 offset
= foffset
+ nregs
* 4;
312 if (offset
+ fsize
>= 0x8000
313 && frame_pointer_needed
314 && (mask
|| fmask
|| fpoffset
))
317 asm_fprintf (stream
, "\t%Omove.l %0I%d,%Ra0\n", -fsize
);
319 asm_fprintf (stream
, "\tmovel %0I%d,%Ra0\n", -fsize
);
325 /* Restore each separately in the same order moveml does.
326 Using two movel instructions instead of a single moveml
327 is about 15% faster for the 68020 and 68030 at no expense
332 /* Undo the work from above. */
333 for (i
= 0; i
< 16; i
++)
339 asm_fprintf (stream
, "\t%Omove.l -%d(%s,%Ra0.l),%s\n",
341 reg_names
[FRAME_POINTER_REGNUM
],
344 asm_fprintf (stream
, "\tmovel %s@(-%d,%Ra0:l),%s\n",
345 reg_names
[FRAME_POINTER_REGNUM
],
346 offset
+ fsize
, reg_names
[i
]);
349 else if (! frame_pointer_needed
)
352 asm_fprintf (stream
, "\t%Omove.l (%Rsp)+,%s\n",
355 asm_fprintf (stream
, "\tmovel %Rsp@+,%s\n",
362 asm_fprintf (stream
, "\t%Omove.l -%d(%s),%s\n",
364 reg_names
[FRAME_POINTER_REGNUM
],
367 asm_fprintf (stream
, "\tmovel %s@(-%d),%s\n",
368 reg_names
[FRAME_POINTER_REGNUM
],
369 offset
+ fsize
, reg_names
[i
]);
380 asm_fprintf (stream
, "\tmovm.l -%d(%s,%Ra0.l),%0I0x%x\n",
382 reg_names
[FRAME_POINTER_REGNUM
],
385 asm_fprintf (stream
, "\tmoveml %s@(-%d,%Ra0:l),%0I0x%x\n",
386 reg_names
[FRAME_POINTER_REGNUM
],
387 offset
+ fsize
, mask
);
390 else if (! frame_pointer_needed
)
393 asm_fprintf (stream
, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask
);
395 asm_fprintf (stream
, "\tmoveml %Rsp@+,%0I0x%x\n", mask
);
401 asm_fprintf (stream
, "\tmovm.l -%d(%s),%0I0x%x\n",
403 reg_names
[FRAME_POINTER_REGNUM
],
406 asm_fprintf (stream
, "\tmoveml %s@(-%d),%0I0x%x\n",
407 reg_names
[FRAME_POINTER_REGNUM
],
408 offset
+ fsize
, mask
);
417 asm_fprintf (stream
, "\tfmovm -%d(%s,%Ra0.l),%0I0x%x\n",
419 reg_names
[FRAME_POINTER_REGNUM
],
422 asm_fprintf (stream
, "\tfmovem %s@(-%d,%Ra0:l),%0I0x%x\n",
423 reg_names
[FRAME_POINTER_REGNUM
],
424 foffset
+ fsize
, fmask
);
427 else if (! frame_pointer_needed
)
430 asm_fprintf (stream
, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask
);
432 asm_fprintf (stream
, "\tfmovem %Rsp@+,%0I0x%x\n", fmask
);
438 asm_fprintf (stream
, "\tfmovm -%d(%s),%0I0x%x\n",
440 reg_names
[FRAME_POINTER_REGNUM
],
443 asm_fprintf (stream
, "\tfmovem %s@(-%d),%0I0x%x\n",
444 reg_names
[FRAME_POINTER_REGNUM
],
445 foffset
+ fsize
, fmask
);
450 for (regno
= 55; regno
>= 24; regno
--)
451 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
456 asm_fprintf (stream
, "\tfpmovd -%d(%s,%Ra0.l), %s\n",
458 reg_names
[FRAME_POINTER_REGNUM
],
461 asm_fprintf (stream
, "\tfpmoved %s@(-%d,%Ra0:l), %s\n",
462 reg_names
[FRAME_POINTER_REGNUM
],
463 fpoffset
+ fsize
, reg_names
[regno
]);
466 else if (! frame_pointer_needed
)
469 asm_fprintf (stream
, "\tfpmovd (%Rsp)+,%s\n",
472 asm_fprintf (stream
, "\tfpmoved %Rsp@+, %s\n",
479 asm_fprintf (stream
, "\tfpmovd -%d(%s), %s\n",
481 reg_names
[FRAME_POINTER_REGNUM
],
484 asm_fprintf (stream
, "\tfpmoved %s@(-%d), %s\n",
485 reg_names
[FRAME_POINTER_REGNUM
],
486 fpoffset
+ fsize
, reg_names
[regno
]);
491 if (frame_pointer_needed
)
492 fprintf (stream
, "\tunlk %s\n",
493 reg_names
[FRAME_POINTER_REGNUM
]);
496 if (fsize
+ 4 < 0x8000)
499 asm_fprintf (stream
, "\tadd.w %0I%d,%Rsp\n", fsize
+ 4);
501 asm_fprintf (stream
, "\taddw %0I%d,%Rsp\n", fsize
+ 4);
507 asm_fprintf (stream
, "\tadd.l %0I%d,%Rsp\n", fsize
+ 4);
509 asm_fprintf (stream
, "\taddl %0I%d,%Rsp\n", fsize
+ 4);
513 if (current_function_pops_args
)
514 asm_fprintf (stream
, "\trtd %0I%d\n", current_function_pops_args
);
516 fprintf (stream
, "\trts\n");
519 /* Similar to general_operand, but exclude stack_pointer_rtx. */
522 not_sp_operand (op
, mode
)
524 enum machine_mode mode
;
526 return op
!= stack_pointer_rtx
&& general_operand (op
, mode
);
529 /* Return TRUE if X is a valid comparison operator for the dbcc
532 Note it rejects floating point comparison operators.
533 (In the future we could use Fdbcc).
535 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
538 valid_dbcc_comparison_p (x
, mode
)
540 enum machine_mode mode
;
542 /* We could add support for these in the future */
543 if (cc_prev_status
.flags
& CC_IN_68881
)
546 switch (GET_CODE (x
))
549 case EQ
: case NE
: case GTU
: case LTU
:
553 /* Reject some when CC_NO_OVERFLOW is set. This may be over
555 case GT
: case LT
: case GE
: case LE
:
556 return ! (cc_prev_status
.flags
& CC_NO_OVERFLOW
);
562 /* Output a dbCC; jCC sequence. Note we do not handle the
563 floating point version of this sequence (Fdbcc). We also
564 do not handle alternative conditions when CC_NO_OVERFLOW is
565 set. It is assumed that valid_dbcc_comparison_p will kick
566 those out before we get here. */
568 output_dbcc_and_branch (operands
)
572 switch (GET_CODE (operands
[3]))
576 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands
);
578 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands
);
584 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands
);
586 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands
);
592 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands
);
594 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands
);
600 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands
);
602 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands
);
608 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands
);
610 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands
);
616 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands
);
618 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands
);
624 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands
);
626 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands
);
632 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands
);
634 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands
);
640 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands
);
642 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands
);
648 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands
);
650 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands
);
658 /* If the decrement is to be done in SImode, then we have
659 to compensate for the fact that dbcc decrements in HImode. */
660 switch (GET_MODE (operands
[0]))
664 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands
);
666 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands
);
679 output_btst (operands
, countop
, dataop
, insn
, signpos
)
685 operands
[0] = countop
;
686 operands
[1] = dataop
;
688 if (GET_CODE (countop
) == CONST_INT
)
690 register int count
= INTVAL (countop
);
691 /* If COUNT is bigger than size of storage unit in use,
692 advance to the containing unit of same size. */
695 int offset
= (count
& ~signpos
) / 8;
696 count
= count
& signpos
;
697 operands
[1] = dataop
= adj_offsettable_operand (dataop
, offset
);
699 if (count
== signpos
)
700 cc_status
.flags
= CC_NOT_POSITIVE
| CC_Z_IN_NOT_N
;
702 cc_status
.flags
= CC_NOT_NEGATIVE
| CC_Z_IN_NOT_N
;
704 /* These three statements used to use next_insns_test_no...
705 but it appears that this should do the same job. */
707 && next_insn_tests_no_inequality (insn
))
710 && next_insn_tests_no_inequality (insn
))
713 && next_insn_tests_no_inequality (insn
))
716 cc_status
.flags
= CC_NOT_NEGATIVE
;
721 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
722 reference and a constant. */
725 symbolic_operand (op
, mode
)
727 enum machine_mode mode
;
729 switch (GET_CODE (op
))
737 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
738 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
739 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
741 #if 0 /* Deleted, with corresponding change in m68k.h,
742 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
744 return GET_MODE (op
) == mode
;
753 /* Legitimize PIC addresses. If the address is already
754 position-independent, we return ORIG. Newly generated
755 position-independent addresses go to REG. If we need more
756 than one register, we lose.
758 An address is legitimized by making an indirect reference
759 through the Global Offset Table with the name of the symbol
762 The assembler and linker are responsible for placing the
763 address of the symbol in the GOT. The function prologue
764 is responsible for initializing a5 to the starting address
767 The assembler is also responsible for translating a symbol name
768 into a constant displacement from the start of the GOT.
770 A quick example may make things a little clearer:
772 When not generating PIC code to store the value 12345 into _foo
773 we would generate the following code:
777 When generating PIC two transformations are made. First, the compiler
778 loads the address of foo into a register. So the first transformation makes:
783 The code in movsi will intercept the lea instruction and call this
784 routine which will transform the instructions into:
786 movel a5@(_foo:w), a0
790 That (in a nutshell) is how *all* symbol and label references are
794 legitimize_pic_address (orig
, mode
, reg
)
796 enum machine_mode mode
;
800 /* First handle a simple SYMBOL_REF or LABEL_REF */
801 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
806 pic_ref
= gen_rtx (MEM
, Pmode
,
807 gen_rtx (PLUS
, Pmode
,
808 pic_offset_table_rtx
, orig
));
809 current_function_uses_pic_offset_table
= 1;
810 RTX_UNCHANGING_P (pic_ref
) = 1;
811 emit_move_insn (reg
, pic_ref
);
814 else if (GET_CODE (orig
) == CONST
)
818 /* Make sure this is CONST has not already been legitimized */
819 if (GET_CODE (XEXP (orig
, 0)) == PLUS
820 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
826 /* legitimize both operands of the PLUS */
827 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
829 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
830 orig
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
831 base
== reg
? 0 : reg
);
835 if (GET_CODE (orig
) == CONST_INT
)
836 return plus_constant_for_output (base
, INTVAL (orig
));
837 pic_ref
= gen_rtx (PLUS
, Pmode
, base
, orig
);
838 /* Likewise, should we set special REG_NOTEs here? */
844 /* Return the best assembler insn template
845 for moving operands[1] into operands[0] as a fullword. */
848 singlemove_string (operands
)
851 #ifdef SUPPORT_SUN_FPA
852 if (FPA_REG_P (operands
[0]) || FPA_REG_P (operands
[1]))
853 return "fpmoves %1,%0";
855 if (DATA_REG_P (operands
[0])
856 && GET_CODE (operands
[1]) == CONST_INT
857 && INTVAL (operands
[1]) < 128
858 && INTVAL (operands
[1]) >= -128)
860 #if defined (MOTOROLA) && !defined (CRDS)
861 return "moveq%.l %1,%0";
863 return "moveq %1,%0";
866 if (operands
[1] != const0_rtx
)
867 return "move%.l %1,%0";
868 if (! ADDRESS_REG_P (operands
[0]))
870 return "sub%.l %0,%0";
874 /* Output assembler code to perform a doubleword move insn
875 with operands OPERANDS. */
878 output_move_double (operands
)
883 REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
888 rtx addreg0
= 0, addreg1
= 0;
889 int dest_overlapped_low
= 0;
890 int size
= GET_MODE_SIZE (GET_MODE (operands
[0]));
895 /* First classify both operands. */
897 if (REG_P (operands
[0]))
899 else if (offsettable_memref_p (operands
[0]))
901 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
903 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
905 else if (GET_CODE (operands
[0]) == MEM
)
910 if (REG_P (operands
[1]))
912 else if (CONSTANT_P (operands
[1]))
914 else if (offsettable_memref_p (operands
[1]))
916 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
918 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
920 else if (GET_CODE (operands
[1]) == MEM
)
925 /* Check for the cases that the operand constraints are not
926 supposed to allow to happen. Abort if we get one,
927 because generating code for these cases is painful. */
929 if (optype0
== RNDOP
|| optype1
== RNDOP
)
932 /* If one operand is decrementing and one is incrementing
933 decrement the former register explicitly
934 and change that operand into ordinary indexing. */
936 if (optype0
== PUSHOP
&& optype1
== POPOP
)
938 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
940 output_asm_insn ("sub%.l %#12,%0", operands
);
942 output_asm_insn ("subq%.l %#8,%0", operands
);
943 if (GET_MODE (operands
[1]) == XFmode
)
944 operands
[0] = gen_rtx (MEM
, XFmode
, operands
[0]);
945 else if (GET_MODE (operands
[0]) == DFmode
)
946 operands
[0] = gen_rtx (MEM
, DFmode
, operands
[0]);
948 operands
[0] = gen_rtx (MEM
, DImode
, operands
[0]);
951 if (optype0
== POPOP
&& optype1
== PUSHOP
)
953 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
955 output_asm_insn ("sub%.l %#12,%1", operands
);
957 output_asm_insn ("subq%.l %#8,%1", operands
);
958 if (GET_MODE (operands
[1]) == XFmode
)
959 operands
[1] = gen_rtx (MEM
, XFmode
, operands
[1]);
960 else if (GET_MODE (operands
[1]) == DFmode
)
961 operands
[1] = gen_rtx (MEM
, DFmode
, operands
[1]);
963 operands
[1] = gen_rtx (MEM
, DImode
, operands
[1]);
967 /* If an operand is an unoffsettable memory ref, find a register
968 we can increment temporarily to make it refer to the second word. */
970 if (optype0
== MEMOP
)
971 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
973 if (optype1
== MEMOP
)
974 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
976 /* Ok, we can do one word at a time.
977 Normally we do the low-numbered word first,
978 but if either operand is autodecrementing then we
979 do the high-numbered word first.
981 In either case, set up in LATEHALF the operands to use
982 for the high-numbered word and in some cases alter the
983 operands in OPERANDS to be suitable for the low-numbered word. */
987 if (optype0
== REGOP
)
989 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 2);
990 middlehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
992 else if (optype0
== OFFSOP
)
994 middlehalf
[0] = adj_offsettable_operand (operands
[0], 4);
995 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
999 middlehalf
[0] = operands
[0];
1000 latehalf
[0] = operands
[0];
1003 if (optype1
== REGOP
)
1005 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 2);
1006 middlehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1008 else if (optype1
== OFFSOP
)
1010 middlehalf
[1] = adj_offsettable_operand (operands
[1], 4);
1011 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1013 else if (optype1
== CNSTOP
)
1015 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
1020 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
1021 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
1022 operands
[1] = GEN_INT (l
[0]);
1023 middlehalf
[1] = GEN_INT (l
[1]);
1024 latehalf
[1] = GEN_INT (l
[2]);
1026 else if (CONSTANT_P (operands
[1]))
1028 /* actually, no non-CONST_DOUBLE constant should ever
1031 if (GET_CODE (operands
[1]) == CONST_INT
&& INTVAL (operands
[1]) < 0)
1032 latehalf
[1] = constm1_rtx
;
1034 latehalf
[1] = const0_rtx
;
1039 middlehalf
[1] = operands
[1];
1040 latehalf
[1] = operands
[1];
1044 /* size is not 12: */
1046 if (optype0
== REGOP
)
1047 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
1048 else if (optype0
== OFFSOP
)
1049 latehalf
[0] = adj_offsettable_operand (operands
[0], size
- 4);
1051 latehalf
[0] = operands
[0];
1053 if (optype1
== REGOP
)
1054 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
1055 else if (optype1
== OFFSOP
)
1056 latehalf
[1] = adj_offsettable_operand (operands
[1], size
- 4);
1057 else if (optype1
== CNSTOP
)
1058 split_double (operands
[1], &operands
[1], &latehalf
[1]);
1060 latehalf
[1] = operands
[1];
1063 /* If insn is effectively movd N(sp),-(sp) then we will do the
1064 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1065 for the low word as well, to compensate for the first decrement of sp. */
1066 if (optype0
== PUSHOP
1067 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
1068 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
1069 operands
[1] = latehalf
[1];
1071 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1072 if the upper part of reg N does not appear in the MEM, arrange to
1073 emit the move late-half first. Otherwise, compute the MEM address
1074 into the upper part of N and use that as a pointer to the memory
1076 if (optype0
== REGOP
1077 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
1079 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0))
1080 && reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1082 /* If both halves of dest are used in the src memory address,
1083 compute the address into latehalf of dest. */
1085 xops
[0] = latehalf
[0];
1086 xops
[1] = XEXP (operands
[1], 0);
1087 output_asm_insn ("lea%L0,%a1,%0", xops
);
1088 if( GET_MODE (operands
[1]) == XFmode
)
1090 operands
[1] = gen_rtx (MEM
, XFmode
, latehalf
[0]);
1091 middlehalf
[1] = adj_offsettable_operand (operands
[1], size
-8);
1092 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1096 operands
[1] = gen_rtx (MEM
, DImode
, latehalf
[0]);
1097 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
1101 && reg_mentioned_p (middlehalf
[0], XEXP (operands
[1], 0)))
1103 /* Check for two regs used by both source and dest. */
1104 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0))
1105 || reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
1108 /* JRV says this can't happen: */
1109 if (addreg0
|| addreg1
)
1112 /* Only the middle reg conflicts; simply put it last. */
1113 output_asm_insn (singlemove_string (operands
), operands
);
1114 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1115 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1118 else if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0)))
1119 /* If the low half of dest is mentioned in the source memory
1120 address, the arrange to emit the move late half first. */
1121 dest_overlapped_low
= 1;
1124 /* If one or both operands autodecrementing,
1125 do the two words, high-numbered first. */
1127 /* Likewise, the first move would clobber the source of the second one,
1128 do them in the other order. This happens only for registers;
1129 such overlap can't happen in memory unless the user explicitly
1130 sets it up, and that is an undefined circumstance. */
1132 if (optype0
== PUSHOP
|| optype1
== PUSHOP
1133 || (optype0
== REGOP
&& optype1
== REGOP
1134 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
1135 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
1136 || dest_overlapped_low
)
1138 /* Make any unoffsettable addresses point at high-numbered word. */
1142 output_asm_insn ("addql %#8,%0", &addreg0
);
1144 output_asm_insn ("addql %#4,%0", &addreg0
);
1149 output_asm_insn ("addql %#8,%0", &addreg1
);
1151 output_asm_insn ("addql %#4,%0", &addreg1
);
1155 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1157 /* Undo the adds we just did. */
1159 output_asm_insn ("subql %#4,%0", &addreg0
);
1161 output_asm_insn ("subql %#4,%0", &addreg1
);
1165 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1167 output_asm_insn ("subql %#4,%0", &addreg0
);
1169 output_asm_insn ("subql %#4,%0", &addreg1
);
1172 /* Do low-numbered word. */
1173 return singlemove_string (operands
);
1176 /* Normal case: do the two words, low-numbered first. */
1178 output_asm_insn (singlemove_string (operands
), operands
);
1180 /* Do the middle one of the three words for long double */
1184 output_asm_insn ("addql %#4,%0", &addreg0
);
1186 output_asm_insn ("addql %#4,%0", &addreg1
);
1188 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
1191 /* Make any unoffsettable addresses point at high-numbered word. */
1193 output_asm_insn ("addql %#4,%0", &addreg0
);
1195 output_asm_insn ("addql %#4,%0", &addreg1
);
1198 output_asm_insn (singlemove_string (latehalf
), latehalf
);
1200 /* Undo the adds we just did. */
1204 output_asm_insn ("subql %#8,%0", &addreg0
);
1206 output_asm_insn ("subql %#4,%0", &addreg0
);
1211 output_asm_insn ("subql %#8,%0", &addreg1
);
1213 output_asm_insn ("subql %#4,%0", &addreg1
);
1219 /* Return a REG that occurs in ADDR with coefficient 1.
1220 ADDR can be effectively incremented by incrementing REG. */
1223 find_addr_reg (addr
)
1226 while (GET_CODE (addr
) == PLUS
)
1228 if (GET_CODE (XEXP (addr
, 0)) == REG
)
1229 addr
= XEXP (addr
, 0);
1230 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
1231 addr
= XEXP (addr
, 1);
1232 else if (CONSTANT_P (XEXP (addr
, 0)))
1233 addr
= XEXP (addr
, 1);
1234 else if (CONSTANT_P (XEXP (addr
, 1)))
1235 addr
= XEXP (addr
, 0);
1239 if (GET_CODE (addr
) == REG
)
1244 /* Store in cc_status the expressions that the condition codes will
1245 describe after execution of an instruction whose pattern is EXP.
1246 Do not alter them if the instruction would not alter the cc's. */
1248 /* On the 68000, all the insns to store in an address register fail to
1249 set the cc's. However, in some cases these instructions can make it
1250 possibly invalid to use the saved cc's. In those cases we clear out
1251 some or all of the saved cc's so they won't be used. */
1253 notice_update_cc (exp
, insn
)
1257 /* If the cc is being set from the fpa and the expression is not an
1258 explicit floating point test instruction (which has code to deal with
1259 this), reinit the CC. */
1260 if (((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1261 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
)))
1262 && !(GET_CODE (exp
) == PARALLEL
1263 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
1264 && XEXP (XVECEXP (exp
, 0, 0), 0) == cc0_rtx
))
1268 else if (GET_CODE (exp
) == SET
)
1270 if (GET_CODE (SET_SRC (exp
)) == CALL
)
1274 else if (ADDRESS_REG_P (SET_DEST (exp
)))
1276 if (cc_status
.value1
1277 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1278 cc_status
.value1
= 0;
1279 if (cc_status
.value2
1280 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1281 cc_status
.value2
= 0;
1283 else if (!FP_REG_P (SET_DEST (exp
))
1284 && SET_DEST (exp
) != cc0_rtx
1285 && (FP_REG_P (SET_SRC (exp
))
1286 || GET_CODE (SET_SRC (exp
)) == FIX
1287 || GET_CODE (SET_SRC (exp
)) == FLOAT_TRUNCATE
1288 || GET_CODE (SET_SRC (exp
)) == FLOAT_EXTEND
))
1292 /* A pair of move insns doesn't produce a useful overall cc. */
1293 else if (!FP_REG_P (SET_DEST (exp
))
1294 && !FP_REG_P (SET_SRC (exp
))
1295 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp
))) > 4
1296 && (GET_CODE (SET_SRC (exp
)) == REG
1297 || GET_CODE (SET_SRC (exp
)) == MEM
1298 || GET_CODE (SET_SRC (exp
)) == CONST_DOUBLE
))
1302 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1306 else if (XEXP (exp
, 0) != pc_rtx
)
1308 cc_status
.flags
= 0;
1309 cc_status
.value1
= XEXP (exp
, 0);
1310 cc_status
.value2
= XEXP (exp
, 1);
1313 else if (GET_CODE (exp
) == PARALLEL
1314 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1316 if (ADDRESS_REG_P (XEXP (XVECEXP (exp
, 0, 0), 0)))
1318 else if (XEXP (XVECEXP (exp
, 0, 0), 0) != pc_rtx
)
1320 cc_status
.flags
= 0;
1321 cc_status
.value1
= XEXP (XVECEXP (exp
, 0, 0), 0);
1322 cc_status
.value2
= XEXP (XVECEXP (exp
, 0, 0), 1);
1327 if (cc_status
.value2
!= 0
1328 && ADDRESS_REG_P (cc_status
.value2
)
1329 && GET_MODE (cc_status
.value2
) == QImode
)
1331 if (cc_status
.value2
!= 0
1332 && !(cc_status
.value1
&& FPA_REG_P (cc_status
.value1
)))
1333 switch (GET_CODE (cc_status
.value2
))
1335 case PLUS
: case MINUS
: case MULT
:
1336 case DIV
: case UDIV
: case MOD
: case UMOD
: case NEG
:
1337 case ASHIFT
: case LSHIFT
: case ASHIFTRT
: case LSHIFTRT
:
1338 case ROTATE
: case ROTATERT
:
1339 if (GET_MODE (cc_status
.value2
) != VOIDmode
)
1340 cc_status
.flags
|= CC_NO_OVERFLOW
;
1343 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1344 ends with a move insn moving r2 in r2's mode.
1345 Thus, the cc's are set for r2.
1346 This can set N bit spuriously. */
1347 cc_status
.flags
|= CC_NOT_NEGATIVE
;
1349 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == REG
1351 && reg_overlap_mentioned_p (cc_status
.value1
, cc_status
.value2
))
1352 cc_status
.value2
= 0;
1353 if (((cc_status
.value1
&& FP_REG_P (cc_status
.value1
))
1354 || (cc_status
.value2
&& FP_REG_P (cc_status
.value2
)))
1355 && !((cc_status
.value1
&& FPA_REG_P (cc_status
.value1
))
1356 || (cc_status
.value2
&& FPA_REG_P (cc_status
.value2
))))
1357 cc_status
.flags
= CC_IN_68881
;
1361 output_move_const_double (operands
)
1364 #ifdef SUPPORT_SUN_FPA
1365 if (TARGET_FPA
&& FPA_REG_P (operands
[0]))
1367 int code
= standard_sun_fpa_constant_p (operands
[1]);
1371 static char buf
[40];
1373 sprintf (buf
, "fpmove%%.d %%%%%d,%%0", code
& 0x1ff);
1376 return "fpmove%.d %1,%0";
1381 int code
= standard_68881_constant_p (operands
[1]);
1385 static char buf
[40];
1387 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1390 return "fmove%.d %1,%0";
1395 output_move_const_single (operands
)
1398 #ifdef SUPPORT_SUN_FPA
1401 int code
= standard_sun_fpa_constant_p (operands
[1]);
1405 static char buf
[40];
1407 sprintf (buf
, "fpmove%%.s %%%%%d,%%0", code
& 0x1ff);
1410 return "fpmove%.s %1,%0";
1413 #endif /* defined SUPPORT_SUN_FPA */
1415 int code
= standard_68881_constant_p (operands
[1]);
1419 static char buf
[40];
1421 sprintf (buf
, "fmovecr %%#0x%x,%%0", code
& 0xff);
1424 return "fmove%.s %f1,%0";
1428 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1429 from the "fmovecr" instruction.
1430 The value, anded with 0xff, gives the code to use in fmovecr
1431 to get the desired constant. */
1433 /* This code has been fixed for cross-compilation. */
1435 static int inited_68881_table
= 0;
1437 char *strings_68881
[7] = {
1447 int codes_68881
[7] = {
1457 REAL_VALUE_TYPE values_68881
[7];
1459 /* Set up values_68881 array by converting the decimal values
1460 strings_68881 to binary. */
1467 enum machine_mode mode
;
1470 for (i
= 0; i
< 7; i
++)
1474 r
= REAL_VALUE_ATOF (strings_68881
[i
], mode
);
1475 values_68881
[i
] = r
;
1477 inited_68881_table
= 1;
1481 standard_68881_constant_p (x
)
1486 enum machine_mode mode
;
1488 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1492 #ifndef REAL_ARITHMETIC
1493 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1494 if (! flag_pretend_float
)
1499 if (! inited_68881_table
)
1500 init_68881_table ();
1502 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1504 for (i
= 0; i
< 6; i
++)
1506 if (REAL_VALUES_EQUAL (r
, values_68881
[i
]))
1507 return (codes_68881
[i
]);
1510 if (GET_MODE (x
) == SFmode
)
1513 if (REAL_VALUES_EQUAL (r
, values_68881
[6]))
1514 return (codes_68881
[6]);
1516 /* larger powers of ten in the constants ram are not used
1517 because they are not equal to a `double' C constant. */
1521 /* If X is a floating-point constant, return the logarithm of X base 2,
1522 or 0 if X is not a power of 2. */
1525 floating_exact_log2 (x
)
1528 REAL_VALUE_TYPE r
, r1
;
1531 #ifndef REAL_ARITHMETIC
1532 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1533 if (! flag_pretend_float
)
1538 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1540 if (REAL_VALUES_LESS (r
, dconst0
))
1545 while (REAL_VALUES_LESS (r1
, r
))
1547 r1
= REAL_VALUE_LDEXP (dconst1
, i
);
1548 if (REAL_VALUES_EQUAL (r1
, r
))
1555 #ifdef SUPPORT_SUN_FPA
1556 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1557 from the Sun FPA's constant RAM.
1558 The value returned, anded with 0x1ff, gives the code to use in fpmove
1559 to get the desired constant. */
1561 static int inited_FPA_table
= 0;
1563 char *strings_FPA
[38] = {
1564 /* small rationals */
1577 /* Decimal equivalents of double precision values */
1578 "2.718281828459045091", /* D_E */
1579 "6.283185307179586477", /* 2 pi */
1580 "3.141592653589793116", /* D_PI */
1581 "1.570796326794896619", /* pi/2 */
1582 "1.414213562373095145", /* D_SQRT2 */
1583 "0.7071067811865475244", /* 1/sqrt(2) */
1584 "-1.570796326794896619", /* -pi/2 */
1585 "1.442695040888963387", /* D_LOG2ofE */
1586 "3.321928024887362182", /* D_LOG2of10 */
1587 "0.6931471805599452862", /* D_LOGEof2 */
1588 "2.302585092994045901", /* D_LOGEof10 */
1589 "0.3010299956639811980", /* D_LOG10of2 */
1590 "0.4342944819032518167", /* D_LOG10ofE */
1591 /* Decimal equivalents of single precision values */
1592 "2.718281745910644531", /* S_E */
1593 "6.283185307179586477", /* 2 pi */
1594 "3.141592741012573242", /* S_PI */
1595 "1.570796326794896619", /* pi/2 */
1596 "1.414213538169860840", /* S_SQRT2 */
1597 "0.7071067811865475244", /* 1/sqrt(2) */
1598 "-1.570796326794896619", /* -pi/2 */
1599 "1.442695021629333496", /* S_LOG2ofE */
1600 "3.321928024291992188", /* S_LOG2of10 */
1601 "0.6931471824645996094", /* S_LOGEof2 */
1602 "2.302585124969482442", /* S_LOGEof10 */
1603 "0.3010300099849700928", /* S_LOG10of2 */
1604 "0.4342944920063018799", /* S_LOG10ofE */
1608 int codes_FPA
[38] = {
1609 /* small rationals */
1622 /* double precision */
1636 /* single precision */
1652 REAL_VALUE_TYPE values_FPA
[38];
1654 /* This code has been fixed for cross-compilation. */
1659 enum machine_mode mode
;
1664 for (i
= 0; i
< 38; i
++)
1668 r
= REAL_VALUE_ATOF (strings_FPA
[i
], mode
);
1671 inited_FPA_table
= 1;
1676 standard_sun_fpa_constant_p (x
)
1682 #ifndef REAL_ARITHMETIC
1683 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1684 if (! flag_pretend_float
)
1689 if (! inited_FPA_table
)
1692 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1694 for (i
=0; i
<12; i
++)
1696 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
1697 return (codes_FPA
[i
]);
1700 if (GET_MODE (x
) == SFmode
)
1702 for (i
=25; i
<38; i
++)
1704 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
1705 return (codes_FPA
[i
]);
1710 for (i
=12; i
<25; i
++)
1712 if (REAL_VALUES_EQUAL (r
, values_FPA
[i
]))
1713 return (codes_FPA
[i
]);
1718 #endif /* define SUPPORT_SUN_FPA */
1720 /* A C compound statement to output to stdio stream STREAM the
1721 assembler syntax for an instruction operand X. X is an RTL
1724 CODE is a value that can be used to specify one of several ways
1725 of printing the operand. It is used when identical operands
1726 must be printed differently depending on the context. CODE
1727 comes from the `%' specification that was used to request
1728 printing of the operand. If the specification was just `%DIGIT'
1729 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
1730 is the ASCII code for LTR.
1732 If X is a register, this macro should print the register's name.
1733 The names can be found in an array `reg_names' whose type is
1734 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
1736 When the machine description has a specification `%PUNCT' (a `%'
1737 followed by a punctuation character), this macro is called with
1738 a null pointer for X and the punctuation character for CODE.
1740 The m68k specific codes are:
1742 '.' for dot needed in Motorola-style opcode names.
1743 '-' for an operand pushing on the stack:
1744 sp@-, -(sp) or -(%sp) depending on the style of syntax.
1745 '+' for an operand pushing on the stack:
1746 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
1747 '@' for a reference to the top word on the stack:
1748 sp@, (sp) or (%sp) depending on the style of syntax.
1749 '#' for an immediate operand prefix (# in MIT and Motorola syntax
1750 but & in SGS syntax).
1751 '!' for the cc register (used in an `and to cc' insn).
1752 '$' for the letter `s' in an op code, but only on the 68040.
1753 '&' for the letter `d' in an op code, but only on the 68040.
1754 '/' for register prefix needed by longlong.h.
1756 'b' for byte insn (no effect, on the Sun; this is for the ISI).
1757 'd' to force memory addressing to be absolute, not relative.
1758 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
1759 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
1760 than directly). Second part of 'y' below.
1761 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
1762 or print pair of registers as rx:ry.
1763 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
1764 CONST_DOUBLE's as SunFPA constant RAM registers if
1765 possible, so it should not be used except for the SunFPA.
1770 print_operand (file
, op
, letter
)
1771 FILE *file
; /* file to write to */
1772 rtx op
; /* operand to print */
1773 int letter
; /* %<letter> or 0 */
1780 asm_fprintf (file
, ".");
1783 else if (letter
== '#')
1785 asm_fprintf (file
, "%0I");
1787 else if (letter
== '-')
1790 asm_fprintf (file
, "-(%Rsp)");
1792 asm_fprintf (file
, "%Rsp@-");
1795 else if (letter
== '+')
1798 asm_fprintf (file
, "(%Rsp)+");
1800 asm_fprintf (file
, "%Rsp@+");
1803 else if (letter
== '@')
1806 asm_fprintf (file
, "(%Rsp)");
1808 asm_fprintf (file
, "%Rsp@");
1811 else if (letter
== '!')
1813 asm_fprintf (file
, "%Rfpcr");
1815 else if (letter
== '$')
1817 if (TARGET_68040_ONLY
)
1819 fprintf (file
, "s");
1822 else if (letter
== '&')
1824 if (TARGET_68040_ONLY
)
1826 fprintf (file
, "d");
1829 else if (letter
== '/')
1831 asm_fprintf (file
, "%R");
1833 else if (GET_CODE (op
) == REG
)
1836 && (letter
== 'y' || letter
== 'x')
1837 && GET_MODE (op
) == DFmode
)
1839 fprintf (file
, "%s:%s", reg_names
[REGNO (op
)],
1840 reg_names
[REGNO (op
)+1]);
1844 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1847 else if (GET_CODE (op
) == MEM
)
1849 output_address (XEXP (op
, 0));
1850 if (letter
== 'd' && ! TARGET_68020
1851 && CONSTANT_ADDRESS_P (XEXP (op
, 0))
1852 && !(GET_CODE (XEXP (op
, 0)) == CONST_INT
1853 && INTVAL (XEXP (op
, 0)) < 0x8000
1854 && INTVAL (XEXP (op
, 0)) >= -0x8000))
1856 fprintf (file
, ":l");
1859 #ifdef SUPPORT_SUN_FPA
1860 else if ((letter
== 'y' || letter
== 'w')
1861 && GET_CODE (op
) == CONST_DOUBLE
1862 && (i
= standard_sun_fpa_constant_p (op
)))
1864 fprintf (file
, "%%%d", i
& 0x1ff);
1867 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == SFmode
)
1870 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1871 ASM_OUTPUT_FLOAT_OPERAND (letter
, file
, r
);
1873 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == XFmode
)
1876 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1877 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file
, r
);
1879 else if (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == DFmode
)
1882 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1883 ASM_OUTPUT_DOUBLE_OPERAND (file
, r
);
1887 asm_fprintf (file
, "%0I"); output_addr_const (file
, op
);
1892 /* A C compound statement to output to stdio stream STREAM the
1893 assembler syntax for an instruction operand that is a memory
1894 reference whose address is ADDR. ADDR is an RTL expression.
1896 Note that this contains a kludge that knows that the only reason
1897 we have an address (plus (label_ref...) (reg...)) when not generating
1898 PIC code is in the insn before a tablejump, and we know that m68k.md
1899 generates a label LInnn: on such an insn.
1901 It is possible for PIC to generate a (plus (label_ref...) (reg...))
1902 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
1904 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
1905 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
1906 we want. This difference can be accommodated by using an assembler
1907 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
1908 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
1909 macro. See m68k/sgs.h for an example; for versions without the bug.
1911 They also do not like things like "pea 1.w", so we simple leave off
1912 the .w on small constants.
1914 This routine is responsible for distinguishing between -fpic and -fPIC
1915 style relocations in an address. When generating -fpic code the
1916 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
1917 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
1920 print_operand_address (file
, addr
)
1924 register rtx reg1
, reg2
, breg
, ireg
;
1927 switch (GET_CODE (addr
))
1931 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
1933 fprintf (file
, "%s@", reg_names
[REGNO (addr
)]);
1938 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
1940 fprintf (file
, "%s@-", reg_names
[REGNO (XEXP (addr
, 0))]);
1945 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
1947 fprintf (file
, "%s@+", reg_names
[REGNO (XEXP (addr
, 0))]);
1951 reg1
= reg2
= ireg
= breg
= offset
= 0;
1952 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
1954 offset
= XEXP (addr
, 0);
1955 addr
= XEXP (addr
, 1);
1957 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
1959 offset
= XEXP (addr
, 1);
1960 addr
= XEXP (addr
, 0);
1962 if (GET_CODE (addr
) != PLUS
)
1966 else if (GET_CODE (XEXP (addr
, 0)) == SIGN_EXTEND
)
1968 reg1
= XEXP (addr
, 0);
1969 addr
= XEXP (addr
, 1);
1971 else if (GET_CODE (XEXP (addr
, 1)) == SIGN_EXTEND
)
1973 reg1
= XEXP (addr
, 1);
1974 addr
= XEXP (addr
, 0);
1976 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
1978 reg1
= XEXP (addr
, 0);
1979 addr
= XEXP (addr
, 1);
1981 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
1983 reg1
= XEXP (addr
, 1);
1984 addr
= XEXP (addr
, 0);
1986 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
1988 reg1
= XEXP (addr
, 0);
1989 addr
= XEXP (addr
, 1);
1991 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
1993 reg1
= XEXP (addr
, 1);
1994 addr
= XEXP (addr
, 0);
1996 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
1997 || GET_CODE (addr
) == SIGN_EXTEND
)
2009 #if 0 /* for OLD_INDEXING */
2010 else if (GET_CODE (addr
) == PLUS
)
2012 if (GET_CODE (XEXP (addr
, 0)) == REG
)
2014 reg2
= XEXP (addr
, 0);
2015 addr
= XEXP (addr
, 1);
2017 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
2019 reg2
= XEXP (addr
, 1);
2020 addr
= XEXP (addr
, 0);
2032 if ((reg1
&& (GET_CODE (reg1
) == SIGN_EXTEND
2033 || GET_CODE (reg1
) == MULT
))
2034 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
2039 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
2044 if (ireg
!= 0 && breg
== 0 && GET_CODE (addr
) == LABEL_REF
2045 && ! (flag_pic
&& ireg
== pic_offset_table_rtx
))
2048 if (GET_CODE (ireg
) == MULT
)
2050 scale
= INTVAL (XEXP (ireg
, 1));
2051 ireg
= XEXP (ireg
, 0);
2053 if (GET_CODE (ireg
) == SIGN_EXTEND
)
2057 asm_fprintf (file
, "%LLD%d(%Rpc,%s.w",
2058 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2059 reg_names
[REGNO (XEXP (ireg
, 0))]);
2061 asm_fprintf (file
, "%LL%d-%LLI%d.b(%Rpc,%s.w",
2062 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2063 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2064 reg_names
[REGNO (XEXP (ireg
, 0))]);
2067 asm_fprintf (file
, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w",
2068 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2069 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2070 reg_names
[REGNO (XEXP (ireg
, 0))]);
2077 asm_fprintf (file
, "%LLD%d(%Rpc,%s.l",
2078 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2079 reg_names
[REGNO (ireg
)]);
2081 asm_fprintf (file
, "%LL%d-%LLI%d.b(%Rpc,%s.l",
2082 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2083 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2084 reg_names
[REGNO (ireg
)]);
2087 asm_fprintf (file
, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
2088 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2089 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2090 reg_names
[REGNO (ireg
)]);
2096 fprintf (file
, "*%d", scale
);
2098 fprintf (file
, ":%d", scale
);
2104 if (breg
!= 0 && ireg
== 0 && GET_CODE (addr
) == LABEL_REF
2105 && ! (flag_pic
&& breg
== pic_offset_table_rtx
))
2109 asm_fprintf (file
, "%LLD%d(%Rpc,%s.l",
2110 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2111 reg_names
[REGNO (breg
)]);
2113 asm_fprintf (file
, "%LL%d-%LLI%d.b(%Rpc,%s.l",
2114 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2115 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2116 reg_names
[REGNO (breg
)]);
2119 asm_fprintf (file
, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
2120 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2121 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2122 reg_names
[REGNO (breg
)]);
2127 if (ireg
!= 0 || breg
!= 0)
2134 if (! flag_pic
&& addr
&& GET_CODE (addr
) == LABEL_REF
)
2141 output_addr_const (file
, addr
);
2142 if (flag_pic
&& (breg
== pic_offset_table_rtx
))
2143 fprintf (file
, "@GOT");
2145 fprintf (file
, "(%s", reg_names
[REGNO (breg
)]);
2151 fprintf (file
, "%s@(", reg_names
[REGNO (breg
)]);
2154 output_addr_const (file
, addr
);
2155 if ((flag_pic
== 1) && (breg
== pic_offset_table_rtx
))
2156 fprintf (file
, ":w");
2157 if ((flag_pic
== 2) && (breg
== pic_offset_table_rtx
))
2158 fprintf (file
, ":l");
2160 if (addr
!= 0 && ireg
!= 0)
2165 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
2167 scale
= INTVAL (XEXP (ireg
, 1));
2168 ireg
= XEXP (ireg
, 0);
2170 if (ireg
!= 0 && GET_CODE (ireg
) == SIGN_EXTEND
)
2173 fprintf (file
, "%s.w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2175 fprintf (file
, "%s:w", reg_names
[REGNO (XEXP (ireg
, 0))]);
2181 fprintf (file
, "%s.l", reg_names
[REGNO (ireg
)]);
2183 fprintf (file
, "%s:l", reg_names
[REGNO (ireg
)]);
2189 fprintf (file
, "*%d", scale
);
2191 fprintf (file
, ":%d", scale
);
2197 else if (reg1
!= 0 && GET_CODE (addr
) == LABEL_REF
2198 && ! (flag_pic
&& reg1
== pic_offset_table_rtx
))
2202 asm_fprintf (file
, "%LLD%d(%Rpc,%s.l)",
2203 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2204 reg_names
[REGNO (reg1
)]);
2206 asm_fprintf (file
, "%LL%d-%LLI%d.b(%Rpc,%s.l)",
2207 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2208 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2209 reg_names
[REGNO (reg1
)]);
2212 asm_fprintf (file
, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)",
2213 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2214 CODE_LABEL_NUMBER (XEXP (addr
, 0)),
2215 reg_names
[REGNO (reg1
)]);
2219 /* FALL-THROUGH (is this really what we want? */
2221 if (GET_CODE (addr
) == CONST_INT
2222 && INTVAL (addr
) < 0x8000
2223 && INTVAL (addr
) >= -0x8000)
2227 /* Many SGS assemblers croak on size specifiers for constants. */
2228 fprintf (file
, "%d", INTVAL (addr
));
2230 fprintf (file
, "%d.w", INTVAL (addr
));
2233 fprintf (file
, "%d:w", INTVAL (addr
));
2238 output_addr_const (file
, addr
);
2244 /* Check for cases where a clr insns can be omitted from code using
2245 strict_low_part sets. For example, the second clrl here is not needed:
2246 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2248 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2249 insn we are checking for redundancy. TARGET is the register set by the
2253 strict_low_part_peephole_ok (mode
, first_insn
, target
)
2254 enum machine_mode mode
;
2260 p
= prev_nonnote_insn (first_insn
);
2264 /* If it isn't an insn, then give up. */
2265 if (GET_CODE (p
) != INSN
)
2268 if (reg_set_p (target
, p
))
2270 rtx set
= single_set (p
);
2273 /* If it isn't an easy to recognize insn, then give up. */
2277 dest
= SET_DEST (set
);
2279 /* If this sets the entire target register to zero, then our
2280 first_insn is redundant. */
2281 if (rtx_equal_p (dest
, target
)
2282 && SET_SRC (set
) == const0_rtx
)
2284 else if (GET_CODE (dest
) == STRICT_LOW_PART
2285 && GET_CODE (XEXP (dest
, 0)) == REG
2286 && REGNO (XEXP (dest
, 0)) == REGNO (target
)
2287 && (GET_MODE_SIZE (GET_MODE (XEXP (dest
, 0)))
2288 <= GET_MODE_SIZE (mode
)))
2289 /* This is a strict low part set which modifies less than
2290 we are using, so it is safe. */
2296 p
= prev_nonnote_insn (p
);
2303 /* Trampoline code for the function entry. */
2304 struct bc_seg
*trampoline
;
2306 /* Emit the machine-code interface trampoline at the beginning of a byte
2307 coded function. The argument is a label name of the interpreter
2308 bytecode callinfo structure; the return value is a label name for
2309 the beginning of the actual bytecode. */
2311 bc_emit_trampoline (callinfo
)
2319 sprintf (mylab
, "*LB%d", n
++);
2321 /* Push a reference to the callinfo structure. */
2322 insn
= 0x4879; /* pea xxx.L */
2323 seg_data (trampoline
, (char *) &insn
, sizeof insn
);
2324 seg_refsym (trampoline
, callinfo
, 0);
2326 /* Call __interp, pop arguments, and return. */
2327 insn
= 0x4EB9; /* jsr xxx.L */
2328 seg_data (trampoline
, (char *) &insn
, sizeof insn
);
2329 seg_refsym (trampoline
, "__callint", 0);
2330 insn
= 0x588F; /* addql #4, sp */
2331 seg_data (trampoline
, (char *) &insn
, sizeof insn
);
2332 insn
= 0x4E75; /* rts */
2333 seg_data (trampoline
, (char *) &insn
, sizeof insn
);
2334 seg_defsym (bytecode
, mylab
);
2335 return sym_lookup (mylab
)->name
;