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