]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/m68k/m68k.c
re PR driver/11417 (fortran options warned about in cc1 when *.F or -x f77-cpp-input)
[thirdparty/gcc.git] / gcc / config / m68k / m68k.c
CommitLineData
79e68feb 1/* Subroutines for insn-output.c for Motorola 68000 family.
79dbeefc 2 Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
4592bdcb 3 Free Software Foundation, Inc.
79e68feb
RS
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
0e29e3c9
RK
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
79e68feb 21
79e68feb 22#include "config.h"
f5220a5d 23#include "system.h"
4977bab6
ZW
24#include "coretypes.h"
25#include "tm.h"
da932f04 26#include "tree.h"
79e68feb 27#include "rtl.h"
49ad7cfa 28#include "function.h"
79e68feb
RS
29#include "regs.h"
30#include "hard-reg-set.h"
31#include "real.h"
32#include "insn-config.h"
33#include "conditions.h"
79e68feb
RS
34#include "output.h"
35#include "insn-attr.h"
1d8eaa6b 36#include "recog.h"
f5220a5d 37#include "toplev.h"
6d5f49b2
RH
38#include "expr.h"
39#include "reload.h"
5505f548 40#include "tm_p.h"
672a6f42
NB
41#include "target.h"
42#include "target-def.h"
2cc07db4 43#include "debug.h"
79e68feb
RS
44
45/* Needed for use_return_insn. */
46#include "flags.h"
47
9eb4f6fc
RS
48/* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
49 if SGS_SWITCH_TABLE. */
50int switch_table_difference_label_flag;
51
5505f548 52static rtx find_addr_reg PARAMS ((rtx));
5505f548 53static const char *singlemove_string PARAMS ((rtx *));
08c148a8
NB
54static void m68k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
55static void m68k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
715bdd29 56static void m68k_coff_asm_named_section PARAMS ((const char *, unsigned int));
d67c7dd8 57#ifdef CTOR_LIST_BEGIN
2cc07db4
RH
58static void m68k_svr3_asm_out_constructor PARAMS ((rtx, int));
59#endif
4977bab6
ZW
60#ifdef HPUX_ASM
61static void m68k_hp320_internal_label PARAMS ((FILE *, const char *, unsigned long));
1bc7c5b6 62static void m68k_hp320_file_start PARAMS ((void));
4977bab6 63#endif
3961e8fe
RH
64static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
65 HOST_WIDE_INT, tree));
2cff4a6e 66static int m68k_save_reg PARAMS ((unsigned int));
3c50106f
RH
67static int const_int_cost PARAMS ((rtx));
68static bool m68k_rtx_costs PARAMS ((rtx, int, int, int *));
79e68feb
RS
69\f
70
ef1dbfb0 71/* Alignment to use for loops and jumps */
7a1929e1 72/* Specify power of two alignment used for loops. */
577c6ece 73const char *m68k_align_loops_string;
7a1929e1 74/* Specify power of two alignment used for non-loop jumps. */
577c6ece 75const char *m68k_align_jumps_string;
7a1929e1 76/* Specify power of two alignment used for functions. */
577c6ece 77const char *m68k_align_funcs_string;
ef1dbfb0 78
7a1929e1 79/* Specify power of two alignment used for loops. */
ef1dbfb0 80int m68k_align_loops;
7a1929e1 81/* Specify power of two alignment used for non-loop jumps. */
ef1dbfb0 82int m68k_align_jumps;
7a1929e1 83/* Specify power of two alignment used for functions. */
ef1dbfb0
RK
84int m68k_align_funcs;
85
2b3600ac
JL
86/* Nonzero if the last compare/test insn had FP operands. The
87 sCC expanders peek at this to determine what to do for the
88 68060, which has no fsCC instructions. */
89int m68k_last_compare_had_fp_operands;
672a6f42
NB
90\f
91/* Initialize the GCC target structure. */
301d03af
RS
92
93#if INT_OP_GROUP == INT_OP_DOT_WORD
94#undef TARGET_ASM_ALIGNED_HI_OP
95#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
96#endif
97
98#if INT_OP_GROUP == INT_OP_NO_DOT
99#undef TARGET_ASM_BYTE_OP
100#define TARGET_ASM_BYTE_OP "\tbyte\t"
101#undef TARGET_ASM_ALIGNED_HI_OP
102#define TARGET_ASM_ALIGNED_HI_OP "\tshort\t"
103#undef TARGET_ASM_ALIGNED_SI_OP
104#define TARGET_ASM_ALIGNED_SI_OP "\tlong\t"
105#endif
106
107#if INT_OP_GROUP == INT_OP_DC
108#undef TARGET_ASM_BYTE_OP
109#define TARGET_ASM_BYTE_OP "\tdc.b\t"
110#undef TARGET_ASM_ALIGNED_HI_OP
111#define TARGET_ASM_ALIGNED_HI_OP "\tdc.w\t"
112#undef TARGET_ASM_ALIGNED_SI_OP
113#define TARGET_ASM_ALIGNED_SI_OP "\tdc.l\t"
114#endif
115
116#undef TARGET_ASM_UNALIGNED_HI_OP
117#define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
118#undef TARGET_ASM_UNALIGNED_SI_OP
119#define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
120
08c148a8
NB
121#undef TARGET_ASM_FUNCTION_PROLOGUE
122#define TARGET_ASM_FUNCTION_PROLOGUE m68k_output_function_prologue
123#undef TARGET_ASM_FUNCTION_EPILOGUE
124#define TARGET_ASM_FUNCTION_EPILOGUE m68k_output_function_epilogue
4977bab6
ZW
125#ifdef HPUX_ASM
126#undef TARGET_ASM_INTERNAL_LABEL
127#define TARGET_ASM_INTERNAL_LABEL m68k_hp320_internal_label
128#endif
ef1dbfb0 129
c590b625
RH
130#undef TARGET_ASM_OUTPUT_MI_THUNK
131#define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk
bdabc150
AS
132#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
133#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
c590b625 134
1bc7c5b6
ZW
135#undef TARGET_ASM_FILE_START_APP_OFF
136#define TARGET_ASM_FILE_START_APP_OFF true
137
3c50106f
RH
138#undef TARGET_RTX_COSTS
139#define TARGET_RTX_COSTS m68k_rtx_costs
140
f6897b10 141struct gcc_target targetm = TARGET_INITIALIZER;
672a6f42 142\f
ef1dbfb0
RK
143/* Sometimes certain combinations of command options do not make
144 sense on a particular target machine. You can define a macro
145 `OVERRIDE_OPTIONS' to take account of this. This macro, if
146 defined, is executed once just after all the command options have
147 been parsed.
148
149 Don't use this macro to turn on various extra optimizations for
150 `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
151
152void
153override_options ()
154{
155 int def_align;
400500c4 156 int i;
ef1dbfb0
RK
157
158 def_align = 1;
159
160 /* Validate -malign-loops= value, or provide default */
400500c4 161 m68k_align_loops = def_align;
ef1dbfb0
RK
162 if (m68k_align_loops_string)
163 {
400500c4
RK
164 i = atoi (m68k_align_loops_string);
165 if (i < 1 || i > MAX_CODE_ALIGN)
166 error ("-malign-loops=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
167 else
168 m68k_align_loops = i;
ef1dbfb0 169 }
ef1dbfb0
RK
170
171 /* Validate -malign-jumps= value, or provide default */
400500c4 172 m68k_align_jumps = def_align;
ef1dbfb0
RK
173 if (m68k_align_jumps_string)
174 {
400500c4
RK
175 i = atoi (m68k_align_jumps_string);
176 if (i < 1 || i > MAX_CODE_ALIGN)
177 error ("-malign-jumps=%d is not between 1 and %d", i, MAX_CODE_ALIGN);
178 else
179 m68k_align_jumps = i;
ef1dbfb0 180 }
ef1dbfb0
RK
181
182 /* Validate -malign-functions= value, or provide default */
400500c4 183 m68k_align_funcs = def_align;
ef1dbfb0
RK
184 if (m68k_align_funcs_string)
185 {
400500c4
RK
186 i = atoi (m68k_align_funcs_string);
187 if (i < 1 || i > MAX_CODE_ALIGN)
188 error ("-malign-functions=%d is not between 1 and %d",
189 i, MAX_CODE_ALIGN);
190 else
191 m68k_align_funcs = i;
ef1dbfb0 192 }
3dc85dfb 193
adf2ac37
RH
194 /* -fPIC uses 32-bit pc-relative displacements, which don't exist
195 until the 68020. */
196 if (! TARGET_68020 && flag_pic == 2)
197 error("-fPIC is not currently supported on the 68000 or 68010\n");
198
199 /* ??? A historic way of turning on pic, or is this intended to
200 be an embedded thing that doesn't have the same name binding
201 significance that it does on hosted ELF systems? */
202 if (TARGET_PCREL && flag_pic == 0)
203 flag_pic = 1;
204
205 /* Turn off function cse if we are doing PIC. We always want function call
206 to be done as `bsr foo@PLTPC', so it will force the assembler to create
207 the PLT entry for `foo'. Doing function cse will cause the address of
208 `foo' to be loaded into a register, which is exactly what we want to
209 avoid when we are doing PIC on svr4 m68k. */
210 if (flag_pic)
211 flag_no_function_cse = 1;
212
213 SUBTARGET_OVERRIDE_OPTIONS;
214
3dc85dfb
RH
215 /* Tell the compiler which flavor of XFmode we're using. */
216 real_format_for_mode[XFmode - QFmode] = &ieee_extended_motorola_format;
ef1dbfb0 217}
79e68feb 218\f
2cff4a6e
AS
219/* Return 1 if we need to save REGNO. */
220static int
221m68k_save_reg (regno)
222 unsigned int regno;
223{
224 if (flag_pic && current_function_uses_pic_offset_table
225 && regno == PIC_OFFSET_TABLE_REGNUM)
226 return 1;
227
228 if (current_function_calls_eh_return)
229 {
230 unsigned int i;
231 for (i = 0; ; i++)
232 {
233 unsigned int test = EH_RETURN_DATA_REGNO (i);
234 if (test == INVALID_REGNUM)
235 break;
236 if (test == regno)
237 return 1;
238 }
239 }
240
241 return (regs_ever_live[regno]
242 && !call_used_regs[regno]
243 && !fixed_regs[regno]
244 && !(regno == FRAME_POINTER_REGNUM && frame_pointer_needed));
245}
246
79e68feb
RS
247/* This function generates the assembly code for function entry.
248 STREAM is a stdio stream to output the code to.
249 SIZE is an int: how many units of temporary storage to allocate.
250 Refer to the array `regs_ever_live' to determine which registers
251 to save; `regs_ever_live[I]' is nonzero if register number I
252 is ever used in the function. This function is responsible for
253 knowing which registers should not be saved even if used. */
254
255
256/* Note that the order of the bit mask for fmovem is the opposite
257 of the order for movem! */
258
08c148a8 259#ifdef CRDS
79e68feb 260
08c148a8
NB
261static void
262m68k_output_function_prologue (stream, size)
263 FILE *stream;
264 HOST_WIDE_INT size;
265{
266 register int regno;
267 register int mask = 0;
08c148a8
NB
268 HOST_WIDE_INT fsize = ((size) + 3) & -4;
269
270 /* unos stack probe */
271 if (fsize > 30000)
272 {
273 fprintf (stream, "\tmovel sp,a0\n");
a69e127b
AS
274 fprintf (stream, "\taddl $-" HOST_WIDE_INT_PRINT_DEC ",a0\n",
275 2048 + fsize);
08c148a8
NB
276 fprintf (stream, "\ttstb (a0)\n");
277 }
278 else
a69e127b
AS
279 fprintf (stream, "\ttstb -" HOST_WIDE_INT_PRINT_DEC "(sp)\n",
280 2048 + fsize);
08c148a8
NB
281
282 if (frame_pointer_needed)
283 {
284 if (TARGET_68020 || fsize < 0x8000)
a69e127b 285 fprintf (stream, "\tlink a6,$" HOST_WIDE_INT_PRINT_DEC "\n", -fsize);
08c148a8 286 else
a69e127b
AS
287 fprintf (stream,
288 "\tlink a6,$0\n\tsubl $" HOST_WIDE_INT_PRINT_DEC ",sp\n",
289 fsize);
08c148a8
NB
290 }
291 else if (fsize)
292 {
293 /* Adding negative number is faster on the 68040. */
294 if (fsize + 4 < 0x8000)
a69e127b
AS
295 fprintf (stream, "\tadd.w $" HOST_WIDE_INT_PRINT_DEC ",sp\n",
296 - (fsize + 4));
08c148a8 297 else
a69e127b
AS
298 fprintf (stream, "\tadd.l $" HOST_WIDE_INT_PRINT_DEC ",sp\n",
299 - (fsize + 4));
08c148a8
NB
300 }
301
302 for (regno = 16; regno < 24; regno++)
2cff4a6e 303 if (m68k_save_reg (regno))
08c148a8
NB
304 mask |= 1 << (regno - 16);
305
306 if ((mask & 0xff) != 0)
307 fprintf (stream, "\tfmovem $0x%x,-(sp)\n", mask & 0xff);
308
309 mask = 0;
310 for (regno = 0; regno < 16; regno++)
2cff4a6e 311 if (m68k_save_reg (regno))
08c148a8 312 mask |= 1 << (15 - regno);
08c148a8
NB
313
314 if (exact_log2 (mask) >= 0)
315 fprintf (stream, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
316 else if (mask)
317 fprintf (stream, "\tmovem $0x%x,-(sp)\n", mask);
318}
319
cbf2f479 320#else /* !CRDS */
08c148a8
NB
321
322static void
323m68k_output_function_prologue (stream, size)
324 FILE *stream;
325 HOST_WIDE_INT size;
79e68feb
RS
326{
327 register int regno;
328 register int mask = 0;
329 int num_saved_regs = 0;
08c148a8
NB
330 HOST_WIDE_INT fsize = (size + 3) & -4;
331 HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
332 HOST_WIDE_INT cfa_store_offset = cfa_offset;
79e68feb 333
a157febd
GK
334 /* If the stack limit is a symbol, we can check it here,
335 before actually allocating the space. */
336 if (current_function_limit_stack
337 && GET_CODE (stack_limit_rtx) == SYMBOL_REF)
338 {
339#if defined (MOTOROLA)
1f85a612 340 asm_fprintf (stream, "\tcmp.l %I%s+%wd,%Rsp\n\ttrapcs\n",
a157febd
GK
341 XSTR (stack_limit_rtx, 0), fsize + 4);
342#else
1f85a612 343 asm_fprintf (stream, "\tcmpl %I%s+%wd,%Rsp\n\ttrapcs\n",
a157febd
GK
344 XSTR (stack_limit_rtx, 0), fsize + 4);
345#endif
346 }
79e68feb
RS
347
348 if (frame_pointer_needed)
349 {
2d0933a2 350 if (fsize == 0 && TARGET_68040)
e4e873f1
RK
351 {
352 /* on the 68040, pea + move is faster than link.w 0 */
353#ifdef MOTOROLA
761c70aa
KG
354 fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
355 reg_names[FRAME_POINTER_REGNUM],
356 reg_names[STACK_POINTER_REGNUM],
357 reg_names[FRAME_POINTER_REGNUM]);
e4e873f1 358#else
761c70aa
KG
359 fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
360 reg_names[FRAME_POINTER_REGNUM],
361 reg_names[STACK_POINTER_REGNUM],
362 reg_names[FRAME_POINTER_REGNUM]);
e4e873f1
RK
363#endif
364 }
365 else if (fsize < 0x8000)
79e68feb
RS
366 {
367#ifdef MOTOROLA
1f85a612 368 asm_fprintf (stream, "\tlink.w %s,%I%wd\n",
79e68feb
RS
369 reg_names[FRAME_POINTER_REGNUM], -fsize);
370#else
1f85a612 371 asm_fprintf (stream, "\tlink %s,%I%wd\n",
79e68feb
RS
372 reg_names[FRAME_POINTER_REGNUM], -fsize);
373#endif
374 }
375 else if (TARGET_68020)
376 {
377#ifdef MOTOROLA
1f85a612 378 asm_fprintf (stream, "\tlink.l %s,%I%wd\n",
79e68feb
RS
379 reg_names[FRAME_POINTER_REGNUM], -fsize);
380#else
1f85a612 381 asm_fprintf (stream, "\tlink %s,%I%wd\n",
79e68feb
RS
382 reg_names[FRAME_POINTER_REGNUM], -fsize);
383#endif
384 }
385 else
386 {
e4e873f1 387 /* Adding negative number is faster on the 68040. */
79e68feb 388#ifdef MOTOROLA
1f85a612 389 asm_fprintf (stream, "\tlink.w %s,%I0\n\tadd.l %I%wd,%Rsp\n",
79e68feb
RS
390 reg_names[FRAME_POINTER_REGNUM], -fsize);
391#else
1f85a612 392 asm_fprintf (stream, "\tlink %s,%I0\n\taddl %I%wd,%Rsp\n",
79e68feb
RS
393 reg_names[FRAME_POINTER_REGNUM], -fsize);
394#endif
395 }
078e983e
AS
396 if (dwarf2out_do_frame ())
397 {
f5c4bc60
BM
398 char *l;
399 l = (char *) dwarf2out_cfi_label ();
078e983e
AS
400 cfa_store_offset += 4;
401 cfa_offset = cfa_store_offset;
078e983e 402 dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
67935d3f 403 dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
078e983e
AS
404 cfa_store_offset += fsize;
405 }
79e68feb
RS
406 }
407 else if (fsize)
408 {
afaff477 409 if (fsize + 4 < 0x8000)
79e68feb 410 {
b0e982be 411#ifndef NO_ADDSUB_Q
7bc88d49 412 if (fsize + 4 <= 8)
afaff477 413 {
7bc88d49
RK
414 if (!TARGET_5200)
415 {
7a1929e1 416 /* asm_fprintf() cannot handle %. */
2d0933a2 417#ifdef MOTOROLA
1f85a612 418 asm_fprintf (stream, "\tsubq.w %I%wd,%Rsp\n", fsize + 4);
2d0933a2 419#else
1f85a612 420 asm_fprintf (stream, "\tsubqw %I%wd,%Rsp\n", fsize + 4);
2d0933a2 421#endif
7bc88d49
RK
422 }
423 else
424 {
7a1929e1 425 /* asm_fprintf() cannot handle %. */
7bc88d49 426#ifdef MOTOROLA
1f85a612 427 asm_fprintf (stream, "\tsubq.l %I%wd,%Rsp\n", fsize + 4);
7bc88d49 428#else
1f85a612 429 asm_fprintf (stream, "\tsubql %I%wd,%Rsp\n", fsize + 4);
7bc88d49
RK
430#endif
431 }
afaff477 432 }
7bc88d49
RK
433 else if (fsize + 4 <= 16 && TARGET_CPU32)
434 {
435 /* On the CPU32 it is faster to use two subqw instructions to
7a1929e1
KH
436 subtract a small integer (8 < N <= 16) to a register. */
437 /* asm_fprintf() cannot handle %. */
7bc88d49 438#ifdef MOTOROLA
a69e127b 439 asm_fprintf (stream,
1f85a612 440 "\tsubq.w %I8,%Rsp\n\tsubq.w %I%wd,%Rsp\n",
63429dd7 441 fsize + 4 - 8);
7bc88d49 442#else
1f85a612 443 asm_fprintf (stream, "\tsubqw %I8,%Rsp\n\tsubqw %I%wd,%Rsp\n",
63429dd7 444 fsize + 4 - 8);
7bc88d49
RK
445#endif
446 }
447 else
b0e982be 448#endif /* not NO_ADDSUB_Q */
7bc88d49 449 if (TARGET_68040)
afaff477 450 {
7bc88d49 451 /* Adding negative number is faster on the 68040. */
7a1929e1 452 /* asm_fprintf() cannot handle %. */
afaff477 453#ifdef MOTOROLA
1f85a612 454 asm_fprintf (stream, "\tadd.w %I%wd,%Rsp\n", - (fsize + 4));
afaff477 455#else
1f85a612 456 asm_fprintf (stream, "\taddw %I%wd,%Rsp\n", - (fsize + 4));
7bc88d49
RK
457#endif
458 }
459 else
460 {
7bc88d49 461#ifdef MOTOROLA
a69e127b 462 asm_fprintf (stream, "\tlea (%wd,%Rsp),%Rsp\n", - (fsize + 4));
7bc88d49 463#else
a69e127b 464 asm_fprintf (stream, "\tlea %Rsp@(%wd),%Rsp\n", - (fsize + 4));
afaff477
RK
465#endif
466 }
79e68feb
RS
467 }
468 else
469 {
7a1929e1 470 /* asm_fprintf() cannot handle %. */
2d0933a2 471#ifdef MOTOROLA
1f85a612 472 asm_fprintf (stream, "\tadd.l %I%wd,%Rsp\n", - (fsize + 4));
2d0933a2 473#else
1f85a612 474 asm_fprintf (stream, "\taddl %I%wd,%Rsp\n", - (fsize + 4));
2d0933a2 475#endif
79e68feb 476 }
078e983e
AS
477 if (dwarf2out_do_frame ())
478 {
79dbeefc 479 cfa_store_offset += fsize + 4;
078e983e
AS
480 cfa_offset = cfa_store_offset;
481 dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
482 }
79e68feb 483 }
f277471f 484 if (TARGET_68881)
79e68feb 485 {
f277471f 486 for (regno = 16; regno < 24; regno++)
2cff4a6e 487 if (m68k_save_reg (regno))
078e983e
AS
488 {
489 mask |= 1 << (regno - 16);
490 num_saved_regs++;
491 }
f277471f
RK
492 if ((mask & 0xff) != 0)
493 {
79e68feb 494#ifdef MOTOROLA
1f85a612 495 asm_fprintf (stream, "\tfmovm %I0x%x,-(%Rsp)\n", mask & 0xff);
79e68feb 496#else
1f85a612 497 asm_fprintf (stream, "\tfmovem %I0x%x,%Rsp@-\n", mask & 0xff);
79e68feb 498#endif
078e983e
AS
499 if (dwarf2out_do_frame ())
500 {
f5c4bc60 501 char *l = (char *) dwarf2out_cfi_label ();
078e983e 502 int n_regs;
a7cc7f29 503
078e983e
AS
504 cfa_store_offset += num_saved_regs * 12;
505 if (! frame_pointer_needed)
506 {
507 cfa_offset = cfa_store_offset;
508 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
509 }
510 for (regno = 16, n_regs = 0; regno < 24; regno++)
511 if (mask & (1 << (regno - 16)))
512 dwarf2out_reg_save (l, regno,
513 -cfa_store_offset + n_regs++ * 12);
514 }
f277471f
RK
515 }
516 mask = 0;
078e983e 517 num_saved_regs = 0;
79e68feb 518 }
79e68feb 519 for (regno = 0; regno < 16; regno++)
2cff4a6e 520 if (m68k_save_reg (regno))
79e68feb
RS
521 {
522 mask |= 1 << (15 - regno);
523 num_saved_regs++;
524 }
99df2465 525
a157febd
GK
526 /* If the stack limit is not a symbol, check it here.
527 This has the disadvantage that it may be too late... */
528 if (current_function_limit_stack)
529 {
530 if (REG_P (stack_limit_rtx))
531 {
532#if defined (MOTOROLA)
533 asm_fprintf (stream, "\tcmp.l %s,%Rsp\n\ttrapcs\n",
534 reg_names[REGNO (stack_limit_rtx)]);
535#else
536 asm_fprintf (stream, "\tcmpl %s,%Rsp\n\ttrapcs\n",
537 reg_names[REGNO (stack_limit_rtx)]);
538#endif
539 }
540 else if (GET_CODE (stack_limit_rtx) != SYMBOL_REF)
541 warning ("stack limit expression is not supported");
542 }
543
79e68feb
RS
544 if (num_saved_regs <= 2)
545 {
546 /* Store each separately in the same order moveml uses.
547 Using two movel instructions instead of a single moveml
548 is about 15% faster for the 68020 and 68030 at no expense
549 in code size */
550
551 int i;
552
7a1929e1 553 /* Undo the work from above. */
79e68feb
RS
554 for (i = 0; i< 16; i++)
555 if (mask & (1 << i))
078e983e
AS
556 {
557 asm_fprintf (stream,
79e68feb 558#ifdef MOTOROLA
078e983e 559 "\t%Omove.l %s,-(%Rsp)\n",
79e68feb 560#else
078e983e 561 "\tmovel %s,%Rsp@-\n",
79e68feb 562#endif
078e983e
AS
563 reg_names[15 - i]);
564 if (dwarf2out_do_frame ())
565 {
f5c4bc60 566 char *l = (char *) dwarf2out_cfi_label ();
a7cc7f29 567
078e983e
AS
568 cfa_store_offset += 4;
569 if (! frame_pointer_needed)
570 {
571 cfa_offset = cfa_store_offset;
572 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
573 }
574 dwarf2out_reg_save (l, 15 - i, -cfa_store_offset);
575 }
576 }
79e68feb
RS
577 }
578 else if (mask)
579 {
afaff477
RK
580 if (TARGET_5200)
581 {
582 /* The coldfire does not support the predecrement form of the
583 movml instruction, so we must adjust the stack pointer and
584 then use the plain address register indirect mode. We also
585 have to invert the register save mask to use the new mode.
586
587 FIXME: if num_saved_regs was calculated earlier, we could
588 combine the stack pointer adjustment with any adjustment
589 done when the initial stack frame is created. This would
590 save an instruction */
591
592 int newmask = 0;
593 int i;
594
595 for (i = 0; i < 16; i++)
596 if (mask & (1 << i))
597 newmask |= (1 << (15-i));
598
599#ifdef MOTOROLA
de649959 600 asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
1f85a612 601 asm_fprintf (stream, "\tmovm.l %I0x%x,(%Rsp)\n", newmask);
afaff477 602#else
de649959 603 asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
1f85a612 604 asm_fprintf (stream, "\tmoveml %I0x%x,%Rsp@\n", newmask);
afaff477
RK
605#endif
606 }
607 else
608 {
79e68feb 609#ifdef MOTOROLA
1f85a612 610 asm_fprintf (stream, "\tmovm.l %I0x%x,-(%Rsp)\n", mask);
79e68feb 611#else
1f85a612 612 asm_fprintf (stream, "\tmoveml %I0x%x,%Rsp@-\n", mask);
79e68feb 613#endif
afaff477 614 }
078e983e
AS
615 if (dwarf2out_do_frame ())
616 {
f5c4bc60 617 char *l = (char *) dwarf2out_cfi_label ();
078e983e 618 int n_regs;
a7cc7f29 619
078e983e
AS
620 cfa_store_offset += num_saved_regs * 4;
621 if (! frame_pointer_needed)
622 {
623 cfa_offset = cfa_store_offset;
624 dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
625 }
626 for (regno = 0, n_regs = 0; regno < 16; regno++)
627 if (mask & (1 << (15 - regno)))
628 dwarf2out_reg_save (l, regno,
629 -cfa_store_offset + n_regs++ * 4);
630 }
79e68feb
RS
631 }
632 if (flag_pic && current_function_uses_pic_offset_table)
633 {
634#ifdef MOTOROLA
66c432a7 635 asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
79e68feb
RS
636 reg_names[PIC_OFFSET_TABLE_REGNUM]);
637#else
1f85a612 638 asm_fprintf (stream, "\tmovel %I__GLOBAL_OFFSET_TABLE_, %s\n",
79e68feb
RS
639 reg_names[PIC_OFFSET_TABLE_REGNUM]);
640 asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
641 reg_names[PIC_OFFSET_TABLE_REGNUM],
642 reg_names[PIC_OFFSET_TABLE_REGNUM]);
643#endif
644 }
645}
08c148a8 646#endif /* !CRDS */
79e68feb
RS
647\f
648/* Return true if this function's epilogue can be output as RTL. */
649
650int
651use_return_insn ()
652{
653 int regno;
654
655 if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
656 return 0;
657
2cff4a6e
AS
658 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
659 if (m68k_save_reg (regno))
79e68feb 660 return 0;
125ed86f 661
79e68feb
RS
662 return 1;
663}
664
665/* This function generates the assembly code for function exit,
08c148a8 666 on machines that need it.
79e68feb
RS
667
668 The function epilogue should not depend on the current stack pointer!
669 It should use the frame pointer only, if there is a frame pointer.
670 This is mandatory because of alloca; we also take advantage of it to
671 omit stack adjustments before returning. */
672
08c148a8
NB
673#ifdef CRDS
674
675static void
676m68k_output_function_epilogue (stream, size)
79e68feb 677 FILE *stream;
08c148a8 678 HOST_WIDE_INT size;
79e68feb
RS
679{
680 register int regno;
681 register int mask, fmask;
682 register int nregs;
1a8965c4 683 HOST_WIDE_INT offset, foffset;
08c148a8
NB
684 HOST_WIDE_INT fsize = ((size) + 3) & -4;
685 int big = 0;
686
1a8965c4 687 nregs = 0; fmask = 0;
08c148a8 688 for (regno = 16; regno < 24; regno++)
2cff4a6e 689 if (m68k_save_reg (regno))
08c148a8
NB
690 {
691 nregs++;
692 fmask |= 1 << (23 - regno);
693 }
694
1a8965c4 695 foffset = nregs * 12;
08c148a8 696 nregs = 0; mask = 0;
08c148a8
NB
697
698 for (regno = 0; regno < 16; regno++)
2cff4a6e 699 if (m68k_save_reg (regno))
08c148a8
NB
700 {
701 nregs++;
702 mask |= 1 << regno;
703 }
704
705 offset = foffset + nregs * 4;
706 if (offset + fsize >= 0x8000
707 && frame_pointer_needed
1a8965c4 708 && (mask || fmask))
08c148a8 709 {
a69e127b 710 fprintf (stream, "\tmovel $" HOST_WIDE_INT_PRINT_DEC ",a0\n", -fsize);
08c148a8
NB
711 fsize = 0, big = 1;
712 }
713
714 if (exact_log2 (mask) >= 0)
715 {
716 if (big)
a69e127b 717 fprintf (stream, "\tmovel -" HOST_WIDE_INT_PRINT_DEC "(a6,a0.l),%s\n",
08c148a8
NB
718 offset + fsize, reg_names[exact_log2 (mask)]);
719 else if (! frame_pointer_needed)
720 fprintf (stream, "\tmovel (sp)+,%s\n",
721 reg_names[exact_log2 (mask)]);
722 else
a69e127b 723 fprintf (stream, "\tmovel -" HOST_WIDE_INT_PRINT_DEC "(a6),%s\n",
08c148a8
NB
724 offset + fsize, reg_names[exact_log2 (mask)]);
725 }
726 else if (mask)
727 {
728 if (big)
a69e127b
AS
729 fprintf (stream,
730 "\tmovem -" HOST_WIDE_INT_PRINT_DEC "(a6,a0.l),$0x%x\n",
08c148a8
NB
731 offset + fsize, mask);
732 else if (! frame_pointer_needed)
733 fprintf (stream, "\tmovem (sp)+,$0x%x\n", mask);
734 else
a69e127b 735 fprintf (stream, "\tmovem -" HOST_WIDE_INT_PRINT_DEC "(a6),$0x%x\n",
08c148a8
NB
736 offset + fsize, mask);
737 }
738
739 if (fmask)
740 {
741 if (big)
a69e127b
AS
742 fprintf (stream,
743 "\tfmovem -" HOST_WIDE_INT_PRINT_DEC "(a6,a0.l),$0x%x\n",
08c148a8
NB
744 foffset + fsize, fmask);
745 else if (! frame_pointer_needed)
746 fprintf (stream, "\tfmovem (sp)+,$0x%x\n", fmask);
747 else
a69e127b 748 fprintf (stream, "\tfmovem -" HOST_WIDE_INT_PRINT_DEC "(a6),$0x%x\n",
08c148a8
NB
749 foffset + fsize, fmask);
750 }
751
08c148a8
NB
752 if (frame_pointer_needed)
753 fprintf (stream, "\tunlk a6\n");
754 else if (fsize)
755 {
756 if (fsize + 4 < 0x8000)
a69e127b
AS
757 fprintf (stream, "\tadd.w $" HOST_WIDE_INT_PRINT_DEC ",sp\n",
758 fsize + 4);
08c148a8 759 else
a69e127b
AS
760 fprintf (stream, "\tadd.l $" HOST_WIDE_INT_PRINT_DEC ",sp\n",
761 fsize + 4);
08c148a8
NB
762 }
763
2cff4a6e
AS
764 if (current_function_calls_eh_return)
765 fprintf (stream, "\tadd.l a0,sp\n");
766
08c148a8
NB
767 if (current_function_pops_args)
768 fprintf (stream, "\trtd $%d\n", current_function_pops_args);
769 else
770 fprintf (stream, "\trts\n");
771}
772
cbf2f479 773#else /* !CRDS */
08c148a8
NB
774
775static void
776m68k_output_function_epilogue (stream, size)
777 FILE *stream;
778 HOST_WIDE_INT size;
779{
780 register int regno;
781 register int mask, fmask;
782 register int nregs;
1a8965c4 783 HOST_WIDE_INT offset, foffset;
08c148a8 784 HOST_WIDE_INT fsize = (size + 3) & -4;
79e68feb
RS
785 int big = 0;
786 rtx insn = get_last_insn ();
6910dd70 787 int restore_from_sp = 0;
79e68feb
RS
788
789 /* If the last insn was a BARRIER, we don't have to write any code. */
790 if (GET_CODE (insn) == NOTE)
791 insn = prev_nonnote_insn (insn);
792 if (insn && GET_CODE (insn) == BARRIER)
cffd0d74
RS
793 {
794 /* Output just a no-op so that debuggers don't get confused
795 about which function the pc is in at this address. */
761c70aa 796 fprintf (stream, "\tnop\n");
cffd0d74
RS
797 return;
798 }
79e68feb
RS
799
800#ifdef FUNCTION_EXTRA_EPILOGUE
801 FUNCTION_EXTRA_EPILOGUE (stream, size);
802#endif
1a8965c4 803 nregs = 0; fmask = 0;
f277471f
RK
804 if (TARGET_68881)
805 {
806 for (regno = 16; regno < 24; regno++)
2cff4a6e 807 if (m68k_save_reg (regno))
f277471f
RK
808 {
809 nregs++;
810 fmask |= 1 << (23 - regno);
811 }
812 }
1a8965c4 813 foffset = nregs * 12;
79e68feb 814 nregs = 0; mask = 0;
79e68feb 815 for (regno = 0; regno < 16; regno++)
2cff4a6e 816 if (m68k_save_reg (regno))
79e68feb
RS
817 {
818 nregs++;
819 mask |= 1 << regno;
820 }
821 offset = foffset + nregs * 4;
c67ddce5
RK
822 /* FIXME : leaf_function_p below is too strong.
823 What we really need to know there is if there could be pending
7a1929e1 824 stack adjustment needed at that point. */
6910dd70
RK
825 restore_from_sp = ! frame_pointer_needed
826 || (! current_function_calls_alloca && leaf_function_p ());
79e68feb 827 if (offset + fsize >= 0x8000
6910dd70 828 && ! restore_from_sp
1a8965c4 829 && (mask || fmask))
79e68feb
RS
830 {
831#ifdef MOTOROLA
1f85a612 832 asm_fprintf (stream, "\t%Omove.l %I%wd,%Ra1\n", -fsize);
79e68feb 833#else
1f85a612 834 asm_fprintf (stream, "\tmovel %I%wd,%Ra1\n", -fsize);
79e68feb
RS
835#endif
836 fsize = 0, big = 1;
837 }
afaff477 838 if (TARGET_5200 || nregs <= 2)
79e68feb
RS
839 {
840 /* Restore each separately in the same order moveml does.
841 Using two movel instructions instead of a single moveml
842 is about 15% faster for the 68020 and 68030 at no expense
7a1929e1 843 in code size. */
79e68feb
RS
844
845 int i;
846
7a1929e1 847 /* Undo the work from above. */
79e68feb
RS
848 for (i = 0; i< 16; i++)
849 if (mask & (1 << i))
850 {
851 if (big)
852 {
853#ifdef MOTOROLA
a69e127b 854 asm_fprintf (stream, "\t%Omove.l -%wd(%s,%Ra1.l),%s\n",
79e68feb
RS
855 offset + fsize,
856 reg_names[FRAME_POINTER_REGNUM],
857 reg_names[i]);
858#else
a69e127b 859 asm_fprintf (stream, "\tmovel %s@(-%wd,%Ra1:l),%s\n",
79e68feb
RS
860 reg_names[FRAME_POINTER_REGNUM],
861 offset + fsize, reg_names[i]);
862#endif
863 }
6910dd70 864 else if (restore_from_sp)
79e68feb
RS
865 {
866#ifdef MOTOROLA
64a184e9 867 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
79e68feb
RS
868 reg_names[i]);
869#else
870 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
871 reg_names[i]);
872#endif
873 }
874 else
875 {
876#ifdef MOTOROLA
a69e127b 877 asm_fprintf (stream, "\t%Omove.l -%wd(%s),%s\n",
79e68feb
RS
878 offset + fsize,
879 reg_names[FRAME_POINTER_REGNUM],
880 reg_names[i]);
881#else
a69e127b
AS
882 fprintf (stream,
883 "\tmovel %s@(-" HOST_WIDE_INT_PRINT_DEC "),%s\n",
761c70aa
KG
884 reg_names[FRAME_POINTER_REGNUM],
885 offset + fsize, reg_names[i]);
79e68feb
RS
886#endif
887 }
888 offset = offset - 4;
889 }
890 }
891 else if (mask)
892 {
893 if (big)
894 {
895#ifdef MOTOROLA
1f85a612 896 asm_fprintf (stream, "\tmovm.l -%wd(%s,%Ra1.l),%I0x%x\n",
79e68feb
RS
897 offset + fsize,
898 reg_names[FRAME_POINTER_REGNUM],
899 mask);
900#else
1f85a612 901 asm_fprintf (stream, "\tmoveml %s@(-%wd,%Ra1:l),%I0x%x\n",
79e68feb
RS
902 reg_names[FRAME_POINTER_REGNUM],
903 offset + fsize, mask);
904#endif
905 }
6910dd70 906 else if (restore_from_sp)
79e68feb
RS
907 {
908#ifdef MOTOROLA
1f85a612 909 asm_fprintf (stream, "\tmovm.l (%Rsp)+,%I0x%x\n", mask);
79e68feb 910#else
1f85a612 911 asm_fprintf (stream, "\tmoveml %Rsp@+,%I0x%x\n", mask);
79e68feb
RS
912#endif
913 }
914 else
915 {
916#ifdef MOTOROLA
1f85a612 917 asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
79e68feb
RS
918 offset + fsize,
919 reg_names[FRAME_POINTER_REGNUM],
920 mask);
921#else
1f85a612 922 asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
79e68feb
RS
923 reg_names[FRAME_POINTER_REGNUM],
924 offset + fsize, mask);
925#endif
926 }
927 }
928 if (fmask)
929 {
930 if (big)
931 {
932#ifdef MOTOROLA
1f85a612 933 asm_fprintf (stream, "\tfmovm -%wd(%s,%Ra1.l),%I0x%x\n",
79e68feb
RS
934 foffset + fsize,
935 reg_names[FRAME_POINTER_REGNUM],
936 fmask);
937#else
1f85a612 938 asm_fprintf (stream, "\tfmovem %s@(-%wd,%Ra1:l),%I0x%x\n",
79e68feb
RS
939 reg_names[FRAME_POINTER_REGNUM],
940 foffset + fsize, fmask);
941#endif
942 }
6910dd70 943 else if (restore_from_sp)
79e68feb
RS
944 {
945#ifdef MOTOROLA
1f85a612 946 asm_fprintf (stream, "\tfmovm (%Rsp)+,%I0x%x\n", fmask);
79e68feb 947#else
1f85a612 948 asm_fprintf (stream, "\tfmovem %Rsp@+,%I0x%x\n", fmask);
79e68feb
RS
949#endif
950 }
951 else
952 {
953#ifdef MOTOROLA
1f85a612 954 asm_fprintf (stream, "\tfmovm -%wd(%s),%I0x%x\n",
79e68feb
RS
955 foffset + fsize,
956 reg_names[FRAME_POINTER_REGNUM],
957 fmask);
958#else
1f85a612 959 asm_fprintf (stream, "\tfmovem %s@(-%wd),%I0x%x\n",
79e68feb
RS
960 reg_names[FRAME_POINTER_REGNUM],
961 foffset + fsize, fmask);
962#endif
963 }
964 }
79e68feb
RS
965 if (frame_pointer_needed)
966 fprintf (stream, "\tunlk %s\n",
967 reg_names[FRAME_POINTER_REGNUM]);
968 else if (fsize)
969 {
b0e982be 970#ifndef NO_ADDSUB_Q
7bc88d49 971 if (fsize + 4 <= 8)
79e68feb 972 {
7bc88d49
RK
973 if (!TARGET_5200)
974 {
2d0933a2 975#ifdef MOTOROLA
1f85a612 976 asm_fprintf (stream, "\taddq.w %I%wd,%Rsp\n", fsize + 4);
2d0933a2 977#else
1f85a612 978 asm_fprintf (stream, "\taddqw %I%wd,%Rsp\n", fsize + 4);
2d0933a2 979#endif
afaff477
RK
980 }
981 else
982 {
7bc88d49 983#ifdef MOTOROLA
1f85a612 984 asm_fprintf (stream, "\taddq.l %I%wd,%Rsp\n", fsize + 4);
7bc88d49 985#else
1f85a612 986 asm_fprintf (stream, "\taddql %I%wd,%Rsp\n", fsize + 4);
7bc88d49
RK
987#endif
988 }
989 }
990 else if (fsize + 4 <= 16 && TARGET_CPU32)
991 {
992 /* On the CPU32 it is faster to use two addqw instructions to
7a1929e1
KH
993 add a small integer (8 < N <= 16) to a register. */
994 /* asm_fprintf() cannot handle %. */
7bc88d49 995#ifdef MOTOROLA
1f85a612 996 asm_fprintf (stream, "\taddq.w %I8,%Rsp\n\taddq.w %I%wd,%Rsp\n",
63429dd7 997 fsize + 4 - 8);
7bc88d49 998#else
1f85a612 999 asm_fprintf (stream, "\taddqw %I8,%Rsp\n\taddqw %I%wd,%Rsp\n",
63429dd7 1000 fsize + 4 - 8);
7bc88d49
RK
1001#endif
1002 }
1003 else
b0e982be 1004#endif /* not NO_ADDSUB_Q */
7bc88d49
RK
1005 if (fsize + 4 < 0x8000)
1006 {
1007 if (TARGET_68040)
1008 {
7a1929e1 1009 /* asm_fprintf() cannot handle %. */
afaff477 1010#ifdef MOTOROLA
1f85a612 1011 asm_fprintf (stream, "\tadd.w %I%wd,%Rsp\n", fsize + 4);
afaff477 1012#else
1f85a612 1013 asm_fprintf (stream, "\taddw %I%wd,%Rsp\n", fsize + 4);
7bc88d49
RK
1014#endif
1015 }
1016 else
1017 {
7bc88d49 1018#ifdef MOTOROLA
a69e127b 1019 asm_fprintf (stream, "\tlea (%wd,%Rsp),%Rsp\n", fsize + 4);
7bc88d49 1020#else
a69e127b 1021 asm_fprintf (stream, "\tlea %Rsp@(%wd),%Rsp\n", fsize + 4);
afaff477
RK
1022#endif
1023 }
79e68feb
RS
1024 }
1025 else
1026 {
7a1929e1 1027 /* asm_fprintf() cannot handle %. */
2d0933a2 1028#ifdef MOTOROLA
1f85a612 1029 asm_fprintf (stream, "\tadd.l %I%wd,%Rsp\n", fsize + 4);
2d0933a2 1030#else
1f85a612 1031 asm_fprintf (stream, "\taddl %I%wd,%Rsp\n", fsize + 4);
2d0933a2 1032#endif
79e68feb
RS
1033 }
1034 }
2cff4a6e
AS
1035 if (current_function_calls_eh_return)
1036 {
1037#ifdef MOTOROLA
1038 asm_fprintf (stream, "\tadd.l %Ra0,%Rsp\n");
1039#else
1040 asm_fprintf (stream, "\taddl %Ra0,%Rsp\n");
1041#endif
1042 }
79e68feb 1043 if (current_function_pops_args)
1f85a612 1044 asm_fprintf (stream, "\trtd %I%d\n", current_function_pops_args);
79e68feb
RS
1045 else
1046 fprintf (stream, "\trts\n");
1047}
08c148a8 1048#endif /* !CRDS */
79e68feb
RS
1049\f
1050/* Similar to general_operand, but exclude stack_pointer_rtx. */
1051
1052int
1053not_sp_operand (op, mode)
1054 register rtx op;
1055 enum machine_mode mode;
1056{
8406d023 1057 return op != stack_pointer_rtx && nonimmediate_operand (op, mode);
79e68feb
RS
1058}
1059
64a184e9
RS
1060/* Return TRUE if X is a valid comparison operator for the dbcc
1061 instruction.
1062
1063 Note it rejects floating point comparison operators.
1064 (In the future we could use Fdbcc).
1065
1066 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
1067
1068int
1069valid_dbcc_comparison_p (x, mode)
1070 rtx x;
f5220a5d 1071 enum machine_mode mode ATTRIBUTE_UNUSED;
64a184e9 1072{
64a184e9
RS
1073 switch (GET_CODE (x))
1074 {
64a184e9
RS
1075 case EQ: case NE: case GTU: case LTU:
1076 case GEU: case LEU:
1077 return 1;
1078
1079 /* Reject some when CC_NO_OVERFLOW is set. This may be over
1080 conservative */
1081 case GT: case LT: case GE: case LE:
1082 return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
1083 default:
1084 return 0;
1085 }
1086}
1087
a0ab749a 1088/* Return nonzero if flags are currently in the 68881 flag register. */
6a0f85e3
TG
1089int
1090flags_in_68881 ()
1091{
1092 /* We could add support for these in the future */
1093 return cc_status.flags & CC_IN_68881;
1094}
1095
64a184e9
RS
1096/* Output a dbCC; jCC sequence. Note we do not handle the
1097 floating point version of this sequence (Fdbcc). We also
1098 do not handle alternative conditions when CC_NO_OVERFLOW is
6a0f85e3
TG
1099 set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
1100 kick those out before we get here. */
64a184e9 1101
1d8eaa6b 1102void
64a184e9
RS
1103output_dbcc_and_branch (operands)
1104 rtx *operands;
1105{
64a184e9
RS
1106 switch (GET_CODE (operands[3]))
1107 {
1108 case EQ:
1109#ifdef MOTOROLA
1110 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
1111#else
1112 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
1113#endif
1114 break;
1115
1116 case NE:
1117#ifdef MOTOROLA
1118 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
1119#else
1120 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
1121#endif
1122 break;
1123
1124 case GT:
1125#ifdef MOTOROLA
1126 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
1127#else
1128 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
1129#endif
1130 break;
1131
1132 case GTU:
1133#ifdef MOTOROLA
1134 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
1135#else
1136 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
1137#endif
1138 break;
1139
1140 case LT:
1141#ifdef MOTOROLA
1142 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
1143#else
1144 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
1145#endif
1146 break;
1147
1148 case LTU:
1149#ifdef MOTOROLA
1150 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
1151#else
1152 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
1153#endif
1154 break;
1155
1156 case GE:
1157#ifdef MOTOROLA
1158 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
1159#else
1160 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
1161#endif
1162 break;
1163
1164 case GEU:
1165#ifdef MOTOROLA
1166 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
1167#else
1168 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
1169#endif
1170 break;
1171
1172 case LE:
1173#ifdef MOTOROLA
1174 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
1175#else
1176 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
1177#endif
1178 break;
1179
1180 case LEU:
1181#ifdef MOTOROLA
1182 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
1183#else
1184 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
1185#endif
1186 break;
1187
1188 default:
1189 abort ();
1190 }
1191
1192 /* If the decrement is to be done in SImode, then we have
7a1929e1 1193 to compensate for the fact that dbcc decrements in HImode. */
64a184e9
RS
1194 switch (GET_MODE (operands[0]))
1195 {
1196 case SImode:
1197#ifdef MOTOROLA
1198 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
1199#else
1200 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
1201#endif
1202 break;
1203
1204 case HImode:
1205 break;
1206
1207 default:
1208 abort ();
1209 }
1210}
1211
5505f548 1212const char *
c59c3b1c
RK
1213output_scc_di(op, operand1, operand2, dest)
1214 rtx op;
1215 rtx operand1;
1216 rtx operand2;
1217 rtx dest;
1218{
1219 rtx loperands[7];
d9832fd2 1220 enum rtx_code op_code = GET_CODE (op);
c59c3b1c 1221
f710504c 1222 /* This does not produce a useful cc. */
906a2d3c
RK
1223 CC_STATUS_INIT;
1224
d9832fd2
RK
1225 /* The m68k cmp.l instruction requires operand1 to be a reg as used
1226 below. Swap the operands and change the op if these requirements
1227 are not fulfilled. */
1228 if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
1229 {
1230 rtx tmp = operand1;
1231
1232 operand1 = operand2;
1233 operand2 = tmp;
1234 op_code = swap_condition (op_code);
1235 }
c59c3b1c
RK
1236 loperands[0] = operand1;
1237 if (GET_CODE (operand1) == REG)
1d8eaa6b 1238 loperands[1] = gen_rtx_REG (SImode, REGNO (operand1) + 1);
c59c3b1c 1239 else
b72f00af 1240 loperands[1] = adjust_address (operand1, SImode, 4);
c59c3b1c
RK
1241 if (operand2 != const0_rtx)
1242 {
1243 loperands[2] = operand2;
1244 if (GET_CODE (operand2) == REG)
1d8eaa6b 1245 loperands[3] = gen_rtx_REG (SImode, REGNO (operand2) + 1);
c59c3b1c 1246 else
b72f00af 1247 loperands[3] = adjust_address (operand2, SImode, 4);
c59c3b1c
RK
1248 }
1249 loperands[4] = gen_label_rtx();
1250 if (operand2 != const0_rtx)
4a8c52e0 1251 {
c59c3b1c 1252#ifdef MOTOROLA
f2121711 1253#ifdef SGS_CMP_ORDER
4a8c52e0 1254 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
c59c3b1c 1255#else
4a8c52e0 1256 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
f2121711
RK
1257#endif
1258#else
1259#ifdef SGS_CMP_ORDER
4a8c52e0 1260 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
f2121711 1261#else
4a8c52e0 1262 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
f2121711 1263#endif
c59c3b1c 1264#endif
4a8c52e0 1265 }
392582fa 1266 else
4a8c52e0
AS
1267 {
1268 if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[0]))
1269 output_asm_insn ("tst%.l %0", loperands);
1270 else
1271 {
392582fa 1272#ifdef SGS_CMP_ORDER
4a8c52e0 1273 output_asm_insn ("cmp%.w %0,%#0", loperands);
392582fa 1274#else
4a8c52e0 1275 output_asm_insn ("cmp%.w %#0,%0", loperands);
392582fa 1276#endif
4a8c52e0
AS
1277 }
1278
1279#ifdef MOTOROLA
1280 output_asm_insn ("jbne %l4", loperands);
392582fa 1281#else
4a8c52e0
AS
1282 output_asm_insn ("jne %l4", loperands);
1283#endif
1284
1285 if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (loperands[1]))
1286 output_asm_insn ("tst%.l %1", loperands);
1287 else
1288 {
392582fa 1289#ifdef SGS_CMP_ORDER
4a8c52e0 1290 output_asm_insn ("cmp%.w %1,%#0", loperands);
392582fa 1291#else
4a8c52e0 1292 output_asm_insn ("cmp%.w %#0,%1", loperands);
c59c3b1c 1293#endif
4a8c52e0
AS
1294 }
1295 }
1296
c59c3b1c
RK
1297 loperands[5] = dest;
1298
d9832fd2 1299 switch (op_code)
c59c3b1c
RK
1300 {
1301 case EQ:
4977bab6 1302 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1303 CODE_LABEL_NUMBER (loperands[4]));
1304 output_asm_insn ("seq %5", loperands);
1305 break;
1306
1307 case NE:
4977bab6 1308 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1309 CODE_LABEL_NUMBER (loperands[4]));
1310 output_asm_insn ("sne %5", loperands);
1311 break;
1312
1313 case GT:
1314 loperands[6] = gen_label_rtx();
1315#ifdef MOTOROLA
1316 output_asm_insn ("shi %5\n\tjbra %l6", loperands);
1317#else
1318 output_asm_insn ("shi %5\n\tjra %l6", loperands);
1319#endif
4977bab6 1320 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1321 CODE_LABEL_NUMBER (loperands[4]));
1322 output_asm_insn ("sgt %5", loperands);
4977bab6 1323 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1324 CODE_LABEL_NUMBER (loperands[6]));
1325 break;
1326
1327 case GTU:
4977bab6 1328 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1329 CODE_LABEL_NUMBER (loperands[4]));
1330 output_asm_insn ("shi %5", loperands);
1331 break;
1332
1333 case LT:
1334 loperands[6] = gen_label_rtx();
1335#ifdef MOTOROLA
1336 output_asm_insn ("scs %5\n\tjbra %l6", loperands);
1337#else
1338 output_asm_insn ("scs %5\n\tjra %l6", loperands);
1339#endif
4977bab6 1340 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1341 CODE_LABEL_NUMBER (loperands[4]));
1342 output_asm_insn ("slt %5", loperands);
4977bab6 1343 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1344 CODE_LABEL_NUMBER (loperands[6]));
1345 break;
1346
1347 case LTU:
4977bab6 1348 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1349 CODE_LABEL_NUMBER (loperands[4]));
1350 output_asm_insn ("scs %5", loperands);
1351 break;
1352
1353 case GE:
1354 loperands[6] = gen_label_rtx();
1355#ifdef MOTOROLA
1356 output_asm_insn ("scc %5\n\tjbra %l6", loperands);
1357#else
1358 output_asm_insn ("scc %5\n\tjra %l6", loperands);
1359#endif
4977bab6 1360 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1361 CODE_LABEL_NUMBER (loperands[4]));
1362 output_asm_insn ("sge %5", loperands);
4977bab6 1363 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1364 CODE_LABEL_NUMBER (loperands[6]));
1365 break;
1366
1367 case GEU:
4977bab6 1368 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1369 CODE_LABEL_NUMBER (loperands[4]));
1370 output_asm_insn ("scc %5", loperands);
1371 break;
1372
1373 case LE:
1374 loperands[6] = gen_label_rtx();
1375#ifdef MOTOROLA
1376 output_asm_insn ("sls %5\n\tjbra %l6", loperands);
1377#else
1378 output_asm_insn ("sls %5\n\tjra %l6", loperands);
1379#endif
4977bab6 1380 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1381 CODE_LABEL_NUMBER (loperands[4]));
1382 output_asm_insn ("sle %5", loperands);
4977bab6 1383 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1384 CODE_LABEL_NUMBER (loperands[6]));
1385 break;
1386
1387 case LEU:
4977bab6 1388 (*targetm.asm_out.internal_label) (asm_out_file, "L",
c59c3b1c
RK
1389 CODE_LABEL_NUMBER (loperands[4]));
1390 output_asm_insn ("sls %5", loperands);
1391 break;
1392
1393 default:
1394 abort ();
1395 }
1396 return "";
1397}
1398
5505f548 1399const char *
79e68feb
RS
1400output_btst (operands, countop, dataop, insn, signpos)
1401 rtx *operands;
1402 rtx countop, dataop;
1403 rtx insn;
1404 int signpos;
1405{
1406 operands[0] = countop;
1407 operands[1] = dataop;
1408
1409 if (GET_CODE (countop) == CONST_INT)
1410 {
1411 register int count = INTVAL (countop);
1412 /* If COUNT is bigger than size of storage unit in use,
1413 advance to the containing unit of same size. */
1414 if (count > signpos)
1415 {
1416 int offset = (count & ~signpos) / 8;
1417 count = count & signpos;
b72f00af 1418 operands[1] = dataop = adjust_address (dataop, QImode, offset);
79e68feb
RS
1419 }
1420 if (count == signpos)
1421 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
1422 else
1423 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
1424
1425 /* These three statements used to use next_insns_test_no...
1426 but it appears that this should do the same job. */
1427 if (count == 31
1428 && next_insn_tests_no_inequality (insn))
1429 return "tst%.l %1";
1430 if (count == 15
1431 && next_insn_tests_no_inequality (insn))
1432 return "tst%.w %1";
1433 if (count == 7
1434 && next_insn_tests_no_inequality (insn))
1435 return "tst%.b %1";
1436
1437 cc_status.flags = CC_NOT_NEGATIVE;
1438 }
1439 return "btst %0,%1";
1440}
1441\f
1442/* Returns 1 if OP is either a symbol reference or a sum of a symbol
1443 reference and a constant. */
1444
1445int
1446symbolic_operand (op, mode)
1447 register rtx op;
f5220a5d 1448 enum machine_mode mode ATTRIBUTE_UNUSED;
79e68feb
RS
1449{
1450 switch (GET_CODE (op))
1451 {
1452 case SYMBOL_REF:
1453 case LABEL_REF:
1454 return 1;
1455
1456 case CONST:
1457 op = XEXP (op, 0);
1458 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1459 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1460 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1461
1462#if 0 /* Deleted, with corresponding change in m68k.h,
1463 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
1464 case CONST_DOUBLE:
1465 return GET_MODE (op) == mode;
1466#endif
1467
1468 default:
1469 return 0;
1470 }
1471}
16f323be 1472\f
7a1929e1 1473/* Check for sign_extend or zero_extend. Used for bit-count operands. */
16f323be
RK
1474
1475int
1476extend_operator(x, mode)
1477 rtx x;
1478 enum machine_mode mode;
1479{
c59c3b1c 1480 if (mode != VOIDmode && GET_MODE(x) != mode)
16f323be
RK
1481 return 0;
1482 switch (GET_CODE(x))
1483 {
1484 case SIGN_EXTEND :
1485 case ZERO_EXTEND :
16f323be
RK
1486 return 1;
1487 default :
1488 return 0;
1489 }
1490}
79e68feb
RS
1491
1492\f
1493/* Legitimize PIC addresses. If the address is already
1494 position-independent, we return ORIG. Newly generated
1495 position-independent addresses go to REG. If we need more
1496 than one register, we lose.
1497
1498 An address is legitimized by making an indirect reference
1499 through the Global Offset Table with the name of the symbol
1500 used as an offset.
1501
1502 The assembler and linker are responsible for placing the
1503 address of the symbol in the GOT. The function prologue
1504 is responsible for initializing a5 to the starting address
1505 of the GOT.
1506
1507 The assembler is also responsible for translating a symbol name
1508 into a constant displacement from the start of the GOT.
1509
1510 A quick example may make things a little clearer:
1511
1512 When not generating PIC code to store the value 12345 into _foo
1513 we would generate the following code:
1514
1515 movel #12345, _foo
1516
1517 When generating PIC two transformations are made. First, the compiler
1518 loads the address of foo into a register. So the first transformation makes:
1519
1520 lea _foo, a0
1521 movel #12345, a0@
1522
1523 The code in movsi will intercept the lea instruction and call this
1524 routine which will transform the instructions into:
1525
1526 movel a5@(_foo:w), a0
1527 movel #12345, a0@
1528
1529
1530 That (in a nutshell) is how *all* symbol and label references are
1531 handled. */
1532
1533rtx
1534legitimize_pic_address (orig, mode, reg)
1535 rtx orig, reg;
f5220a5d 1536 enum machine_mode mode ATTRIBUTE_UNUSED;
79e68feb
RS
1537{
1538 rtx pic_ref = orig;
1539
1540 /* First handle a simple SYMBOL_REF or LABEL_REF */
1541 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1542 {
1543 if (reg == 0)
1544 abort ();
1545
1d8eaa6b
AS
1546 pic_ref = gen_rtx_MEM (Pmode,
1547 gen_rtx_PLUS (Pmode,
1548 pic_offset_table_rtx, orig));
79e68feb
RS
1549 current_function_uses_pic_offset_table = 1;
1550 RTX_UNCHANGING_P (pic_ref) = 1;
1551 emit_move_insn (reg, pic_ref);
1552 return reg;
1553 }
1554 else if (GET_CODE (orig) == CONST)
1555 {
1d8eaa6b 1556 rtx base;
79e68feb
RS
1557
1558 /* Make sure this is CONST has not already been legitimized */
1559 if (GET_CODE (XEXP (orig, 0)) == PLUS
1560 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1561 return orig;
1562
1563 if (reg == 0)
1564 abort ();
1565
1566 /* legitimize both operands of the PLUS */
1567 if (GET_CODE (XEXP (orig, 0)) == PLUS)
1568 {
1569 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
1570 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1571 base == reg ? 0 : reg);
1572 }
1573 else abort ();
1574
1575 if (GET_CODE (orig) == CONST_INT)
ed8908e7 1576 return plus_constant (base, INTVAL (orig));
1d8eaa6b 1577 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
79e68feb
RS
1578 /* Likewise, should we set special REG_NOTEs here? */
1579 }
1580 return pic_ref;
1581}
1582
1583\f
0ce6f9fb
RK
1584typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
1585
5505f548
KG
1586static CONST_METHOD const_method PARAMS ((rtx));
1587
6910dd70 1588#define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
0ce6f9fb 1589
5505f548 1590static CONST_METHOD
0ce6f9fb
RK
1591const_method (constant)
1592 rtx constant;
1593{
1594 int i;
1595 unsigned u;
1596
1597 i = INTVAL (constant);
6910dd70 1598 if (USE_MOVQ (i))
0ce6f9fb 1599 return MOVQ;
24092242 1600
7a1929e1 1601 /* The Coldfire doesn't have byte or word operations. */
24092242
RK
1602 /* FIXME: This may not be useful for the m68060 either */
1603 if (!TARGET_5200)
1604 {
1605 /* if -256 < N < 256 but N is not in range for a moveq
7a1929e1 1606 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
24092242
RK
1607 if (USE_MOVQ (i ^ 0xff))
1608 return NOTB;
1609 /* Likewise, try with not.w */
1610 if (USE_MOVQ (i ^ 0xffff))
1611 return NOTW;
1612 /* This is the only value where neg.w is useful */
1613 if (i == -65408)
1614 return NEGW;
1615 /* Try also with swap */
1616 u = i;
1617 if (USE_MOVQ ((u >> 16) | (u << 16)))
1618 return SWAP;
1619 }
0ce6f9fb
RK
1620 /* Otherwise, use move.l */
1621 return MOVL;
1622}
1623
3c50106f 1624static int
0ce6f9fb
RK
1625const_int_cost (constant)
1626 rtx constant;
1627{
1628 switch (const_method (constant))
1629 {
1630 case MOVQ :
1631 /* Constants between -128 and 127 are cheap due to moveq */
1632 return 0;
1633 case NOTB :
1634 case NOTW :
1635 case NEGW :
1636 case SWAP :
1637 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
1638 return 1;
1639 case MOVL :
1640 return 2;
1641 default :
1642 abort ();
1643 }
1644}
1645
3c50106f
RH
1646static bool
1647m68k_rtx_costs (x, code, outer_code, total)
1648 rtx x;
1649 int code, outer_code;
1650 int *total;
1651{
1652 switch (code)
1653 {
1654 case CONST_INT:
1655 /* Constant zero is super cheap due to clr instruction. */
1656 if (x == const0_rtx)
1657 *total = 0;
1658 else
1659 *total = const_int_cost (x);
1660 return true;
1661
1662 case CONST:
1663 case LABEL_REF:
1664 case SYMBOL_REF:
1665 *total = 3;
1666 return true;
1667
1668 case CONST_DOUBLE:
1669 /* Make 0.0 cheaper than other floating constants to
1670 encourage creating tstsf and tstdf insns. */
1671 if (outer_code == COMPARE
1672 && (x == CONST0_RTX (SFmode) || x == CONST0_RTX (DFmode)))
1673 *total = 4;
1674 else
1675 *total = 5;
1676 return true;
1677
1678 /* These are vaguely right for a 68020. */
1679 /* The costs for long multiply have been adjusted to work properly
1680 in synth_mult on the 68020, relative to an average of the time
1681 for add and the time for shift, taking away a little more because
1682 sometimes move insns are needed. */
1683 /* div?.w is relatively cheaper on 68000 counted in COSTS_N_INSNS terms. */
1684#define MULL_COST (TARGET_68060 ? 2 : TARGET_68040 ? 5 : 13)
1685#define MULW_COST (TARGET_68060 ? 2 : TARGET_68040 ? 3 : TARGET_68020 ? 8 : 5)
1686#define DIVW_COST (TARGET_68020 ? 27 : 12)
1687
1688 case PLUS:
1689 /* An lea costs about three times as much as a simple add. */
1690 if (GET_MODE (x) == SImode
1691 && GET_CODE (XEXP (x, 1)) == REG
1692 && GET_CODE (XEXP (x, 0)) == MULT
1693 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
1694 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
1695 && (INTVAL (XEXP (XEXP (x, 0), 1)) == 2
1696 || INTVAL (XEXP (XEXP (x, 0), 1)) == 4
1697 || INTVAL (XEXP (XEXP (x, 0), 1)) == 8))
1698 *total = COSTS_N_INSNS (3); /* lea an@(dx:l:i),am */
1699 return false;
1700
1701 case ASHIFT:
1702 case ASHIFTRT:
1703 case LSHIFTRT:
1704 if (TARGET_68060)
1705 {
1706 *total = COSTS_N_INSNS(1);
1707 return true;
1708 }
1709 if (! TARGET_68020)
1710 {
1711 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1712 {
1713 if (INTVAL (XEXP (x, 1)) < 16)
1714 *total = COSTS_N_INSNS (2) + INTVAL (XEXP (x, 1)) / 2;
1715 else
1716 /* We're using clrw + swap for these cases. */
1717 *total = COSTS_N_INSNS (4) + (INTVAL (XEXP (x, 1)) - 16) / 2;
1718 }
1719 else
1720 *total = COSTS_N_INSNS (10); /* worst case */
1721 return true;
1722 }
1723 /* A shift by a big integer takes an extra instruction. */
1724 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1725 && (INTVAL (XEXP (x, 1)) == 16))
1726 {
1727 *total = COSTS_N_INSNS (2); /* clrw;swap */
1728 return true;
1729 }
1730 if (GET_CODE (XEXP (x, 1)) == CONST_INT
1731 && !(INTVAL (XEXP (x, 1)) > 0
1732 && INTVAL (XEXP (x, 1)) <= 8))
1733 {
1734 *total = COSTS_N_INSNS (3); /* lsr #i,dn */
1735 return true;
1736 }
1737 return false;
1738
1739 case MULT:
1740 if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
1741 || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
1742 && GET_MODE (x) == SImode)
1743 *total = COSTS_N_INSNS (MULW_COST);
1744 else if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
1745 *total = COSTS_N_INSNS (MULW_COST);
1746 else
1747 *total = COSTS_N_INSNS (MULL_COST);
1748 return true;
1749
1750 case DIV:
1751 case UDIV:
1752 case MOD:
1753 case UMOD:
1754 if (GET_MODE (x) == QImode || GET_MODE (x) == HImode)
1755 *total = COSTS_N_INSNS (DIVW_COST); /* div.w */
1756 else
1757 *total = COSTS_N_INSNS (43); /* div.l */
1758 return true;
1759
1760 default:
1761 return false;
1762 }
1763}
1764
5505f548 1765const char *
0ce6f9fb
RK
1766output_move_const_into_data_reg (operands)
1767 rtx *operands;
1768{
1769 int i;
1770
1771 i = INTVAL (operands[1]);
1772 switch (const_method (operands[1]))
1773 {
1774 case MOVQ :
1775#if defined (MOTOROLA) && !defined (CRDS)
1776 return "moveq%.l %1,%0";
1777#else
1778 return "moveq %1,%0";
1779#endif
1780 case NOTB :
1d8eaa6b 1781 operands[1] = GEN_INT (i ^ 0xff);
0ce6f9fb
RK
1782#if defined (MOTOROLA) && !defined (CRDS)
1783 return "moveq%.l %1,%0\n\tnot%.b %0";
1784#else
1785 return "moveq %1,%0\n\tnot%.b %0";
1786#endif
1787 case NOTW :
1d8eaa6b 1788 operands[1] = GEN_INT (i ^ 0xffff);
0ce6f9fb
RK
1789#if defined (MOTOROLA) && !defined (CRDS)
1790 return "moveq%.l %1,%0\n\tnot%.w %0";
1791#else
1792 return "moveq %1,%0\n\tnot%.w %0";
1793#endif
1794 case NEGW :
1795#if defined (MOTOROLA) && !defined (CRDS)
1796 return "moveq%.l %#-128,%0\n\tneg%.w %0";
1797#else
1798 return "moveq %#-128,%0\n\tneg%.w %0";
1799#endif
1800 case SWAP :
1801 {
1802 unsigned u = i;
1803
1d8eaa6b 1804 operands[1] = GEN_INT ((u << 16) | (u >> 16));
0ce6f9fb
RK
1805#if defined (MOTOROLA) && !defined (CRDS)
1806 return "moveq%.l %1,%0\n\tswap %0";
1807#else
1808 return "moveq %1,%0\n\tswap %0";
1809#endif
1810 }
1811 case MOVL :
1812 return "move%.l %1,%0";
1813 default :
1814 abort ();
1815 }
1816}
1817
5505f548 1818const char *
02ed0c07
RK
1819output_move_simode_const (operands)
1820 rtx *operands;
1821{
1822 if (operands[1] == const0_rtx
1823 && (DATA_REG_P (operands[0])
1824 || GET_CODE (operands[0]) == MEM)
1825 /* clr insns on 68000 read before writing.
c67ddce5 1826 This isn't so on the 68010, but we have no TARGET_68010. */
0cb7cfed 1827 && ((TARGET_68020 || TARGET_5200)
02ed0c07
RK
1828 || !(GET_CODE (operands[0]) == MEM
1829 && MEM_VOLATILE_P (operands[0]))))
1830 return "clr%.l %0";
38198304
AS
1831 else if (operands[1] == const0_rtx
1832 && ADDRESS_REG_P (operands[0]))
1833 return "sub%.l %0,%0";
02ed0c07
RK
1834 else if (DATA_REG_P (operands[0]))
1835 return output_move_const_into_data_reg (operands);
1836 else if (ADDRESS_REG_P (operands[0])
1837 && INTVAL (operands[1]) < 0x8000
1838 && INTVAL (operands[1]) >= -0x8000)
1839 return "move%.w %1,%0";
1840 else if (GET_CODE (operands[0]) == MEM
1841 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1842 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1843 && INTVAL (operands[1]) < 0x8000
1844 && INTVAL (operands[1]) >= -0x8000)
1845 return "pea %a1";
1846 return "move%.l %1,%0";
1847}
1848
5505f548 1849const char *
f4e80198
RK
1850output_move_simode (operands)
1851 rtx *operands;
1852{
1853 if (GET_CODE (operands[1]) == CONST_INT)
1854 return output_move_simode_const (operands);
1855 else if ((GET_CODE (operands[1]) == SYMBOL_REF
1856 || GET_CODE (operands[1]) == CONST)
1857 && push_operand (operands[0], SImode))
1858 return "pea %a1";
1859 else if ((GET_CODE (operands[1]) == SYMBOL_REF
1860 || GET_CODE (operands[1]) == CONST)
1861 && ADDRESS_REG_P (operands[0]))
1862 return "lea %a1,%0";
1863 return "move%.l %1,%0";
1864}
1865
5505f548 1866const char *
f4e80198
RK
1867output_move_himode (operands)
1868 rtx *operands;
1869{
1870 if (GET_CODE (operands[1]) == CONST_INT)
1871 {
1872 if (operands[1] == const0_rtx
1873 && (DATA_REG_P (operands[0])
1874 || GET_CODE (operands[0]) == MEM)
1875 /* clr insns on 68000 read before writing.
1876 This isn't so on the 68010, but we have no TARGET_68010. */
1877 && ((TARGET_68020 || TARGET_5200)
1878 || !(GET_CODE (operands[0]) == MEM
1879 && MEM_VOLATILE_P (operands[0]))))
1880 return "clr%.w %0";
38198304
AS
1881 else if (operands[1] == const0_rtx
1882 && ADDRESS_REG_P (operands[0]))
1883 return "sub%.l %0,%0";
f4e80198
RK
1884 else if (DATA_REG_P (operands[0])
1885 && INTVAL (operands[1]) < 128
1886 && INTVAL (operands[1]) >= -128)
1887 {
1888#if defined(MOTOROLA) && !defined(CRDS)
1889 return "moveq%.l %1,%0";
1890#else
1891 return "moveq %1,%0";
1892#endif
1893 }
1894 else if (INTVAL (operands[1]) < 0x8000
1895 && INTVAL (operands[1]) >= -0x8000)
1896 return "move%.w %1,%0";
1897 }
1898 else if (CONSTANT_P (operands[1]))
1899 return "move%.l %1,%0";
1900#ifndef SGS_NO_LI
1901 /* Recognize the insn before a tablejump, one that refers
1902 to a table of offsets. Such an insn will need to refer
1903 to a label on the insn. So output one. Use the label-number
1904 of the table of offsets to generate this label. This code,
1905 and similar code below, assumes that there will be at most one
1906 reference to each table. */
1907 if (GET_CODE (operands[1]) == MEM
1908 && GET_CODE (XEXP (operands[1], 0)) == PLUS
1909 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
1910 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
1911 {
1912 rtx labelref = XEXP (XEXP (operands[1], 0), 1);
1913#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
1914#ifdef SGS
1915 asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
1916 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1917#else /* not SGS */
1918 asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
1919 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1920#endif /* not SGS */
1921#else /* SGS_SWITCH_TABLES or not MOTOROLA */
4977bab6 1922 (*targetm.asm_out.internal_label) (asm_out_file, "LI",
f4e80198
RK
1923 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
1924#ifdef SGS_SWITCH_TABLES
1925 /* Set flag saying we need to define the symbol
1926 LD%n (with value L%n-LI%n) at the end of the switch table. */
1927 switch_table_difference_label_flag = 1;
1928#endif /* SGS_SWITCH_TABLES */
1929#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
1930 }
1931#endif /* SGS_NO_LI */
1932 return "move%.w %1,%0";
1933}
1934
5505f548 1935const char *
f4e80198
RK
1936output_move_qimode (operands)
1937 rtx *operands;
1938{
1939 rtx xoperands[4];
1940
1941 /* This is probably useless, since it loses for pushing a struct
1942 of several bytes a byte at a time. */
102701ff
JW
1943 /* 68k family always modifies the stack pointer by at least 2, even for
1944 byte pushes. The 5200 (coldfire) does not do this. */
f4e80198
RK
1945 if (GET_CODE (operands[0]) == MEM
1946 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1947 && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
102701ff
JW
1948 && ! ADDRESS_REG_P (operands[1])
1949 && ! TARGET_5200)
f4e80198
RK
1950 {
1951 xoperands[1] = operands[1];
1952 xoperands[2]
1d8eaa6b
AS
1953 = gen_rtx_MEM (QImode,
1954 gen_rtx_PLUS (VOIDmode, stack_pointer_rtx, const1_rtx));
f4e80198
RK
1955 /* Just pushing a byte puts it in the high byte of the halfword. */
1956 /* We must put it in the low-order, high-numbered byte. */
3879920c
RK
1957 if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
1958 {
1959 xoperands[3] = stack_pointer_rtx;
1960#ifndef NO_ADDSUB_Q
1961 output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
1962#else
1963 output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
1964#endif
1965 }
1966 else
1967 output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
f4e80198
RK
1968 return "";
1969 }
1970
1971 /* clr and st insns on 68000 read before writing.
1972 This isn't so on the 68010, but we have no TARGET_68010. */
1973 if (!ADDRESS_REG_P (operands[0])
1974 && ((TARGET_68020 || TARGET_5200)
1975 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
1976 {
1977 if (operands[1] == const0_rtx)
1978 return "clr%.b %0";
1979 if ((!TARGET_5200 || DATA_REG_P (operands[0]))
1980 && GET_CODE (operands[1]) == CONST_INT
1981 && (INTVAL (operands[1]) & 255) == 255)
1982 {
1983 CC_STATUS_INIT;
1984 return "st %0";
1985 }
1986 }
1987 if (GET_CODE (operands[1]) == CONST_INT
1988 && DATA_REG_P (operands[0])
1989 && INTVAL (operands[1]) < 128
1990 && INTVAL (operands[1]) >= -128)
1991 {
1992#if defined(MOTOROLA) && !defined(CRDS)
1993 return "moveq%.l %1,%0";
1994#else
1995 return "moveq %1,%0";
1996#endif
1997 }
38198304
AS
1998 if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
1999 return "sub%.l %0,%0";
f4e80198
RK
2000 if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
2001 return "move%.l %1,%0";
37834fc8
JL
2002 /* 68k family (including the 5200 coldfire) does not support byte moves to
2003 from address registers. */
2004 if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
f4e80198
RK
2005 return "move%.w %1,%0";
2006 return "move%.b %1,%0";
2007}
2008
5505f548 2009const char *
9b55bf04
RK
2010output_move_stricthi (operands)
2011 rtx *operands;
2012{
2013 if (operands[1] == const0_rtx
2014 /* clr insns on 68000 read before writing.
2015 This isn't so on the 68010, but we have no TARGET_68010. */
2016 && ((TARGET_68020 || TARGET_5200)
2017 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2018 return "clr%.w %0";
2019 return "move%.w %1,%0";
2020}
2021
5505f548 2022const char *
9b55bf04
RK
2023output_move_strictqi (operands)
2024 rtx *operands;
2025{
2026 if (operands[1] == const0_rtx
2027 /* clr insns on 68000 read before writing.
2028 This isn't so on the 68010, but we have no TARGET_68010. */
2029 && ((TARGET_68020 || TARGET_5200)
2030 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
2031 return "clr%.b %0";
2032 return "move%.b %1,%0";
2033}
2034
79e68feb
RS
2035/* Return the best assembler insn template
2036 for moving operands[1] into operands[0] as a fullword. */
2037
5505f548 2038static const char *
79e68feb
RS
2039singlemove_string (operands)
2040 rtx *operands;
2041{
02ed0c07
RK
2042 if (GET_CODE (operands[1]) == CONST_INT)
2043 return output_move_simode_const (operands);
2044 return "move%.l %1,%0";
79e68feb
RS
2045}
2046
2505bc97 2047
79e68feb
RS
2048/* Output assembler code to perform a doubleword move insn
2049 with operands OPERANDS. */
2050
5505f548 2051const char *
79e68feb
RS
2052output_move_double (operands)
2053 rtx *operands;
2054{
2505bc97
RS
2055 enum
2056 {
2057 REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
2058 } optype0, optype1;
79e68feb 2059 rtx latehalf[2];
2505bc97 2060 rtx middlehalf[2];
7f98eeb6 2061 rtx xops[2];
79e68feb 2062 rtx addreg0 = 0, addreg1 = 0;
7f98eeb6 2063 int dest_overlapped_low = 0;
184916bc 2064 int size = GET_MODE_SIZE (GET_MODE (operands[0]));
2505bc97
RS
2065
2066 middlehalf[0] = 0;
2067 middlehalf[1] = 0;
79e68feb
RS
2068
2069 /* First classify both operands. */
2070
2071 if (REG_P (operands[0]))
2072 optype0 = REGOP;
2073 else if (offsettable_memref_p (operands[0]))
2074 optype0 = OFFSOP;
2075 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
2076 optype0 = POPOP;
2077 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
2078 optype0 = PUSHOP;
2079 else if (GET_CODE (operands[0]) == MEM)
2080 optype0 = MEMOP;
2081 else
2082 optype0 = RNDOP;
2083
2084 if (REG_P (operands[1]))
2085 optype1 = REGOP;
2086 else if (CONSTANT_P (operands[1]))
2087 optype1 = CNSTOP;
2088 else if (offsettable_memref_p (operands[1]))
2089 optype1 = OFFSOP;
2090 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
2091 optype1 = POPOP;
2092 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
2093 optype1 = PUSHOP;
2094 else if (GET_CODE (operands[1]) == MEM)
2095 optype1 = MEMOP;
2096 else
2097 optype1 = RNDOP;
2098
2099 /* Check for the cases that the operand constraints are not
2100 supposed to allow to happen. Abort if we get one,
2101 because generating code for these cases is painful. */
2102
2103 if (optype0 == RNDOP || optype1 == RNDOP)
2104 abort ();
2105
2106 /* If one operand is decrementing and one is incrementing
2107 decrement the former register explicitly
2108 and change that operand into ordinary indexing. */
2109
2110 if (optype0 == PUSHOP && optype1 == POPOP)
2111 {
2112 operands[0] = XEXP (XEXP (operands[0], 0), 0);
2505bc97
RS
2113 if (size == 12)
2114 output_asm_insn ("sub%.l %#12,%0", operands);
2115 else
2116 output_asm_insn ("subq%.l %#8,%0", operands);
2117 if (GET_MODE (operands[1]) == XFmode)
1d8eaa6b 2118 operands[0] = gen_rtx_MEM (XFmode, operands[0]);
2505bc97 2119 else if (GET_MODE (operands[0]) == DFmode)
1d8eaa6b 2120 operands[0] = gen_rtx_MEM (DFmode, operands[0]);
2505bc97 2121 else
1d8eaa6b 2122 operands[0] = gen_rtx_MEM (DImode, operands[0]);
79e68feb
RS
2123 optype0 = OFFSOP;
2124 }
2125 if (optype0 == POPOP && optype1 == PUSHOP)
2126 {
2127 operands[1] = XEXP (XEXP (operands[1], 0), 0);
2505bc97
RS
2128 if (size == 12)
2129 output_asm_insn ("sub%.l %#12,%1", operands);
2130 else
2131 output_asm_insn ("subq%.l %#8,%1", operands);
2132 if (GET_MODE (operands[1]) == XFmode)
1d8eaa6b 2133 operands[1] = gen_rtx_MEM (XFmode, operands[1]);
2505bc97 2134 else if (GET_MODE (operands[1]) == DFmode)
1d8eaa6b 2135 operands[1] = gen_rtx_MEM (DFmode, operands[1]);
2505bc97 2136 else
1d8eaa6b 2137 operands[1] = gen_rtx_MEM (DImode, operands[1]);
79e68feb
RS
2138 optype1 = OFFSOP;
2139 }
2140
2141 /* If an operand is an unoffsettable memory ref, find a register
2142 we can increment temporarily to make it refer to the second word. */
2143
2144 if (optype0 == MEMOP)
2145 addreg0 = find_addr_reg (XEXP (operands[0], 0));
2146
2147 if (optype1 == MEMOP)
2148 addreg1 = find_addr_reg (XEXP (operands[1], 0));
2149
2150 /* Ok, we can do one word at a time.
2151 Normally we do the low-numbered word first,
2152 but if either operand is autodecrementing then we
2153 do the high-numbered word first.
2154
2155 In either case, set up in LATEHALF the operands to use
2156 for the high-numbered word and in some cases alter the
2157 operands in OPERANDS to be suitable for the low-numbered word. */
2158
2505bc97
RS
2159 if (size == 12)
2160 {
2161 if (optype0 == REGOP)
2162 {
1d8eaa6b
AS
2163 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
2164 middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2505bc97
RS
2165 }
2166 else if (optype0 == OFFSOP)
2167 {
b72f00af
RK
2168 middlehalf[0] = adjust_address (operands[0], SImode, 4);
2169 latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2505bc97
RS
2170 }
2171 else
2172 {
2173 middlehalf[0] = operands[0];
2174 latehalf[0] = operands[0];
2175 }
2176
2177 if (optype1 == REGOP)
2178 {
1d8eaa6b
AS
2179 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
2180 middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2505bc97
RS
2181 }
2182 else if (optype1 == OFFSOP)
2183 {
b72f00af
RK
2184 middlehalf[1] = adjust_address (operands[1], SImode, 4);
2185 latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2505bc97
RS
2186 }
2187 else if (optype1 == CNSTOP)
2188 {
2189 if (GET_CODE (operands[1]) == CONST_DOUBLE)
2190 {
2191 REAL_VALUE_TYPE r;
2192 long l[3];
2193
2194 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2195 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
2196 operands[1] = GEN_INT (l[0]);
2197 middlehalf[1] = GEN_INT (l[1]);
2198 latehalf[1] = GEN_INT (l[2]);
2199 }
2200 else if (CONSTANT_P (operands[1]))
2201 {
2202 /* actually, no non-CONST_DOUBLE constant should ever
2203 appear here. */
2204 abort ();
2205 if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
2206 latehalf[1] = constm1_rtx;
2207 else
2208 latehalf[1] = const0_rtx;
2209 }
2210 }
2211 else
2212 {
2213 middlehalf[1] = operands[1];
2214 latehalf[1] = operands[1];
2215 }
2216 }
79e68feb 2217 else
2505bc97
RS
2218 /* size is not 12: */
2219 {
2220 if (optype0 == REGOP)
1d8eaa6b 2221 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
2505bc97 2222 else if (optype0 == OFFSOP)
b72f00af 2223 latehalf[0] = adjust_address (operands[0], SImode, size - 4);
2505bc97
RS
2224 else
2225 latehalf[0] = operands[0];
2226
2227 if (optype1 == REGOP)
1d8eaa6b 2228 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
2505bc97 2229 else if (optype1 == OFFSOP)
b72f00af 2230 latehalf[1] = adjust_address (operands[1], SImode, size - 4);
2505bc97
RS
2231 else if (optype1 == CNSTOP)
2232 split_double (operands[1], &operands[1], &latehalf[1]);
2233 else
2234 latehalf[1] = operands[1];
2235 }
79e68feb
RS
2236
2237 /* If insn is effectively movd N(sp),-(sp) then we will do the
2238 high word first. We should use the adjusted operand 1 (which is N+4(sp))
2239 for the low word as well, to compensate for the first decrement of sp. */
2240 if (optype0 == PUSHOP
2241 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
2242 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
c88aeaf8 2243 operands[1] = middlehalf[1] = latehalf[1];
79e68feb 2244
7f98eeb6
RS
2245 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
2246 if the upper part of reg N does not appear in the MEM, arrange to
2247 emit the move late-half first. Otherwise, compute the MEM address
2248 into the upper part of N and use that as a pointer to the memory
2249 operand. */
2250 if (optype0 == REGOP
2251 && (optype1 == OFFSOP || optype1 == MEMOP))
2252 {
1d8eaa6b 2253 rtx testlow = gen_rtx_REG (SImode, REGNO (operands[0]));
3a58400f
RS
2254
2255 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
d7e8d581 2256 && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
7f98eeb6
RS
2257 {
2258 /* If both halves of dest are used in the src memory address,
3a58400f
RS
2259 compute the address into latehalf of dest.
2260 Note that this can't happen if the dest is two data regs. */
7f98eeb6
RS
2261compadr:
2262 xops[0] = latehalf[0];
2263 xops[1] = XEXP (operands[1], 0);
d7e8d581 2264 output_asm_insn ("lea %a1,%0", xops);
b72f00af 2265 if (GET_MODE (operands[1]) == XFmode )
7f98eeb6 2266 {
1d8eaa6b 2267 operands[1] = gen_rtx_MEM (XFmode, latehalf[0]);
b72f00af
RK
2268 middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
2269 latehalf[1] = adjust_address (operands[1], DImode, size - 4);
7f98eeb6
RS
2270 }
2271 else
2272 {
1d8eaa6b 2273 operands[1] = gen_rtx_MEM (DImode, latehalf[0]);
b72f00af 2274 latehalf[1] = adjust_address (operands[1], DImode, size - 4);
7f98eeb6
RS
2275 }
2276 }
2277 else if (size == 12
d7e8d581
RS
2278 && reg_overlap_mentioned_p (middlehalf[0],
2279 XEXP (operands[1], 0)))
7f98eeb6 2280 {
3a58400f
RS
2281 /* Check for two regs used by both source and dest.
2282 Note that this can't happen if the dest is all data regs.
2283 It can happen if the dest is d6, d7, a0.
2284 But in that case, latehalf is an addr reg, so
2285 the code at compadr does ok. */
2286
2287 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
d7e8d581
RS
2288 || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
2289 goto compadr;
7f98eeb6
RS
2290
2291 /* JRV says this can't happen: */
2292 if (addreg0 || addreg1)
d7e8d581 2293 abort ();
7f98eeb6 2294
7a1929e1 2295 /* Only the middle reg conflicts; simply put it last. */
7f98eeb6
RS
2296 output_asm_insn (singlemove_string (operands), operands);
2297 output_asm_insn (singlemove_string (latehalf), latehalf);
2298 output_asm_insn (singlemove_string (middlehalf), middlehalf);
2299 return "";
2300 }
2fb8a81d 2301 else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
7f98eeb6
RS
2302 /* If the low half of dest is mentioned in the source memory
2303 address, the arrange to emit the move late half first. */
2304 dest_overlapped_low = 1;
2305 }
2306
79e68feb
RS
2307 /* If one or both operands autodecrementing,
2308 do the two words, high-numbered first. */
2309
2310 /* Likewise, the first move would clobber the source of the second one,
2311 do them in the other order. This happens only for registers;
2312 such overlap can't happen in memory unless the user explicitly
2313 sets it up, and that is an undefined circumstance. */
2314
2315 if (optype0 == PUSHOP || optype1 == PUSHOP
2316 || (optype0 == REGOP && optype1 == REGOP
2505bc97 2317 && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
7f98eeb6
RS
2318 || REGNO (operands[0]) == REGNO (latehalf[1])))
2319 || dest_overlapped_low)
79e68feb
RS
2320 {
2321 /* Make any unoffsettable addresses point at high-numbered word. */
2322 if (addreg0)
2505bc97
RS
2323 {
2324 if (size == 12)
07eced4d 2325 output_asm_insn ("addq%.l %#8,%0", &addreg0);
2505bc97 2326 else
07eced4d 2327 output_asm_insn ("addq%.l %#4,%0", &addreg0);
2505bc97 2328 }
79e68feb 2329 if (addreg1)
2505bc97
RS
2330 {
2331 if (size == 12)
07eced4d 2332 output_asm_insn ("addq%.l %#8,%0", &addreg1);
2505bc97 2333 else
07eced4d 2334 output_asm_insn ("addq%.l %#4,%0", &addreg1);
2505bc97 2335 }
79e68feb
RS
2336
2337 /* Do that word. */
2338 output_asm_insn (singlemove_string (latehalf), latehalf);
2339
2340 /* Undo the adds we just did. */
2341 if (addreg0)
07eced4d 2342 output_asm_insn ("subq%.l %#4,%0", &addreg0);
79e68feb 2343 if (addreg1)
07eced4d 2344 output_asm_insn ("subq%.l %#4,%0", &addreg1);
79e68feb 2345
2505bc97
RS
2346 if (size == 12)
2347 {
2348 output_asm_insn (singlemove_string (middlehalf), middlehalf);
2349 if (addreg0)
07eced4d 2350 output_asm_insn ("subq%.l %#4,%0", &addreg0);
2505bc97 2351 if (addreg1)
07eced4d 2352 output_asm_insn ("subq%.l %#4,%0", &addreg1);
2505bc97
RS
2353 }
2354
79e68feb
RS
2355 /* Do low-numbered word. */
2356 return singlemove_string (operands);
2357 }
2358
2359 /* Normal case: do the two words, low-numbered first. */
2360
2361 output_asm_insn (singlemove_string (operands), operands);
2362
2505bc97
RS
2363 /* Do the middle one of the three words for long double */
2364 if (size == 12)
2365 {
2366 if (addreg0)
07eced4d 2367 output_asm_insn ("addq%.l %#4,%0", &addreg0);
2505bc97 2368 if (addreg1)
07eced4d 2369 output_asm_insn ("addq%.l %#4,%0", &addreg1);
2505bc97
RS
2370
2371 output_asm_insn (singlemove_string (middlehalf), middlehalf);
2372 }
2373
79e68feb
RS
2374 /* Make any unoffsettable addresses point at high-numbered word. */
2375 if (addreg0)
07eced4d 2376 output_asm_insn ("addq%.l %#4,%0", &addreg0);
79e68feb 2377 if (addreg1)
07eced4d 2378 output_asm_insn ("addq%.l %#4,%0", &addreg1);
79e68feb
RS
2379
2380 /* Do that word. */
2381 output_asm_insn (singlemove_string (latehalf), latehalf);
2382
2383 /* Undo the adds we just did. */
2384 if (addreg0)
2505bc97
RS
2385 {
2386 if (size == 12)
07eced4d 2387 output_asm_insn ("subq%.l %#8,%0", &addreg0);
2505bc97 2388 else
07eced4d 2389 output_asm_insn ("subq%.l %#4,%0", &addreg0);
2505bc97 2390 }
79e68feb 2391 if (addreg1)
2505bc97
RS
2392 {
2393 if (size == 12)
07eced4d 2394 output_asm_insn ("subq%.l %#8,%0", &addreg1);
2505bc97 2395 else
07eced4d 2396 output_asm_insn ("subq%.l %#4,%0", &addreg1);
2505bc97 2397 }
79e68feb
RS
2398
2399 return "";
2400}
2401
2402/* Return a REG that occurs in ADDR with coefficient 1.
2403 ADDR can be effectively incremented by incrementing REG. */
2404
2405static rtx
2406find_addr_reg (addr)
2407 rtx addr;
2408{
2409 while (GET_CODE (addr) == PLUS)
2410 {
2411 if (GET_CODE (XEXP (addr, 0)) == REG)
2412 addr = XEXP (addr, 0);
2413 else if (GET_CODE (XEXP (addr, 1)) == REG)
2414 addr = XEXP (addr, 1);
2415 else if (CONSTANT_P (XEXP (addr, 0)))
2416 addr = XEXP (addr, 1);
2417 else if (CONSTANT_P (XEXP (addr, 1)))
2418 addr = XEXP (addr, 0);
2419 else
2420 abort ();
2421 }
2422 if (GET_CODE (addr) == REG)
2423 return addr;
2424 abort ();
2425}
9ee3c687
JW
2426
2427/* Output assembler code to perform a 32 bit 3 operand add. */
2428
5505f548 2429const char *
9ee3c687
JW
2430output_addsi3 (operands)
2431 rtx *operands;
2432{
2433 if (! operands_match_p (operands[0], operands[1]))
2434 {
2435 if (!ADDRESS_REG_P (operands[1]))
2436 {
2437 rtx tmp = operands[1];
2438
2439 operands[1] = operands[2];
2440 operands[2] = tmp;
2441 }
2442
2443 /* These insns can result from reloads to access
2444 stack slots over 64k from the frame pointer. */
2445 if (GET_CODE (operands[2]) == CONST_INT
2446 && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
8c61b6c1 2447 return "move%.l %2,%0\n\tadd%.l %1,%0";
9ee3c687
JW
2448#ifdef SGS
2449 if (GET_CODE (operands[2]) == REG)
2450 return "lea 0(%1,%2.l),%0";
2451 else
2452 return "lea %c2(%1),%0";
2453#else /* not SGS */
2454#ifdef MOTOROLA
2455 if (GET_CODE (operands[2]) == REG)
2456 return "lea (%1,%2.l),%0";
2457 else
2458 return "lea (%c2,%1),%0";
2459#else /* not MOTOROLA (MIT syntax) */
2460 if (GET_CODE (operands[2]) == REG)
2461 return "lea %1@(0,%2:l),%0";
2462 else
2463 return "lea %1@(%c2),%0";
2464#endif /* not MOTOROLA */
2465#endif /* not SGS */
2466 }
2467 if (GET_CODE (operands[2]) == CONST_INT)
2468 {
2469#ifndef NO_ADDSUB_Q
2470 if (INTVAL (operands[2]) > 0
2471 && INTVAL (operands[2]) <= 8)
2472 return "addq%.l %2,%0";
2473 if (INTVAL (operands[2]) < 0
2474 && INTVAL (operands[2]) >= -8)
2475 {
c5c76735 2476 operands[2] = GEN_INT (- INTVAL (operands[2]));
9ee3c687
JW
2477 return "subq%.l %2,%0";
2478 }
2479 /* On the CPU32 it is faster to use two addql instructions to
2480 add a small integer (8 < N <= 16) to a register.
7a1929e1 2481 Likewise for subql. */
9ee3c687
JW
2482 if (TARGET_CPU32 && REG_P (operands[0]))
2483 {
2484 if (INTVAL (operands[2]) > 8
2485 && INTVAL (operands[2]) <= 16)
2486 {
1d8eaa6b 2487 operands[2] = GEN_INT (INTVAL (operands[2]) - 8);
8c61b6c1 2488 return "addq%.l %#8,%0\n\taddq%.l %2,%0";
9ee3c687
JW
2489 }
2490 if (INTVAL (operands[2]) < -8
2491 && INTVAL (operands[2]) >= -16)
2492 {
c5c76735 2493 operands[2] = GEN_INT (- INTVAL (operands[2]) - 8);
8c61b6c1 2494 return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
9ee3c687
JW
2495 }
2496 }
2497#endif
2498 if (ADDRESS_REG_P (operands[0])
2499 && INTVAL (operands[2]) >= -0x8000
2500 && INTVAL (operands[2]) < 0x8000)
2501 {
2502 if (TARGET_68040)
2503 return "add%.w %2,%0";
2504 else
2505#ifdef MOTOROLA
2506 return "lea (%c2,%0),%0";
2507#else
2508 return "lea %0@(%c2),%0";
2509#endif
2510 }
2511 }
2512 return "add%.l %2,%0";
2513}
79e68feb
RS
2514\f
2515/* Store in cc_status the expressions that the condition codes will
2516 describe after execution of an instruction whose pattern is EXP.
2517 Do not alter them if the instruction would not alter the cc's. */
2518
2519/* On the 68000, all the insns to store in an address register fail to
2520 set the cc's. However, in some cases these instructions can make it
2521 possibly invalid to use the saved cc's. In those cases we clear out
2522 some or all of the saved cc's so they won't be used. */
2523
1d8eaa6b 2524void
79e68feb
RS
2525notice_update_cc (exp, insn)
2526 rtx exp;
2527 rtx insn;
2528{
1a8965c4 2529 if (GET_CODE (exp) == SET)
79e68feb
RS
2530 {
2531 if (GET_CODE (SET_SRC (exp)) == CALL)
2532 {
2533 CC_STATUS_INIT;
2534 }
2535 else if (ADDRESS_REG_P (SET_DEST (exp)))
2536 {
f5963e61 2537 if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
79e68feb 2538 cc_status.value1 = 0;
f5963e61 2539 if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
79e68feb
RS
2540 cc_status.value2 = 0;
2541 }
2542 else if (!FP_REG_P (SET_DEST (exp))
2543 && SET_DEST (exp) != cc0_rtx
2544 && (FP_REG_P (SET_SRC (exp))
2545 || GET_CODE (SET_SRC (exp)) == FIX
2546 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
2547 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
2548 {
2549 CC_STATUS_INIT;
2550 }
2551 /* A pair of move insns doesn't produce a useful overall cc. */
2552 else if (!FP_REG_P (SET_DEST (exp))
2553 && !FP_REG_P (SET_SRC (exp))
2554 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
2555 && (GET_CODE (SET_SRC (exp)) == REG
2556 || GET_CODE (SET_SRC (exp)) == MEM
2557 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
2558 {
2559 CC_STATUS_INIT;
2560 }
2561 else if (GET_CODE (SET_SRC (exp)) == CALL)
2562 {
2563 CC_STATUS_INIT;
2564 }
2565 else if (XEXP (exp, 0) != pc_rtx)
2566 {
2567 cc_status.flags = 0;
2568 cc_status.value1 = XEXP (exp, 0);
2569 cc_status.value2 = XEXP (exp, 1);
2570 }
2571 }
2572 else if (GET_CODE (exp) == PARALLEL
2573 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2574 {
2575 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
2576 CC_STATUS_INIT;
2577 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
2578 {
2579 cc_status.flags = 0;
2580 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
2581 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
2582 }
2583 }
2584 else
2585 CC_STATUS_INIT;
2586 if (cc_status.value2 != 0
2587 && ADDRESS_REG_P (cc_status.value2)
2588 && GET_MODE (cc_status.value2) == QImode)
2589 CC_STATUS_INIT;
1a8965c4 2590 if (cc_status.value2 != 0)
79e68feb
RS
2591 switch (GET_CODE (cc_status.value2))
2592 {
2593 case PLUS: case MINUS: case MULT:
2594 case DIV: case UDIV: case MOD: case UMOD: case NEG:
b757e352 2595#if 0 /* These instructions always clear the overflow bit */
996a5f59 2596 case ASHIFT: case ASHIFTRT: case LSHIFTRT:
79e68feb 2597 case ROTATE: case ROTATERT:
b757e352 2598#endif
79e68feb
RS
2599 if (GET_MODE (cc_status.value2) != VOIDmode)
2600 cc_status.flags |= CC_NO_OVERFLOW;
2601 break;
2602 case ZERO_EXTEND:
2603 /* (SET r1 (ZERO_EXTEND r2)) on this machine
2604 ends with a move insn moving r2 in r2's mode.
2605 Thus, the cc's are set for r2.
7a1929e1 2606 This can set N bit spuriously. */
79e68feb 2607 cc_status.flags |= CC_NOT_NEGATIVE;
1d8eaa6b
AS
2608
2609 default:
2610 break;
79e68feb
RS
2611 }
2612 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
2613 && cc_status.value2
2614 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
2615 cc_status.value2 = 0;
2616 if (((cc_status.value1 && FP_REG_P (cc_status.value1))
1a8965c4 2617 || (cc_status.value2 && FP_REG_P (cc_status.value2))))
79e68feb
RS
2618 cc_status.flags = CC_IN_68881;
2619}
2620\f
5505f548 2621const char *
79e68feb
RS
2622output_move_const_double (operands)
2623 rtx *operands;
2624{
1a8965c4 2625 int code = standard_68881_constant_p (operands[1]);
79e68feb 2626
1a8965c4 2627 if (code != 0)
79e68feb 2628 {
1a8965c4 2629 static char buf[40];
79e68feb 2630
1a8965c4
AS
2631 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2632 return buf;
79e68feb 2633 }
1a8965c4 2634 return "fmove%.d %1,%0";
79e68feb
RS
2635}
2636
5505f548 2637const char *
79e68feb
RS
2638output_move_const_single (operands)
2639 rtx *operands;
2640{
1a8965c4 2641 int code = standard_68881_constant_p (operands[1]);
79e68feb 2642
1a8965c4 2643 if (code != 0)
79e68feb 2644 {
1a8965c4 2645 static char buf[40];
79e68feb 2646
1a8965c4
AS
2647 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
2648 return buf;
79e68feb 2649 }
1a8965c4 2650 return "fmove%.s %f1,%0";
79e68feb
RS
2651}
2652
2653/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2654 from the "fmovecr" instruction.
2655 The value, anded with 0xff, gives the code to use in fmovecr
2656 to get the desired constant. */
2657
7a1929e1 2658/* This code has been fixed for cross-compilation. */
c1cfb2ae
RS
2659
2660static int inited_68881_table = 0;
2661
5505f548 2662static const char *const strings_68881[7] = {
c1cfb2ae
RS
2663 "0.0",
2664 "1.0",
2665 "10.0",
2666 "100.0",
2667 "10000.0",
2668 "1e8",
2669 "1e16"
2670 };
2671
8b60264b 2672static const int codes_68881[7] = {
c1cfb2ae
RS
2673 0x0f,
2674 0x32,
2675 0x33,
2676 0x34,
2677 0x35,
2678 0x36,
2679 0x37
2680 };
2681
2682REAL_VALUE_TYPE values_68881[7];
2683
2684/* Set up values_68881 array by converting the decimal values
7a1929e1 2685 strings_68881 to binary. */
c1cfb2ae
RS
2686
2687void
2688init_68881_table ()
2689{
2690 int i;
2691 REAL_VALUE_TYPE r;
2692 enum machine_mode mode;
2693
16d82c3c 2694 mode = SFmode;
c1cfb2ae
RS
2695 for (i = 0; i < 7; i++)
2696 {
2697 if (i == 6)
16d82c3c 2698 mode = DFmode;
c1cfb2ae
RS
2699 r = REAL_VALUE_ATOF (strings_68881[i], mode);
2700 values_68881[i] = r;
2701 }
2702 inited_68881_table = 1;
2703}
79e68feb
RS
2704
2705int
2706standard_68881_constant_p (x)
2707 rtx x;
2708{
c1cfb2ae
RS
2709 REAL_VALUE_TYPE r;
2710 int i;
79e68feb 2711
a5d54cc5
RK
2712#ifdef NO_ASM_FMOVECR
2713 return 0;
2714#endif
2715
e18db50d 2716 /* fmovecr must be emulated on the 68040 and 68060, so it shouldn't be
7a1929e1 2717 used at all on those chips. */
e18db50d 2718 if (TARGET_68040 || TARGET_68060)
79e68feb
RS
2719 return 0;
2720
c1cfb2ae
RS
2721 if (! inited_68881_table)
2722 init_68881_table ();
2723
2724 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2725
64c0b414
AS
2726 /* Use REAL_VALUES_IDENTICAL instead of REAL_VALUES_EQUAL so that -0.0
2727 is rejected. */
c1cfb2ae
RS
2728 for (i = 0; i < 6; i++)
2729 {
64c0b414 2730 if (REAL_VALUES_IDENTICAL (r, values_68881[i]))
c1cfb2ae
RS
2731 return (codes_68881[i]);
2732 }
2733
79e68feb
RS
2734 if (GET_MODE (x) == SFmode)
2735 return 0;
c1cfb2ae
RS
2736
2737 if (REAL_VALUES_EQUAL (r, values_68881[6]))
2738 return (codes_68881[6]);
2739
79e68feb
RS
2740 /* larger powers of ten in the constants ram are not used
2741 because they are not equal to a `double' C constant. */
2742 return 0;
2743}
2744
2745/* If X is a floating-point constant, return the logarithm of X base 2,
2746 or 0 if X is not a power of 2. */
2747
2748int
2749floating_exact_log2 (x)
2750 rtx x;
2751{
c1cfb2ae 2752 REAL_VALUE_TYPE r, r1;
eaff3bf8 2753 int exp;
79e68feb 2754
c1cfb2ae 2755 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
79e68feb 2756
eaff3bf8 2757 if (REAL_VALUES_LESS (r, dconst1))
79e68feb
RS
2758 return 0;
2759
eaff3bf8
RH
2760 exp = real_exponent (&r);
2761 real_2expN (&r1, exp);
2762 if (REAL_VALUES_EQUAL (r1, r))
2763 return exp;
2764
79e68feb
RS
2765 return 0;
2766}
2767\f
79e68feb
RS
2768/* A C compound statement to output to stdio stream STREAM the
2769 assembler syntax for an instruction operand X. X is an RTL
2770 expression.
2771
2772 CODE is a value that can be used to specify one of several ways
2773 of printing the operand. It is used when identical operands
2774 must be printed differently depending on the context. CODE
2775 comes from the `%' specification that was used to request
2776 printing of the operand. If the specification was just `%DIGIT'
2777 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2778 is the ASCII code for LTR.
2779
2780 If X is a register, this macro should print the register's name.
2781 The names can be found in an array `reg_names' whose type is
2782 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2783
2784 When the machine description has a specification `%PUNCT' (a `%'
2785 followed by a punctuation character), this macro is called with
2786 a null pointer for X and the punctuation character for CODE.
2787
2788 The m68k specific codes are:
2789
2790 '.' for dot needed in Motorola-style opcode names.
2791 '-' for an operand pushing on the stack:
2792 sp@-, -(sp) or -(%sp) depending on the style of syntax.
2793 '+' for an operand pushing on the stack:
2794 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2795 '@' for a reference to the top word on the stack:
2796 sp@, (sp) or (%sp) depending on the style of syntax.
2797 '#' for an immediate operand prefix (# in MIT and Motorola syntax
a7e2b014 2798 but & in SGS syntax, $ in CRDS/UNOS syntax).
79e68feb
RS
2799 '!' for the cc register (used in an `and to cc' insn).
2800 '$' for the letter `s' in an op code, but only on the 68040.
2801 '&' for the letter `d' in an op code, but only on the 68040.
2ac5f14a 2802 '/' for register prefix needed by longlong.h.
79e68feb
RS
2803
2804 'b' for byte insn (no effect, on the Sun; this is for the ISI).
2805 'd' to force memory addressing to be absolute, not relative.
2806 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2c8ec431
DL
2807 'o' for operands to go directly to output_operand_address (bypassing
2808 print_operand_address--used only for SYMBOL_REFs under TARGET_PCREL)
79e68feb
RS
2809 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2810 or print pair of registers as rx:ry.
79e68feb
RS
2811
2812 */
2813
2814void
2815print_operand (file, op, letter)
2816 FILE *file; /* file to write to */
2817 rtx op; /* operand to print */
2818 int letter; /* %<letter> or 0 */
2819{
79e68feb
RS
2820 if (letter == '.')
2821 {
a7e2b014 2822#if defined (MOTOROLA) && !defined (CRDS)
761c70aa 2823 fprintf (file, ".");
79e68feb
RS
2824#endif
2825 }
2826 else if (letter == '#')
2827 {
1f85a612 2828 asm_fprintf (file, "%I");
79e68feb
RS
2829 }
2830 else if (letter == '-')
2831 {
2832#ifdef MOTOROLA
2833 asm_fprintf (file, "-(%Rsp)");
2834#else
2835 asm_fprintf (file, "%Rsp@-");
2836#endif
2837 }
2838 else if (letter == '+')
2839 {
2840#ifdef MOTOROLA
2841 asm_fprintf (file, "(%Rsp)+");
2842#else
2843 asm_fprintf (file, "%Rsp@+");
2844#endif
2845 }
2846 else if (letter == '@')
2847 {
2848#ifdef MOTOROLA
2849 asm_fprintf (file, "(%Rsp)");
2850#else
2851 asm_fprintf (file, "%Rsp@");
2852#endif
2853 }
2854 else if (letter == '!')
2855 {
cffd0d74 2856 asm_fprintf (file, "%Rfpcr");
79e68feb
RS
2857 }
2858 else if (letter == '$')
2859 {
2860 if (TARGET_68040_ONLY)
2861 {
2862 fprintf (file, "s");
2863 }
2864 }
2865 else if (letter == '&')
2866 {
2867 if (TARGET_68040_ONLY)
2868 {
2869 fprintf (file, "d");
2870 }
2871 }
2ac5f14a
ILT
2872 else if (letter == '/')
2873 {
2874 asm_fprintf (file, "%R");
2875 }
2c8ec431
DL
2876 else if (letter == 'o')
2877 {
2878 /* This is only for direct addresses with TARGET_PCREL */
2879 if (GET_CODE (op) != MEM || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
2880 || !TARGET_PCREL)
2881 abort ();
2882 output_addr_const (file, XEXP (op, 0));
2883 }
79e68feb
RS
2884 else if (GET_CODE (op) == REG)
2885 {
1a8965c4
AS
2886 if (letter == 'R')
2887 /* Print out the second register name of a register pair.
2888 I.e., R (6) => 7. */
2889 fputs (reg_names[REGNO (op) + 1], file);
79e68feb 2890 else
1a8965c4 2891 fputs (reg_names[REGNO (op)], file);
79e68feb
RS
2892 }
2893 else if (GET_CODE (op) == MEM)
2894 {
2895 output_address (XEXP (op, 0));
2896 if (letter == 'd' && ! TARGET_68020
2897 && CONSTANT_ADDRESS_P (XEXP (op, 0))
2898 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
2899 && INTVAL (XEXP (op, 0)) < 0x8000
2900 && INTVAL (XEXP (op, 0)) >= -0x8000))
2901 {
3f889ae8
RK
2902#ifdef MOTOROLA
2903 fprintf (file, ".l");
2904#else
79e68feb 2905 fprintf (file, ":l");
3f889ae8 2906#endif
79e68feb
RS
2907 }
2908 }
79e68feb
RS
2909 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
2910 {
c1cfb2ae
RS
2911 REAL_VALUE_TYPE r;
2912 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2913 ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
2914 }
2915 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
2916 {
2917 REAL_VALUE_TYPE r;
2918 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2919 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
79e68feb 2920 }
e2c0a924 2921 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
79e68feb 2922 {
c1cfb2ae
RS
2923 REAL_VALUE_TYPE r;
2924 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2925 ASM_OUTPUT_DOUBLE_OPERAND (file, r);
79e68feb
RS
2926 }
2927 else
2928 {
2c8ec431
DL
2929 /* Use `print_operand_address' instead of `output_addr_const'
2930 to ensure that we print relevant PIC stuff. */
1f85a612 2931 asm_fprintf (file, "%I");
2c8ec431
DL
2932 if (TARGET_PCREL
2933 && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST))
2934 print_operand_address (file, op);
2935 else
2936 output_addr_const (file, op);
79e68feb
RS
2937 }
2938}
2939
2940\f
2941/* A C compound statement to output to stdio stream STREAM the
2942 assembler syntax for an instruction operand that is a memory
2943 reference whose address is ADDR. ADDR is an RTL expression.
2944
2945 Note that this contains a kludge that knows that the only reason
2946 we have an address (plus (label_ref...) (reg...)) when not generating
2947 PIC code is in the insn before a tablejump, and we know that m68k.md
2948 generates a label LInnn: on such an insn.
2949
2950 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2951 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2952
2953 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2954 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2955 we want. This difference can be accommodated by using an assembler
2956 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2957 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
ad7c12b2 2958 macro. See m68k/sgs.h for an example; for versions without the bug.
f4a6e73b
RK
2959 Some assemblers refuse all the above solutions. The workaround is to
2960 emit "K(pc,d0.l*2)" with K being a small constant known to give the
a0ab749a 2961 right behavior.
79e68feb
RS
2962
2963 They also do not like things like "pea 1.w", so we simple leave off
2964 the .w on small constants.
2965
2966 This routine is responsible for distinguishing between -fpic and -fPIC
2967 style relocations in an address. When generating -fpic code the
2968 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2969 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2970
f4a6e73b
RK
2971#ifndef ASM_OUTPUT_CASE_FETCH
2972#ifdef MOTOROLA
2973#ifdef SGS
2974#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2975 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2976#else
2977#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2978 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2979#endif
2980#else
2981#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2982 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2983#endif
2984#endif /* ASM_OUTPUT_CASE_FETCH */
2985
79e68feb
RS
2986void
2987print_operand_address (file, addr)
2988 FILE *file;
2989 rtx addr;
2990{
2991 register rtx reg1, reg2, breg, ireg;
2992 rtx offset;
2993
2994 switch (GET_CODE (addr))
2995 {
2996 case REG:
2997#ifdef MOTOROLA
2998 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
2999#else
3000 fprintf (file, "%s@", reg_names[REGNO (addr)]);
3001#endif
3002 break;
3003 case PRE_DEC:
3004#ifdef MOTOROLA
3005 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
3006#else
3007 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
3008#endif
3009 break;
3010 case POST_INC:
3011#ifdef MOTOROLA
3012 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
3013#else
3014 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
3015#endif
3016 break;
3017 case PLUS:
3018 reg1 = reg2 = ireg = breg = offset = 0;
3019 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
3020 {
3021 offset = XEXP (addr, 0);
3022 addr = XEXP (addr, 1);
3023 }
3024 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
3025 {
3026 offset = XEXP (addr, 1);
3027 addr = XEXP (addr, 0);
3028 }
3029 if (GET_CODE (addr) != PLUS)
3030 {
3031 ;
3032 }
3033 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
3034 {
3035 reg1 = XEXP (addr, 0);
3036 addr = XEXP (addr, 1);
3037 }
3038 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
3039 {
3040 reg1 = XEXP (addr, 1);
3041 addr = XEXP (addr, 0);
3042 }
3043 else if (GET_CODE (XEXP (addr, 0)) == MULT)
3044 {
3045 reg1 = XEXP (addr, 0);
3046 addr = XEXP (addr, 1);
3047 }
3048 else if (GET_CODE (XEXP (addr, 1)) == MULT)
3049 {
3050 reg1 = XEXP (addr, 1);
3051 addr = XEXP (addr, 0);
3052 }
3053 else if (GET_CODE (XEXP (addr, 0)) == REG)
3054 {
3055 reg1 = XEXP (addr, 0);
3056 addr = XEXP (addr, 1);
3057 }
3058 else if (GET_CODE (XEXP (addr, 1)) == REG)
3059 {
3060 reg1 = XEXP (addr, 1);
3061 addr = XEXP (addr, 0);
3062 }
3063 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
3064 || GET_CODE (addr) == SIGN_EXTEND)
3065 {
3066 if (reg1 == 0)
3067 {
3068 reg1 = addr;
3069 }
3070 else
3071 {
3072 reg2 = addr;
3073 }
3074 addr = 0;
3075 }
3076#if 0 /* for OLD_INDEXING */
3077 else if (GET_CODE (addr) == PLUS)
3078 {
3079 if (GET_CODE (XEXP (addr, 0)) == REG)
3080 {
3081 reg2 = XEXP (addr, 0);
3082 addr = XEXP (addr, 1);
3083 }
3084 else if (GET_CODE (XEXP (addr, 1)) == REG)
3085 {
3086 reg2 = XEXP (addr, 1);
3087 addr = XEXP (addr, 0);
3088 }
3089 }
3090#endif
3091 if (offset != 0)
3092 {
3093 if (addr != 0)
3094 {
3095 abort ();
3096 }
3097 addr = offset;
3098 }
3099 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
3100 || GET_CODE (reg1) == MULT))
3101 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
3102 {
3103 breg = reg2;
3104 ireg = reg1;
3105 }
3106 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
3107 {
3108 breg = reg1;
3109 ireg = reg2;
3110 }
3111 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
63d415c0 3112 && ! (flag_pic && ireg == pic_offset_table_rtx))
79e68feb
RS
3113 {
3114 int scale = 1;
3115 if (GET_CODE (ireg) == MULT)
3116 {
3117 scale = INTVAL (XEXP (ireg, 1));
3118 ireg = XEXP (ireg, 0);
3119 }
3120 if (GET_CODE (ireg) == SIGN_EXTEND)
3121 {
f4a6e73b 3122 ASM_OUTPUT_CASE_FETCH (file,
79e68feb
RS
3123 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3124 reg_names[REGNO (XEXP (ireg, 0))]);
f4a6e73b 3125 fprintf (file, "w");
79e68feb
RS
3126 }
3127 else
3128 {
f4a6e73b 3129 ASM_OUTPUT_CASE_FETCH (file,
79e68feb
RS
3130 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3131 reg_names[REGNO (ireg)]);
f4a6e73b 3132 fprintf (file, "l");
79e68feb
RS
3133 }
3134 if (scale != 1)
3135 {
3136#ifdef MOTOROLA
3137 fprintf (file, "*%d", scale);
3138#else
3139 fprintf (file, ":%d", scale);
3140#endif
3141 }
3142 putc (')', file);
3143 break;
3144 }
3145 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
63d415c0 3146 && ! (flag_pic && breg == pic_offset_table_rtx))
79e68feb 3147 {
f4a6e73b 3148 ASM_OUTPUT_CASE_FETCH (file,
79e68feb
RS
3149 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3150 reg_names[REGNO (breg)]);
f4a6e73b 3151 fprintf (file, "l)");
79e68feb
RS
3152 break;
3153 }
3154 if (ireg != 0 || breg != 0)
3155 {
3156 int scale = 1;
3157 if (breg == 0)
3158 {
3159 abort ();
3160 }
3161 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
3162 {
3163 abort ();
3164 }
3165#ifdef MOTOROLA
3166 if (addr != 0)
3167 {
3168 output_addr_const (file, addr);
66c432a7 3169 if (flag_pic && (breg == pic_offset_table_rtx))
e9a25f70
JL
3170 {
3171 fprintf (file, "@GOT");
3172 if (flag_pic == 1)
3173 fprintf (file, ".w");
3174 }
79e68feb
RS
3175 }
3176 fprintf (file, "(%s", reg_names[REGNO (breg)]);
3177 if (ireg != 0)
3178 {
3179 putc (',', file);
3180 }
3181#else
3182 fprintf (file, "%s@(", reg_names[REGNO (breg)]);
3183 if (addr != 0)
3184 {
3185 output_addr_const (file, addr);
3186 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
3187 fprintf (file, ":w");
3188 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
3189 fprintf (file, ":l");
3190 }
3191 if (addr != 0 && ireg != 0)
3192 {
3193 putc (',', file);
3194 }
3195#endif
3196 if (ireg != 0 && GET_CODE (ireg) == MULT)
3197 {
3198 scale = INTVAL (XEXP (ireg, 1));
3199 ireg = XEXP (ireg, 0);
3200 }
3201 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
3202 {
3203#ifdef MOTOROLA
3204 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
3205#else
3206 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
3207#endif
3208 }
3209 else if (ireg != 0)
3210 {
3211#ifdef MOTOROLA
3212 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
3213#else
3214 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
3215#endif
3216 }
3217 if (scale != 1)
3218 {
3219#ifdef MOTOROLA
3220 fprintf (file, "*%d", scale);
3221#else
3222 fprintf (file, ":%d", scale);
3223#endif
3224 }
3225 putc (')', file);
3226 break;
3227 }
3228 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
63d415c0 3229 && ! (flag_pic && reg1 == pic_offset_table_rtx))
79e68feb 3230 {
f4a6e73b 3231 ASM_OUTPUT_CASE_FETCH (file,
79e68feb
RS
3232 CODE_LABEL_NUMBER (XEXP (addr, 0)),
3233 reg_names[REGNO (reg1)]);
f4a6e73b 3234 fprintf (file, "l)");
79e68feb
RS
3235 break;
3236 }
2c8ec431 3237 /* FALL-THROUGH (is this really what we want?) */
79e68feb
RS
3238 default:
3239 if (GET_CODE (addr) == CONST_INT
3240 && INTVAL (addr) < 0x8000
3241 && INTVAL (addr) >= -0x8000)
3242 {
3243#ifdef MOTOROLA
3244#ifdef SGS
7a1929e1 3245 /* Many SGS assemblers croak on size specifiers for constants. */
6d5f49b2 3246 fprintf (file, "%d", (int) INTVAL (addr));
79e68feb 3247#else
6d5f49b2 3248 fprintf (file, "%d.w", (int) INTVAL (addr));
79e68feb
RS
3249#endif
3250#else
6d5f49b2 3251 fprintf (file, "%d:w", (int) INTVAL (addr));
79e68feb
RS
3252#endif
3253 }
2c8ec431
DL
3254 else if (GET_CODE (addr) == CONST_INT)
3255 {
6d5f49b2 3256 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
2c8ec431
DL
3257 }
3258 else if (TARGET_PCREL)
3259 {
3260 fputc ('(', file);
3261 output_addr_const (file, addr);
3262 if (flag_pic == 1)
3263 asm_fprintf (file, ":w,%Rpc)");
3264 else
3265 asm_fprintf (file, ":l,%Rpc)");
3266 }
79e68feb
RS
3267 else
3268 {
c2ac2ff6
AS
3269 /* Special case for SYMBOL_REF if the symbol name ends in
3270 `.<letter>', this can be mistaken as a size suffix. Put
3271 the name in parentheses. */
3272 if (GET_CODE (addr) == SYMBOL_REF
3273 && strlen (XSTR (addr, 0)) > 2
3274 && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
3275 {
3276 putc ('(', file);
3277 output_addr_const (file, addr);
3278 putc (')', file);
3279 }
3280 else
3281 output_addr_const (file, addr);
79e68feb
RS
3282 }
3283 break;
3284 }
3285}
af13f02d
JW
3286\f
3287/* Check for cases where a clr insns can be omitted from code using
3288 strict_low_part sets. For example, the second clrl here is not needed:
3289 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
3290
3291 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
3292 insn we are checking for redundancy. TARGET is the register set by the
3293 clear insn. */
3294
3295int
3296strict_low_part_peephole_ok (mode, first_insn, target)
3297 enum machine_mode mode;
3298 rtx first_insn;
3299 rtx target;
3300{
3301 rtx p;
3302
3303 p = prev_nonnote_insn (first_insn);
3304
3305 while (p)
3306 {
3307 /* If it isn't an insn, then give up. */
3308 if (GET_CODE (p) != INSN)
3309 return 0;
3310
3311 if (reg_set_p (target, p))
3312 {
3313 rtx set = single_set (p);
3314 rtx dest;
3315
3316 /* If it isn't an easy to recognize insn, then give up. */
3317 if (! set)
3318 return 0;
3319
3320 dest = SET_DEST (set);
3321
3322 /* If this sets the entire target register to zero, then our
3323 first_insn is redundant. */
3324 if (rtx_equal_p (dest, target)
3325 && SET_SRC (set) == const0_rtx)
3326 return 1;
3327 else if (GET_CODE (dest) == STRICT_LOW_PART
3328 && GET_CODE (XEXP (dest, 0)) == REG
3329 && REGNO (XEXP (dest, 0)) == REGNO (target)
3330 && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
3331 <= GET_MODE_SIZE (mode)))
3332 /* This is a strict low part set which modifies less than
3333 we are using, so it is safe. */
3334 ;
3335 else
3336 return 0;
3337 }
3338
3339 p = prev_nonnote_insn (p);
3340
3341 }
3342
3343 return 0;
3344}
67cd4f83
TG
3345
3346/* Accept integer operands in the range 0..0xffffffff. We have to check the
3347 range carefully since this predicate is used in DImode contexts. Also, we
3348 need some extra crud to make it work when hosted on 64-bit machines. */
3349
3350int
3351const_uint32_operand (op, mode)
3352 rtx op;
97660e20 3353 enum machine_mode mode;
67cd4f83 3354{
97660e20
RH
3355 /* It doesn't make sense to ask this question with a mode that is
3356 not larger than 32 bits. */
3357 if (GET_MODE_BITSIZE (mode) <= 32)
3358 abort ();
3359
67cd4f83
TG
3360#if HOST_BITS_PER_WIDE_INT > 32
3361 /* All allowed constants will fit a CONST_INT. */
3362 return (GET_CODE (op) == CONST_INT
3363 && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
3364#else
07ed7ecf 3365 return (GET_CODE (op) == CONST_INT
67cd4f83
TG
3366 || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
3367#endif
3368}
3369
3370/* Accept integer operands in the range -0x80000000..0x7fffffff. We have
3371 to check the range carefully since this predicate is used in DImode
3372 contexts. */
3373
3374int
3375const_sint32_operand (op, mode)
3376 rtx op;
97660e20 3377 enum machine_mode mode;
67cd4f83 3378{
97660e20
RH
3379 /* It doesn't make sense to ask this question with a mode that is
3380 not larger than 32 bits. */
3381 if (GET_MODE_BITSIZE (mode) <= 32)
3382 abort ();
3383
67cd4f83
TG
3384 /* All allowed constants will fit a CONST_INT. */
3385 return (GET_CODE (op) == CONST_INT
3386 && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
3387}
29ae8a3c 3388
2c8ec431
DL
3389/* Operand predicates for implementing asymmetric pc-relative addressing
3390 on m68k. The m68k supports pc-relative addressing (mode 7, register 2)
dab66575 3391 when used as a source operand, but not as a destination operand.
2c8ec431
DL
3392
3393 We model this by restricting the meaning of the basic predicates
3394 (general_operand, memory_operand, etc) to forbid the use of this
3395 addressing mode, and then define the following predicates that permit
3396 this addressing mode. These predicates can then be used for the
3397 source operands of the appropriate instructions.
3398
3399 n.b. While it is theoretically possible to change all machine patterns
3400 to use this addressing more where permitted by the architecture,
3401 it has only been implemented for "common" cases: SImode, HImode, and
3402 QImode operands, and only for the principle operations that would
3403 require this addressing mode: data movement and simple integer operations.
3404
3405 In parallel with these new predicates, two new constraint letters
3406 were defined: 'S' and 'T'. 'S' is the -mpcrel analog of 'm'.
3407 'T' replaces 's' in the non-pcrel case. It is a no-op in the pcrel case.
3408 In the pcrel case 's' is only valid in combination with 'a' registers.
3409 See addsi3, subsi3, cmpsi, and movsi patterns for a better understanding
3410 of how these constraints are used.
3411
3412 The use of these predicates is strictly optional, though patterns that
3413 don't will cause an extra reload register to be allocated where one
3414 was not necessary:
3415
3416 lea (abc:w,%pc),%a0 ; need to reload address
3417 moveq &1,%d1 ; since write to pc-relative space
3418 movel %d1,%a0@ ; is not allowed
3419 ...
3420 lea (abc:w,%pc),%a1 ; no need to reload address here
3421 movel %a1@,%d0 ; since "movel (abc:w,%pc),%d0" is ok
3422
3423 For more info, consult tiemann@cygnus.com.
3424
3425
3426 All of the ugliness with predicates and constraints is due to the
3427 simple fact that the m68k does not allow a pc-relative addressing
3428 mode as a destination. gcc does not distinguish between source and
3429 destination addresses. Hence, if we claim that pc-relative address
3430 modes are valid, e.g. GO_IF_LEGITIMATE_ADDRESS accepts them, then we
3431 end up with invalid code. To get around this problem, we left
3432 pc-relative modes as invalid addresses, and then added special
3433 predicates and constraints to accept them.
3434
3435 A cleaner way to handle this is to modify gcc to distinguish
3436 between source and destination addresses. We can then say that
3437 pc-relative is a valid source address but not a valid destination
3438 address, and hopefully avoid a lot of the predicate and constraint
3439 hackery. Unfortunately, this would be a pretty big change. It would
3440 be a useful change for a number of ports, but there aren't any current
3441 plans to undertake this.
3442
3443 ***************************************************************************/
3444
3445
3446/* Special case of a general operand that's used as a source operand.
3447 Use this to permit reads from PC-relative memory when -mpcrel
3448 is specified. */
3449
3450int
3451general_src_operand (op, mode)
3452 rtx op;
3453 enum machine_mode mode;
3454{
3455 if (TARGET_PCREL
3456 && GET_CODE (op) == MEM
3457 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3458 || GET_CODE (XEXP (op, 0)) == LABEL_REF
3459 || GET_CODE (XEXP (op, 0)) == CONST))
3460 return 1;
3461 return general_operand (op, mode);
3462}
3463
3464/* Special case of a nonimmediate operand that's used as a source.
3465 Use this to permit reads from PC-relative memory when -mpcrel
3466 is specified. */
3467
3468int
3469nonimmediate_src_operand (op, mode)
3470 rtx op;
3471 enum machine_mode mode;
3472{
3473 if (TARGET_PCREL && GET_CODE (op) == MEM
3474 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3475 || GET_CODE (XEXP (op, 0)) == LABEL_REF
3476 || GET_CODE (XEXP (op, 0)) == CONST))
3477 return 1;
3478 return nonimmediate_operand (op, mode);
3479}
3480
3481/* Special case of a memory operand that's used as a source.
3482 Use this to permit reads from PC-relative memory when -mpcrel
3483 is specified. */
3484
3485int
3486memory_src_operand (op, mode)
3487 rtx op;
3488 enum machine_mode mode;
3489{
3490 if (TARGET_PCREL && GET_CODE (op) == MEM
3491 && (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3492 || GET_CODE (XEXP (op, 0)) == LABEL_REF
3493 || GET_CODE (XEXP (op, 0)) == CONST))
3494 return 1;
3495 return memory_operand (op, mode);
3496}
3497
3498/* Predicate that accepts only a pc-relative address. This is needed
3499 because pc-relative addresses don't satisfy the predicate
3500 "general_src_operand". */
3501
3502int
3503pcrel_address (op, mode)
3504 rtx op;
5505f548 3505 enum machine_mode mode ATTRIBUTE_UNUSED;
2c8ec431
DL
3506{
3507 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF
3508 || GET_CODE (op) == CONST);
3509}
3510
5505f548 3511const char *
29ae8a3c
RK
3512output_andsi3 (operands)
3513 rtx *operands;
3514{
3515 int logval;
3516 if (GET_CODE (operands[2]) == CONST_INT
3517 && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
3518 && (DATA_REG_P (operands[0])
3519 || offsettable_memref_p (operands[0]))
3520 && !TARGET_5200)
3521 {
3522 if (GET_CODE (operands[0]) != REG)
b72f00af 3523 operands[0] = adjust_address (operands[0], HImode, 2);
1d8eaa6b 3524 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
29ae8a3c
RK
3525 /* Do not delete a following tstl %0 insn; that would be incorrect. */
3526 CC_STATUS_INIT;
3527 if (operands[2] == const0_rtx)
3528 return "clr%.w %0";
3529 return "and%.w %2,%0";
3530 }
3531 if (GET_CODE (operands[2]) == CONST_INT
3532 && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
3533 && (DATA_REG_P (operands[0])
3534 || offsettable_memref_p (operands[0])))
3535 {
3536 if (DATA_REG_P (operands[0]))
3537 {
1d8eaa6b 3538 operands[1] = GEN_INT (logval);
29ae8a3c
RK
3539 }
3540 else
3541 {
b72f00af 3542 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
1d8eaa6b 3543 operands[1] = GEN_INT (logval % 8);
29ae8a3c
RK
3544 }
3545 /* This does not set condition codes in a standard way. */
3546 CC_STATUS_INIT;
3547 return "bclr %1,%0";
3548 }
3549 return "and%.l %2,%0";
3550}
3551
5505f548 3552const char *
29ae8a3c
RK
3553output_iorsi3 (operands)
3554 rtx *operands;
3555{
3556 register int logval;
3557 if (GET_CODE (operands[2]) == CONST_INT
3558 && INTVAL (operands[2]) >> 16 == 0
3559 && (DATA_REG_P (operands[0])
3560 || offsettable_memref_p (operands[0]))
3561 && !TARGET_5200)
3562 {
3563 if (GET_CODE (operands[0]) != REG)
b72f00af 3564 operands[0] = adjust_address (operands[0], HImode, 2);
29ae8a3c
RK
3565 /* Do not delete a following tstl %0 insn; that would be incorrect. */
3566 CC_STATUS_INIT;
3567 if (INTVAL (operands[2]) == 0xffff)
3568 return "mov%.w %2,%0";
3569 return "or%.w %2,%0";
3570 }
3571 if (GET_CODE (operands[2]) == CONST_INT
3572 && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
3573 && (DATA_REG_P (operands[0])
3574 || offsettable_memref_p (operands[0])))
3575 {
3576 if (DATA_REG_P (operands[0]))
b72f00af 3577 operands[1] = GEN_INT (logval);
29ae8a3c
RK
3578 else
3579 {
b72f00af 3580 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
1d8eaa6b 3581 operands[1] = GEN_INT (logval % 8);
29ae8a3c
RK
3582 }
3583 CC_STATUS_INIT;
3584 return "bset %1,%0";
3585 }
3586 return "or%.l %2,%0";
3587}
3588
5505f548 3589const char *
29ae8a3c
RK
3590output_xorsi3 (operands)
3591 rtx *operands;
3592{
3593 register int logval;
3594 if (GET_CODE (operands[2]) == CONST_INT
3595 && INTVAL (operands[2]) >> 16 == 0
3596 && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
3597 && !TARGET_5200)
3598 {
3599 if (! DATA_REG_P (operands[0]))
b72f00af 3600 operands[0] = adjust_address (operands[0], HImode, 2);
29ae8a3c
RK
3601 /* Do not delete a following tstl %0 insn; that would be incorrect. */
3602 CC_STATUS_INIT;
3603 if (INTVAL (operands[2]) == 0xffff)
3604 return "not%.w %0";
3605 return "eor%.w %2,%0";
3606 }
3607 if (GET_CODE (operands[2]) == CONST_INT
3608 && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
3609 && (DATA_REG_P (operands[0])
3610 || offsettable_memref_p (operands[0])))
3611 {
3612 if (DATA_REG_P (operands[0]))
b72f00af 3613 operands[1] = GEN_INT (logval);
29ae8a3c
RK
3614 else
3615 {
b72f00af 3616 operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
1d8eaa6b 3617 operands[1] = GEN_INT (logval % 8);
29ae8a3c
RK
3618 }
3619 CC_STATUS_INIT;
3620 return "bchg %1,%0";
3621 }
3622 return "eor%.l %2,%0";
3623}
7c262518
RH
3624
3625/* Output assembly to switch to section NAME with attribute FLAGS. */
3626
3627static void
715bdd29 3628m68k_coff_asm_named_section (name, flags)
7c262518
RH
3629 const char *name;
3630 unsigned int flags;
7c262518
RH
3631{
3632 char flagchar;
3633
3634 if (flags & SECTION_WRITE)
3635 flagchar = 'd';
3636 else
3637 flagchar = 'x';
3638
3639 fprintf (asm_out_file, "\t.section\t%s,\"%c\"\n", name, flagchar);
3640}
2cc07db4 3641
d67c7dd8 3642#ifdef CTOR_LIST_BEGIN
2cc07db4
RH
3643static void
3644m68k_svr3_asm_out_constructor (symbol, priority)
3645 rtx symbol;
3646 int priority ATTRIBUTE_UNUSED;
3647{
3648 rtx xop[2];
3649
3650 xop[1] = symbol;
3651 xop[0] = gen_rtx_MEM (SImode, gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
3652
3653 init_section ();
3654 output_asm_insn (output_move_simode (xop), xop);
3655}
3656#endif
483ab821 3657
4977bab6
ZW
3658#ifdef HPUX_ASM
3659static void
3660m68k_hp320_internal_label (stream, prefix, labelno)
3661 FILE *stream;
3662 const char *prefix;
3663 unsigned long labelno;
3664{
3665 if (prefix[0] == 'L' && prefix[1] == 'I')
3666 fprintf(stream, "\tset %s%ld,.+2\n", prefix, labelno);
3667 else
3668 fprintf (stream, "%s%ld:\n", prefix, labelno);
3669}
1bc7c5b6
ZW
3670
3671static void
3672m68k_hp320_file_start ()
3673{
3674 /* version 1: 68010.
3675 2: 68020 without FPU.
3676 3: 68020 with FPU. */
3677 fprintf (asm_out_file, "\tversion %d\n",
3678 TARGET_68020 ? (TARGET_68881 ? 3 : 2) : 1);
3679}
4977bab6
ZW
3680#endif
3681
c590b625 3682static void
3961e8fe 3683m68k_output_mi_thunk (file, thunk, delta, vcall_offset, function)
483ab821
MM
3684 FILE *file;
3685 tree thunk ATTRIBUTE_UNUSED;
16f7d029 3686 HOST_WIDE_INT delta;
3961e8fe 3687 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
483ab821
MM
3688 tree function;
3689{
c590b625
RH
3690 rtx xops[1];
3691 const char *fmt;
3692
3693 if (delta > 0 && delta <= 8)
1d6302b1 3694#ifdef MOTOROLA
eb0424da 3695 asm_fprintf (file, "\taddq.l %I%d,4(%Rsp)\n", (int) delta);
1d6302b1
GN
3696#else
3697 asm_fprintf (file, "\taddql %I%d,%Rsp@(4)\n", (int) delta);
3698#endif
c590b625 3699 else if (delta < 0 && delta >= -8)
1d6302b1 3700#ifdef MOTOROLA
eb0424da 3701 asm_fprintf (file, "\tsubq.l %I%d,4(%Rsp)\n", (int) -delta);
1d6302b1
GN
3702#else
3703 asm_fprintf (file, "\tsubql %I%d,%Rsp@(4)\n", (int) -delta);
3704#endif
c590b625 3705 else
1d6302b1 3706#ifdef MOTOROLA
c53dddc2 3707 asm_fprintf (file, "\tadd.l %I%wd,4(%Rsp)\n", delta);
1d6302b1
GN
3708#else
3709 asm_fprintf (file, "\taddl %I%wd,%Rsp@(4)\n", delta);
3710#endif
c590b625
RH
3711
3712 xops[0] = DECL_RTL (function);
3713
3714 /* Logic taken from call patterns in m68k.md. */
3715 if (flag_pic)
3716 {
3717 if (TARGET_PCREL)
3718 fmt = "bra.l %o0";
3719 else
3720 {
3721#ifdef MOTOROLA
3722#ifdef HPUX_ASM
3723 fmt = "bra.l %0";
3724#else
3725#ifdef USE_GAS
3726 fmt = "bra.l %0@PLTPC";
3727#else
3728 fmt = "bra %0@PLTPC";
3729#endif
3730#endif
3731#else
3732#ifdef USE_GAS
3733 fmt = "bra.l %0";
3734#else
1d6302b1 3735 fmt = "jra %0,a1";
c590b625
RH
3736#endif
3737#endif
3738 }
3739 }
3740 else
3741 {
3742#if defined (MOTOROLA) && !defined (USE_GAS)
3743#ifdef MOTOROLA_BSR
3744 fmt = "bra %0";
3745#else
3746 fmt = "jmp %0";
3747#endif
3748#else
1d6302b1 3749 fmt = "jra %0";
c590b625
RH
3750#endif
3751 }
3752
3753 output_asm_insn (fmt, xops);
483ab821 3754}