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