OSDN Git Service

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