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