Update comments.
[gcc.git] / gcc / config / m68k / m68k.c
1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 /* Some output-actions in m68k.md need these. */
23 #include <stdio.h>
24 #include "config.h"
25 #include "rtl.h"
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"
34
35 /* Needed for use_return_insn. */
36 #include "flags.h"
37
38 #ifdef SUPPORT_SUN_FPA
39
40 /* Index into this array by (register number >> 3) to find the
41 smallest class which contains that register. */
42 enum reg_class regno_reg_class[]
43 = { DATA_REGS, ADDR_REGS, FP_REGS,
44 LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
45
46 #endif /* defined SUPPORT_SUN_FPA */
47
48 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
49 if SGS_SWITCH_TABLE. */
50 int switch_table_difference_label_flag;
51
52 static rtx find_addr_reg ();
53 rtx legitimize_pic_address ();
54 \f
55
56 /* Alignment to use for loops and jumps */
57 /* Specify power of two alignment used for loops. */
58 char *m68k_align_loops_string;
59 /* Specify power of two alignment used for non-loop jumps. */
60 char *m68k_align_jumps_string;
61 /* Specify power of two alignment used for functions. */
62 char *m68k_align_funcs_string;
63
64 /* Specify power of two alignment used for loops. */
65 int m68k_align_loops;
66 /* Specify power of two alignment used for non-loop jumps. */
67 int m68k_align_jumps;
68 /* Specify power of two alignment used for functions. */
69 int m68k_align_funcs;
70
71
72 /* Sometimes certain combinations of command options do not make
73 sense on a particular target machine. You can define a macro
74 `OVERRIDE_OPTIONS' to take account of this. This macro, if
75 defined, is executed once just after all the command options have
76 been parsed.
77
78 Don't use this macro to turn on various extra optimizations for
79 `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
80
81 void
82 override_options ()
83 {
84 int def_align;
85
86 def_align = 1;
87
88 /* Validate -malign-loops= value, or provide default */
89 if (m68k_align_loops_string)
90 {
91 m68k_align_loops = atoi (m68k_align_loops_string);
92 if (m68k_align_loops < 1 || m68k_align_loops > MAX_CODE_ALIGN)
93 fatal ("-malign-loops=%d is not between 1 and %d",
94 m68k_align_loops, MAX_CODE_ALIGN);
95 }
96 else
97 m68k_align_loops = def_align;
98
99 /* Validate -malign-jumps= value, or provide default */
100 if (m68k_align_jumps_string)
101 {
102 m68k_align_jumps = atoi (m68k_align_jumps_string);
103 if (m68k_align_jumps < 1 || m68k_align_jumps > MAX_CODE_ALIGN)
104 fatal ("-malign-jumps=%d is not between 1 and %d",
105 m68k_align_jumps, MAX_CODE_ALIGN);
106 }
107 else
108 m68k_align_jumps = def_align;
109
110 /* Validate -malign-functions= value, or provide default */
111 if (m68k_align_funcs_string)
112 {
113 m68k_align_funcs = atoi (m68k_align_funcs_string);
114 if (m68k_align_funcs < 1 || m68k_align_funcs > MAX_CODE_ALIGN)
115 fatal ("-malign-functions=%d is not between 1 and %d",
116 m68k_align_funcs, MAX_CODE_ALIGN);
117 }
118 else
119 m68k_align_funcs = def_align;
120 }
121 \f
122 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
123 function at any time during the compilation process. In the future
124 we should try and eliminate the USE if we can easily determine that
125 all PIC references were deleted from the current function. That would
126 save an address register */
127
128 void
129 finalize_pic ()
130 {
131 if (flag_pic && current_function_uses_pic_offset_table)
132 {
133 rtx insn = gen_rtx (USE, VOIDmode, pic_offset_table_rtx);
134 emit_insn_after (insn, get_insns ());
135 emit_insn (insn);
136 }
137 }
138
139 \f
140 /* This function generates the assembly code for function entry.
141 STREAM is a stdio stream to output the code to.
142 SIZE is an int: how many units of temporary storage to allocate.
143 Refer to the array `regs_ever_live' to determine which registers
144 to save; `regs_ever_live[I]' is nonzero if register number I
145 is ever used in the function. This function is responsible for
146 knowing which registers should not be saved even if used. */
147
148
149 /* Note that the order of the bit mask for fmovem is the opposite
150 of the order for movem! */
151
152
153 void
154 output_function_prologue (stream, size)
155 FILE *stream;
156 int size;
157 {
158 register int regno;
159 register int mask = 0;
160 int num_saved_regs = 0;
161 extern char call_used_regs[];
162 int fsize = (size + 3) & -4;
163
164
165 if (frame_pointer_needed)
166 {
167 if (fsize == 0 && TARGET_68040)
168 {
169 /* on the 68040, pea + move is faster than link.w 0 */
170 #ifdef MOTOROLA
171 asm_fprintf (stream, "\tpea (%s)\n\tmove.l %s,%s\n",
172 reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
173 reg_names[FRAME_POINTER_REGNUM]);
174 #else
175 asm_fprintf (stream, "\tpea %s@\n\tmovel %s,%s\n",
176 reg_names[FRAME_POINTER_REGNUM], reg_names[STACK_POINTER_REGNUM],
177 reg_names[FRAME_POINTER_REGNUM]);
178 #endif
179 }
180 else if (fsize < 0x8000)
181 {
182 #ifdef MOTOROLA
183 asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
184 reg_names[FRAME_POINTER_REGNUM], -fsize);
185 #else
186 asm_fprintf (stream, "\tlink %s,%0I%d\n",
187 reg_names[FRAME_POINTER_REGNUM], -fsize);
188 #endif
189 }
190 else if (TARGET_68020)
191 {
192 #ifdef MOTOROLA
193 asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
194 reg_names[FRAME_POINTER_REGNUM], -fsize);
195 #else
196 asm_fprintf (stream, "\tlink %s,%0I%d\n",
197 reg_names[FRAME_POINTER_REGNUM], -fsize);
198 #endif
199 }
200 else
201 {
202 /* Adding negative number is faster on the 68040. */
203 #ifdef MOTOROLA
204 asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
205 reg_names[FRAME_POINTER_REGNUM], -fsize);
206 #else
207 asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
208 reg_names[FRAME_POINTER_REGNUM], -fsize);
209 #endif
210 }
211 }
212 else if (fsize)
213 {
214 /* Adding negative number is faster on the 68040. */
215 if (fsize + 4 < 0x8000)
216 {
217 if (TARGET_5200)
218 {
219 #ifdef MOTOROLA
220 asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));
221 #else
222 asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));
223 #endif
224 }
225 else
226 {
227 /* asm_fprintf() cannot handle %. */
228 #ifdef MOTOROLA
229 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
230 #else
231 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
232 #endif
233 }
234 }
235 else
236 {
237 /* asm_fprintf() cannot handle %. */
238 #ifdef MOTOROLA
239 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
240 #else
241 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
242 #endif
243 }
244 }
245 #ifdef SUPPORT_SUN_FPA
246 for (regno = 24; regno < 56; regno++)
247 if (regs_ever_live[regno] && ! call_used_regs[regno])
248 {
249 #ifdef MOTOROLA
250 asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
251 reg_names[regno]);
252 #else
253 asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
254 reg_names[regno]);
255 #endif
256 }
257 #endif
258 if (TARGET_68881)
259 {
260 for (regno = 16; regno < 24; regno++)
261 if (regs_ever_live[regno] && ! call_used_regs[regno])
262 mask |= 1 << (regno - 16);
263 if ((mask & 0xff) != 0)
264 {
265 #ifdef MOTOROLA
266 asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
267 #else
268 asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
269 #endif
270 }
271 mask = 0;
272 }
273 for (regno = 0; regno < 16; regno++)
274 if (regs_ever_live[regno] && ! call_used_regs[regno])
275 {
276 mask |= 1 << (15 - regno);
277 num_saved_regs++;
278 }
279 if (frame_pointer_needed)
280 {
281 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
282 num_saved_regs--;
283 }
284
285 #if NEED_PROBE
286 asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
287 #endif
288
289 if (num_saved_regs <= 2)
290 {
291 /* Store each separately in the same order moveml uses.
292 Using two movel instructions instead of a single moveml
293 is about 15% faster for the 68020 and 68030 at no expense
294 in code size */
295
296 int i;
297
298 /* Undo the work from above. */
299 for (i = 0; i< 16; i++)
300 if (mask & (1 << i))
301 asm_fprintf (stream,
302 #ifdef MOTOROLA
303 "\t%Omove.l %s,-(%Rsp)\n",
304 #else
305 "\tmovel %s,%Rsp@-\n",
306 #endif
307 reg_names[15 - i]);
308 }
309 else if (mask)
310 {
311 if (TARGET_5200)
312 {
313 /* The coldfire does not support the predecrement form of the
314 movml instruction, so we must adjust the stack pointer and
315 then use the plain address register indirect mode. We also
316 have to invert the register save mask to use the new mode.
317
318 FIXME: if num_saved_regs was calculated earlier, we could
319 combine the stack pointer adjustment with any adjustment
320 done when the initial stack frame is created. This would
321 save an instruction */
322
323 int newmask = 0;
324 int i;
325
326 for (i = 0; i < 16; i++)
327 if (mask & (1 << i))
328 newmask |= (1 << (15-i));
329
330 #ifdef MOTOROLA
331 asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
332 asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);
333 #else
334 asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
335 asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);
336 #endif
337 }
338 else
339 {
340 #ifdef MOTOROLA
341 asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
342 #else
343 asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
344 #endif
345 }
346 }
347 if (flag_pic && current_function_uses_pic_offset_table)
348 {
349 #ifdef MOTOROLA
350 asm_fprintf (stream, "\t%Olea (%Rpc, %U_GLOBAL_OFFSET_TABLE_@GOTPC), %s\n",
351 reg_names[PIC_OFFSET_TABLE_REGNUM]);
352 #else
353 asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
354 reg_names[PIC_OFFSET_TABLE_REGNUM]);
355 asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
356 reg_names[PIC_OFFSET_TABLE_REGNUM],
357 reg_names[PIC_OFFSET_TABLE_REGNUM]);
358 #endif
359 }
360 }
361 \f
362 /* Return true if this function's epilogue can be output as RTL. */
363
364 int
365 use_return_insn ()
366 {
367 int regno;
368
369 if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
370 return 0;
371
372 /* Copied from output_function_epilogue (). We should probably create a
373 separate layout routine to perform the common work. */
374
375 for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
376 if (regs_ever_live[regno] && ! call_used_regs[regno])
377 return 0;
378
379 return 1;
380 }
381
382 /* This function generates the assembly code for function exit,
383 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
384
385 The function epilogue should not depend on the current stack pointer!
386 It should use the frame pointer only, if there is a frame pointer.
387 This is mandatory because of alloca; we also take advantage of it to
388 omit stack adjustments before returning. */
389
390 void
391 output_function_epilogue (stream, size)
392 FILE *stream;
393 int size;
394 {
395 register int regno;
396 register int mask, fmask;
397 register int nregs;
398 int offset, foffset, fpoffset;
399 extern char call_used_regs[];
400 int fsize = (size + 3) & -4;
401 int big = 0;
402 rtx insn = get_last_insn ();
403 int restore_from_sp = 0;
404
405 /* If the last insn was a BARRIER, we don't have to write any code. */
406 if (GET_CODE (insn) == NOTE)
407 insn = prev_nonnote_insn (insn);
408 if (insn && GET_CODE (insn) == BARRIER)
409 {
410 /* Output just a no-op so that debuggers don't get confused
411 about which function the pc is in at this address. */
412 asm_fprintf (stream, "\tnop\n");
413 return;
414 }
415
416 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
417 if (profile_block_flag == 2)
418 {
419 FUNCTION_BLOCK_PROFILER_EXIT (stream);
420 }
421 #endif
422
423 #ifdef FUNCTION_EXTRA_EPILOGUE
424 FUNCTION_EXTRA_EPILOGUE (stream, size);
425 #endif
426 nregs = 0; fmask = 0; fpoffset = 0;
427 #ifdef SUPPORT_SUN_FPA
428 for (regno = 24 ; regno < 56 ; regno++)
429 if (regs_ever_live[regno] && ! call_used_regs[regno])
430 nregs++;
431 fpoffset = nregs * 8;
432 #endif
433 nregs = 0;
434 if (TARGET_68881)
435 {
436 for (regno = 16; regno < 24; regno++)
437 if (regs_ever_live[regno] && ! call_used_regs[regno])
438 {
439 nregs++;
440 fmask |= 1 << (23 - regno);
441 }
442 }
443 foffset = fpoffset + nregs * 12;
444 nregs = 0; mask = 0;
445 if (frame_pointer_needed)
446 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
447 for (regno = 0; regno < 16; regno++)
448 if (regs_ever_live[regno] && ! call_used_regs[regno])
449 {
450 nregs++;
451 mask |= 1 << regno;
452 }
453 offset = foffset + nregs * 4;
454 /* FIXME : leaf_function_p below is too strong.
455 What we really need to know there is if there could be pending
456 stack adjustment needed at that point. */
457 restore_from_sp = ! frame_pointer_needed
458 || (! current_function_calls_alloca && leaf_function_p ());
459 if (offset + fsize >= 0x8000
460 && ! restore_from_sp
461 && (mask || fmask || fpoffset))
462 {
463 #ifdef MOTOROLA
464 asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra1\n", -fsize);
465 #else
466 asm_fprintf (stream, "\tmovel %0I%d,%Ra1\n", -fsize);
467 #endif
468 fsize = 0, big = 1;
469 }
470 if (TARGET_5200 || nregs <= 2)
471 {
472 /* Restore each separately in the same order moveml does.
473 Using two movel instructions instead of a single moveml
474 is about 15% faster for the 68020 and 68030 at no expense
475 in code size. */
476
477 int i;
478
479 /* Undo the work from above. */
480 for (i = 0; i< 16; i++)
481 if (mask & (1 << i))
482 {
483 if (big)
484 {
485 #ifdef MOTOROLA
486 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra1.l),%s\n",
487 offset + fsize,
488 reg_names[FRAME_POINTER_REGNUM],
489 reg_names[i]);
490 #else
491 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra1:l),%s\n",
492 reg_names[FRAME_POINTER_REGNUM],
493 offset + fsize, reg_names[i]);
494 #endif
495 }
496 else if (restore_from_sp)
497 {
498 #ifdef MOTOROLA
499 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
500 reg_names[i]);
501 #else
502 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
503 reg_names[i]);
504 #endif
505 }
506 else
507 {
508 #ifdef MOTOROLA
509 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
510 offset + fsize,
511 reg_names[FRAME_POINTER_REGNUM],
512 reg_names[i]);
513 #else
514 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
515 reg_names[FRAME_POINTER_REGNUM],
516 offset + fsize, reg_names[i]);
517 #endif
518 }
519 offset = offset - 4;
520 }
521 }
522 else if (mask)
523 {
524 if (big)
525 {
526 #ifdef MOTOROLA
527 asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra1.l),%0I0x%x\n",
528 offset + fsize,
529 reg_names[FRAME_POINTER_REGNUM],
530 mask);
531 #else
532 asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra1:l),%0I0x%x\n",
533 reg_names[FRAME_POINTER_REGNUM],
534 offset + fsize, mask);
535 #endif
536 }
537 else if (restore_from_sp)
538 {
539 #ifdef MOTOROLA
540 asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
541 #else
542 asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
543 #endif
544 }
545 else
546 {
547 #ifdef MOTOROLA
548 asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
549 offset + fsize,
550 reg_names[FRAME_POINTER_REGNUM],
551 mask);
552 #else
553 asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
554 reg_names[FRAME_POINTER_REGNUM],
555 offset + fsize, mask);
556 #endif
557 }
558 }
559 if (fmask)
560 {
561 if (big)
562 {
563 #ifdef MOTOROLA
564 asm_fprintf (stream, "\tfmovm -%d(%s,%Ra1.l),%0I0x%x\n",
565 foffset + fsize,
566 reg_names[FRAME_POINTER_REGNUM],
567 fmask);
568 #else
569 asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra1:l),%0I0x%x\n",
570 reg_names[FRAME_POINTER_REGNUM],
571 foffset + fsize, fmask);
572 #endif
573 }
574 else if (restore_from_sp)
575 {
576 #ifdef MOTOROLA
577 asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
578 #else
579 asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
580 #endif
581 }
582 else
583 {
584 #ifdef MOTOROLA
585 asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
586 foffset + fsize,
587 reg_names[FRAME_POINTER_REGNUM],
588 fmask);
589 #else
590 asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
591 reg_names[FRAME_POINTER_REGNUM],
592 foffset + fsize, fmask);
593 #endif
594 }
595 }
596 if (fpoffset != 0)
597 for (regno = 55; regno >= 24; regno--)
598 if (regs_ever_live[regno] && ! call_used_regs[regno])
599 {
600 if (big)
601 {
602 #ifdef MOTOROLA
603 asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra1.l), %s\n",
604 fpoffset + fsize,
605 reg_names[FRAME_POINTER_REGNUM],
606 reg_names[regno]);
607 #else
608 asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra1:l), %s\n",
609 reg_names[FRAME_POINTER_REGNUM],
610 fpoffset + fsize, reg_names[regno]);
611 #endif
612 }
613 else if (restore_from_sp)
614 {
615 #ifdef MOTOROLA
616 asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
617 reg_names[regno]);
618 #else
619 asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
620 reg_names[regno]);
621 #endif
622 }
623 else
624 {
625 #ifdef MOTOROLA
626 asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
627 fpoffset + fsize,
628 reg_names[FRAME_POINTER_REGNUM],
629 reg_names[regno]);
630 #else
631 asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
632 reg_names[FRAME_POINTER_REGNUM],
633 fpoffset + fsize, reg_names[regno]);
634 #endif
635 }
636 fpoffset -= 8;
637 }
638 if (frame_pointer_needed)
639 fprintf (stream, "\tunlk %s\n",
640 reg_names[FRAME_POINTER_REGNUM]);
641 else if (fsize)
642 {
643 if (fsize + 4 < 0x8000)
644 {
645 if (TARGET_5200)
646 {
647 #ifdef MOTOROLA
648 asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);
649 #else
650 asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);
651 #endif
652 }
653 else
654 {
655 /* asm_fprintf() cannot handle %. */
656 #ifdef MOTOROLA
657 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
658 #else
659 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
660 #endif
661 }
662 }
663 else
664 {
665 /* asm_fprintf() cannot handle %. */
666 #ifdef MOTOROLA
667 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
668 #else
669 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
670 #endif
671 }
672 }
673 if (current_function_pops_args)
674 asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
675 else
676 fprintf (stream, "\trts\n");
677 }
678 \f
679 /* Similar to general_operand, but exclude stack_pointer_rtx. */
680
681 int
682 not_sp_operand (op, mode)
683 register rtx op;
684 enum machine_mode mode;
685 {
686 return op != stack_pointer_rtx && general_operand (op, mode);
687 }
688
689 /* Return TRUE if X is a valid comparison operator for the dbcc
690 instruction.
691
692 Note it rejects floating point comparison operators.
693 (In the future we could use Fdbcc).
694
695 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
696
697 int
698 valid_dbcc_comparison_p (x, mode)
699 rtx x;
700 enum machine_mode mode;
701 {
702 switch (GET_CODE (x))
703 {
704 case EQ: case NE: case GTU: case LTU:
705 case GEU: case LEU:
706 return 1;
707
708 /* Reject some when CC_NO_OVERFLOW is set. This may be over
709 conservative */
710 case GT: case LT: case GE: case LE:
711 return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
712 default:
713 return 0;
714 }
715 }
716
717 /* Return non-zero if flags are currently in the 68881 flag register. */
718 int
719 flags_in_68881 ()
720 {
721 /* We could add support for these in the future */
722 return cc_status.flags & CC_IN_68881;
723 }
724
725 /* Output a dbCC; jCC sequence. Note we do not handle the
726 floating point version of this sequence (Fdbcc). We also
727 do not handle alternative conditions when CC_NO_OVERFLOW is
728 set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
729 kick those out before we get here. */
730
731 output_dbcc_and_branch (operands)
732 rtx *operands;
733 {
734 switch (GET_CODE (operands[3]))
735 {
736 case EQ:
737 #ifdef MOTOROLA
738 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
739 #else
740 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
741 #endif
742 break;
743
744 case NE:
745 #ifdef MOTOROLA
746 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
747 #else
748 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
749 #endif
750 break;
751
752 case GT:
753 #ifdef MOTOROLA
754 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
755 #else
756 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
757 #endif
758 break;
759
760 case GTU:
761 #ifdef MOTOROLA
762 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
763 #else
764 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
765 #endif
766 break;
767
768 case LT:
769 #ifdef MOTOROLA
770 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
771 #else
772 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
773 #endif
774 break;
775
776 case LTU:
777 #ifdef MOTOROLA
778 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
779 #else
780 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
781 #endif
782 break;
783
784 case GE:
785 #ifdef MOTOROLA
786 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
787 #else
788 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
789 #endif
790 break;
791
792 case GEU:
793 #ifdef MOTOROLA
794 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
795 #else
796 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
797 #endif
798 break;
799
800 case LE:
801 #ifdef MOTOROLA
802 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
803 #else
804 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
805 #endif
806 break;
807
808 case LEU:
809 #ifdef MOTOROLA
810 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
811 #else
812 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
813 #endif
814 break;
815
816 default:
817 abort ();
818 }
819
820 /* If the decrement is to be done in SImode, then we have
821 to compensate for the fact that dbcc decrements in HImode. */
822 switch (GET_MODE (operands[0]))
823 {
824 case SImode:
825 #ifdef MOTOROLA
826 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
827 #else
828 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
829 #endif
830 break;
831
832 case HImode:
833 break;
834
835 default:
836 abort ();
837 }
838 }
839
840 char *
841 output_scc_di(op, operand1, operand2, dest)
842 rtx op;
843 rtx operand1;
844 rtx operand2;
845 rtx dest;
846 {
847 rtx loperands[7];
848 enum rtx_code op_code = GET_CODE (op);
849
850 /* The m68k cmp.l instruction requires operand1 to be a reg as used
851 below. Swap the operands and change the op if these requirements
852 are not fulfilled. */
853 if (GET_CODE (operand2) == REG && GET_CODE (operand1) != REG)
854 {
855 rtx tmp = operand1;
856
857 operand1 = operand2;
858 operand2 = tmp;
859 op_code = swap_condition (op_code);
860 }
861 loperands[0] = operand1;
862 if (GET_CODE (operand1) == REG)
863 loperands[1] = gen_rtx (REG, SImode, REGNO (operand1) + 1);
864 else
865 loperands[1] = adj_offsettable_operand (operand1, 4);
866 if (operand2 != const0_rtx)
867 {
868 loperands[2] = operand2;
869 if (GET_CODE (operand2) == REG)
870 loperands[3] = gen_rtx (REG, SImode, REGNO (operand2) + 1);
871 else
872 loperands[3] = adj_offsettable_operand (operand2, 4);
873 }
874 loperands[4] = gen_label_rtx();
875 if (operand2 != const0_rtx)
876 #ifdef MOTOROLA
877 #ifdef SGS_CMP_ORDER
878 output_asm_insn ("cmp%.l %0,%2\n\tjbne %l4\n\tcmp%.l %1,%3", loperands);
879 #else
880 output_asm_insn ("cmp%.l %2,%0\n\tjbne %l4\n\tcmp%.l %3,%1", loperands);
881 #endif
882 #else
883 #ifdef SGS_CMP_ORDER
884 output_asm_insn ("cmp%.l %0,%2\n\tjne %l4\n\tcmp%.l %1,%3", loperands);
885 #else
886 output_asm_insn ("cmp%.l %2,%0\n\tjne %l4\n\tcmp%.l %3,%1", loperands);
887 #endif
888 #endif
889 else
890 #ifdef MOTOROLA
891 output_asm_insn ("tst%.l %0\n\tjbne %l4\n\ttst%.l %1", loperands);
892 #else
893 output_asm_insn ("tst%.l %0\n\tjne %l4\n\ttst%.l %1", loperands);
894 #endif
895 loperands[5] = dest;
896
897 switch (op_code)
898 {
899 case EQ:
900 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
901 CODE_LABEL_NUMBER (loperands[4]));
902 output_asm_insn ("seq %5", loperands);
903 break;
904
905 case NE:
906 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
907 CODE_LABEL_NUMBER (loperands[4]));
908 output_asm_insn ("sne %5", loperands);
909 break;
910
911 case GT:
912 loperands[6] = gen_label_rtx();
913 #ifdef MOTOROLA
914 output_asm_insn ("shi %5\n\tjbra %l6", loperands);
915 #else
916 output_asm_insn ("shi %5\n\tjra %l6", loperands);
917 #endif
918 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
919 CODE_LABEL_NUMBER (loperands[4]));
920 output_asm_insn ("sgt %5", loperands);
921 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
922 CODE_LABEL_NUMBER (loperands[6]));
923 break;
924
925 case GTU:
926 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
927 CODE_LABEL_NUMBER (loperands[4]));
928 output_asm_insn ("shi %5", loperands);
929 break;
930
931 case LT:
932 loperands[6] = gen_label_rtx();
933 #ifdef MOTOROLA
934 output_asm_insn ("scs %5\n\tjbra %l6", loperands);
935 #else
936 output_asm_insn ("scs %5\n\tjra %l6", loperands);
937 #endif
938 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
939 CODE_LABEL_NUMBER (loperands[4]));
940 output_asm_insn ("slt %5", loperands);
941 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
942 CODE_LABEL_NUMBER (loperands[6]));
943 break;
944
945 case LTU:
946 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
947 CODE_LABEL_NUMBER (loperands[4]));
948 output_asm_insn ("scs %5", loperands);
949 break;
950
951 case GE:
952 loperands[6] = gen_label_rtx();
953 #ifdef MOTOROLA
954 output_asm_insn ("scc %5\n\tjbra %l6", loperands);
955 #else
956 output_asm_insn ("scc %5\n\tjra %l6", loperands);
957 #endif
958 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
959 CODE_LABEL_NUMBER (loperands[4]));
960 output_asm_insn ("sge %5", loperands);
961 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
962 CODE_LABEL_NUMBER (loperands[6]));
963 break;
964
965 case GEU:
966 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
967 CODE_LABEL_NUMBER (loperands[4]));
968 output_asm_insn ("scc %5", loperands);
969 break;
970
971 case LE:
972 loperands[6] = gen_label_rtx();
973 #ifdef MOTOROLA
974 output_asm_insn ("sls %5\n\tjbra %l6", loperands);
975 #else
976 output_asm_insn ("sls %5\n\tjra %l6", loperands);
977 #endif
978 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
979 CODE_LABEL_NUMBER (loperands[4]));
980 output_asm_insn ("sle %5", loperands);
981 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
982 CODE_LABEL_NUMBER (loperands[6]));
983 break;
984
985 case LEU:
986 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
987 CODE_LABEL_NUMBER (loperands[4]));
988 output_asm_insn ("sls %5", loperands);
989 break;
990
991 default:
992 abort ();
993 }
994 return "";
995 }
996
997 char *
998 output_btst (operands, countop, dataop, insn, signpos)
999 rtx *operands;
1000 rtx countop, dataop;
1001 rtx insn;
1002 int signpos;
1003 {
1004 operands[0] = countop;
1005 operands[1] = dataop;
1006
1007 if (GET_CODE (countop) == CONST_INT)
1008 {
1009 register int count = INTVAL (countop);
1010 /* If COUNT is bigger than size of storage unit in use,
1011 advance to the containing unit of same size. */
1012 if (count > signpos)
1013 {
1014 int offset = (count & ~signpos) / 8;
1015 count = count & signpos;
1016 operands[1] = dataop = adj_offsettable_operand (dataop, offset);
1017 }
1018 if (count == signpos)
1019 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
1020 else
1021 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
1022
1023 /* These three statements used to use next_insns_test_no...
1024 but it appears that this should do the same job. */
1025 if (count == 31
1026 && next_insn_tests_no_inequality (insn))
1027 return "tst%.l %1";
1028 if (count == 15
1029 && next_insn_tests_no_inequality (insn))
1030 return "tst%.w %1";
1031 if (count == 7
1032 && next_insn_tests_no_inequality (insn))
1033 return "tst%.b %1";
1034
1035 cc_status.flags = CC_NOT_NEGATIVE;
1036 }
1037 return "btst %0,%1";
1038 }
1039 \f
1040 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1041 reference and a constant. */
1042
1043 int
1044 symbolic_operand (op, mode)
1045 register rtx op;
1046 enum machine_mode mode;
1047 {
1048 switch (GET_CODE (op))
1049 {
1050 case SYMBOL_REF:
1051 case LABEL_REF:
1052 return 1;
1053
1054 case CONST:
1055 op = XEXP (op, 0);
1056 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1057 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1058 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1059
1060 #if 0 /* Deleted, with corresponding change in m68k.h,
1061 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
1062 case CONST_DOUBLE:
1063 return GET_MODE (op) == mode;
1064 #endif
1065
1066 default:
1067 return 0;
1068 }
1069 }
1070 \f
1071 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
1072
1073 int
1074 extend_operator(x, mode)
1075 rtx x;
1076 enum machine_mode mode;
1077 {
1078 if (mode != VOIDmode && GET_MODE(x) != mode)
1079 return 0;
1080 switch (GET_CODE(x))
1081 {
1082 case SIGN_EXTEND :
1083 case ZERO_EXTEND :
1084 return 1;
1085 default :
1086 return 0;
1087 }
1088 }
1089
1090 \f
1091 /* Legitimize PIC addresses. If the address is already
1092 position-independent, we return ORIG. Newly generated
1093 position-independent addresses go to REG. If we need more
1094 than one register, we lose.
1095
1096 An address is legitimized by making an indirect reference
1097 through the Global Offset Table with the name of the symbol
1098 used as an offset.
1099
1100 The assembler and linker are responsible for placing the
1101 address of the symbol in the GOT. The function prologue
1102 is responsible for initializing a5 to the starting address
1103 of the GOT.
1104
1105 The assembler is also responsible for translating a symbol name
1106 into a constant displacement from the start of the GOT.
1107
1108 A quick example may make things a little clearer:
1109
1110 When not generating PIC code to store the value 12345 into _foo
1111 we would generate the following code:
1112
1113 movel #12345, _foo
1114
1115 When generating PIC two transformations are made. First, the compiler
1116 loads the address of foo into a register. So the first transformation makes:
1117
1118 lea _foo, a0
1119 movel #12345, a0@
1120
1121 The code in movsi will intercept the lea instruction and call this
1122 routine which will transform the instructions into:
1123
1124 movel a5@(_foo:w), a0
1125 movel #12345, a0@
1126
1127
1128 That (in a nutshell) is how *all* symbol and label references are
1129 handled. */
1130
1131 rtx
1132 legitimize_pic_address (orig, mode, reg)
1133 rtx orig, reg;
1134 enum machine_mode mode;
1135 {
1136 rtx pic_ref = orig;
1137
1138 /* First handle a simple SYMBOL_REF or LABEL_REF */
1139 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1140 {
1141 if (reg == 0)
1142 abort ();
1143
1144 pic_ref = gen_rtx (MEM, Pmode,
1145 gen_rtx (PLUS, Pmode,
1146 pic_offset_table_rtx, orig));
1147 current_function_uses_pic_offset_table = 1;
1148 RTX_UNCHANGING_P (pic_ref) = 1;
1149 emit_move_insn (reg, pic_ref);
1150 return reg;
1151 }
1152 else if (GET_CODE (orig) == CONST)
1153 {
1154 rtx base, offset;
1155
1156 /* Make sure this is CONST has not already been legitimized */
1157 if (GET_CODE (XEXP (orig, 0)) == PLUS
1158 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1159 return orig;
1160
1161 if (reg == 0)
1162 abort ();
1163
1164 /* legitimize both operands of the PLUS */
1165 if (GET_CODE (XEXP (orig, 0)) == PLUS)
1166 {
1167 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
1168 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1169 base == reg ? 0 : reg);
1170 }
1171 else abort ();
1172
1173 if (GET_CODE (orig) == CONST_INT)
1174 return plus_constant_for_output (base, INTVAL (orig));
1175 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
1176 /* Likewise, should we set special REG_NOTEs here? */
1177 }
1178 return pic_ref;
1179 }
1180
1181 \f
1182 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
1183
1184 #define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
1185
1186 CONST_METHOD
1187 const_method (constant)
1188 rtx constant;
1189 {
1190 int i;
1191 unsigned u;
1192
1193 i = INTVAL (constant);
1194 if (USE_MOVQ (i))
1195 return MOVQ;
1196
1197 /* The Coldfire doesn't have byte or word operations. */
1198 /* FIXME: This may not be useful for the m68060 either */
1199 if (!TARGET_5200)
1200 {
1201 /* if -256 < N < 256 but N is not in range for a moveq
1202 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
1203 if (USE_MOVQ (i ^ 0xff))
1204 return NOTB;
1205 /* Likewise, try with not.w */
1206 if (USE_MOVQ (i ^ 0xffff))
1207 return NOTW;
1208 /* This is the only value where neg.w is useful */
1209 if (i == -65408)
1210 return NEGW;
1211 /* Try also with swap */
1212 u = i;
1213 if (USE_MOVQ ((u >> 16) | (u << 16)))
1214 return SWAP;
1215 }
1216 /* Otherwise, use move.l */
1217 return MOVL;
1218 }
1219
1220 const_int_cost (constant)
1221 rtx constant;
1222 {
1223 switch (const_method (constant))
1224 {
1225 case MOVQ :
1226 /* Constants between -128 and 127 are cheap due to moveq */
1227 return 0;
1228 case NOTB :
1229 case NOTW :
1230 case NEGW :
1231 case SWAP :
1232 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
1233 return 1;
1234 case MOVL :
1235 return 2;
1236 default :
1237 abort ();
1238 }
1239 }
1240
1241 char *
1242 output_move_const_into_data_reg (operands)
1243 rtx *operands;
1244 {
1245 int i;
1246
1247 i = INTVAL (operands[1]);
1248 switch (const_method (operands[1]))
1249 {
1250 case MOVQ :
1251 #if defined (MOTOROLA) && !defined (CRDS)
1252 return "moveq%.l %1,%0";
1253 #else
1254 return "moveq %1,%0";
1255 #endif
1256 case NOTB :
1257 operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xff);
1258 #if defined (MOTOROLA) && !defined (CRDS)
1259 return "moveq%.l %1,%0\n\tnot%.b %0";
1260 #else
1261 return "moveq %1,%0\n\tnot%.b %0";
1262 #endif
1263 case NOTW :
1264 operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xffff);
1265 #if defined (MOTOROLA) && !defined (CRDS)
1266 return "moveq%.l %1,%0\n\tnot%.w %0";
1267 #else
1268 return "moveq %1,%0\n\tnot%.w %0";
1269 #endif
1270 case NEGW :
1271 #if defined (MOTOROLA) && !defined (CRDS)
1272 return "moveq%.l %#-128,%0\n\tneg%.w %0";
1273 #else
1274 return "moveq %#-128,%0\n\tneg%.w %0";
1275 #endif
1276 case SWAP :
1277 {
1278 unsigned u = i;
1279
1280 operands[1] = gen_rtx (CONST_INT, VOIDmode, (u << 16) | (u >> 16));
1281 #if defined (MOTOROLA) && !defined (CRDS)
1282 return "moveq%.l %1,%0\n\tswap %0";
1283 #else
1284 return "moveq %1,%0\n\tswap %0";
1285 #endif
1286 }
1287 case MOVL :
1288 return "move%.l %1,%0";
1289 default :
1290 abort ();
1291 }
1292 }
1293
1294 char *
1295 output_move_simode_const (operands)
1296 rtx *operands;
1297 {
1298 if (operands[1] == const0_rtx
1299 && (DATA_REG_P (operands[0])
1300 || GET_CODE (operands[0]) == MEM)
1301 /* clr insns on 68000 read before writing.
1302 This isn't so on the 68010, but we have no TARGET_68010. */
1303 && (TARGET_68020
1304 || !(GET_CODE (operands[0]) == MEM
1305 && MEM_VOLATILE_P (operands[0]))))
1306 return "clr%.l %0";
1307 else if (DATA_REG_P (operands[0]))
1308 return output_move_const_into_data_reg (operands);
1309 else if (ADDRESS_REG_P (operands[0])
1310 && INTVAL (operands[1]) < 0x8000
1311 && INTVAL (operands[1]) >= -0x8000)
1312 return "move%.w %1,%0";
1313 else if (GET_CODE (operands[0]) == MEM
1314 && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
1315 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1316 && INTVAL (operands[1]) < 0x8000
1317 && INTVAL (operands[1]) >= -0x8000)
1318 return "pea %a1";
1319 return "move%.l %1,%0";
1320 }
1321
1322 /* Return the best assembler insn template
1323 for moving operands[1] into operands[0] as a fullword. */
1324
1325 static char *
1326 singlemove_string (operands)
1327 rtx *operands;
1328 {
1329 #ifdef SUPPORT_SUN_FPA
1330 if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
1331 return "fpmoves %1,%0";
1332 #endif
1333 if (GET_CODE (operands[1]) == CONST_INT)
1334 return output_move_simode_const (operands);
1335 return "move%.l %1,%0";
1336 }
1337
1338
1339 /* Output assembler code to perform a doubleword move insn
1340 with operands OPERANDS. */
1341
1342 char *
1343 output_move_double (operands)
1344 rtx *operands;
1345 {
1346 enum
1347 {
1348 REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
1349 } optype0, optype1;
1350 rtx latehalf[2];
1351 rtx middlehalf[2];
1352 rtx xops[2];
1353 rtx addreg0 = 0, addreg1 = 0;
1354 int dest_overlapped_low = 0;
1355 int size = GET_MODE_SIZE (GET_MODE (operands[0]));
1356
1357 middlehalf[0] = 0;
1358 middlehalf[1] = 0;
1359
1360 /* First classify both operands. */
1361
1362 if (REG_P (operands[0]))
1363 optype0 = REGOP;
1364 else if (offsettable_memref_p (operands[0]))
1365 optype0 = OFFSOP;
1366 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
1367 optype0 = POPOP;
1368 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
1369 optype0 = PUSHOP;
1370 else if (GET_CODE (operands[0]) == MEM)
1371 optype0 = MEMOP;
1372 else
1373 optype0 = RNDOP;
1374
1375 if (REG_P (operands[1]))
1376 optype1 = REGOP;
1377 else if (CONSTANT_P (operands[1]))
1378 optype1 = CNSTOP;
1379 else if (offsettable_memref_p (operands[1]))
1380 optype1 = OFFSOP;
1381 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
1382 optype1 = POPOP;
1383 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
1384 optype1 = PUSHOP;
1385 else if (GET_CODE (operands[1]) == MEM)
1386 optype1 = MEMOP;
1387 else
1388 optype1 = RNDOP;
1389
1390 /* Check for the cases that the operand constraints are not
1391 supposed to allow to happen. Abort if we get one,
1392 because generating code for these cases is painful. */
1393
1394 if (optype0 == RNDOP || optype1 == RNDOP)
1395 abort ();
1396
1397 /* If one operand is decrementing and one is incrementing
1398 decrement the former register explicitly
1399 and change that operand into ordinary indexing. */
1400
1401 if (optype0 == PUSHOP && optype1 == POPOP)
1402 {
1403 operands[0] = XEXP (XEXP (operands[0], 0), 0);
1404 if (size == 12)
1405 output_asm_insn ("sub%.l %#12,%0", operands);
1406 else
1407 output_asm_insn ("subq%.l %#8,%0", operands);
1408 if (GET_MODE (operands[1]) == XFmode)
1409 operands[0] = gen_rtx (MEM, XFmode, operands[0]);
1410 else if (GET_MODE (operands[0]) == DFmode)
1411 operands[0] = gen_rtx (MEM, DFmode, operands[0]);
1412 else
1413 operands[0] = gen_rtx (MEM, DImode, operands[0]);
1414 optype0 = OFFSOP;
1415 }
1416 if (optype0 == POPOP && optype1 == PUSHOP)
1417 {
1418 operands[1] = XEXP (XEXP (operands[1], 0), 0);
1419 if (size == 12)
1420 output_asm_insn ("sub%.l %#12,%1", operands);
1421 else
1422 output_asm_insn ("subq%.l %#8,%1", operands);
1423 if (GET_MODE (operands[1]) == XFmode)
1424 operands[1] = gen_rtx (MEM, XFmode, operands[1]);
1425 else if (GET_MODE (operands[1]) == DFmode)
1426 operands[1] = gen_rtx (MEM, DFmode, operands[1]);
1427 else
1428 operands[1] = gen_rtx (MEM, DImode, operands[1]);
1429 optype1 = OFFSOP;
1430 }
1431
1432 /* If an operand is an unoffsettable memory ref, find a register
1433 we can increment temporarily to make it refer to the second word. */
1434
1435 if (optype0 == MEMOP)
1436 addreg0 = find_addr_reg (XEXP (operands[0], 0));
1437
1438 if (optype1 == MEMOP)
1439 addreg1 = find_addr_reg (XEXP (operands[1], 0));
1440
1441 /* Ok, we can do one word at a time.
1442 Normally we do the low-numbered word first,
1443 but if either operand is autodecrementing then we
1444 do the high-numbered word first.
1445
1446 In either case, set up in LATEHALF the operands to use
1447 for the high-numbered word and in some cases alter the
1448 operands in OPERANDS to be suitable for the low-numbered word. */
1449
1450 if (size == 12)
1451 {
1452 if (optype0 == REGOP)
1453 {
1454 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
1455 middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1456 }
1457 else if (optype0 == OFFSOP)
1458 {
1459 middlehalf[0] = adj_offsettable_operand (operands[0], 4);
1460 latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1461 }
1462 else
1463 {
1464 middlehalf[0] = operands[0];
1465 latehalf[0] = operands[0];
1466 }
1467
1468 if (optype1 == REGOP)
1469 {
1470 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
1471 middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1472 }
1473 else if (optype1 == OFFSOP)
1474 {
1475 middlehalf[1] = adj_offsettable_operand (operands[1], 4);
1476 latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1477 }
1478 else if (optype1 == CNSTOP)
1479 {
1480 if (GET_CODE (operands[1]) == CONST_DOUBLE)
1481 {
1482 REAL_VALUE_TYPE r;
1483 long l[3];
1484
1485 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
1486 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
1487 operands[1] = GEN_INT (l[0]);
1488 middlehalf[1] = GEN_INT (l[1]);
1489 latehalf[1] = GEN_INT (l[2]);
1490 }
1491 else if (CONSTANT_P (operands[1]))
1492 {
1493 /* actually, no non-CONST_DOUBLE constant should ever
1494 appear here. */
1495 abort ();
1496 if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
1497 latehalf[1] = constm1_rtx;
1498 else
1499 latehalf[1] = const0_rtx;
1500 }
1501 }
1502 else
1503 {
1504 middlehalf[1] = operands[1];
1505 latehalf[1] = operands[1];
1506 }
1507 }
1508 else
1509 /* size is not 12: */
1510 {
1511 if (optype0 == REGOP)
1512 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1513 else if (optype0 == OFFSOP)
1514 latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1515 else
1516 latehalf[0] = operands[0];
1517
1518 if (optype1 == REGOP)
1519 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1520 else if (optype1 == OFFSOP)
1521 latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1522 else if (optype1 == CNSTOP)
1523 split_double (operands[1], &operands[1], &latehalf[1]);
1524 else
1525 latehalf[1] = operands[1];
1526 }
1527
1528 /* If insn is effectively movd N(sp),-(sp) then we will do the
1529 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1530 for the low word as well, to compensate for the first decrement of sp. */
1531 if (optype0 == PUSHOP
1532 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1533 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1534 operands[1] = middlehalf[1] = latehalf[1];
1535
1536 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1537 if the upper part of reg N does not appear in the MEM, arrange to
1538 emit the move late-half first. Otherwise, compute the MEM address
1539 into the upper part of N and use that as a pointer to the memory
1540 operand. */
1541 if (optype0 == REGOP
1542 && (optype1 == OFFSOP || optype1 == MEMOP))
1543 {
1544 rtx testlow = gen_rtx (REG, SImode, REGNO (operands[0]));
1545
1546 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1547 && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1548 {
1549 /* If both halves of dest are used in the src memory address,
1550 compute the address into latehalf of dest.
1551 Note that this can't happen if the dest is two data regs. */
1552 compadr:
1553 xops[0] = latehalf[0];
1554 xops[1] = XEXP (operands[1], 0);
1555 output_asm_insn ("lea %a1,%0", xops);
1556 if( GET_MODE (operands[1]) == XFmode )
1557 {
1558 operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
1559 middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
1560 latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1561 }
1562 else
1563 {
1564 operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
1565 latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1566 }
1567 }
1568 else if (size == 12
1569 && reg_overlap_mentioned_p (middlehalf[0],
1570 XEXP (operands[1], 0)))
1571 {
1572 /* Check for two regs used by both source and dest.
1573 Note that this can't happen if the dest is all data regs.
1574 It can happen if the dest is d6, d7, a0.
1575 But in that case, latehalf is an addr reg, so
1576 the code at compadr does ok. */
1577
1578 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1579 || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1580 goto compadr;
1581
1582 /* JRV says this can't happen: */
1583 if (addreg0 || addreg1)
1584 abort ();
1585
1586 /* Only the middle reg conflicts; simply put it last. */
1587 output_asm_insn (singlemove_string (operands), operands);
1588 output_asm_insn (singlemove_string (latehalf), latehalf);
1589 output_asm_insn (singlemove_string (middlehalf), middlehalf);
1590 return "";
1591 }
1592 else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
1593 /* If the low half of dest is mentioned in the source memory
1594 address, the arrange to emit the move late half first. */
1595 dest_overlapped_low = 1;
1596 }
1597
1598 /* If one or both operands autodecrementing,
1599 do the two words, high-numbered first. */
1600
1601 /* Likewise, the first move would clobber the source of the second one,
1602 do them in the other order. This happens only for registers;
1603 such overlap can't happen in memory unless the user explicitly
1604 sets it up, and that is an undefined circumstance. */
1605
1606 if (optype0 == PUSHOP || optype1 == PUSHOP
1607 || (optype0 == REGOP && optype1 == REGOP
1608 && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
1609 || REGNO (operands[0]) == REGNO (latehalf[1])))
1610 || dest_overlapped_low)
1611 {
1612 /* Make any unoffsettable addresses point at high-numbered word. */
1613 if (addreg0)
1614 {
1615 if (size == 12)
1616 output_asm_insn ("addq%.l %#8,%0", &addreg0);
1617 else
1618 output_asm_insn ("addq%.l %#4,%0", &addreg0);
1619 }
1620 if (addreg1)
1621 {
1622 if (size == 12)
1623 output_asm_insn ("addq%.l %#8,%0", &addreg1);
1624 else
1625 output_asm_insn ("addq%.l %#4,%0", &addreg1);
1626 }
1627
1628 /* Do that word. */
1629 output_asm_insn (singlemove_string (latehalf), latehalf);
1630
1631 /* Undo the adds we just did. */
1632 if (addreg0)
1633 output_asm_insn ("subq%.l %#4,%0", &addreg0);
1634 if (addreg1)
1635 output_asm_insn ("subq%.l %#4,%0", &addreg1);
1636
1637 if (size == 12)
1638 {
1639 output_asm_insn (singlemove_string (middlehalf), middlehalf);
1640 if (addreg0)
1641 output_asm_insn ("subq%.l %#4,%0", &addreg0);
1642 if (addreg1)
1643 output_asm_insn ("subq%.l %#4,%0", &addreg1);
1644 }
1645
1646 /* Do low-numbered word. */
1647 return singlemove_string (operands);
1648 }
1649
1650 /* Normal case: do the two words, low-numbered first. */
1651
1652 output_asm_insn (singlemove_string (operands), operands);
1653
1654 /* Do the middle one of the three words for long double */
1655 if (size == 12)
1656 {
1657 if (addreg0)
1658 output_asm_insn ("addq%.l %#4,%0", &addreg0);
1659 if (addreg1)
1660 output_asm_insn ("addq%.l %#4,%0", &addreg1);
1661
1662 output_asm_insn (singlemove_string (middlehalf), middlehalf);
1663 }
1664
1665 /* Make any unoffsettable addresses point at high-numbered word. */
1666 if (addreg0)
1667 output_asm_insn ("addq%.l %#4,%0", &addreg0);
1668 if (addreg1)
1669 output_asm_insn ("addq%.l %#4,%0", &addreg1);
1670
1671 /* Do that word. */
1672 output_asm_insn (singlemove_string (latehalf), latehalf);
1673
1674 /* Undo the adds we just did. */
1675 if (addreg0)
1676 {
1677 if (size == 12)
1678 output_asm_insn ("subq%.l %#8,%0", &addreg0);
1679 else
1680 output_asm_insn ("subq%.l %#4,%0", &addreg0);
1681 }
1682 if (addreg1)
1683 {
1684 if (size == 12)
1685 output_asm_insn ("subq%.l %#8,%0", &addreg1);
1686 else
1687 output_asm_insn ("subq%.l %#4,%0", &addreg1);
1688 }
1689
1690 return "";
1691 }
1692
1693 /* Return a REG that occurs in ADDR with coefficient 1.
1694 ADDR can be effectively incremented by incrementing REG. */
1695
1696 static rtx
1697 find_addr_reg (addr)
1698 rtx addr;
1699 {
1700 while (GET_CODE (addr) == PLUS)
1701 {
1702 if (GET_CODE (XEXP (addr, 0)) == REG)
1703 addr = XEXP (addr, 0);
1704 else if (GET_CODE (XEXP (addr, 1)) == REG)
1705 addr = XEXP (addr, 1);
1706 else if (CONSTANT_P (XEXP (addr, 0)))
1707 addr = XEXP (addr, 1);
1708 else if (CONSTANT_P (XEXP (addr, 1)))
1709 addr = XEXP (addr, 0);
1710 else
1711 abort ();
1712 }
1713 if (GET_CODE (addr) == REG)
1714 return addr;
1715 abort ();
1716 }
1717 \f
1718 /* Store in cc_status the expressions that the condition codes will
1719 describe after execution of an instruction whose pattern is EXP.
1720 Do not alter them if the instruction would not alter the cc's. */
1721
1722 /* On the 68000, all the insns to store in an address register fail to
1723 set the cc's. However, in some cases these instructions can make it
1724 possibly invalid to use the saved cc's. In those cases we clear out
1725 some or all of the saved cc's so they won't be used. */
1726
1727 notice_update_cc (exp, insn)
1728 rtx exp;
1729 rtx insn;
1730 {
1731 /* If the cc is being set from the fpa and the expression is not an
1732 explicit floating point test instruction (which has code to deal with
1733 this), reinit the CC. */
1734 if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
1735 || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
1736 && !(GET_CODE (exp) == PARALLEL
1737 && GET_CODE (XVECEXP (exp, 0, 0)) == SET
1738 && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
1739 {
1740 CC_STATUS_INIT;
1741 }
1742 else if (GET_CODE (exp) == SET)
1743 {
1744 if (GET_CODE (SET_SRC (exp)) == CALL)
1745 {
1746 CC_STATUS_INIT;
1747 }
1748 else if (ADDRESS_REG_P (SET_DEST (exp)))
1749 {
1750 if (cc_status.value1
1751 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1752 cc_status.value1 = 0;
1753 if (cc_status.value2
1754 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1755 cc_status.value2 = 0;
1756 }
1757 else if (!FP_REG_P (SET_DEST (exp))
1758 && SET_DEST (exp) != cc0_rtx
1759 && (FP_REG_P (SET_SRC (exp))
1760 || GET_CODE (SET_SRC (exp)) == FIX
1761 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
1762 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
1763 {
1764 CC_STATUS_INIT;
1765 }
1766 /* A pair of move insns doesn't produce a useful overall cc. */
1767 else if (!FP_REG_P (SET_DEST (exp))
1768 && !FP_REG_P (SET_SRC (exp))
1769 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
1770 && (GET_CODE (SET_SRC (exp)) == REG
1771 || GET_CODE (SET_SRC (exp)) == MEM
1772 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
1773 {
1774 CC_STATUS_INIT;
1775 }
1776 else if (GET_CODE (SET_SRC (exp)) == CALL)
1777 {
1778 CC_STATUS_INIT;
1779 }
1780 else if (XEXP (exp, 0) != pc_rtx)
1781 {
1782 cc_status.flags = 0;
1783 cc_status.value1 = XEXP (exp, 0);
1784 cc_status.value2 = XEXP (exp, 1);
1785 }
1786 }
1787 else if (GET_CODE (exp) == PARALLEL
1788 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1789 {
1790 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
1791 CC_STATUS_INIT;
1792 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
1793 {
1794 cc_status.flags = 0;
1795 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
1796 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
1797 }
1798 }
1799 else
1800 CC_STATUS_INIT;
1801 if (cc_status.value2 != 0
1802 && ADDRESS_REG_P (cc_status.value2)
1803 && GET_MODE (cc_status.value2) == QImode)
1804 CC_STATUS_INIT;
1805 if (cc_status.value2 != 0
1806 && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
1807 switch (GET_CODE (cc_status.value2))
1808 {
1809 case PLUS: case MINUS: case MULT:
1810 case DIV: case UDIV: case MOD: case UMOD: case NEG:
1811 #if 0 /* These instructions always clear the overflow bit */
1812 case ASHIFT: case ASHIFTRT: case LSHIFTRT:
1813 case ROTATE: case ROTATERT:
1814 #endif
1815 if (GET_MODE (cc_status.value2) != VOIDmode)
1816 cc_status.flags |= CC_NO_OVERFLOW;
1817 break;
1818 case ZERO_EXTEND:
1819 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1820 ends with a move insn moving r2 in r2's mode.
1821 Thus, the cc's are set for r2.
1822 This can set N bit spuriously. */
1823 cc_status.flags |= CC_NOT_NEGATIVE;
1824 }
1825 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1826 && cc_status.value2
1827 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1828 cc_status.value2 = 0;
1829 if (((cc_status.value1 && FP_REG_P (cc_status.value1))
1830 || (cc_status.value2 && FP_REG_P (cc_status.value2)))
1831 && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
1832 || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
1833 cc_status.flags = CC_IN_68881;
1834 }
1835 \f
1836 char *
1837 output_move_const_double (operands)
1838 rtx *operands;
1839 {
1840 #ifdef SUPPORT_SUN_FPA
1841 if (TARGET_FPA && FPA_REG_P (operands[0]))
1842 {
1843 int code = standard_sun_fpa_constant_p (operands[1]);
1844
1845 if (code != 0)
1846 {
1847 static char buf[40];
1848
1849 sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
1850 return buf;
1851 }
1852 return "fpmove%.d %1,%0";
1853 }
1854 else
1855 #endif
1856 {
1857 int code = standard_68881_constant_p (operands[1]);
1858
1859 if (code != 0)
1860 {
1861 static char buf[40];
1862
1863 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1864 return buf;
1865 }
1866 return "fmove%.d %1,%0";
1867 }
1868 }
1869
1870 char *
1871 output_move_const_single (operands)
1872 rtx *operands;
1873 {
1874 #ifdef SUPPORT_SUN_FPA
1875 if (TARGET_FPA)
1876 {
1877 int code = standard_sun_fpa_constant_p (operands[1]);
1878
1879 if (code != 0)
1880 {
1881 static char buf[40];
1882
1883 sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
1884 return buf;
1885 }
1886 return "fpmove%.s %1,%0";
1887 }
1888 else
1889 #endif /* defined SUPPORT_SUN_FPA */
1890 {
1891 int code = standard_68881_constant_p (operands[1]);
1892
1893 if (code != 0)
1894 {
1895 static char buf[40];
1896
1897 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1898 return buf;
1899 }
1900 return "fmove%.s %f1,%0";
1901 }
1902 }
1903
1904 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1905 from the "fmovecr" instruction.
1906 The value, anded with 0xff, gives the code to use in fmovecr
1907 to get the desired constant. */
1908
1909 /* This code has been fixed for cross-compilation. */
1910
1911 static int inited_68881_table = 0;
1912
1913 char *strings_68881[7] = {
1914 "0.0",
1915 "1.0",
1916 "10.0",
1917 "100.0",
1918 "10000.0",
1919 "1e8",
1920 "1e16"
1921 };
1922
1923 int codes_68881[7] = {
1924 0x0f,
1925 0x32,
1926 0x33,
1927 0x34,
1928 0x35,
1929 0x36,
1930 0x37
1931 };
1932
1933 REAL_VALUE_TYPE values_68881[7];
1934
1935 /* Set up values_68881 array by converting the decimal values
1936 strings_68881 to binary. */
1937
1938 void
1939 init_68881_table ()
1940 {
1941 int i;
1942 REAL_VALUE_TYPE r;
1943 enum machine_mode mode;
1944
1945 mode = SFmode;
1946 for (i = 0; i < 7; i++)
1947 {
1948 if (i == 6)
1949 mode = DFmode;
1950 r = REAL_VALUE_ATOF (strings_68881[i], mode);
1951 values_68881[i] = r;
1952 }
1953 inited_68881_table = 1;
1954 }
1955
1956 int
1957 standard_68881_constant_p (x)
1958 rtx x;
1959 {
1960 REAL_VALUE_TYPE r;
1961 int i;
1962 enum machine_mode mode;
1963
1964 #ifdef NO_ASM_FMOVECR
1965 return 0;
1966 #endif
1967
1968 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1969 if (TARGET_68040)
1970 return 0;
1971
1972 #ifndef REAL_ARITHMETIC
1973 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1974 if (! flag_pretend_float)
1975 return 0;
1976 #endif
1977 #endif
1978
1979 if (! inited_68881_table)
1980 init_68881_table ();
1981
1982 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1983
1984 for (i = 0; i < 6; i++)
1985 {
1986 if (REAL_VALUES_EQUAL (r, values_68881[i]))
1987 return (codes_68881[i]);
1988 }
1989
1990 if (GET_MODE (x) == SFmode)
1991 return 0;
1992
1993 if (REAL_VALUES_EQUAL (r, values_68881[6]))
1994 return (codes_68881[6]);
1995
1996 /* larger powers of ten in the constants ram are not used
1997 because they are not equal to a `double' C constant. */
1998 return 0;
1999 }
2000
2001 /* If X is a floating-point constant, return the logarithm of X base 2,
2002 or 0 if X is not a power of 2. */
2003
2004 int
2005 floating_exact_log2 (x)
2006 rtx x;
2007 {
2008 REAL_VALUE_TYPE r, r1;
2009 int i;
2010
2011 #ifndef REAL_ARITHMETIC
2012 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2013 if (! flag_pretend_float)
2014 return 0;
2015 #endif
2016 #endif
2017
2018 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2019
2020 if (REAL_VALUES_LESS (r, dconst0))
2021 return 0;
2022
2023 r1 = dconst1;
2024 i = 0;
2025 while (REAL_VALUES_LESS (r1, r))
2026 {
2027 r1 = REAL_VALUE_LDEXP (dconst1, i);
2028 if (REAL_VALUES_EQUAL (r1, r))
2029 return i;
2030 i = i + 1;
2031 }
2032 return 0;
2033 }
2034 \f
2035 #ifdef SUPPORT_SUN_FPA
2036 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
2037 from the Sun FPA's constant RAM.
2038 The value returned, anded with 0x1ff, gives the code to use in fpmove
2039 to get the desired constant. */
2040
2041 static int inited_FPA_table = 0;
2042
2043 char *strings_FPA[38] = {
2044 /* small rationals */
2045 "0.0",
2046 "1.0",
2047 "0.5",
2048 "-1.0",
2049 "2.0",
2050 "3.0",
2051 "4.0",
2052 "8.0",
2053 "0.25",
2054 "0.125",
2055 "10.0",
2056 "-0.5",
2057 /* Decimal equivalents of double precision values */
2058 "2.718281828459045091", /* D_E */
2059 "6.283185307179586477", /* 2 pi */
2060 "3.141592653589793116", /* D_PI */
2061 "1.570796326794896619", /* pi/2 */
2062 "1.414213562373095145", /* D_SQRT2 */
2063 "0.7071067811865475244", /* 1/sqrt(2) */
2064 "-1.570796326794896619", /* -pi/2 */
2065 "1.442695040888963387", /* D_LOG2ofE */
2066 "3.321928024887362182", /* D_LOG2of10 */
2067 "0.6931471805599452862", /* D_LOGEof2 */
2068 "2.302585092994045901", /* D_LOGEof10 */
2069 "0.3010299956639811980", /* D_LOG10of2 */
2070 "0.4342944819032518167", /* D_LOG10ofE */
2071 /* Decimal equivalents of single precision values */
2072 "2.718281745910644531", /* S_E */
2073 "6.283185307179586477", /* 2 pi */
2074 "3.141592741012573242", /* S_PI */
2075 "1.570796326794896619", /* pi/2 */
2076 "1.414213538169860840", /* S_SQRT2 */
2077 "0.7071067811865475244", /* 1/sqrt(2) */
2078 "-1.570796326794896619", /* -pi/2 */
2079 "1.442695021629333496", /* S_LOG2ofE */
2080 "3.321928024291992188", /* S_LOG2of10 */
2081 "0.6931471824645996094", /* S_LOGEof2 */
2082 "2.302585124969482442", /* S_LOGEof10 */
2083 "0.3010300099849700928", /* S_LOG10of2 */
2084 "0.4342944920063018799", /* S_LOG10ofE */
2085 };
2086
2087
2088 int codes_FPA[38] = {
2089 /* small rationals */
2090 0x200,
2091 0xe,
2092 0xf,
2093 0x10,
2094 0x11,
2095 0xb1,
2096 0x12,
2097 0x13,
2098 0x15,
2099 0x16,
2100 0x17,
2101 0x2e,
2102 /* double precision */
2103 0x8,
2104 0x9,
2105 0xa,
2106 0xb,
2107 0xc,
2108 0xd,
2109 0x27,
2110 0x28,
2111 0x29,
2112 0x2a,
2113 0x2b,
2114 0x2c,
2115 0x2d,
2116 /* single precision */
2117 0x8,
2118 0x9,
2119 0xa,
2120 0xb,
2121 0xc,
2122 0xd,
2123 0x27,
2124 0x28,
2125 0x29,
2126 0x2a,
2127 0x2b,
2128 0x2c,
2129 0x2d
2130 };
2131
2132 REAL_VALUE_TYPE values_FPA[38];
2133
2134 /* This code has been fixed for cross-compilation. */
2135
2136 void
2137 init_FPA_table ()
2138 {
2139 enum machine_mode mode;
2140 int i;
2141 REAL_VALUE_TYPE r;
2142
2143 mode = DFmode;
2144 for (i = 0; i < 38; i++)
2145 {
2146 if (i == 25)
2147 mode = SFmode;
2148 r = REAL_VALUE_ATOF (strings_FPA[i], mode);
2149 values_FPA[i] = r;
2150 }
2151 inited_FPA_table = 1;
2152 }
2153
2154
2155 int
2156 standard_sun_fpa_constant_p (x)
2157 rtx x;
2158 {
2159 REAL_VALUE_TYPE r;
2160 int i;
2161
2162 #ifndef REAL_ARITHMETIC
2163 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2164 if (! flag_pretend_float)
2165 return 0;
2166 #endif
2167 #endif
2168
2169 if (! inited_FPA_table)
2170 init_FPA_table ();
2171
2172 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2173
2174 for (i=0; i<12; i++)
2175 {
2176 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2177 return (codes_FPA[i]);
2178 }
2179
2180 if (GET_MODE (x) == SFmode)
2181 {
2182 for (i=25; i<38; i++)
2183 {
2184 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2185 return (codes_FPA[i]);
2186 }
2187 }
2188 else
2189 {
2190 for (i=12; i<25; i++)
2191 {
2192 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
2193 return (codes_FPA[i]);
2194 }
2195 }
2196 return 0x0;
2197 }
2198 #endif /* define SUPPORT_SUN_FPA */
2199 \f
2200 /* A C compound statement to output to stdio stream STREAM the
2201 assembler syntax for an instruction operand X. X is an RTL
2202 expression.
2203
2204 CODE is a value that can be used to specify one of several ways
2205 of printing the operand. It is used when identical operands
2206 must be printed differently depending on the context. CODE
2207 comes from the `%' specification that was used to request
2208 printing of the operand. If the specification was just `%DIGIT'
2209 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
2210 is the ASCII code for LTR.
2211
2212 If X is a register, this macro should print the register's name.
2213 The names can be found in an array `reg_names' whose type is
2214 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2215
2216 When the machine description has a specification `%PUNCT' (a `%'
2217 followed by a punctuation character), this macro is called with
2218 a null pointer for X and the punctuation character for CODE.
2219
2220 The m68k specific codes are:
2221
2222 '.' for dot needed in Motorola-style opcode names.
2223 '-' for an operand pushing on the stack:
2224 sp@-, -(sp) or -(%sp) depending on the style of syntax.
2225 '+' for an operand pushing on the stack:
2226 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
2227 '@' for a reference to the top word on the stack:
2228 sp@, (sp) or (%sp) depending on the style of syntax.
2229 '#' for an immediate operand prefix (# in MIT and Motorola syntax
2230 but & in SGS syntax).
2231 '!' for the cc register (used in an `and to cc' insn).
2232 '$' for the letter `s' in an op code, but only on the 68040.
2233 '&' for the letter `d' in an op code, but only on the 68040.
2234 '/' for register prefix needed by longlong.h.
2235
2236 'b' for byte insn (no effect, on the Sun; this is for the ISI).
2237 'd' to force memory addressing to be absolute, not relative.
2238 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
2239 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
2240 than directly). Second part of 'y' below.
2241 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
2242 or print pair of registers as rx:ry.
2243 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
2244 CONST_DOUBLE's as SunFPA constant RAM registers if
2245 possible, so it should not be used except for the SunFPA.
2246
2247 */
2248
2249 void
2250 print_operand (file, op, letter)
2251 FILE *file; /* file to write to */
2252 rtx op; /* operand to print */
2253 int letter; /* %<letter> or 0 */
2254 {
2255 int i;
2256
2257 if (letter == '.')
2258 {
2259 #ifdef MOTOROLA
2260 asm_fprintf (file, ".");
2261 #endif
2262 }
2263 else if (letter == '#')
2264 {
2265 asm_fprintf (file, "%0I");
2266 }
2267 else if (letter == '-')
2268 {
2269 #ifdef MOTOROLA
2270 asm_fprintf (file, "-(%Rsp)");
2271 #else
2272 asm_fprintf (file, "%Rsp@-");
2273 #endif
2274 }
2275 else if (letter == '+')
2276 {
2277 #ifdef MOTOROLA
2278 asm_fprintf (file, "(%Rsp)+");
2279 #else
2280 asm_fprintf (file, "%Rsp@+");
2281 #endif
2282 }
2283 else if (letter == '@')
2284 {
2285 #ifdef MOTOROLA
2286 asm_fprintf (file, "(%Rsp)");
2287 #else
2288 asm_fprintf (file, "%Rsp@");
2289 #endif
2290 }
2291 else if (letter == '!')
2292 {
2293 asm_fprintf (file, "%Rfpcr");
2294 }
2295 else if (letter == '$')
2296 {
2297 if (TARGET_68040_ONLY)
2298 {
2299 fprintf (file, "s");
2300 }
2301 }
2302 else if (letter == '&')
2303 {
2304 if (TARGET_68040_ONLY)
2305 {
2306 fprintf (file, "d");
2307 }
2308 }
2309 else if (letter == '/')
2310 {
2311 asm_fprintf (file, "%R");
2312 }
2313 else if (GET_CODE (op) == REG)
2314 {
2315 #ifdef SUPPORT_SUN_FPA
2316 if (REGNO (op) < 16
2317 && (letter == 'y' || letter == 'x')
2318 && GET_MODE (op) == DFmode)
2319 {
2320 fprintf (file, "%s:%s", reg_names[REGNO (op)],
2321 reg_names[REGNO (op)+1]);
2322 }
2323 else
2324 #endif
2325 {
2326 if (letter == 'R')
2327 /* Print out the second register name of a register pair.
2328 I.e., R (6) => 7. */
2329 fputs (reg_names[REGNO (op) + 1], file);
2330 else
2331 fputs (reg_names[REGNO (op)], file);
2332 }
2333 }
2334 else if (GET_CODE (op) == MEM)
2335 {
2336 output_address (XEXP (op, 0));
2337 if (letter == 'd' && ! TARGET_68020
2338 && CONSTANT_ADDRESS_P (XEXP (op, 0))
2339 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
2340 && INTVAL (XEXP (op, 0)) < 0x8000
2341 && INTVAL (XEXP (op, 0)) >= -0x8000))
2342 {
2343 #ifdef MOTOROLA
2344 fprintf (file, ".l");
2345 #else
2346 fprintf (file, ":l");
2347 #endif
2348 }
2349 }
2350 #ifdef SUPPORT_SUN_FPA
2351 else if ((letter == 'y' || letter == 'w')
2352 && GET_CODE (op) == CONST_DOUBLE
2353 && (i = standard_sun_fpa_constant_p (op)))
2354 {
2355 fprintf (file, "%%%d", i & 0x1ff);
2356 }
2357 #endif
2358 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
2359 {
2360 REAL_VALUE_TYPE r;
2361 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2362 ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
2363 }
2364 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
2365 {
2366 REAL_VALUE_TYPE r;
2367 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2368 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
2369 }
2370 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
2371 {
2372 REAL_VALUE_TYPE r;
2373 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2374 ASM_OUTPUT_DOUBLE_OPERAND (file, r);
2375 }
2376 else
2377 {
2378 asm_fprintf (file, "%0I"); output_addr_const (file, op);
2379 }
2380 }
2381
2382 \f
2383 /* A C compound statement to output to stdio stream STREAM the
2384 assembler syntax for an instruction operand that is a memory
2385 reference whose address is ADDR. ADDR is an RTL expression.
2386
2387 Note that this contains a kludge that knows that the only reason
2388 we have an address (plus (label_ref...) (reg...)) when not generating
2389 PIC code is in the insn before a tablejump, and we know that m68k.md
2390 generates a label LInnn: on such an insn.
2391
2392 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2393 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2394
2395 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2396 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2397 we want. This difference can be accommodated by using an assembler
2398 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2399 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2400 macro. See m68k/sgs.h for an example; for versions without the bug.
2401 Some assemblers refuse all the above solutions. The workaround is to
2402 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2403 right behaviour.
2404
2405 They also do not like things like "pea 1.w", so we simple leave off
2406 the .w on small constants.
2407
2408 This routine is responsible for distinguishing between -fpic and -fPIC
2409 style relocations in an address. When generating -fpic code the
2410 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2411 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2412
2413 #ifndef ASM_OUTPUT_CASE_FETCH
2414 #ifdef MOTOROLA
2415 #ifdef SGS
2416 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2417 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2418 #else
2419 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2420 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2421 #endif
2422 #else
2423 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2424 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2425 #endif
2426 #endif /* ASM_OUTPUT_CASE_FETCH */
2427
2428 void
2429 print_operand_address (file, addr)
2430 FILE *file;
2431 rtx addr;
2432 {
2433 register rtx reg1, reg2, breg, ireg;
2434 rtx offset;
2435
2436 switch (GET_CODE (addr))
2437 {
2438 case REG:
2439 #ifdef MOTOROLA
2440 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
2441 #else
2442 fprintf (file, "%s@", reg_names[REGNO (addr)]);
2443 #endif
2444 break;
2445 case PRE_DEC:
2446 #ifdef MOTOROLA
2447 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
2448 #else
2449 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
2450 #endif
2451 break;
2452 case POST_INC:
2453 #ifdef MOTOROLA
2454 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
2455 #else
2456 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
2457 #endif
2458 break;
2459 case PLUS:
2460 reg1 = reg2 = ireg = breg = offset = 0;
2461 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
2462 {
2463 offset = XEXP (addr, 0);
2464 addr = XEXP (addr, 1);
2465 }
2466 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
2467 {
2468 offset = XEXP (addr, 1);
2469 addr = XEXP (addr, 0);
2470 }
2471 if (GET_CODE (addr) != PLUS)
2472 {
2473 ;
2474 }
2475 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
2476 {
2477 reg1 = XEXP (addr, 0);
2478 addr = XEXP (addr, 1);
2479 }
2480 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
2481 {
2482 reg1 = XEXP (addr, 1);
2483 addr = XEXP (addr, 0);
2484 }
2485 else if (GET_CODE (XEXP (addr, 0)) == MULT)
2486 {
2487 reg1 = XEXP (addr, 0);
2488 addr = XEXP (addr, 1);
2489 }
2490 else if (GET_CODE (XEXP (addr, 1)) == MULT)
2491 {
2492 reg1 = XEXP (addr, 1);
2493 addr = XEXP (addr, 0);
2494 }
2495 else if (GET_CODE (XEXP (addr, 0)) == REG)
2496 {
2497 reg1 = XEXP (addr, 0);
2498 addr = XEXP (addr, 1);
2499 }
2500 else if (GET_CODE (XEXP (addr, 1)) == REG)
2501 {
2502 reg1 = XEXP (addr, 1);
2503 addr = XEXP (addr, 0);
2504 }
2505 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
2506 || GET_CODE (addr) == SIGN_EXTEND)
2507 {
2508 if (reg1 == 0)
2509 {
2510 reg1 = addr;
2511 }
2512 else
2513 {
2514 reg2 = addr;
2515 }
2516 addr = 0;
2517 }
2518 #if 0 /* for OLD_INDEXING */
2519 else if (GET_CODE (addr) == PLUS)
2520 {
2521 if (GET_CODE (XEXP (addr, 0)) == REG)
2522 {
2523 reg2 = XEXP (addr, 0);
2524 addr = XEXP (addr, 1);
2525 }
2526 else if (GET_CODE (XEXP (addr, 1)) == REG)
2527 {
2528 reg2 = XEXP (addr, 1);
2529 addr = XEXP (addr, 0);
2530 }
2531 }
2532 #endif
2533 if (offset != 0)
2534 {
2535 if (addr != 0)
2536 {
2537 abort ();
2538 }
2539 addr = offset;
2540 }
2541 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
2542 || GET_CODE (reg1) == MULT))
2543 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2544 {
2545 breg = reg2;
2546 ireg = reg1;
2547 }
2548 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2549 {
2550 breg = reg1;
2551 ireg = reg2;
2552 }
2553 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
2554 && ! (flag_pic && ireg == pic_offset_table_rtx))
2555 {
2556 int scale = 1;
2557 if (GET_CODE (ireg) == MULT)
2558 {
2559 scale = INTVAL (XEXP (ireg, 1));
2560 ireg = XEXP (ireg, 0);
2561 }
2562 if (GET_CODE (ireg) == SIGN_EXTEND)
2563 {
2564 ASM_OUTPUT_CASE_FETCH (file,
2565 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2566 reg_names[REGNO (XEXP (ireg, 0))]);
2567 fprintf (file, "w");
2568 }
2569 else
2570 {
2571 ASM_OUTPUT_CASE_FETCH (file,
2572 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2573 reg_names[REGNO (ireg)]);
2574 fprintf (file, "l");
2575 }
2576 if (scale != 1)
2577 {
2578 #ifdef MOTOROLA
2579 fprintf (file, "*%d", scale);
2580 #else
2581 fprintf (file, ":%d", scale);
2582 #endif
2583 }
2584 putc (')', file);
2585 break;
2586 }
2587 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
2588 && ! (flag_pic && breg == pic_offset_table_rtx))
2589 {
2590 ASM_OUTPUT_CASE_FETCH (file,
2591 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2592 reg_names[REGNO (breg)]);
2593 fprintf (file, "l)");
2594 break;
2595 }
2596 if (ireg != 0 || breg != 0)
2597 {
2598 int scale = 1;
2599 if (breg == 0)
2600 {
2601 abort ();
2602 }
2603 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
2604 {
2605 abort ();
2606 }
2607 #ifdef MOTOROLA
2608 if (addr != 0)
2609 {
2610 output_addr_const (file, addr);
2611 if (flag_pic && (breg == pic_offset_table_rtx))
2612 fprintf (file, "@GOT");
2613 }
2614 fprintf (file, "(%s", reg_names[REGNO (breg)]);
2615 if (ireg != 0)
2616 {
2617 putc (',', file);
2618 }
2619 #else
2620 fprintf (file, "%s@(", reg_names[REGNO (breg)]);
2621 if (addr != 0)
2622 {
2623 output_addr_const (file, addr);
2624 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
2625 fprintf (file, ":w");
2626 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
2627 fprintf (file, ":l");
2628 }
2629 if (addr != 0 && ireg != 0)
2630 {
2631 putc (',', file);
2632 }
2633 #endif
2634 if (ireg != 0 && GET_CODE (ireg) == MULT)
2635 {
2636 scale = INTVAL (XEXP (ireg, 1));
2637 ireg = XEXP (ireg, 0);
2638 }
2639 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
2640 {
2641 #ifdef MOTOROLA
2642 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
2643 #else
2644 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
2645 #endif
2646 }
2647 else if (ireg != 0)
2648 {
2649 #ifdef MOTOROLA
2650 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
2651 #else
2652 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
2653 #endif
2654 }
2655 if (scale != 1)
2656 {
2657 #ifdef MOTOROLA
2658 fprintf (file, "*%d", scale);
2659 #else
2660 fprintf (file, ":%d", scale);
2661 #endif
2662 }
2663 putc (')', file);
2664 break;
2665 }
2666 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
2667 && ! (flag_pic && reg1 == pic_offset_table_rtx))
2668 {
2669 ASM_OUTPUT_CASE_FETCH (file,
2670 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2671 reg_names[REGNO (reg1)]);
2672 fprintf (file, "l)");
2673 break;
2674 }
2675 /* FALL-THROUGH (is this really what we want? */
2676 default:
2677 if (GET_CODE (addr) == CONST_INT
2678 && INTVAL (addr) < 0x8000
2679 && INTVAL (addr) >= -0x8000)
2680 {
2681 #ifdef MOTOROLA
2682 #ifdef SGS
2683 /* Many SGS assemblers croak on size specifiers for constants. */
2684 fprintf (file, "%d", INTVAL (addr));
2685 #else
2686 fprintf (file, "%d.w", INTVAL (addr));
2687 #endif
2688 #else
2689 fprintf (file, "%d:w", INTVAL (addr));
2690 #endif
2691 }
2692 else
2693 {
2694 output_addr_const (file, addr);
2695 }
2696 break;
2697 }
2698 }
2699 \f
2700 /* Check for cases where a clr insns can be omitted from code using
2701 strict_low_part sets. For example, the second clrl here is not needed:
2702 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2703
2704 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2705 insn we are checking for redundancy. TARGET is the register set by the
2706 clear insn. */
2707
2708 int
2709 strict_low_part_peephole_ok (mode, first_insn, target)
2710 enum machine_mode mode;
2711 rtx first_insn;
2712 rtx target;
2713 {
2714 rtx p;
2715
2716 p = prev_nonnote_insn (first_insn);
2717
2718 while (p)
2719 {
2720 /* If it isn't an insn, then give up. */
2721 if (GET_CODE (p) != INSN)
2722 return 0;
2723
2724 if (reg_set_p (target, p))
2725 {
2726 rtx set = single_set (p);
2727 rtx dest;
2728
2729 /* If it isn't an easy to recognize insn, then give up. */
2730 if (! set)
2731 return 0;
2732
2733 dest = SET_DEST (set);
2734
2735 /* If this sets the entire target register to zero, then our
2736 first_insn is redundant. */
2737 if (rtx_equal_p (dest, target)
2738 && SET_SRC (set) == const0_rtx)
2739 return 1;
2740 else if (GET_CODE (dest) == STRICT_LOW_PART
2741 && GET_CODE (XEXP (dest, 0)) == REG
2742 && REGNO (XEXP (dest, 0)) == REGNO (target)
2743 && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
2744 <= GET_MODE_SIZE (mode)))
2745 /* This is a strict low part set which modifies less than
2746 we are using, so it is safe. */
2747 ;
2748 else
2749 return 0;
2750 }
2751
2752 p = prev_nonnote_insn (p);
2753
2754 }
2755
2756 return 0;
2757 }
2758
2759 /* Accept integer operands in the range 0..0xffffffff. We have to check the
2760 range carefully since this predicate is used in DImode contexts. Also, we
2761 need some extra crud to make it work when hosted on 64-bit machines. */
2762
2763 int
2764 const_uint32_operand (op, mode)
2765 rtx op;
2766 enum machine_mode mode;
2767 {
2768 #if HOST_BITS_PER_WIDE_INT > 32
2769 /* All allowed constants will fit a CONST_INT. */
2770 return (GET_CODE (op) == CONST_INT
2771 && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
2772 #else
2773 return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
2774 || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
2775 #endif
2776 }
2777
2778 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
2779 to check the range carefully since this predicate is used in DImode
2780 contexts. */
2781
2782 int
2783 const_sint32_operand (op, mode)
2784 rtx op;
2785 enum machine_mode mode;
2786 {
2787 /* All allowed constants will fit a CONST_INT. */
2788 return (GET_CODE (op) == CONST_INT
2789 && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
2790 }