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