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