1 /* Subroutines for insn-output.c for Motorola 68000 family.
2 Copyright (C) 1987 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* Some output-actions in m68k.md need these. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-flags.h"
32 #include "insn-attr.h"
34 /* Needed for use_return_insn. */
37 #ifdef SUPPORT_SUN_FPA
39 /* Index into this array by (register number >> 3) to find the
40 smallest class which contains that register. */
41 enum reg_class regno_reg_class[]
42 = { DATA_REGS, ADDR_REGS, FP_REGS,
43 LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
45 #endif /* defined SUPPORT_SUN_FPA */
47 /* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
48 if SGS_SWITCH_TABLE. */
49 int switch_table_difference_label_flag;
51 static rtx find_addr_reg ();
52 rtx legitimize_pic_address ();
55 /* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
56 function at any time during the compilation process. In the future
57 we should try and eliminate the USE if we can easily determine that
58 all PIC references were deleted from the current function. That would
59 save an address register */
63 if (flag_pic && current_function_uses_pic_offset_table)
64 emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
68 /* This function generates the assembly code for function entry.
69 STREAM is a stdio stream to output the code to.
70 SIZE is an int: how many units of temporary storage to allocate.
71 Refer to the array `regs_ever_live' to determine which registers
72 to save; `regs_ever_live[I]' is nonzero if register number I
73 is ever used in the function. This function is responsible for
74 knowing which registers should not be saved even if used. */
77 /* Note that the order of the bit mask for fmovem is the opposite
78 of the order for movem! */
82 output_function_prologue (stream, size)
87 register int mask = 0;
88 int num_saved_regs = 0;
89 extern char call_used_regs[];
90 int fsize = (size + 3) & -4;
93 if (frame_pointer_needed)
95 /* Adding negative number is faster on the 68040. */
96 if (fsize < 0x8000 && !TARGET_68040)
99 asm_fprintf (stream, "\tlink.w %s,%0I%d\n",
100 reg_names[FRAME_POINTER_REGNUM], -fsize);
102 asm_fprintf (stream, "\tlink %s,%0I%d\n",
103 reg_names[FRAME_POINTER_REGNUM], -fsize);
106 else if (TARGET_68020)
109 asm_fprintf (stream, "\tlink.l %s,%0I%d\n",
110 reg_names[FRAME_POINTER_REGNUM], -fsize);
112 asm_fprintf (stream, "\tlink %s,%0I%d\n",
113 reg_names[FRAME_POINTER_REGNUM], -fsize);
119 asm_fprintf (stream, "\tlink.w %s,%0I0\n\tadd.l %0I%d,%Rsp\n",
120 reg_names[FRAME_POINTER_REGNUM], -fsize);
122 asm_fprintf (stream, "\tlink %s,%0I0\n\taddl %0I%d,%Rsp\n",
123 reg_names[FRAME_POINTER_REGNUM], -fsize);
129 /* Adding negative number is faster on the 68040. */
130 if (fsize + 4 < 0x8000)
133 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
135 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
141 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", - (fsize + 4));
143 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
147 #ifdef SUPPORT_SUN_FPA
148 for (regno = 24; regno < 56; regno++)
149 if (regs_ever_live[regno] && ! call_used_regs[regno])
152 asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
155 asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
160 for (regno = 16; regno < 24; regno++)
161 if (regs_ever_live[regno] && ! call_used_regs[regno])
162 mask |= 1 << (regno - 16);
163 if ((mask & 0xff) != 0)
166 asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
168 asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
172 for (regno = 0; regno < 16; regno++)
173 if (regs_ever_live[regno] && ! call_used_regs[regno])
175 mask |= 1 << (15 - regno);
178 if (frame_pointer_needed)
180 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
185 fprintf (stream, "\ttstl sp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
188 if (num_saved_regs <= 2)
190 /* Store each separately in the same order moveml uses.
191 Using two movel instructions instead of a single moveml
192 is about 15% faster for the 68020 and 68030 at no expense
197 /* Undo the work from above. */
198 for (i = 0; i< 16; i++)
202 "\t%Omove.l %s,-(%Rsp)\n",
204 "\tmovel %s,%Rsp@-\n",
211 asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
213 asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
216 if (flag_pic && current_function_uses_pic_offset_table)
219 asm_fprintf (stream, "\t%Omove.l %0I__GLOBAL_OFFSET_TABLE_, %s\n",
220 reg_names[PIC_OFFSET_TABLE_REGNUM]);
221 asm_fprintf (stream, "\tlea.l (%Rpc,%s.l),%s\n",
222 reg_names[PIC_OFFSET_TABLE_REGNUM],
223 reg_names[PIC_OFFSET_TABLE_REGNUM]);
225 asm_fprintf (stream, "\tmovel %0I__GLOBAL_OFFSET_TABLE_, %s\n",
226 reg_names[PIC_OFFSET_TABLE_REGNUM]);
227 asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n",
228 reg_names[PIC_OFFSET_TABLE_REGNUM],
229 reg_names[PIC_OFFSET_TABLE_REGNUM]);
234 /* Return true if this function's epilogue can be output as RTL. */
241 if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
244 /* Copied from output_function_epilogue (). We should probably create a
245 separate layout routine to perform the common work. */
247 for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
248 if (regs_ever_live[regno] && ! call_used_regs[regno])
254 /* This function generates the assembly code for function exit,
255 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
257 The function epilogue should not depend on the current stack pointer!
258 It should use the frame pointer only, if there is a frame pointer.
259 This is mandatory because of alloca; we also take advantage of it to
260 omit stack adjustments before returning. */
263 output_function_epilogue (stream, size)
268 register int mask, fmask;
270 int offset, foffset, fpoffset;
271 extern char call_used_regs[];
272 int fsize = (size + 3) & -4;
274 rtx insn = get_last_insn ();
276 /* If the last insn was a BARRIER, we don't have to write any code. */
277 if (GET_CODE (insn) == NOTE)
278 insn = prev_nonnote_insn (insn);
279 if (insn && GET_CODE (insn) == BARRIER)
281 /* Output just a no-op so that debuggers don't get confused
282 about which function the pc is in at this address. */
283 asm_fprintf (stream, "\tnop\n");
287 #ifdef FUNCTION_EXTRA_EPILOGUE
288 FUNCTION_EXTRA_EPILOGUE (stream, size);
290 nregs = 0; fmask = 0; fpoffset = 0;
291 #ifdef SUPPORT_SUN_FPA
292 for (regno = 24 ; regno < 56 ; regno++)
293 if (regs_ever_live[regno] && ! call_used_regs[regno])
295 fpoffset = nregs * 8;
298 for (regno = 16; regno < 24; regno++)
299 if (regs_ever_live[regno] && ! call_used_regs[regno])
302 fmask |= 1 << (23 - regno);
304 foffset = fpoffset + nregs * 12;
306 if (frame_pointer_needed)
307 regs_ever_live[FRAME_POINTER_REGNUM] = 0;
308 for (regno = 0; regno < 16; regno++)
309 if (regs_ever_live[regno] && ! call_used_regs[regno])
314 offset = foffset + nregs * 4;
315 if (offset + fsize >= 0x8000
316 && frame_pointer_needed
317 && (mask || fmask || fpoffset))
320 asm_fprintf (stream, "\t%Omove.l %0I%d,%Ra0\n", -fsize);
322 asm_fprintf (stream, "\tmovel %0I%d,%Ra0\n", -fsize);
328 /* Restore each separately in the same order moveml does.
329 Using two movel instructions instead of a single moveml
330 is about 15% faster for the 68020 and 68030 at no expense
335 /* Undo the work from above. */
336 for (i = 0; i< 16; i++)
342 asm_fprintf (stream, "\t%Omove.l -%d(%s,%Ra0.l),%s\n",
344 reg_names[FRAME_POINTER_REGNUM],
347 asm_fprintf (stream, "\tmovel %s@(-%d,%Ra0:l),%s\n",
348 reg_names[FRAME_POINTER_REGNUM],
349 offset + fsize, reg_names[i]);
352 else if (! frame_pointer_needed)
355 asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
358 asm_fprintf (stream, "\tmovel %Rsp@+,%s\n",
365 asm_fprintf (stream, "\t%Omove.l -%d(%s),%s\n",
367 reg_names[FRAME_POINTER_REGNUM],
370 asm_fprintf (stream, "\tmovel %s@(-%d),%s\n",
371 reg_names[FRAME_POINTER_REGNUM],
372 offset + fsize, reg_names[i]);
383 asm_fprintf (stream, "\tmovm.l -%d(%s,%Ra0.l),%0I0x%x\n",
385 reg_names[FRAME_POINTER_REGNUM],
388 asm_fprintf (stream, "\tmoveml %s@(-%d,%Ra0:l),%0I0x%x\n",
389 reg_names[FRAME_POINTER_REGNUM],
390 offset + fsize, mask);
393 else if (! frame_pointer_needed)
396 asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
398 asm_fprintf (stream, "\tmoveml %Rsp@+,%0I0x%x\n", mask);
404 asm_fprintf (stream, "\tmovm.l -%d(%s),%0I0x%x\n",
406 reg_names[FRAME_POINTER_REGNUM],
409 asm_fprintf (stream, "\tmoveml %s@(-%d),%0I0x%x\n",
410 reg_names[FRAME_POINTER_REGNUM],
411 offset + fsize, mask);
420 asm_fprintf (stream, "\tfmovm -%d(%s,%Ra0.l),%0I0x%x\n",
422 reg_names[FRAME_POINTER_REGNUM],
425 asm_fprintf (stream, "\tfmovem %s@(-%d,%Ra0:l),%0I0x%x\n",
426 reg_names[FRAME_POINTER_REGNUM],
427 foffset + fsize, fmask);
430 else if (! frame_pointer_needed)
433 asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
435 asm_fprintf (stream, "\tfmovem %Rsp@+,%0I0x%x\n", fmask);
441 asm_fprintf (stream, "\tfmovm -%d(%s),%0I0x%x\n",
443 reg_names[FRAME_POINTER_REGNUM],
446 asm_fprintf (stream, "\tfmovem %s@(-%d),%0I0x%x\n",
447 reg_names[FRAME_POINTER_REGNUM],
448 foffset + fsize, fmask);
453 for (regno = 55; regno >= 24; regno--)
454 if (regs_ever_live[regno] && ! call_used_regs[regno])
459 asm_fprintf (stream, "\tfpmovd -%d(%s,%Ra0.l), %s\n",
461 reg_names[FRAME_POINTER_REGNUM],
464 asm_fprintf (stream, "\tfpmoved %s@(-%d,%Ra0:l), %s\n",
465 reg_names[FRAME_POINTER_REGNUM],
466 fpoffset + fsize, reg_names[regno]);
469 else if (! frame_pointer_needed)
472 asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
475 asm_fprintf (stream, "\tfpmoved %Rsp@+, %s\n",
482 asm_fprintf (stream, "\tfpmovd -%d(%s), %s\n",
484 reg_names[FRAME_POINTER_REGNUM],
487 asm_fprintf (stream, "\tfpmoved %s@(-%d), %s\n",
488 reg_names[FRAME_POINTER_REGNUM],
489 fpoffset + fsize, reg_names[regno]);
494 if (frame_pointer_needed)
495 fprintf (stream, "\tunlk %s\n",
496 reg_names[FRAME_POINTER_REGNUM]);
499 if (fsize + 4 < 0x8000)
502 asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
504 asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
510 asm_fprintf (stream, "\tadd.l %0I%d,%Rsp\n", fsize + 4);
512 asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", fsize + 4);
516 if (current_function_pops_args)
517 asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
519 fprintf (stream, "\trts\n");
522 /* Similar to general_operand, but exclude stack_pointer_rtx. */
525 not_sp_operand (op, mode)
527 enum machine_mode mode;
529 return op != stack_pointer_rtx && general_operand (op, mode);
532 /* Return TRUE if X is a valid comparison operator for the dbcc
535 Note it rejects floating point comparison operators.
536 (In the future we could use Fdbcc).
538 It also rejects some comparisons when CC_NO_OVERFLOW is set. */
541 valid_dbcc_comparison_p (x, mode)
543 enum machine_mode mode;
545 /* We could add support for these in the future */
546 if (cc_prev_status.flags & CC_IN_68881)
549 switch (GET_CODE (x))
552 case EQ: case NE: case GTU: case LTU:
556 /* Reject some when CC_NO_OVERFLOW is set. This may be over
558 case GT: case LT: case GE: case LE:
559 return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
565 /* Output a dbCC; jCC sequence. Note we do not handle the
566 floating point version of this sequence (Fdbcc). We also
567 do not handle alternative conditions when CC_NO_OVERFLOW is
568 set. It is assumed that valid_dbcc_comparison_p will kick
569 those out before we get here. */
571 output_dbcc_and_branch (operands)
575 switch (GET_CODE (operands[3]))
579 output_asm_insn ("dbeq %0,%l1\n\tjbeq %l2", operands);
581 output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
587 output_asm_insn ("dbne %0,%l1\n\tjbne %l2", operands);
589 output_asm_insn ("dbne %0,%l1\n\tjne %l2", operands);
595 output_asm_insn ("dbgt %0,%l1\n\tjbgt %l2", operands);
597 output_asm_insn ("dbgt %0,%l1\n\tjgt %l2", operands);
603 output_asm_insn ("dbhi %0,%l1\n\tjbhi %l2", operands);
605 output_asm_insn ("dbhi %0,%l1\n\tjhi %l2", operands);
611 output_asm_insn ("dblt %0,%l1\n\tjblt %l2", operands);
613 output_asm_insn ("dblt %0,%l1\n\tjlt %l2", operands);
619 output_asm_insn ("dbcs %0,%l1\n\tjbcs %l2", operands);
621 output_asm_insn ("dbcs %0,%l1\n\tjcs %l2", operands);
627 output_asm_insn ("dbge %0,%l1\n\tjbge %l2", operands);
629 output_asm_insn ("dbge %0,%l1\n\tjge %l2", operands);
635 output_asm_insn ("dbcc %0,%l1\n\tjbcc %l2", operands);
637 output_asm_insn ("dbcc %0,%l1\n\tjcc %l2", operands);
643 output_asm_insn ("dble %0,%l1\n\tjble %l2", operands);
645 output_asm_insn ("dble %0,%l1\n\tjle %l2", operands);
651 output_asm_insn ("dbls %0,%l1\n\tjbls %l2", operands);
653 output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
661 /* If the decrement is to be done in SImode, then we have
662 to compensate for the fact that dbcc decrements in HImode. */
663 switch (GET_MODE (operands[0]))
667 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjbpl %l1", operands);
669 output_asm_insn ("clr%.w %0\n\tsubq%.l %#1,%0\n\tjpl %l1", operands);
682 output_btst (operands, countop, dataop, insn, signpos)
688 operands[0] = countop;
689 operands[1] = dataop;
691 if (GET_CODE (countop) == CONST_INT)
693 register int count = INTVAL (countop);
694 /* If COUNT is bigger than size of storage unit in use,
695 advance to the containing unit of same size. */
698 int offset = (count & ~signpos) / 8;
699 count = count & signpos;
700 operands[1] = dataop = adj_offsettable_operand (dataop, offset);
702 if (count == signpos)
703 cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
705 cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
707 /* These three statements used to use next_insns_test_no...
708 but it appears that this should do the same job. */
710 && next_insn_tests_no_inequality (insn))
713 && next_insn_tests_no_inequality (insn))
716 && next_insn_tests_no_inequality (insn))
719 cc_status.flags = CC_NOT_NEGATIVE;
724 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
725 reference and a constant. */
728 symbolic_operand (op, mode)
730 enum machine_mode mode;
732 switch (GET_CODE (op))
740 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
741 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
742 && GET_CODE (XEXP (op, 1)) == CONST_INT);
744 #if 0 /* Deleted, with corresponding change in m68k.h,
745 so as to fit the specs. No CONST_DOUBLE is ever symbolic. */
747 return GET_MODE (op) == mode;
756 /* Legitimize PIC addresses. If the address is already
757 position-independent, we return ORIG. Newly generated
758 position-independent addresses go to REG. If we need more
759 than one register, we lose.
761 An address is legitimized by making an indirect reference
762 through the Global Offset Table with the name of the symbol
765 The assembler and linker are responsible for placing the
766 address of the symbol in the GOT. The function prologue
767 is responsible for initializing a5 to the starting address
770 The assembler is also responsible for translating a symbol name
771 into a constant displacement from the start of the GOT.
773 A quick example may make things a little clearer:
775 When not generating PIC code to store the value 12345 into _foo
776 we would generate the following code:
780 When generating PIC two transformations are made. First, the compiler
781 loads the address of foo into a register. So the first transformation makes:
786 The code in movsi will intercept the lea instruction and call this
787 routine which will transform the instructions into:
789 movel a5@(_foo:w), a0
793 That (in a nutshell) is how *all* symbol and label references are
797 legitimize_pic_address (orig, mode, reg)
799 enum machine_mode mode;
803 /* First handle a simple SYMBOL_REF or LABEL_REF */
804 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
809 pic_ref = gen_rtx (MEM, Pmode,
810 gen_rtx (PLUS, Pmode,
811 pic_offset_table_rtx, orig));
812 current_function_uses_pic_offset_table = 1;
813 RTX_UNCHANGING_P (pic_ref) = 1;
814 emit_move_insn (reg, pic_ref);
817 else if (GET_CODE (orig) == CONST)
821 /* Make sure this is CONST has not already been legitimized */
822 if (GET_CODE (XEXP (orig, 0)) == PLUS
823 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
829 /* legitimize both operands of the PLUS */
830 if (GET_CODE (XEXP (orig, 0)) == PLUS)
832 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
833 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
834 base == reg ? 0 : reg);
838 if (GET_CODE (orig) == CONST_INT)
839 return plus_constant_for_output (base, INTVAL (orig));
840 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
841 /* Likewise, should we set special REG_NOTEs here? */
847 /* Return the best assembler insn template
848 for moving operands[1] into operands[0] as a fullword. */
851 singlemove_string (operands)
854 #ifdef SUPPORT_SUN_FPA
855 if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
856 return "fpmoves %1,%0";
858 if (DATA_REG_P (operands[0])
859 && GET_CODE (operands[1]) == CONST_INT
860 && INTVAL (operands[1]) < 128
861 && INTVAL (operands[1]) >= -128)
863 #if defined (MOTOROLA) && !defined (CRDS)
864 return "moveq%.l %1,%0";
866 return "moveq %1,%0";
869 if (operands[1] != const0_rtx)
870 return "move%.l %1,%0";
871 if (! ADDRESS_REG_P (operands[0]))
873 return "sub%.l %0,%0";
876 /* Output assembler code to perform a doubleword move insn
877 with operands OPERANDS. */
880 output_move_double (operands)
883 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
885 rtx addreg0 = 0, addreg1 = 0;
887 /* First classify both operands. */
889 if (REG_P (operands[0]))
891 else if (offsettable_memref_p (operands[0]))
893 else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
895 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
897 else if (GET_CODE (operands[0]) == MEM)
902 if (REG_P (operands[1]))
904 else if (CONSTANT_P (operands[1]))
906 else if (offsettable_memref_p (operands[1]))
908 else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
910 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
912 else if (GET_CODE (operands[1]) == MEM)
917 /* Check for the cases that the operand constraints are not
918 supposed to allow to happen. Abort if we get one,
919 because generating code for these cases is painful. */
921 if (optype0 == RNDOP || optype1 == RNDOP)
924 /* If one operand is decrementing and one is incrementing
925 decrement the former register explicitly
926 and change that operand into ordinary indexing. */
928 if (optype0 == PUSHOP && optype1 == POPOP)
930 operands[0] = XEXP (XEXP (operands[0], 0), 0);
931 output_asm_insn ("subq%.l %#8,%0", operands);
932 operands[0] = gen_rtx (MEM, DImode, operands[0]);
935 if (optype0 == POPOP && optype1 == PUSHOP)
937 operands[1] = XEXP (XEXP (operands[1], 0), 0);
938 output_asm_insn ("subq%.l %#8,%1", operands);
939 operands[1] = gen_rtx (MEM, DImode, operands[1]);
943 /* If an operand is an unoffsettable memory ref, find a register
944 we can increment temporarily to make it refer to the second word. */
946 if (optype0 == MEMOP)
947 addreg0 = find_addr_reg (XEXP (operands[0], 0));
949 if (optype1 == MEMOP)
950 addreg1 = find_addr_reg (XEXP (operands[1], 0));
952 /* Ok, we can do one word at a time.
953 Normally we do the low-numbered word first,
954 but if either operand is autodecrementing then we
955 do the high-numbered word first.
957 In either case, set up in LATEHALF the operands to use
958 for the high-numbered word and in some cases alter the
959 operands in OPERANDS to be suitable for the low-numbered word. */
961 if (optype0 == REGOP)
962 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
963 else if (optype0 == OFFSOP)
964 latehalf[0] = adj_offsettable_operand (operands[0], 4);
966 latehalf[0] = operands[0];
968 if (optype1 == REGOP)
969 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
970 else if (optype1 == OFFSOP)
971 latehalf[1] = adj_offsettable_operand (operands[1], 4);
972 else if (optype1 == CNSTOP)
973 split_double (operands[1], &operands[1], &latehalf[1]);
975 latehalf[1] = operands[1];
977 /* If insn is effectively movd N(sp),-(sp) then we will do the
978 high word first. We should use the adjusted operand 1 (which is N+4(sp))
979 for the low word as well, to compensate for the first decrement of sp. */
980 if (optype0 == PUSHOP
981 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
982 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
983 operands[1] = latehalf[1];
985 /* If one or both operands autodecrementing,
986 do the two words, high-numbered first. */
988 /* Likewise, the first move would clobber the source of the second one,
989 do them in the other order. This happens only for registers;
990 such overlap can't happen in memory unless the user explicitly
991 sets it up, and that is an undefined circumstance. */
993 if (optype0 == PUSHOP || optype1 == PUSHOP
994 || (optype0 == REGOP && optype1 == REGOP
995 && REGNO (operands[0]) == REGNO (latehalf[1])))
997 /* Make any unoffsettable addresses point at high-numbered word. */
999 output_asm_insn ("addql %#4,%0", &addreg0);
1001 output_asm_insn ("addql %#4,%0", &addreg1);
1004 output_asm_insn (singlemove_string (latehalf), latehalf);
1006 /* Undo the adds we just did. */
1008 output_asm_insn ("subql %#4,%0", &addreg0);
1010 output_asm_insn ("subql %#4,%0", &addreg1);
1012 /* Do low-numbered word. */
1013 return singlemove_string (operands);
1016 /* Normal case: do the two words, low-numbered first. */
1018 output_asm_insn (singlemove_string (operands), operands);
1020 /* Make any unoffsettable addresses point at high-numbered word. */
1022 output_asm_insn ("addql %#4,%0", &addreg0);
1024 output_asm_insn ("addql %#4,%0", &addreg1);
1027 output_asm_insn (singlemove_string (latehalf), latehalf);
1029 /* Undo the adds we just did. */
1031 output_asm_insn ("subql %#4,%0", &addreg0);
1033 output_asm_insn ("subql %#4,%0", &addreg1);
1038 /* Return a REG that occurs in ADDR with coefficient 1.
1039 ADDR can be effectively incremented by incrementing REG. */
1042 find_addr_reg (addr)
1045 while (GET_CODE (addr) == PLUS)
1047 if (GET_CODE (XEXP (addr, 0)) == REG)
1048 addr = XEXP (addr, 0);
1049 else if (GET_CODE (XEXP (addr, 1)) == REG)
1050 addr = XEXP (addr, 1);
1051 else if (CONSTANT_P (XEXP (addr, 0)))
1052 addr = XEXP (addr, 1);
1053 else if (CONSTANT_P (XEXP (addr, 1)))
1054 addr = XEXP (addr, 0);
1058 if (GET_CODE (addr) == REG)
1063 /* Store in cc_status the expressions that the condition codes will
1064 describe after execution of an instruction whose pattern is EXP.
1065 Do not alter them if the instruction would not alter the cc's. */
1067 /* On the 68000, all the insns to store in an address register fail to
1068 set the cc's. However, in some cases these instructions can make it
1069 possibly invalid to use the saved cc's. In those cases we clear out
1070 some or all of the saved cc's so they won't be used. */
1072 notice_update_cc (exp, insn)
1076 /* If the cc is being set from the fpa and the expression is not an
1077 explicit floating point test instruction (which has code to deal with
1078 this), reinit the CC. */
1079 if (((cc_status.value1 && FPA_REG_P (cc_status.value1))
1080 || (cc_status.value2 && FPA_REG_P (cc_status.value2)))
1081 && !(GET_CODE (exp) == PARALLEL
1082 && GET_CODE (XVECEXP (exp, 0, 0)) == SET
1083 && XEXP (XVECEXP (exp, 0, 0), 0) == cc0_rtx))
1087 else if (GET_CODE (exp) == SET)
1089 if (GET_CODE (SET_SRC (exp)) == CALL)
1093 else if (ADDRESS_REG_P (SET_DEST (exp)))
1095 if (cc_status.value1
1096 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1097 cc_status.value1 = 0;
1098 if (cc_status.value2
1099 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1100 cc_status.value2 = 0;
1102 else if (!FP_REG_P (SET_DEST (exp))
1103 && SET_DEST (exp) != cc0_rtx
1104 && (FP_REG_P (SET_SRC (exp))
1105 || GET_CODE (SET_SRC (exp)) == FIX
1106 || GET_CODE (SET_SRC (exp)) == FLOAT_TRUNCATE
1107 || GET_CODE (SET_SRC (exp)) == FLOAT_EXTEND))
1111 /* A pair of move insns doesn't produce a useful overall cc. */
1112 else if (!FP_REG_P (SET_DEST (exp))
1113 && !FP_REG_P (SET_SRC (exp))
1114 && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
1115 && (GET_CODE (SET_SRC (exp)) == REG
1116 || GET_CODE (SET_SRC (exp)) == MEM
1117 || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
1121 else if (GET_CODE (SET_SRC (exp)) == CALL)
1125 else if (XEXP (exp, 0) != pc_rtx)
1127 cc_status.flags = 0;
1128 cc_status.value1 = XEXP (exp, 0);
1129 cc_status.value2 = XEXP (exp, 1);
1132 else if (GET_CODE (exp) == PARALLEL
1133 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1135 if (ADDRESS_REG_P (XEXP (XVECEXP (exp, 0, 0), 0)))
1137 else if (XEXP (XVECEXP (exp, 0, 0), 0) != pc_rtx)
1139 cc_status.flags = 0;
1140 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
1141 cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
1146 if (cc_status.value2 != 0
1147 && ADDRESS_REG_P (cc_status.value2)
1148 && GET_MODE (cc_status.value2) == QImode)
1150 if (cc_status.value2 != 0
1151 && !(cc_status.value1 && FPA_REG_P (cc_status.value1)))
1152 switch (GET_CODE (cc_status.value2))
1154 case PLUS: case MINUS: case MULT:
1155 case DIV: case UDIV: case MOD: case UMOD: case NEG:
1156 case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT:
1157 case ROTATE: case ROTATERT:
1158 if (GET_MODE (cc_status.value2) != VOIDmode)
1159 cc_status.flags |= CC_NO_OVERFLOW;
1162 /* (SET r1 (ZERO_EXTEND r2)) on this machine
1163 ends with a move insn moving r2 in r2's mode.
1164 Thus, the cc's are set for r2.
1165 This can set N bit spuriously. */
1166 cc_status.flags |= CC_NOT_NEGATIVE;
1168 if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
1170 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1171 cc_status.value2 = 0;
1172 if (((cc_status.value1 && FP_REG_P (cc_status.value1))
1173 || (cc_status.value2 && FP_REG_P (cc_status.value2)))
1174 && !((cc_status.value1 && FPA_REG_P (cc_status.value1))
1175 || (cc_status.value2 && FPA_REG_P (cc_status.value2))))
1176 cc_status.flags = CC_IN_68881;
1180 output_move_const_double (operands)
1183 #ifdef SUPPORT_SUN_FPA
1184 if (TARGET_FPA && FPA_REG_P (operands[0]))
1186 int code = standard_sun_fpa_constant_p (operands[1]);
1190 static char buf[40];
1192 sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
1195 return "fpmove%.d %1,%0";
1200 int code = standard_68881_constant_p (operands[1]);
1204 static char buf[40];
1206 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1209 return "fmove%.d %1,%0";
1214 output_move_const_single (operands)
1217 #ifdef SUPPORT_SUN_FPA
1220 int code = standard_sun_fpa_constant_p (operands[1]);
1224 static char buf[40];
1226 sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
1229 return "fpmove%.s %1,%0";
1232 #endif /* defined SUPPORT_SUN_FPA */
1234 int code = standard_68881_constant_p (operands[1]);
1238 static char buf[40];
1240 sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
1243 return "fmove%.s %f1,%0";
1247 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1248 from the "fmovecr" instruction.
1249 The value, anded with 0xff, gives the code to use in fmovecr
1250 to get the desired constant. */
1252 /* ??? This code should be fixed for cross-compilation. */
1255 standard_68881_constant_p (x)
1260 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1264 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1265 if (! flag_pretend_float)
1269 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1273 /* Note: there are various other constants available
1274 but it is a nuisance to put in their values here. */
1285 if (GET_MODE (x) == SFmode)
1289 /* larger powers of ten in the constants ram are not used
1290 because they are not equal to a `double' C constant. */
1294 /* If X is a floating-point constant, return the logarithm of X base 2,
1295 or 0 if X is not a power of 2. */
1298 floating_exact_log2 (x)
1301 register double d, d1;
1304 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1305 if (! flag_pretend_float)
1309 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1314 for (d1 = 1.0, i = 0; d1 < d; d1 *= 2.0, i++)
1323 #ifdef SUPPORT_SUN_FPA
1324 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1325 from the Sun FPA's constant RAM.
1326 The value returned, anded with 0x1ff, gives the code to use in fpmove
1327 to get the desired constant. */
1328 #define S_E (2.718281745910644531)
1329 #define D_E (2.718281828459045091)
1330 #define S_PI (3.141592741012573242)
1331 #define D_PI (3.141592653589793116)
1332 #define S_SQRT2 (1.414213538169860840)
1333 #define D_SQRT2 (1.414213562373095145)
1334 #define S_LOG2ofE (1.442695021629333496)
1335 #define D_LOG2ofE (1.442695040888963387)
1336 #define S_LOG2of10 (3.321928024291992188)
1337 #define D_LOG2of10 (3.321928024887362182)
1338 #define S_LOGEof2 (0.6931471824645996094)
1339 #define D_LOGEof2 (0.6931471805599452862)
1340 #define S_LOGEof10 (2.302585124969482442)
1341 #define D_LOGEof10 (2.302585092994045901)
1342 #define S_LOG10of2 (0.3010300099849700928)
1343 #define D_LOG10of2 (0.3010299956639811980)
1344 #define S_LOG10ofE (0.4342944920063018799)
1345 #define D_LOG10ofE (0.4342944819032518167)
1347 /* This code should be fixed for cross-compilation. */
1350 standard_sun_fpa_constant_p (x)
1355 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1356 if (! flag_pretend_float)
1360 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1363 return 0x200; /* 0 once 0x1ff is anded with it */
1384 if (d == -(1.0/2.0))
1388 * Stuff that looks different if it's single or double
1390 if (GET_MODE (x) == SFmode)
1398 if (d == (S_PI / 2.0))
1402 if (d == (1.0 / S_SQRT2))
1404 /* Large powers of 10 in the constant
1405 ram are not used because they are
1406 not equal to a C double constant */
1407 if (d == -(S_PI / 2.0))
1411 if (d == S_LOG2of10)
1415 if (d == S_LOGEof10)
1417 if (d == S_LOG10of2)
1419 if (d == S_LOG10ofE)
1430 if (d == (D_PI / 2.0))
1434 if (d == (1.0 / D_SQRT2))
1436 /* Large powers of 10 in the constant
1437 ram are not used because they are
1438 not equal to a C double constant */
1439 if (d == -(D_PI / 2.0))
1443 if (d == D_LOG2of10)
1447 if (d == D_LOGEof10)
1449 if (d == D_LOG10of2)
1451 if (d == D_LOG10ofE)
1456 #endif /* define SUPPORT_SUN_FPA */
1458 /* A C compound statement to output to stdio stream STREAM the
1459 assembler syntax for an instruction operand X. X is an RTL
1462 CODE is a value that can be used to specify one of several ways
1463 of printing the operand. It is used when identical operands
1464 must be printed differently depending on the context. CODE
1465 comes from the `%' specification that was used to request
1466 printing of the operand. If the specification was just `%DIGIT'
1467 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
1468 is the ASCII code for LTR.
1470 If X is a register, this macro should print the register's name.
1471 The names can be found in an array `reg_names' whose type is
1472 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
1474 When the machine description has a specification `%PUNCT' (a `%'
1475 followed by a punctuation character), this macro is called with
1476 a null pointer for X and the punctuation character for CODE.
1478 The m68k specific codes are:
1480 '.' for dot needed in Motorola-style opcode names.
1481 '-' for an operand pushing on the stack:
1482 sp@-, -(sp) or -(%sp) depending on the style of syntax.
1483 '+' for an operand pushing on the stack:
1484 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
1485 '@' for a reference to the top word on the stack:
1486 sp@, (sp) or (%sp) depending on the style of syntax.
1487 '#' for an immediate operand prefix (# in MIT and Motorola syntax
1488 but & in SGS syntax).
1489 '!' for the cc register (used in an `and to cc' insn).
1490 '$' for the letter `s' in an op code, but only on the 68040.
1491 '&' for the letter `d' in an op code, but only on the 68040.
1492 '/' for register prefix needed by longlong.h.
1494 'b' for byte insn (no effect, on the Sun; this is for the ISI).
1495 'd' to force memory addressing to be absolute, not relative.
1496 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
1497 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
1498 than directly). Second part of 'y' below.
1499 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
1500 or print pair of registers as rx:ry.
1501 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
1502 CONST_DOUBLE's as SunFPA constant RAM registers if
1503 possible, so it should not be used except for the SunFPA.
1508 print_operand (file, op, letter)
1509 FILE *file; /* file to write to */
1510 rtx op; /* operand to print */
1511 int letter; /* %<letter> or 0 */
1518 asm_fprintf (file, ".");
1521 else if (letter == '#')
1523 asm_fprintf (file, "%0I");
1525 else if (letter == '-')
1528 asm_fprintf (file, "-(%Rsp)");
1530 asm_fprintf (file, "%Rsp@-");
1533 else if (letter == '+')
1536 asm_fprintf (file, "(%Rsp)+");
1538 asm_fprintf (file, "%Rsp@+");
1541 else if (letter == '@')
1544 asm_fprintf (file, "(%Rsp)");
1546 asm_fprintf (file, "%Rsp@");
1549 else if (letter == '!')
1551 asm_fprintf (file, "%Rfpcr");
1553 else if (letter == '$')
1555 if (TARGET_68040_ONLY)
1557 fprintf (file, "s");
1560 else if (letter == '&')
1562 if (TARGET_68040_ONLY)
1564 fprintf (file, "d");
1567 else if (letter == '/')
1569 asm_fprintf (file, "%R");
1571 else if (GET_CODE (op) == REG)
1574 && (letter == 'y' || letter == 'x')
1575 && GET_MODE (op) == DFmode)
1577 fprintf (file, "%s:%s", reg_names[REGNO (op)],
1578 reg_names[REGNO (op)+1]);
1582 fprintf (file, "%s", reg_names[REGNO (op)]);
1585 else if (GET_CODE (op) == MEM)
1587 output_address (XEXP (op, 0));
1588 if (letter == 'd' && ! TARGET_68020
1589 && CONSTANT_ADDRESS_P (XEXP (op, 0))
1590 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
1591 && INTVAL (XEXP (op, 0)) < 0x8000
1592 && INTVAL (XEXP (op, 0)) >= -0x8000))
1594 fprintf (file, ":l");
1597 #ifdef SUPPORT_SUN_FPA
1598 else if ((letter == 'y' || letter == 'w')
1599 && GET_CODE (op) == CONST_DOUBLE
1600 && (i = standard_sun_fpa_constant_p (op)))
1602 fprintf (file, "%%%d", i & 0x1ff);
1605 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
1608 union { float f; int i; } u1;
1609 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1611 PRINT_OPERAND_PRINT_FLOAT (letter, file);
1613 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode)
1616 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1617 ASM_OUTPUT_DOUBLE_OPERAND (file, d);
1621 asm_fprintf (file, "%0I"); output_addr_const (file, op);
1626 /* A C compound statement to output to stdio stream STREAM the
1627 assembler syntax for an instruction operand that is a memory
1628 reference whose address is ADDR. ADDR is an RTL expression.
1630 Note that this contains a kludge that knows that the only reason
1631 we have an address (plus (label_ref...) (reg...)) when not generating
1632 PIC code is in the insn before a tablejump, and we know that m68k.md
1633 generates a label LInnn: on such an insn.
1635 It is possible for PIC to generate a (plus (label_ref...) (reg...))
1636 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
1638 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
1639 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
1640 we want. This difference can be accommodated by using an assembler
1641 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
1642 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
1643 macro. See m68k/sgs.h for an example; for versions without the bug.
1645 They also do not like things like "pea 1.w", so we simple leave off
1646 the .w on small constants.
1648 This routine is responsible for distinguishing between -fpic and -fPIC
1649 style relocations in an address. When generating -fpic code the
1650 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
1651 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
1654 print_operand_address (file, addr)
1658 register rtx reg1, reg2, breg, ireg;
1661 switch (GET_CODE (addr))
1665 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
1667 fprintf (file, "%s@", reg_names[REGNO (addr)]);
1672 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
1674 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
1679 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
1681 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
1685 reg1 = reg2 = ireg = breg = offset = 0;
1686 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
1688 offset = XEXP (addr, 0);
1689 addr = XEXP (addr, 1);
1691 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
1693 offset = XEXP (addr, 1);
1694 addr = XEXP (addr, 0);
1696 if (GET_CODE (addr) != PLUS)
1700 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
1702 reg1 = XEXP (addr, 0);
1703 addr = XEXP (addr, 1);
1705 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
1707 reg1 = XEXP (addr, 1);
1708 addr = XEXP (addr, 0);
1710 else if (GET_CODE (XEXP (addr, 0)) == MULT)
1712 reg1 = XEXP (addr, 0);
1713 addr = XEXP (addr, 1);
1715 else if (GET_CODE (XEXP (addr, 1)) == MULT)
1717 reg1 = XEXP (addr, 1);
1718 addr = XEXP (addr, 0);
1720 else if (GET_CODE (XEXP (addr, 0)) == REG)
1722 reg1 = XEXP (addr, 0);
1723 addr = XEXP (addr, 1);
1725 else if (GET_CODE (XEXP (addr, 1)) == REG)
1727 reg1 = XEXP (addr, 1);
1728 addr = XEXP (addr, 0);
1730 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
1731 || GET_CODE (addr) == SIGN_EXTEND)
1743 #if 0 /* for OLD_INDEXING */
1744 else if (GET_CODE (addr) == PLUS)
1746 if (GET_CODE (XEXP (addr, 0)) == REG)
1748 reg2 = XEXP (addr, 0);
1749 addr = XEXP (addr, 1);
1751 else if (GET_CODE (XEXP (addr, 1)) == REG)
1753 reg2 = XEXP (addr, 1);
1754 addr = XEXP (addr, 0);
1766 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
1767 || GET_CODE (reg1) == MULT))
1768 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
1773 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
1778 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
1779 && ! (flag_pic && ireg == pic_offset_table_rtx))
1782 if (GET_CODE (ireg) == MULT)
1784 scale = INTVAL (XEXP (ireg, 1));
1785 ireg = XEXP (ireg, 0);
1787 if (GET_CODE (ireg) == SIGN_EXTEND)
1791 asm_fprintf (file, "%LLD%d(%Rpc,%s.w",
1792 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1793 reg_names[REGNO (XEXP (ireg, 0))]);
1795 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.w",
1796 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1797 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1798 reg_names[REGNO (XEXP (ireg, 0))]);
1801 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w",
1802 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1803 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1804 reg_names[REGNO (XEXP (ireg, 0))]);
1811 asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1812 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1813 reg_names[REGNO (ireg)]);
1815 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
1816 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1817 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1818 reg_names[REGNO (ireg)]);
1821 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1822 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1823 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1824 reg_names[REGNO (ireg)]);
1830 fprintf (file, "*%d", scale);
1832 fprintf (file, ":%d", scale);
1838 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
1839 && ! (flag_pic && breg == pic_offset_table_rtx))
1843 asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1844 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1845 reg_names[REGNO (breg)]);
1847 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l",
1848 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1849 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1850 reg_names[REGNO (breg)]);
1853 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1854 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1855 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1856 reg_names[REGNO (breg)]);
1861 if (ireg != 0 || breg != 0)
1868 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
1875 output_addr_const (file, addr);
1876 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
1877 fprintf (file, ".w");
1878 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
1879 fprintf (file, ".l");
1881 fprintf (file, "(%s", reg_names[REGNO (breg)]);
1887 fprintf (file, "%s@(", reg_names[REGNO (breg)]);
1890 output_addr_const (file, addr);
1891 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
1892 fprintf (file, ":w");
1893 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
1894 fprintf (file, ":l");
1896 if (addr != 0 && ireg != 0)
1901 if (ireg != 0 && GET_CODE (ireg) == MULT)
1903 scale = INTVAL (XEXP (ireg, 1));
1904 ireg = XEXP (ireg, 0);
1906 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
1909 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
1911 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
1917 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
1919 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
1925 fprintf (file, "*%d", scale);
1927 fprintf (file, ":%d", scale);
1933 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
1934 && ! (flag_pic && reg1 == pic_offset_table_rtx))
1938 asm_fprintf (file, "%LLD%d(%Rpc,%s.l)",
1939 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1940 reg_names[REGNO (reg1)]);
1942 asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.l)",
1943 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1944 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1945 reg_names[REGNO (reg1)]);
1948 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)",
1949 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1950 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1951 reg_names[REGNO (reg1)]);
1955 /* FALL-THROUGH (is this really what we want? */
1957 if (GET_CODE (addr) == CONST_INT
1958 && INTVAL (addr) < 0x8000
1959 && INTVAL (addr) >= -0x8000)
1963 /* Many SGS assemblers croak on size specifiers for constants. */
1964 fprintf (file, "%d", INTVAL (addr));
1966 fprintf (file, "%d.w", INTVAL (addr));
1969 fprintf (file, "%d:w", INTVAL (addr));
1974 output_addr_const (file, addr);
1980 /* Check for cases where a clr insns can be omitted from code using
1981 strict_low_part sets. For example, the second clrl here is not needed:
1982 clrl d0; movw a0@+,d0; use d0; clrl d0; movw a0@+; use d0; ...
1984 MODE is the mode of this STRICT_LOW_PART set. FIRST_INSN is the clear
1985 insn we are checking for redundancy. TARGET is the register set by the
1989 strict_low_part_peephole_ok (mode, first_insn, target)
1990 enum machine_mode mode;
1996 p = prev_nonnote_insn (first_insn);
2000 /* If it isn't an insn, then give up. */
2001 if (GET_CODE (p) != INSN)
2004 if (reg_set_p (target, p))
2006 rtx set = single_set (p);
2009 /* If it isn't an easy to recognize insn, then give up. */
2013 dest = SET_DEST (set);
2015 /* If this sets the entire target register to zero, then our
2016 first_insn is redundant. */
2017 if (rtx_equal_p (dest, target)
2018 && SET_SRC (set) == const0_rtx)
2020 else if (GET_CODE (dest) == STRICT_LOW_PART
2021 && GET_CODE (XEXP (dest, 0)) == REG
2022 && REGNO (XEXP (dest, 0)) == REGNO (target)
2023 && (GET_MODE_SIZE (GET_MODE (XEXP (dest, 0)))
2024 <= GET_MODE_SIZE (mode)))
2025 /* This is a strict low part set which modifies less than
2026 we are using, so it is safe. */
2032 p = prev_nonnote_insn (p);