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