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