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