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