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