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