(const_uint32_operand): New function.
[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_btst (operands, countop, dataop, insn, signpos)
698 rtx *operands;
699 rtx countop, dataop;
700 rtx insn;
701 int signpos;
702 {
703 operands[0] = countop;
704 operands[1] = dataop;
705
706 if (GET_CODE (countop) == CONST_INT)
707 {
708 register int count = INTVAL (countop);
709 /* If COUNT is bigger than size of storage unit in use,
710 advance to the containing unit of same size. */
711 if (count > signpos)
712 {
713 int offset = (count & ~signpos) / 8;
714 count = count & signpos;
715 operands[1] = dataop = adj_offsettable_operand (dataop, offset);
716 }
717 if (count == signpos)
718 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
719 else
720 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
721
722 /* These three statements used to use next_insns_test_no...
723 but it appears that this should do the same job. */
724 if (count == 31
725 && next_insn_tests_no_inequality (insn))
726 return "tst%.l %1";
727 if (count == 15
728 && next_insn_tests_no_inequality (insn))
729 return "tst%.w %1";
730 if (count == 7
731 && next_insn_tests_no_inequality (insn))
732 return "tst%.b %1";
733
734 cc_status.flags = CC_NOT_NEGATIVE;
735 }
736 return "btst %0,%1";
737 }
738 \f
739 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
740 reference and a constant. */
741
742 int
743 symbolic_operand (op, mode)
744 register rtx op;
745 enum machine_mode mode;
746 {
747 switch (GET_CODE (op))
748 {
749 case SYMBOL_REF:
750 case LABEL_REF:
751 return 1;
752
753 case CONST:
754 op = XEXP (op, 0);
755 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
756 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
757 && GET_CODE (XEXP (op, 1)) == CONST_INT);
758
759 #if 0 /* Deleted, with corresponding change in m68k.h,
760 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
761 case CONST_DOUBLE:
762 return GET_MODE (op) == mode;
763 #endif
764
765 default:
766 return 0;
767 }
768 }
769 \f
770 /* Check for sign_extend or zero_extend. Used for bit-count operands. */
771
772 int
773 extend_operator(x, mode)
774 rtx x;
775 enum machine_mode mode;
776 {
777 if (GET_MODE(x) != SImode)
778 return 0;
779 switch (GET_CODE(x))
780 {
781 case SIGN_EXTEND :
782 case ZERO_EXTEND :
783 break;
784 default :
785 return 0;
786 }
787 switch (GET_MODE(XEXP(x, 0)))
788 {
789 case HImode :
790 case QImode :
791 return 1;
792 default :
793 return 0;
794 }
795 }
796
797 \f
798 /* Legitimize PIC addresses. If the address is already
799 position-independent, we return ORIG. Newly generated
800 position-independent addresses go to REG. If we need more
801 than one register, we lose.
802
803 An address is legitimized by making an indirect reference
804 through the Global Offset Table with the name of the symbol
805 used as an offset.
806
807 The assembler and linker are responsible for placing the
808 address of the symbol in the GOT. The function prologue
809 is responsible for initializing a5 to the starting address
810 of the GOT.
811
812 The assembler is also responsible for translating a symbol name
813 into a constant displacement from the start of the GOT.
814
815 A quick example may make things a little clearer:
816
817 When not generating PIC code to store the value 12345 into _foo
818 we would generate the following code:
819
820 movel #12345, _foo
821
822 When generating PIC two transformations are made. First, the compiler
823 loads the address of foo into a register. So the first transformation makes:
824
825 lea _foo, a0
826 movel #12345, a0@
827
828 The code in movsi will intercept the lea instruction and call this
829 routine which will transform the instructions into:
830
831 movel a5@(_foo:w), a0
832 movel #12345, a0@
833
834
835 That (in a nutshell) is how *all* symbol and label references are
836 handled. */
837
838 rtx
839 legitimize_pic_address (orig, mode, reg)
840 rtx orig, reg;
841 enum machine_mode mode;
842 {
843 rtx pic_ref = orig;
844
845 /* First handle a simple SYMBOL_REF or LABEL_REF */
846 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
847 {
848 if (reg == 0)
849 abort ();
850
851 pic_ref = gen_rtx (MEM, Pmode,
852 gen_rtx (PLUS, Pmode,
853 pic_offset_table_rtx, orig));
854 current_function_uses_pic_offset_table = 1;
855 RTX_UNCHANGING_P (pic_ref) = 1;
856 emit_move_insn (reg, pic_ref);
857 return reg;
858 }
859 else if (GET_CODE (orig) == CONST)
860 {
861 rtx base, offset;
862
863 /* Make sure this is CONST has not already been legitimized */
864 if (GET_CODE (XEXP (orig, 0)) == PLUS
865 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
866 return orig;
867
868 if (reg == 0)
869 abort ();
870
871 /* legitimize both operands of the PLUS */
872 if (GET_CODE (XEXP (orig, 0)) == PLUS)
873 {
874 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
875 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
876 base == reg ? 0 : reg);
877 }
878 else abort ();
879
880 if (GET_CODE (orig) == CONST_INT)
881 return plus_constant_for_output (base, INTVAL (orig));
882 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
883 /* Likewise, should we set special REG_NOTEs here? */
884 }
885 return pic_ref;
886 }
887
888 \f
889 typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
890
891 use_movq (i)
892 int i;
893 {
894 return (i >= -128 && i <= 127);
895 }
896
897 CONST_METHOD
898 const_method (constant)
899 rtx constant;
900 {
901 int i;
902 unsigned u;
903
904 i = INTVAL (constant);
905 if (use_movq (i))
906 return MOVQ;
907 /* if -256 < N < 256 but N is not in range for a moveq
908 N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
909 if (use_movq (i ^ 0xff))
910 return NOTB;
911 /* Likewise, try with not.w */
912 if (use_movq (i ^ 0xffff))
913 return NOTW;
914 /* This is the only value where neg.w is usefull */
915 if (i == -65408)
916 return NEGW;
917 /* Try also with swap */
918 u = i;
919 if (use_movq ((u >> 16) | (u << 16)))
920 return SWAP;
921 /* Otherwise, use move.l */
922 return MOVL;
923 }
924
925 const_int_cost (constant)
926 rtx constant;
927 {
928 switch (const_method (constant))
929 {
930 case MOVQ :
931 /* Constants between -128 and 127 are cheap due to moveq */
932 return 0;
933 case NOTB :
934 case NOTW :
935 case NEGW :
936 case SWAP :
937 /* Constants easily generated by moveq + not.b/not.w/neg.w/swap */
938 return 1;
939 case MOVL :
940 return 2;
941 default :
942 abort ();
943 }
944 }
945
946 char *
947 output_move_const_into_data_reg (operands)
948 rtx *operands;
949 {
950 int i;
951
952 i = INTVAL (operands[1]);
953 switch (const_method (operands[1]))
954 {
955 case MOVQ :
956 #if defined (MOTOROLA) && !defined (CRDS)
957 return "moveq%.l %1,%0";
958 #else
959 return "moveq %1,%0";
960 #endif
961 case NOTB :
962 operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xff);
963 #if defined (MOTOROLA) && !defined (CRDS)
964 return "moveq%.l %1,%0\n\tnot%.b %0";
965 #else
966 return "moveq %1,%0\n\tnot%.b %0";
967 #endif
968 case NOTW :
969 operands[1] = gen_rtx (CONST_INT, VOIDmode, i ^ 0xffff);
970 #if defined (MOTOROLA) && !defined (CRDS)
971 return "moveq%.l %1,%0\n\tnot%.w %0";
972 #else
973 return "moveq %1,%0\n\tnot%.w %0";
974 #endif
975 case NEGW :
976 #if defined (MOTOROLA) && !defined (CRDS)
977 return "moveq%.l %#-128,%0\n\tneg%.w %0";
978 #else
979 return "moveq %#-128,%0\n\tneg%.w %0";
980 #endif
981 case SWAP :
982 {
983 unsigned u = i;
984
985 operands[1] = gen_rtx (CONST_INT, VOIDmode, (u << 16) | (u >> 16));
986 #if defined (MOTOROLA) && !defined (CRDS)
987 return "moveq%.l %1,%0\n\tswap %0";
988 #else
989 return "moveq %1,%0\n\tswap %0";
990 #endif
991 }
992 case MOVL :
993 return "move%.l %1,%0";
994 default :
995 abort ();
996 }
997 }
998
999 /* Return the best assembler insn template
1000 for moving operands[1] into operands[0] as a fullword. */
1001
1002 static char *
1003 singlemove_string (operands)
1004 rtx *operands;
1005 {
1006 #ifdef SUPPORT_SUN_FPA
1007 if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
1008 return "fpmoves %1,%0";
1009 #endif
1010 if (DATA_REG_P (operands[0])
1011 && GET_CODE (operands[1]) == CONST_INT)
1012 return output_move_const_into_data_reg (operands);
1013 if (operands[1] != const0_rtx)
1014 return "move%.l %1,%0";
1015 if (! ADDRESS_REG_P (operands[0]))
1016 return "clr%.l %0";
1017 return "sub%.l %0,%0";
1018 }
1019
1020
1021 /* Output assembler code to perform a doubleword move insn
1022 with operands OPERANDS. */
1023
1024 char *
1025 output_move_double (operands)
1026 rtx *operands;
1027 {
1028 enum
1029 {
1030 REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP
1031 } optype0, optype1;
1032 rtx latehalf[2];
1033 rtx middlehalf[2];
1034 rtx xops[2];
1035 rtx addreg0 = 0, addreg1 = 0;
1036 int dest_overlapped_low = 0;
1037 int size = GET_MODE_SIZE (GET_MODE (operands[0]));
1038
1039 middlehalf[0] = 0;
1040 middlehalf[1] = 0;
1041
1042 /* First classify both operands. */
1043
1044 if (REG_P (operands[0]))
1045 optype0 = REGOP;
1046 else if (offsettable_memref_p (operands[0]))
1047 optype0 = OFFSOP;
1048 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
1049 optype0 = POPOP;
1050 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
1051 optype0 = PUSHOP;
1052 else if (GET_CODE (operands[0]) == MEM)
1053 optype0 = MEMOP;
1054 else
1055 optype0 = RNDOP;
1056
1057 if (REG_P (operands[1]))
1058 optype1 = REGOP;
1059 else if (CONSTANT_P (operands[1]))
1060 optype1 = CNSTOP;
1061 else if (offsettable_memref_p (operands[1]))
1062 optype1 = OFFSOP;
1063 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
1064 optype1 = POPOP;
1065 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
1066 optype1 = PUSHOP;
1067 else if (GET_CODE (operands[1]) == MEM)
1068 optype1 = MEMOP;
1069 else
1070 optype1 = RNDOP;
1071
1072 /* Check for the cases that the operand constraints are not
1073 supposed to allow to happen. Abort if we get one,
1074 because generating code for these cases is painful. */
1075
1076 if (optype0 == RNDOP || optype1 == RNDOP)
1077 abort ();
1078
1079 /* If one operand is decrementing and one is incrementing
1080 decrement the former register explicitly
1081 and change that operand into ordinary indexing. */
1082
1083 if (optype0 == PUSHOP && optype1 == POPOP)
1084 {
1085 operands[0] = XEXP (XEXP (operands[0], 0), 0);
1086 if (size == 12)
1087 output_asm_insn ("sub%.l %#12,%0", operands);
1088 else
1089 output_asm_insn ("subq%.l %#8,%0", operands);
1090 if (GET_MODE (operands[1]) == XFmode)
1091 operands[0] = gen_rtx (MEM, XFmode, operands[0]);
1092 else if (GET_MODE (operands[0]) == DFmode)
1093 operands[0] = gen_rtx (MEM, DFmode, operands[0]);
1094 else
1095 operands[0] = gen_rtx (MEM, DImode, operands[0]);
1096 optype0 = OFFSOP;
1097 }
1098 if (optype0 == POPOP && optype1 == PUSHOP)
1099 {
1100 operands[1] = XEXP (XEXP (operands[1], 0), 0);
1101 if (size == 12)
1102 output_asm_insn ("sub%.l %#12,%1", operands);
1103 else
1104 output_asm_insn ("subq%.l %#8,%1", operands);
1105 if (GET_MODE (operands[1]) == XFmode)
1106 operands[1] = gen_rtx (MEM, XFmode, operands[1]);
1107 else if (GET_MODE (operands[1]) == DFmode)
1108 operands[1] = gen_rtx (MEM, DFmode, operands[1]);
1109 else
1110 operands[1] = gen_rtx (MEM, DImode, operands[1]);
1111 optype1 = OFFSOP;
1112 }
1113
1114 /* If an operand is an unoffsettable memory ref, find a register
1115 we can increment temporarily to make it refer to the second word. */
1116
1117 if (optype0 == MEMOP)
1118 addreg0 = find_addr_reg (XEXP (operands[0], 0));
1119
1120 if (optype1 == MEMOP)
1121 addreg1 = find_addr_reg (XEXP (operands[1], 0));
1122
1123 /* Ok, we can do one word at a time.
1124 Normally we do the low-numbered word first,
1125 but if either operand is autodecrementing then we
1126 do the high-numbered word first.
1127
1128 In either case, set up in LATEHALF the operands to use
1129 for the high-numbered word and in some cases alter the
1130 operands in OPERANDS to be suitable for the low-numbered word. */
1131
1132 if (size == 12)
1133 {
1134 if (optype0 == REGOP)
1135 {
1136 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
1137 middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1138 }
1139 else if (optype0 == OFFSOP)
1140 {
1141 middlehalf[0] = adj_offsettable_operand (operands[0], 4);
1142 latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1143 }
1144 else
1145 {
1146 middlehalf[0] = operands[0];
1147 latehalf[0] = operands[0];
1148 }
1149
1150 if (optype1 == REGOP)
1151 {
1152 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
1153 middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1154 }
1155 else if (optype1 == OFFSOP)
1156 {
1157 middlehalf[1] = adj_offsettable_operand (operands[1], 4);
1158 latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1159 }
1160 else if (optype1 == CNSTOP)
1161 {
1162 if (GET_CODE (operands[1]) == CONST_DOUBLE)
1163 {
1164 REAL_VALUE_TYPE r;
1165 long l[3];
1166
1167 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
1168 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
1169 operands[1] = GEN_INT (l[0]);
1170 middlehalf[1] = GEN_INT (l[1]);
1171 latehalf[1] = GEN_INT (l[2]);
1172 }
1173 else if (CONSTANT_P (operands[1]))
1174 {
1175 /* actually, no non-CONST_DOUBLE constant should ever
1176 appear here. */
1177 abort ();
1178 if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0)
1179 latehalf[1] = constm1_rtx;
1180 else
1181 latehalf[1] = const0_rtx;
1182 }
1183 }
1184 else
1185 {
1186 middlehalf[1] = operands[1];
1187 latehalf[1] = operands[1];
1188 }
1189 }
1190 else
1191 /* size is not 12: */
1192 {
1193 if (optype0 == REGOP)
1194 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1195 else if (optype0 == OFFSOP)
1196 latehalf[0] = adj_offsettable_operand (operands[0], size - 4);
1197 else
1198 latehalf[0] = operands[0];
1199
1200 if (optype1 == REGOP)
1201 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1202 else if (optype1 == OFFSOP)
1203 latehalf[1] = adj_offsettable_operand (operands[1], size - 4);
1204 else if (optype1 == CNSTOP)
1205 split_double (operands[1], &operands[1], &latehalf[1]);
1206 else
1207 latehalf[1] = operands[1];
1208 }
1209
1210 /* If insn is effectively movd N(sp),-(sp) then we will do the
1211 high word first. We should use the adjusted operand 1 (which is N+4(sp))
1212 for the low word as well, to compensate for the first decrement of sp. */
1213 if (optype0 == PUSHOP
1214 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1215 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1216 operands[1] = middlehalf[1] = latehalf[1];
1217
1218 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1219 if the upper part of reg N does not appear in the MEM, arrange to
1220 emit the move late-half first. Otherwise, compute the MEM address
1221 into the upper part of N and use that as a pointer to the memory
1222 operand. */
1223 if (optype0 == REGOP
1224 && (optype1 == OFFSOP || optype1 == MEMOP))
1225 {
1226 rtx testlow = gen_rtx (REG, SImode, REGNO (operands[0]));
1227
1228 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1229 && reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1230 {
1231 /* If both halves of dest are used in the src memory address,
1232 compute the address into latehalf of dest.
1233 Note that this can't happen if the dest is two data regs. */
1234 compadr:
1235 xops[0] = latehalf[0];
1236 xops[1] = XEXP (operands[1], 0);
1237 output_asm_insn ("lea %a1,%0", xops);
1238 if( GET_MODE (operands[1]) == XFmode )
1239 {
1240 operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
1241 middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
1242 latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1243 }
1244 else
1245 {
1246 operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
1247 latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1248 }
1249 }
1250 else if (size == 12
1251 && reg_overlap_mentioned_p (middlehalf[0],
1252 XEXP (operands[1], 0)))
1253 {
1254 /* Check for two regs used by both source and dest.
1255 Note that this can't happen if the dest is all data regs.
1256 It can happen if the dest is d6, d7, a0.
1257 But in that case, latehalf is an addr reg, so
1258 the code at compadr does ok. */
1259
1260 if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))
1261 || reg_overlap_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1262 goto compadr;
1263
1264 /* JRV says this can't happen: */
1265 if (addreg0 || addreg1)
1266 abort ();
1267
1268 /* Only the middle reg conflicts; simply put it last. */
1269 output_asm_insn (singlemove_string (operands), operands);
1270 output_asm_insn (singlemove_string (latehalf), latehalf);
1271 output_asm_insn (singlemove_string (middlehalf), middlehalf);
1272 return "";
1273 }
1274 else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
1275 /* If the low half of dest is mentioned in the source memory
1276 address, the arrange to emit the move late half first. */
1277 dest_overlapped_low = 1;
1278 }
1279
1280 /* If one or both operands autodecrementing,
1281 do the two words, high-numbered first. */
1282
1283 /* Likewise, the first move would clobber the source of the second one,
1284 do them in the other order. This happens only for registers;
1285 such overlap can't happen in memory unless the user explicitly
1286 sets it up, and that is an undefined circumstance. */
1287
1288 if (optype0 == PUSHOP || optype1 == PUSHOP
1289 || (optype0 == REGOP && optype1 == REGOP
1290 && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
1291 || REGNO (operands[0]) == REGNO (latehalf[1])))
1292 || dest_overlapped_low)
1293 {
1294 /* Make any unoffsettable addresses point at high-numbered word. */
1295 if (addreg0)
1296 {
1297 if (size == 12)
1298 output_asm_insn ("addq%.l %#8,%0", &addreg0);
1299 else
1300 output_asm_insn ("addq%.l %#4,%0", &addreg0);
1301 }
1302 if (addreg1)
1303 {
1304 if (size == 12)
1305 output_asm_insn ("addq%.l %#8,%0", &addreg1);
1306 else
1307 output_asm_insn ("addq%.l %#4,%0", &addreg1);
1308 }
1309
1310 /* Do that word. */
1311 output_asm_insn (singlemove_string (latehalf), latehalf);
1312
1313 /* Undo the adds we just did. */
1314 if (addreg0)
1315 output_asm_insn ("subq%.l %#4,%0", &addreg0);
1316 if (addreg1)
1317 output_asm_insn ("subq%.l %#4,%0", &addreg1);
1318
1319 if (size == 12)
1320 {
1321 output_asm_insn (singlemove_string (middlehalf), middlehalf);
1322 if (addreg0)
1323 output_asm_insn ("subq%.l %#4,%0", &addreg0);
1324 if (addreg1)
1325 output_asm_insn ("subq%.l %#4,%0", &addreg1);
1326 }
1327
1328 /* Do low-numbered word. */
1329 return singlemove_string (operands);
1330 }
1331
1332 /* Normal case: do the two words, low-numbered first. */
1333
1334 output_asm_insn (singlemove_string (operands), operands);
1335
1336 /* Do the middle one of the three words for long double */
1337 if (size == 12)
1338 {
1339 if (addreg0)
1340 output_asm_insn ("addq%.l %#4,%0", &addreg0);
1341 if (addreg1)
1342 output_asm_insn ("addq%.l %#4,%0", &addreg1);
1343
1344 output_asm_insn (singlemove_string (middlehalf), middlehalf);
1345 }
1346
1347 /* Make any unoffsettable addresses point at high-numbered word. */
1348 if (addreg0)
1349 output_asm_insn ("addq%.l %#4,%0", &addreg0);
1350 if (addreg1)
1351 output_asm_insn ("addq%.l %#4,%0", &addreg1);
1352
1353 /* Do that word. */
1354 output_asm_insn (singlemove_string (latehalf), latehalf);
1355
1356 /* Undo the adds we just did. */
1357 if (addreg0)
1358 {
1359 if (size == 12)
1360 output_asm_insn ("subq%.l %#8,%0", &addreg0);
1361 else
1362 output_asm_insn ("subq%.l %#4,%0", &addreg0);
1363 }
1364 if (addreg1)
1365 {
1366 if (size == 12)
1367 output_asm_insn ("subq%.l %#8,%0", &addreg1);
1368 else
1369 output_asm_insn ("subq%.l %#4,%0", &addreg1);
1370 }
1371
1372 return "";
1373 }
1374
1375 /* Return a REG that occurs in ADDR with coefficient 1.
1376 ADDR can be effectively incremented by incrementing REG. */
1377
1378 static rtx
1379 find_addr_reg (addr)
1380 rtx addr;
1381 {
1382 while (GET_CODE (addr) == PLUS)
1383 {
1384 if (GET_CODE (XEXP (addr, 0)) == REG)
1385 addr = XEXP (addr, 0);
1386 else if (GET_CODE (XEXP (addr, 1)) == REG)
1387 addr = XEXP (addr, 1);
1388 else if (CONSTANT_P (XEXP (addr, 0)))
1389 addr = XEXP (addr, 1);
1390 else if (CONSTANT_P (XEXP (addr, 1)))
1391 addr = XEXP (addr, 0);
1392 else
1393 abort ();
1394 }
1395 if (GET_CODE (addr) == REG)
1396 return addr;
1397 abort ();
1398 }
1399 \f
1400 /* Store in cc_status the expressions that the condition codes will
1401 describe after execution of an instruction whose pattern is EXP.
1402 Do not alter them if the instruction would not alter the cc's. */
1403
1404 /* On the 68000, all the insns to store in an address register fail to
1405 set the cc's. However, in some cases these instructions can make it
1406 possibly invalid to use the saved cc's. In those cases we clear out
1407 some or all of the saved cc's so they won't be used. */
1408
1409 notice_update_cc (exp, insn)
1410 rtx exp;
1411 rtx insn;
1412 {
1413 /* If the cc is being set from the fpa and the expression is not an
1414 explicit floating point test instruction (which has code to deal with
1415 this), reinit the CC. */
1416 if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
1417 || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
1418 && !(GET_CODE (exp) == PARALLEL
1419 && GET_CODE (XVECEXP (exp, 0, 0)) == SET
1420 && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
1421 {
1422 CC_STATUS_INIT;
1423 }
1424 else if (GET_CODE (exp) == SET)
1425 {
1426 if (GET_CODE (SET_SRC (exp)) == CALL)
1427 {
1428 CC_STATUS_INIT;
1429 }
1430 else if (ADDRESS_REG_P (SET_DEST (exp)))
1431 {
1432 if (cc_status.value1
1433 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1434 cc_status.value1 = 0;
1435 if (cc_status.value2
1436 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1437 cc_status.value2 = 0;
1438 }
1439 else if (!FP_REG_P (SET_DEST (exp))
1440 && SET_DEST (exp) != cc0_rtx
1441 && (FP_REG_P (SET_SRC (exp))
1442 || GET_CODE (SET_SRC (exp)) == FIX
1443 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
1444 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
1445 {
1446 CC_STATUS_INIT;
1447 }
1448 /* A pair of move insns doesn't produce a useful overall cc. */
1449 else if (!FP_REG_P (SET_DEST (exp))
1450 && !FP_REG_P (SET_SRC (exp))
1451 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
1452 && (GET_CODE (SET_SRC (exp)) == REG
1453 || GET_CODE (SET_SRC (exp)) == MEM
1454 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
1455 {
1456 CC_STATUS_INIT;
1457 }
1458 else if (GET_CODE (SET_SRC (exp)) == CALL)
1459 {
1460 CC_STATUS_INIT;
1461 }
1462 else if (XEXP (exp, 0) != pc_rtx)
1463 {
1464 cc_status.flags = 0;
1465 cc_status.value1 = XEXP (exp, 0);
1466 cc_status.value2 = XEXP (exp, 1);
1467 }
1468 }
1469 else if (GET_CODE (exp) == PARALLEL
1470 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1471 {
1472 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
1473 CC_STATUS_INIT;
1474 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
1475 {
1476 cc_status.flags = 0;
1477 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
1478 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
1479 }
1480 }
1481 else
1482 CC_STATUS_INIT;
1483 if (cc_status.value2 != 0
1484 && ADDRESS_REG_P (cc_status.value2)
1485 && GET_MODE (cc_status.value2) == QImode)
1486 CC_STATUS_INIT;
1487 if (cc_status.value2 != 0
1488 && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
1489 switch (GET_CODE (cc_status.value2))
1490 {
1491 case PLUS: case MINUS: case MULT:
1492 case DIV: case UDIV: case MOD: case UMOD: case NEG:
1493 case ASHIFT: case ASHIFTRT: case LSHIFTRT:
1494 case ROTATE: case ROTATERT:
1495 if (GET_MODE (cc_status.value2) != VOIDmode)
1496 cc_status.flags |= CC_NO_OVERFLOW;
1497 break;
1498 case ZERO_EXTEND:
1499 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1500 ends with a move insn moving r2 in r2's mode.
1501 Thus, the cc's are set for r2.
1502 This can set N bit spuriously. */
1503 cc_status.flags |= CC_NOT_NEGATIVE;
1504 }
1505 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1506 && cc_status.value2
1507 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1508 cc_status.value2 = 0;
1509 if (((cc_status.value1 && FP_REG_P (cc_status.value1))
1510 || (cc_status.value2 && FP_REG_P (cc_status.value2)))
1511 && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
1512 || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
1513 cc_status.flags = CC_IN_68881;
1514 }
1515 \f
1516 char *
1517 output_move_const_double (operands)
1518 rtx *operands;
1519 {
1520 #ifdef SUPPORT_SUN_FPA
1521 if (TARGET_FPA && FPA_REG_P (operands[0]))
1522 {
1523 int code = standard_sun_fpa_constant_p (operands[1]);
1524
1525 if (code != 0)
1526 {
1527 static char buf[40];
1528
1529 sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
1530 return buf;
1531 }
1532 return "fpmove%.d %1,%0";
1533 }
1534 else
1535 #endif
1536 {
1537 int code = standard_68881_constant_p (operands[1]);
1538
1539 if (code != 0)
1540 {
1541 static char buf[40];
1542
1543 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1544 return buf;
1545 }
1546 return "fmove%.d %1,%0";
1547 }
1548 }
1549
1550 char *
1551 output_move_const_single (operands)
1552 rtx *operands;
1553 {
1554 #ifdef SUPPORT_SUN_FPA
1555 if (TARGET_FPA)
1556 {
1557 int code = standard_sun_fpa_constant_p (operands[1]);
1558
1559 if (code != 0)
1560 {
1561 static char buf[40];
1562
1563 sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
1564 return buf;
1565 }
1566 return "fpmove%.s %1,%0";
1567 }
1568 else
1569 #endif /* defined SUPPORT_SUN_FPA */
1570 {
1571 int code = standard_68881_constant_p (operands[1]);
1572
1573 if (code != 0)
1574 {
1575 static char buf[40];
1576
1577 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1578 return buf;
1579 }
1580 return "fmove%.s %f1,%0";
1581 }
1582 }
1583
1584 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1585 from the "fmovecr" instruction.
1586 The value, anded with 0xff, gives the code to use in fmovecr
1587 to get the desired constant. */
1588
1589 /* This code has been fixed for cross-compilation. */
1590
1591 static int inited_68881_table = 0;
1592
1593 char *strings_68881[7] = {
1594 "0.0",
1595 "1.0",
1596 "10.0",
1597 "100.0",
1598 "10000.0",
1599 "1e8",
1600 "1e16"
1601 };
1602
1603 int codes_68881[7] = {
1604 0x0f,
1605 0x32,
1606 0x33,
1607 0x34,
1608 0x35,
1609 0x36,
1610 0x37
1611 };
1612
1613 REAL_VALUE_TYPE values_68881[7];
1614
1615 /* Set up values_68881 array by converting the decimal values
1616 strings_68881 to binary. */
1617
1618 void
1619 init_68881_table ()
1620 {
1621 int i;
1622 REAL_VALUE_TYPE r;
1623 enum machine_mode mode;
1624
1625 mode = DFmode;
1626 for (i = 0; i < 7; i++)
1627 {
1628 if (i == 6)
1629 mode = SFmode;
1630 r = REAL_VALUE_ATOF (strings_68881[i], mode);
1631 values_68881[i] = r;
1632 }
1633 inited_68881_table = 1;
1634 }
1635
1636 int
1637 standard_68881_constant_p (x)
1638 rtx x;
1639 {
1640 REAL_VALUE_TYPE r;
1641 int i;
1642 enum machine_mode mode;
1643
1644 #ifdef NO_ASM_FMOVECR
1645 return 0;
1646 #endif
1647
1648 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1649 if (TARGET_68040)
1650 return 0;
1651
1652 #ifndef REAL_ARITHMETIC
1653 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1654 if (! flag_pretend_float)
1655 return 0;
1656 #endif
1657 #endif
1658
1659 if (! inited_68881_table)
1660 init_68881_table ();
1661
1662 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1663
1664 for (i = 0; i < 6; i++)
1665 {
1666 if (REAL_VALUES_EQUAL (r, values_68881[i]))
1667 return (codes_68881[i]);
1668 }
1669
1670 if (GET_MODE (x) == SFmode)
1671 return 0;
1672
1673 if (REAL_VALUES_EQUAL (r, values_68881[6]))
1674 return (codes_68881[6]);
1675
1676 /* larger powers of ten in the constants ram are not used
1677 because they are not equal to a `double' C constant. */
1678 return 0;
1679 }
1680
1681 /* If X is a floating-point constant, return the logarithm of X base 2,
1682 or 0 if X is not a power of 2. */
1683
1684 int
1685 floating_exact_log2 (x)
1686 rtx x;
1687 {
1688 REAL_VALUE_TYPE r, r1;
1689 int i;
1690
1691 #ifndef REAL_ARITHMETIC
1692 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1693 if (! flag_pretend_float)
1694 return 0;
1695 #endif
1696 #endif
1697
1698 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1699
1700 if (REAL_VALUES_LESS (r, dconst0))
1701 return 0;
1702
1703 r1 = dconst1;
1704 i = 0;
1705 while (REAL_VALUES_LESS (r1, r))
1706 {
1707 r1 = REAL_VALUE_LDEXP (dconst1, i);
1708 if (REAL_VALUES_EQUAL (r1, r))
1709 return i;
1710 i = i + 1;
1711 }
1712 return 0;
1713 }
1714 \f
1715 #ifdef SUPPORT_SUN_FPA
1716 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1717 from the Sun FPA's constant RAM.
1718 The value returned, anded with 0x1ff, gives the code to use in fpmove
1719 to get the desired constant. */
1720
1721 static int inited_FPA_table = 0;
1722
1723 char *strings_FPA[38] = {
1724 /* small rationals */
1725 "0.0",
1726 "1.0",
1727 "0.5",
1728 "-1.0",
1729 "2.0",
1730 "3.0",
1731 "4.0",
1732 "8.0",
1733 "0.25",
1734 "0.125",
1735 "10.0",
1736 "-0.5",
1737 /* Decimal equivalents of double precision values */
1738 "2.718281828459045091", /* D_E */
1739 "6.283185307179586477", /* 2 pi */
1740 "3.141592653589793116", /* D_PI */
1741 "1.570796326794896619", /* pi/2 */
1742 "1.414213562373095145", /* D_SQRT2 */
1743 "0.7071067811865475244", /* 1/sqrt(2) */
1744 "-1.570796326794896619", /* -pi/2 */
1745 "1.442695040888963387", /* D_LOG2ofE */
1746 "3.321928024887362182", /* D_LOG2of10 */
1747 "0.6931471805599452862", /* D_LOGEof2 */
1748 "2.302585092994045901", /* D_LOGEof10 */
1749 "0.3010299956639811980", /* D_LOG10of2 */
1750 "0.4342944819032518167", /* D_LOG10ofE */
1751 /* Decimal equivalents of single precision values */
1752 "2.718281745910644531", /* S_E */
1753 "6.283185307179586477", /* 2 pi */
1754 "3.141592741012573242", /* S_PI */
1755 "1.570796326794896619", /* pi/2 */
1756 "1.414213538169860840", /* S_SQRT2 */
1757 "0.7071067811865475244", /* 1/sqrt(2) */
1758 "-1.570796326794896619", /* -pi/2 */
1759 "1.442695021629333496", /* S_LOG2ofE */
1760 "3.321928024291992188", /* S_LOG2of10 */
1761 "0.6931471824645996094", /* S_LOGEof2 */
1762 "2.302585124969482442", /* S_LOGEof10 */
1763 "0.3010300099849700928", /* S_LOG10of2 */
1764 "0.4342944920063018799", /* S_LOG10ofE */
1765 };
1766
1767
1768 int codes_FPA[38] = {
1769 /* small rationals */
1770 0x200,
1771 0xe,
1772 0xf,
1773 0x10,
1774 0x11,
1775 0xb1,
1776 0x12,
1777 0x13,
1778 0x15,
1779 0x16,
1780 0x17,
1781 0x2e,
1782 /* double precision */
1783 0x8,
1784 0x9,
1785 0xa,
1786 0xb,
1787 0xc,
1788 0xd,
1789 0x27,
1790 0x28,
1791 0x29,
1792 0x2a,
1793 0x2b,
1794 0x2c,
1795 0x2d,
1796 /* single precision */
1797 0x8,
1798 0x9,
1799 0xa,
1800 0xb,
1801 0xc,
1802 0xd,
1803 0x27,
1804 0x28,
1805 0x29,
1806 0x2a,
1807 0x2b,
1808 0x2c,
1809 0x2d
1810 };
1811
1812 REAL_VALUE_TYPE values_FPA[38];
1813
1814 /* This code has been fixed for cross-compilation. */
1815
1816 void
1817 init_FPA_table ()
1818 {
1819 enum machine_mode mode;
1820 int i;
1821 REAL_VALUE_TYPE r;
1822
1823 mode = DFmode;
1824 for (i = 0; i < 38; i++)
1825 {
1826 if (i == 25)
1827 mode = SFmode;
1828 r = REAL_VALUE_ATOF (strings_FPA[i], mode);
1829 values_FPA[i] = r;
1830 }
1831 inited_FPA_table = 1;
1832 }
1833
1834
1835 int
1836 standard_sun_fpa_constant_p (x)
1837 rtx x;
1838 {
1839 REAL_VALUE_TYPE r;
1840 int i;
1841
1842 #ifndef REAL_ARITHMETIC
1843 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1844 if (! flag_pretend_float)
1845 return 0;
1846 #endif
1847 #endif
1848
1849 if (! inited_FPA_table)
1850 init_FPA_table ();
1851
1852 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1853
1854 for (i=0; i<12; i++)
1855 {
1856 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
1857 return (codes_FPA[i]);
1858 }
1859
1860 if (GET_MODE (x) == SFmode)
1861 {
1862 for (i=25; i<38; i++)
1863 {
1864 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
1865 return (codes_FPA[i]);
1866 }
1867 }
1868 else
1869 {
1870 for (i=12; i<25; i++)
1871 {
1872 if (REAL_VALUES_EQUAL (r, values_FPA[i]))
1873 return (codes_FPA[i]);
1874 }
1875 }
1876 return 0x0;
1877 }
1878 #endif /* define SUPPORT_SUN_FPA */
1879 \f
1880 /* A C compound statement to output to stdio stream STREAM the
1881 assembler syntax for an instruction operand X. X is an RTL
1882 expression.
1883
1884 CODE is a value that can be used to specify one of several ways
1885 of printing the operand. It is used when identical operands
1886 must be printed differently depending on the context. CODE
1887 comes from the `%' specification that was used to request
1888 printing of the operand. If the specification was just `%DIGIT'
1889 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
1890 is the ASCII code for LTR.
1891
1892 If X is a register, this macro should print the register's name.
1893 The names can be found in an array `reg_names' whose type is
1894 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
1895
1896 When the machine description has a specification `%PUNCT' (a `%'
1897 followed by a punctuation character), this macro is called with
1898 a null pointer for X and the punctuation character for CODE.
1899
1900 The m68k specific codes are:
1901
1902 '.' for dot needed in Motorola-style opcode names.
1903 '-' for an operand pushing on the stack:
1904 sp@-, -(sp) or -(%sp) depending on the style of syntax.
1905 '+' for an operand pushing on the stack:
1906 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
1907 '@' for a reference to the top word on the stack:
1908 sp@, (sp) or (%sp) depending on the style of syntax.
1909 '#' for an immediate operand prefix (# in MIT and Motorola syntax
1910 but & in SGS syntax).
1911 '!' for the cc register (used in an `and to cc' insn).
1912 '$' for the letter `s' in an op code, but only on the 68040.
1913 '&' for the letter `d' in an op code, but only on the 68040.
1914 '/' for register prefix needed by longlong.h.
1915
1916 'b' for byte insn (no effect, on the Sun; this is for the ISI).
1917 'd' to force memory addressing to be absolute, not relative.
1918 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
1919 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
1920 than directly). Second part of 'y' below.
1921 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
1922 or print pair of registers as rx:ry.
1923 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
1924 CONST_DOUBLE's as SunFPA constant RAM registers if
1925 possible, so it should not be used except for the SunFPA.
1926
1927 */
1928
1929 void
1930 print_operand (file, op, letter)
1931 FILE *file; /* file to write to */
1932 rtx op; /* operand to print */
1933 int letter; /* %<letter> or 0 */
1934 {
1935 int i;
1936
1937 if (letter == '.')
1938 {
1939 #ifdef MOTOROLA
1940 asm_fprintf (file, ".");
1941 #endif
1942 }
1943 else if (letter == '#')
1944 {
1945 asm_fprintf (file, "%0I");
1946 }
1947 else if (letter == '-')
1948 {
1949 #ifdef MOTOROLA
1950 asm_fprintf (file, "-(%Rsp)");
1951 #else
1952 asm_fprintf (file, "%Rsp@-");
1953 #endif
1954 }
1955 else if (letter == '+')
1956 {
1957 #ifdef MOTOROLA
1958 asm_fprintf (file, "(%Rsp)+");
1959 #else
1960 asm_fprintf (file, "%Rsp@+");
1961 #endif
1962 }
1963 else if (letter == '@')
1964 {
1965 #ifdef MOTOROLA
1966 asm_fprintf (file, "(%Rsp)");
1967 #else
1968 asm_fprintf (file, "%Rsp@");
1969 #endif
1970 }
1971 else if (letter == '!')
1972 {
1973 asm_fprintf (file, "%Rfpcr");
1974 }
1975 else if (letter == '$')
1976 {
1977 if (TARGET_68040_ONLY)
1978 {
1979 fprintf (file, "s");
1980 }
1981 }
1982 else if (letter == '&')
1983 {
1984 if (TARGET_68040_ONLY)
1985 {
1986 fprintf (file, "d");
1987 }
1988 }
1989 else if (letter == '/')
1990 {
1991 asm_fprintf (file, "%R");
1992 }
1993 else if (GET_CODE (op) == REG)
1994 {
1995 #ifdef SUPPORT_SUN_FPA
1996 if (REGNO (op) < 16
1997 && (letter == 'y' || letter == 'x')
1998 && GET_MODE (op) == DFmode)
1999 {
2000 fprintf (file, "%s:%s", reg_names[REGNO (op)],
2001 reg_names[REGNO (op)+1]);
2002 }
2003 else
2004 #endif
2005 {
2006 fprintf (file, "%s", reg_names[REGNO (op)]);
2007 }
2008 }
2009 else if (GET_CODE (op) == MEM)
2010 {
2011 output_address (XEXP (op, 0));
2012 if (letter == 'd' && ! TARGET_68020
2013 && CONSTANT_ADDRESS_P (XEXP (op, 0))
2014 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
2015 && INTVAL (XEXP (op, 0)) < 0x8000
2016 && INTVAL (XEXP (op, 0)) >= -0x8000))
2017 {
2018 fprintf (file, ":l");
2019 }
2020 }
2021 #ifdef SUPPORT_SUN_FPA
2022 else if ((letter == 'y' || letter == 'w')
2023 && GET_CODE (op) == CONST_DOUBLE
2024 && (i = standard_sun_fpa_constant_p (op)))
2025 {
2026 fprintf (file, "%%%d", i & 0x1ff);
2027 }
2028 #endif
2029 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
2030 {
2031 REAL_VALUE_TYPE r;
2032 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2033 ASM_OUTPUT_FLOAT_OPERAND (letter, file, r);
2034 }
2035 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == XFmode)
2036 {
2037 REAL_VALUE_TYPE r;
2038 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2039 ASM_OUTPUT_LONG_DOUBLE_OPERAND (file, r);
2040 }
2041 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
2042 {
2043 REAL_VALUE_TYPE r;
2044 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
2045 ASM_OUTPUT_DOUBLE_OPERAND (file, r);
2046 }
2047 else
2048 {
2049 asm_fprintf (file, "%0I"); output_addr_const (file, op);
2050 }
2051 }
2052
2053 \f
2054 /* A C compound statement to output to stdio stream STREAM the
2055 assembler syntax for an instruction operand that is a memory
2056 reference whose address is ADDR. ADDR is an RTL expression.
2057
2058 Note that this contains a kludge that knows that the only reason
2059 we have an address (plus (label_ref...) (reg...)) when not generating
2060 PIC code is in the insn before a tablejump, and we know that m68k.md
2061 generates a label LInnn: on such an insn.
2062
2063 It is possible for PIC to generate a (plus (label_ref...) (reg...))
2064 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
2065
2066 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
2067 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
2068 we want. This difference can be accommodated by using an assembler
2069 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
2070 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
2071 macro. See m68k/sgs.h for an example; for versions without the bug.
2072 Some assemblers refuse all the above solutions. The workaround is to
2073 emit "K(pc,d0.l*2)" with K being a small constant known to give the
2074 right behaviour.
2075
2076 They also do not like things like "pea 1.w", so we simple leave off
2077 the .w on small constants.
2078
2079 This routine is responsible for distinguishing between -fpic and -fPIC
2080 style relocations in an address. When generating -fpic code the
2081 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
2082 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
2083
2084 #ifndef ASM_OUTPUT_CASE_FETCH
2085 #ifdef MOTOROLA
2086 #ifdef SGS
2087 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2088 asm_fprintf (file, "%LLD%d(%Rpc,%s.", labelno, regname)
2089 #else
2090 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2091 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
2092 #endif
2093 #else
2094 #define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
2095 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
2096 #endif
2097 #endif /* ASM_OUTPUT_CASE_FETCH */
2098
2099 void
2100 print_operand_address (file, addr)
2101 FILE *file;
2102 rtx addr;
2103 {
2104 register rtx reg1, reg2, breg, ireg;
2105 rtx offset;
2106
2107 switch (GET_CODE (addr))
2108 {
2109 case REG:
2110 #ifdef MOTOROLA
2111 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
2112 #else
2113 fprintf (file, "%s@", reg_names[REGNO (addr)]);
2114 #endif
2115 break;
2116 case PRE_DEC:
2117 #ifdef MOTOROLA
2118 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
2119 #else
2120 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
2121 #endif
2122 break;
2123 case POST_INC:
2124 #ifdef MOTOROLA
2125 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
2126 #else
2127 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
2128 #endif
2129 break;
2130 case PLUS:
2131 reg1 = reg2 = ireg = breg = offset = 0;
2132 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
2133 {
2134 offset = XEXP (addr, 0);
2135 addr = XEXP (addr, 1);
2136 }
2137 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
2138 {
2139 offset = XEXP (addr, 1);
2140 addr = XEXP (addr, 0);
2141 }
2142 if (GET_CODE (addr) != PLUS)
2143 {
2144 ;
2145 }
2146 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
2147 {
2148 reg1 = XEXP (addr, 0);
2149 addr = XEXP (addr, 1);
2150 }
2151 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
2152 {
2153 reg1 = XEXP (addr, 1);
2154 addr = XEXP (addr, 0);
2155 }
2156 else if (GET_CODE (XEXP (addr, 0)) == MULT)
2157 {
2158 reg1 = XEXP (addr, 0);
2159 addr = XEXP (addr, 1);
2160 }
2161 else if (GET_CODE (XEXP (addr, 1)) == MULT)
2162 {
2163 reg1 = XEXP (addr, 1);
2164 addr = XEXP (addr, 0);
2165 }
2166 else if (GET_CODE (XEXP (addr, 0)) == REG)
2167 {
2168 reg1 = XEXP (addr, 0);
2169 addr = XEXP (addr, 1);
2170 }
2171 else if (GET_CODE (XEXP (addr, 1)) == REG)
2172 {
2173 reg1 = XEXP (addr, 1);
2174 addr = XEXP (addr, 0);
2175 }
2176 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
2177 || GET_CODE (addr) == SIGN_EXTEND)
2178 {
2179 if (reg1 == 0)
2180 {
2181 reg1 = addr;
2182 }
2183 else
2184 {
2185 reg2 = addr;
2186 }
2187 addr = 0;
2188 }
2189 #if 0 /* for OLD_INDEXING */
2190 else if (GET_CODE (addr) == PLUS)
2191 {
2192 if (GET_CODE (XEXP (addr, 0)) == REG)
2193 {
2194 reg2 = XEXP (addr, 0);
2195 addr = XEXP (addr, 1);
2196 }
2197 else if (GET_CODE (XEXP (addr, 1)) == REG)
2198 {
2199 reg2 = XEXP (addr, 1);
2200 addr = XEXP (addr, 0);
2201 }
2202 }
2203 #endif
2204 if (offset != 0)
2205 {
2206 if (addr != 0)
2207 {
2208 abort ();
2209 }
2210 addr = offset;
2211 }
2212 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
2213 || GET_CODE (reg1) == MULT))
2214 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2215 {
2216 breg = reg2;
2217 ireg = reg1;
2218 }
2219 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2220 {
2221 breg = reg1;
2222 ireg = reg2;
2223 }
2224 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
2225 && ! (flag_pic && ireg == pic_offset_table_rtx))
2226 {
2227 int scale = 1;
2228 if (GET_CODE (ireg) == MULT)
2229 {
2230 scale = INTVAL (XEXP (ireg, 1));
2231 ireg = XEXP (ireg, 0);
2232 }
2233 if (GET_CODE (ireg) == SIGN_EXTEND)
2234 {
2235 ASM_OUTPUT_CASE_FETCH (file,
2236 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2237 reg_names[REGNO (XEXP (ireg, 0))]);
2238 fprintf (file, "w");
2239 }
2240 else
2241 {
2242 ASM_OUTPUT_CASE_FETCH (file,
2243 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2244 reg_names[REGNO (ireg)]);
2245 fprintf (file, "l");
2246 }
2247 if (scale != 1)
2248 {
2249 #ifdef MOTOROLA
2250 fprintf (file, "*%d", scale);
2251 #else
2252 fprintf (file, ":%d", scale);
2253 #endif
2254 }
2255 putc (')', file);
2256 break;
2257 }
2258 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
2259 && ! (flag_pic && breg == pic_offset_table_rtx))
2260 {
2261 ASM_OUTPUT_CASE_FETCH (file,
2262 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2263 reg_names[REGNO (breg)]);
2264 fprintf (file, "l)");
2265 break;
2266 }
2267 if (ireg != 0 || breg != 0)
2268 {
2269 int scale = 1;
2270 if (breg == 0)
2271 {
2272 abort ();
2273 }
2274 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
2275 {
2276 abort ();
2277 }
2278 #ifdef MOTOROLA
2279 if (addr != 0)
2280 {
2281 output_addr_const (file, addr);
2282 if (flag_pic && (breg == pic_offset_table_rtx))
2283 fprintf (file, "@GOT");
2284 }
2285 fprintf (file, "(%s", reg_names[REGNO (breg)]);
2286 if (ireg != 0)
2287 {
2288 putc (',', file);
2289 }
2290 #else
2291 fprintf (file, "%s@(", reg_names[REGNO (breg)]);
2292 if (addr != 0)
2293 {
2294 output_addr_const (file, addr);
2295 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
2296 fprintf (file, ":w");
2297 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
2298 fprintf (file, ":l");
2299 }
2300 if (addr != 0 && ireg != 0)
2301 {
2302 putc (',', file);
2303 }
2304 #endif
2305 if (ireg != 0 && GET_CODE (ireg) == MULT)
2306 {
2307 scale = INTVAL (XEXP (ireg, 1));
2308 ireg = XEXP (ireg, 0);
2309 }
2310 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
2311 {
2312 #ifdef MOTOROLA
2313 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
2314 #else
2315 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
2316 #endif
2317 }
2318 else if (ireg != 0)
2319 {
2320 #ifdef MOTOROLA
2321 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
2322 #else
2323 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
2324 #endif
2325 }
2326 if (scale != 1)
2327 {
2328 #ifdef MOTOROLA
2329 fprintf (file, "*%d", scale);
2330 #else
2331 fprintf (file, ":%d", scale);
2332 #endif
2333 }
2334 putc (')', file);
2335 break;
2336 }
2337 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
2338 && ! (flag_pic && reg1 == pic_offset_table_rtx))
2339 {
2340 ASM_OUTPUT_CASE_FETCH (file,
2341 CODE_LABEL_NUMBER (XEXP (addr, 0)),
2342 reg_names[REGNO (reg1)]);
2343 fprintf (file, "l)");
2344 break;
2345 }
2346 /* FALL-THROUGH (is this really what we want? */
2347 default:
2348 if (GET_CODE (addr) == CONST_INT
2349 && INTVAL (addr) < 0x8000
2350 && INTVAL (addr) >= -0x8000)
2351 {
2352 #ifdef MOTOROLA
2353 #ifdef SGS
2354 /* Many SGS assemblers croak on size specifiers for constants. */
2355 fprintf (file, "%d", INTVAL (addr));
2356 #else
2357 fprintf (file, "%d.w", INTVAL (addr));
2358 #endif
2359 #else
2360 fprintf (file, "%d:w", INTVAL (addr));
2361 #endif
2362 }
2363 else
2364 {
2365 output_addr_const (file, addr);
2366 }
2367 break;
2368 }
2369 }
2370 \f
2371 /* Check for cases where a clr insns can be omitted from code using
2372 strict_low_part sets. For example, the second clrl here is not needed:
2373 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
2374
2375 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
2376 insn we are checking for redundancy. TARGET is the register set by the
2377 clear insn. */
2378
2379 int
2380 strict_low_part_peephole_ok (mode, first_insn, target)
2381 enum machine_mode mode;
2382 rtx first_insn;
2383 rtx target;
2384 {
2385 rtx p;
2386
2387 p = prev_nonnote_insn (first_insn);
2388
2389 while (p)
2390 {
2391 /* If it isn't an insn, then give up. */
2392 if (GET_CODE (p) != INSN)
2393 return 0;
2394
2395 if (reg_set_p (target, p))
2396 {
2397 rtx set = single_set (p);
2398 rtx dest;
2399
2400 /* If it isn't an easy to recognize insn, then give up. */
2401 if (! set)
2402 return 0;
2403
2404 dest = SET_DEST (set);
2405
2406 /* If this sets the entire target register to zero, then our
2407 first_insn is redundant. */
2408 if (rtx_equal_p (dest, target)
2409 && SET_SRC (set) == const0_rtx)
2410 return 1;
2411 else if (GET_CODE (dest) == STRICT_LOW_PART
2412 && GET_CODE (XEXP (dest, 0)) == REG
2413 && REGNO (XEXP (dest, 0)) == REGNO (target)
2414 && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
2415 <= GET_MODE_SIZE (mode)))
2416 /* This is a strict low part set which modifies less than
2417 we are using, so it is safe. */
2418 ;
2419 else
2420 return 0;
2421 }
2422
2423 p = prev_nonnote_insn (p);
2424
2425 }
2426
2427 return 0;
2428 }
2429
2430 /* Accept integer operands in the range 0..0xffffffff. We have to check the
2431 range carefully since this predicate is used in DImode contexts. Also, we
2432 need some extra crud to make it work when hosted on 64-bit machines. */
2433
2434 int
2435 const_uint32_operand (op, mode)
2436 rtx op;
2437 enum machine_mode mode;
2438 {
2439 #if HOST_BITS_PER_WIDE_INT > 32
2440 /* All allowed constants will fit a CONST_INT. */
2441 return (GET_CODE (op) == CONST_INT
2442 && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
2443 #else
2444 return (GET_CODE (op) == CONST_INT
2445 || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
2446 #endif
2447 }
2448
2449 /* Accept integer operands in the range -0x80000000..0x7fffffff. We have
2450 to check the range carefully since this predicate is used in DImode
2451 contexts. */
2452
2453 int
2454 const_sint32_operand (op, mode)
2455 rtx op;
2456 enum machine_mode mode;
2457 {
2458 /* All allowed constants will fit a CONST_INT. */
2459 return (GET_CODE (op) == CONST_INT
2460 && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
2461 }