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