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