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