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)
1258 union {double d; int i[2];} u;
1261 /* fmovecr must be emulated on the 68040, so it shouldn't be used at all. */
1265 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1266 if (! flag_pretend_float)
1270 #ifdef HOST_WORDS_BIG_ENDIAN
1271 u.i[0] = CONST_DOUBLE_LOW (x);
1272 u.i[1] = CONST_DOUBLE_HIGH (x);
1274 u.i[0] = CONST_DOUBLE_HIGH (x);
1275 u.i[1] = CONST_DOUBLE_LOW (x);
1281 /* Note: there are various other constants available
1282 but it is a nuisance to put in their values here. */
1293 if (GET_MODE (x) == SFmode)
1297 /* larger powers of ten in the constants ram are not used
1298 because they are not equal to a `double' C constant. */
1302 /* If X is a floating-point constant, return the logarithm of X base 2,
1303 or 0 if X is not a power of 2. */
1306 floating_exact_log2 (x)
1309 union {double d; int i[2];} u;
1310 register double d, d1;
1313 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1314 if (! flag_pretend_float)
1318 #ifdef HOST_WORDS_BIG_ENDIAN
1319 u.i[0] = CONST_DOUBLE_LOW (x);
1320 u.i[1] = CONST_DOUBLE_HIGH (x);
1322 u.i[0] = CONST_DOUBLE_HIGH (x);
1323 u.i[1] = CONST_DOUBLE_LOW (x);
1330 for (d1 = 1.0, i = 0; d1 < d; d1 *= 2.0, i++)
1339 #ifdef SUPPORT_SUN_FPA
1340 /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
1341 from the Sun FPA's constant RAM.
1342 The value returned, anded with 0x1ff, gives the code to use in fpmove
1343 to get the desired constant. */
1344 #define S_E (2.718281745910644531)
1345 #define D_E (2.718281828459045091)
1346 #define S_PI (3.141592741012573242)
1347 #define D_PI (3.141592653589793116)
1348 #define S_SQRT2 (1.414213538169860840)
1349 #define D_SQRT2 (1.414213562373095145)
1350 #define S_LOG2ofE (1.442695021629333496)
1351 #define D_LOG2ofE (1.442695040888963387)
1352 #define S_LOG2of10 (3.321928024291992188)
1353 #define D_LOG2of10 (3.321928024887362182)
1354 #define S_LOGEof2 (0.6931471824645996094)
1355 #define D_LOGEof2 (0.6931471805599452862)
1356 #define S_LOGEof10 (2.302585124969482442)
1357 #define D_LOGEof10 (2.302585092994045901)
1358 #define S_LOG10of2 (0.3010300099849700928)
1359 #define D_LOG10of2 (0.3010299956639811980)
1360 #define S_LOG10ofE (0.4342944920063018799)
1361 #define D_LOG10ofE (0.4342944819032518167)
1363 /* This code should be fixed for cross-compilation. */
1366 standard_sun_fpa_constant_p (x)
1369 union {double d; int i[2];} u;
1372 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
1373 if (! flag_pretend_float)
1378 u.i[0] = CONST_DOUBLE_LOW (x);
1379 u.i[1] = CONST_DOUBLE_HIGH (x);
1383 return 0x200; /* 0 once 0x1ff is anded with it */
1404 if (d == -(1.0/2.0))
1408 * Stuff that looks different if it's single or double
1410 if (GET_MODE (x) == SFmode)
1418 if (d == (S_PI / 2.0))
1422 if (d == (1.0 / S_SQRT2))
1424 /* Large powers of 10 in the constant
1425 ram are not used because they are
1426 not equal to a C double constant */
1427 if (d == -(S_PI / 2.0))
1431 if (d == S_LOG2of10)
1435 if (d == S_LOGEof10)
1437 if (d == S_LOG10of2)
1439 if (d == S_LOG10ofE)
1450 if (d == (D_PI / 2.0))
1454 if (d == (1.0 / D_SQRT2))
1456 /* Large powers of 10 in the constant
1457 ram are not used because they are
1458 not equal to a C double constant */
1459 if (d == -(D_PI / 2.0))
1463 if (d == D_LOG2of10)
1467 if (d == D_LOGEof10)
1469 if (d == D_LOG10of2)
1471 if (d == D_LOG10ofE)
1476 #endif /* define SUPPORT_SUN_FPA */
1478 /* A C compound statement to output to stdio stream STREAM the
1479 assembler syntax for an instruction operand X. X is an RTL
1482 CODE is a value that can be used to specify one of several ways
1483 of printing the operand. It is used when identical operands
1484 must be printed differently depending on the context. CODE
1485 comes from the `%' specification that was used to request
1486 printing of the operand. If the specification was just `%DIGIT'
1487 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
1488 is the ASCII code for LTR.
1490 If X is a register, this macro should print the register's name.
1491 The names can be found in an array `reg_names' whose type is
1492 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
1494 When the machine description has a specification `%PUNCT' (a `%'
1495 followed by a punctuation character), this macro is called with
1496 a null pointer for X and the punctuation character for CODE.
1498 The m68k specific codes are:
1500 '.' for dot needed in Motorola-style opcode names.
1501 '-' for an operand pushing on the stack:
1502 sp@-, -(sp) or -(%sp) depending on the style of syntax.
1503 '+' for an operand pushing on the stack:
1504 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
1505 '@' for a reference to the top word on the stack:
1506 sp@, (sp) or (%sp) depending on the style of syntax.
1507 '#' for an immediate operand prefix (# in MIT and Motorola syntax
1508 but & in SGS syntax).
1509 '!' for the cc register (used in an `and to cc' insn).
1510 '$' for the letter `s' in an op code, but only on the 68040.
1511 '&' for the letter `d' in an op code, but only on the 68040.
1513 'b' for byte insn (no effect, on the Sun; this is for the ISI).
1514 'd' to force memory addressing to be absolute, not relative.
1515 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
1516 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
1517 than directly). Second part of 'y' below.
1518 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
1519 or print pair of registers as rx:ry.
1520 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
1521 CONST_DOUBLE's as SunFPA constant RAM registers if
1522 possible, so it should not be used except for the SunFPA.
1527 print_operand (file, op, letter)
1528 FILE *file; /* file to write to */
1529 rtx op; /* operand to print */
1530 int letter; /* %<letter> or 0 */
1537 asm_fprintf (file, ".");
1540 else if (letter == '#')
1542 asm_fprintf (file, "%0I");
1544 else if (letter == '-')
1547 asm_fprintf (file, "-(%Rsp)");
1549 asm_fprintf (file, "%Rsp@-");
1552 else if (letter == '+')
1555 asm_fprintf (file, "(%Rsp)+");
1557 asm_fprintf (file, "%Rsp@+");
1560 else if (letter == '@')
1563 asm_fprintf (file, "(%Rsp)");
1565 asm_fprintf (file, "%Rsp@");
1568 else if (letter == '!')
1570 asm_fprintf (file, "%Rfpcr");
1572 else if (letter == '$')
1574 if (TARGET_68040_ONLY)
1576 fprintf (file, "s");
1579 else if (letter == '&')
1581 if (TARGET_68040_ONLY)
1583 fprintf (file, "d");
1586 else if (GET_CODE (op) == REG)
1589 && (letter == 'y' || letter == 'x')
1590 && GET_MODE (op) == DFmode)
1592 fprintf (file, "%s:%s", reg_names[REGNO (op)],
1593 reg_names[REGNO (op)+1]);
1597 fprintf (file, "%s", reg_names[REGNO (op)]);
1600 else if (GET_CODE (op) == MEM)
1602 output_address (XEXP (op, 0));
1603 if (letter == 'd' && ! TARGET_68020
1604 && CONSTANT_ADDRESS_P (XEXP (op, 0))
1605 && !(GET_CODE (XEXP (op, 0)) == CONST_INT
1606 && INTVAL (XEXP (op, 0)) < 0x8000
1607 && INTVAL (XEXP (op, 0)) >= -0x8000))
1609 fprintf (file, ":l");
1612 #ifdef SUPPORT_SUN_FPA
1613 else if ((letter == 'y' || letter == 'w')
1614 && GET_CODE (op) == CONST_DOUBLE
1615 && (i = standard_sun_fpa_constant_p (op)))
1617 fprintf (file, "%%%d", i & 0x1ff);
1620 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
1622 union { double d; int i[2]; } u;
1623 union { float f; int i; } u1;
1624 PRINT_OPERAND_EXTRACT_FLOAT (op);
1626 PRINT_OPERAND_PRINT_FLOAT (letter, file);
1628 else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) != DImode)
1630 union { double d; int i[2]; } u;
1631 PRINT_OPERAND_EXTRACT_FLOAT (op);
1632 ASM_OUTPUT_DOUBLE_OPERAND (file, u.d);
1636 asm_fprintf (file, "%0I"); output_addr_const (file, op);
1641 /* A C compound statement to output to stdio stream STREAM the
1642 assembler syntax for an instruction operand that is a memory
1643 reference whose address is ADDR. ADDR is an RTL expression.
1645 Note that this contains a kludge that knows that the only reason
1646 we have an address (plus (label_ref...) (reg...)) when not generating
1647 PIC code is in the insn before a tablejump, and we know that m68k.md
1648 generates a label LInnn: on such an insn.
1650 It is possible for PIC to generate a (plus (label_ref...) (reg...))
1651 and we handle that just like we would a (plus (symbol_ref...) (reg...)).
1653 Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
1654 fails to assemble. Luckily "Lnnn(pc,d0.l*2)" produces the results
1655 we want. This difference can be accommodated by using an assembler
1656 define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
1657 string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
1658 macro. See m68ksgs.h for an example; for versions without the bug.
1660 They also do not like things like "pea 1.w", so we simple leave off
1661 the .w on small constants.
1663 This routine is responsible for distinguishing between -fpic and -fPIC
1664 style relocations in an address. When generating -fpic code the
1665 offset is output in word mode (eg movel a5@(_foo:w), a0). When generating
1666 -fPIC code the offset is output in long mode (eg movel a5@(_foo:l), a0) */
1669 print_operand_address (file, addr)
1673 register rtx reg1, reg2, breg, ireg;
1676 switch (GET_CODE (addr))
1680 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
1682 fprintf (file, "%s@", reg_names[REGNO (addr)]);
1687 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
1689 fprintf (file, "%s@-", reg_names[REGNO (XEXP (addr, 0))]);
1694 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
1696 fprintf (file, "%s@+", reg_names[REGNO (XEXP (addr, 0))]);
1700 reg1 = reg2 = ireg = breg = offset = 0;
1701 if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
1703 offset = XEXP (addr, 0);
1704 addr = XEXP (addr, 1);
1706 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
1708 offset = XEXP (addr, 1);
1709 addr = XEXP (addr, 0);
1711 if (GET_CODE (addr) != PLUS)
1715 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
1717 reg1 = XEXP (addr, 0);
1718 addr = XEXP (addr, 1);
1720 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
1722 reg1 = XEXP (addr, 1);
1723 addr = XEXP (addr, 0);
1725 else if (GET_CODE (XEXP (addr, 0)) == MULT)
1727 reg1 = XEXP (addr, 0);
1728 addr = XEXP (addr, 1);
1730 else if (GET_CODE (XEXP (addr, 1)) == MULT)
1732 reg1 = XEXP (addr, 1);
1733 addr = XEXP (addr, 0);
1735 else if (GET_CODE (XEXP (addr, 0)) == REG)
1737 reg1 = XEXP (addr, 0);
1738 addr = XEXP (addr, 1);
1740 else if (GET_CODE (XEXP (addr, 1)) == REG)
1742 reg1 = XEXP (addr, 1);
1743 addr = XEXP (addr, 0);
1745 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
1746 || GET_CODE (addr) == SIGN_EXTEND)
1758 #if 0 /* for OLD_INDEXING */
1759 else if (GET_CODE (addr) == PLUS)
1761 if (GET_CODE (XEXP (addr, 0)) == REG)
1763 reg2 = XEXP (addr, 0);
1764 addr = XEXP (addr, 1);
1766 else if (GET_CODE (XEXP (addr, 1)) == REG)
1768 reg2 = XEXP (addr, 1);
1769 addr = XEXP (addr, 0);
1781 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
1782 || GET_CODE (reg1) == MULT))
1783 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
1788 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
1793 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
1794 && ! (flag_pic && ireg == pic_offset_table_rtx))
1797 if (GET_CODE (ireg) == MULT)
1799 scale = INTVAL (XEXP (ireg, 1));
1800 ireg = XEXP (ireg, 0);
1802 if (GET_CODE (ireg) == SIGN_EXTEND)
1806 asm_fprintf (file, "%LLD%d(%Rpc,%s.w",
1807 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1808 reg_names[REGNO (XEXP (ireg, 0))]);
1810 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.w",
1811 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1812 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1813 reg_names[REGNO (XEXP (ireg, 0))]);
1816 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:w",
1817 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1818 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1819 reg_names[REGNO (XEXP (ireg, 0))]);
1826 asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1827 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1828 reg_names[REGNO (ireg)]);
1830 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l",
1831 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1832 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1833 reg_names[REGNO (ireg)]);
1836 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1837 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1838 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1839 reg_names[REGNO (ireg)]);
1845 fprintf (file, "*%d", scale);
1847 fprintf (file, ":%d", scale);
1853 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
1854 && ! (flag_pic && breg == pic_offset_table_rtx))
1858 asm_fprintf (file, "%LLD%d(%Rpc,%s.l",
1859 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1860 reg_names[REGNO (breg)]);
1862 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l",
1863 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1864 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1865 reg_names[REGNO (breg)]);
1868 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l",
1869 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1870 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1871 reg_names[REGNO (breg)]);
1876 if (ireg != 0 || breg != 0)
1883 if (! flag_pic && addr && GET_CODE (addr) == LABEL_REF)
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 fprintf (file, "(%s", reg_names[REGNO (breg)]);
1902 fprintf (file, "%s@(", reg_names[REGNO (breg)]);
1905 output_addr_const (file, addr);
1906 if ((flag_pic == 1) && (breg == pic_offset_table_rtx))
1907 fprintf (file, ":w");
1908 if ((flag_pic == 2) && (breg == pic_offset_table_rtx))
1909 fprintf (file, ":l");
1911 if (addr != 0 && ireg != 0)
1916 if (ireg != 0 && GET_CODE (ireg) == MULT)
1918 scale = INTVAL (XEXP (ireg, 1));
1919 ireg = XEXP (ireg, 0);
1921 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
1924 fprintf (file, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);
1926 fprintf (file, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]);
1932 fprintf (file, "%s.l", reg_names[REGNO (ireg)]);
1934 fprintf (file, "%s:l", reg_names[REGNO (ireg)]);
1940 fprintf (file, "*%d", scale);
1942 fprintf (file, ":%d", scale);
1948 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
1949 && ! (flag_pic && reg1 == pic_offset_table_rtx))
1953 asm_fprintf (file, "%LLD%d(%Rpc,%s.l)",
1954 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1955 reg_names[REGNO (reg1)]);
1957 asm_fprintf (file, "%LL%d-%LLI%d-2.b(%Rpc,%s.l)",
1958 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1959 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1960 reg_names[REGNO (reg1)]);
1963 asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:l)",
1964 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1965 CODE_LABEL_NUMBER (XEXP (addr, 0)),
1966 reg_names[REGNO (reg1)]);
1970 /* FALL-THROUGH (is this really what we want? */
1972 if (GET_CODE (addr) == CONST_INT
1973 && INTVAL (addr) < 0x8000
1974 && INTVAL (addr) >= -0x8000)
1978 /* Many SGS assemblers croak on size specifiers for constants. */
1979 fprintf (file, "%d", INTVAL (addr));
1981 fprintf (file, "%d.w", INTVAL (addr));
1984 fprintf (file, "%d:w", INTVAL (addr));
1989 output_addr_const (file, addr);