1 /* Definitions of target machine for GNU compiler.
2 Bull DPX/2 200 and 300 systems (m68k, SysVr3).
3 Copyright (C) 1987, 1993, 1994, 1995, 1996, 1999 Free Software Foundation, Inc.
4 Contributed by Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr).
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #define MOTOROLA /* Use Motorola syntax rather than "MIT" */
26 #define SGS_NO_LI /* Suppress jump table label usage */
27 #define VERSADOS /* This is the name of the assembler we have */
30 #include "m68k/m68k.h"
31 #undef SELECT_RTX_SECTION
34 /* See m68k.h. 7 means 68020 with 68881.
35 * We really have 68030 and 68882,
36 * but this will get us going.
38 #ifndef TARGET_DEFAULT
39 #define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
42 #define OBJECT_FORMAT_COFF
48 * define all the things the compiler should
51 # define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -Dncl_mr=1 -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
54 # define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -Dncl_el -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
56 # define CPP_PREDEFINES "-Dunix -Dbull -DDPX2 -DSVR3 -Dmc68000 -Dmc68020 -D_BULL_SOURCE -D_POSIX_SOURCE -D_XOPEN_SOURCE -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
62 * you can't get a DPX/2 without a 68882 but allow it
65 # define __HAVE_68881__ 1
66 # define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__ }"
68 #undef DO_GLOBAL_CTORS_BODY /* don't use svr3.h version */
69 #undef DO_GLOBAL_DTORS_BODY
73 * handle the native MOTOROLA VERSAdos assembler.
76 /* See m68k.h. 3 means 68020 with 68881 and no bitfield
77 * bitfield instructions do not seem to work a clean way.
80 #define TARGET_DEFAULT (MASK_68881|MASK_68020)
82 /* The native assembler doesn't support fmovecr. */
83 #define NO_ASM_FMOVECR
86 #undef EXTRA_SECTION_FUNCTIONS
87 #undef READONLY_DATA_SECTION
88 #define READONLY_DATA_SECTION data_section
90 #undef SELECT_RTX_SECTION
91 #define fini_section() while (0)
93 #undef CTORS_SECTION_ASM_OP
94 #define CTORS_SECTION_ASM_OP "\tsection 15"
95 #undef DTORS_SECTION_ASM_OP
96 #define DTORS_SECTION_ASM_OP "\tsection 15"
97 #undef INIT_SECTION_ASM_OP
98 #define BSS_SECTION_ASM_OP "\tsection 14"
99 #undef TEXT_SECTION_ASM_OP
100 #define TEXT_SECTION_ASM_OP "\tsection 10"
101 #undef DATA_SECTION_ASM_OP
102 #define DATA_SECTION_ASM_OP "\tsection 15"
105 /* Don't try using XFmode. */
106 #undef LONG_DOUBLE_TYPE_SIZE
107 #define LONG_DOUBLE_TYPE_SIZE 64
109 /* Define if you don't want extended real, but do want to use the
110 software floating point emulator for REAL_ARITHMETIC and
111 decimal <-> binary conversion. */
112 #define REAL_ARITHMETIC
114 #undef ASM_OUTPUT_SOURCE_FILENAME
115 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, NA) \
116 do { fprintf ((FILE), "\t.file\t'%s'\n", (NA)); } while (0)
118 /* Assembler pseudos to introduce constants of various size. */
121 #define ASM_BYTE_OP "\tdc.b"
123 #define ASM_LONG "\tdc.l"
126 * we don't seem to support any of:
132 #undef ASM_OUTPUT_SKIP
133 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
134 fprintf (FILE, "\tdcb.b %u,0\n", (SIZE))
137 #define GLOBAL_ASM_OP "\txdef"
139 #undef ASM_OUTPUT_ALIGN
140 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
142 fprintf (FILE, "\tds.w 0\n");
145 #define STRING_LIMIT (0)
147 #define ASM_APP_ON ""
149 #define ASM_APP_OFF ""
151 * dc.b 'hello, world!'
153 * is how we have to output "hello, world!\n"
155 #undef ASM_OUTPUT_ASCII
156 #define ASM_OUTPUT_ASCII(asm_out_file, p, thissize) \
157 do { register int i, c, f=0, len=0; \
158 for (i = 0; i < thissize; i++) { \
160 if (c == '\'' || c < ' ' || c > 127) { \
162 case 0: /* need to output dc.b etc */ \
163 fprintf(asm_out_file, "\tdc.b %d", c); \
167 fprintf(asm_out_file, ",%d", c); \
170 /* close a string */ \
171 fprintf(asm_out_file, "'\n\tdc.b %d", c); \
178 fprintf(asm_out_file, "\tdc.b '%c", c); \
183 fprintf(asm_out_file, "'\n\tdc.b '%c", c); \
186 fprintf(asm_out_file, "%c", c); \
190 fprintf(asm_out_file, "\n\tdc.b '%c", c); \
198 putc('\'', asm_out_file); \
199 putc('\n', asm_out_file); } while (0)
201 /* This is how to output an insn to push a register on the stack.
202 It need not be very fast code. */
204 #undef ASM_OUTPUT_REG_PUSH
205 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
206 fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[REGNO])
208 /* This is how to output an insn to pop a register from the stack.
209 It need not be very fast code. */
211 #undef ASM_OUTPUT_REG_POP
212 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
213 fprintf (FILE, "\tmove.l (sp)+,%s\n", reg_names[REGNO])
216 #define PUT_SDB_FUNCTION_START(LINE) \
217 fprintf (asm_out_file, \
218 "\t.def\t.bf%s\t.val\t*%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
219 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
221 #define PUT_SDB_FUNCTION_END(LINE) \
222 fprintf (asm_out_file, \
223 "\t.def\t.ef%s\t.val\t*%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
224 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
226 #define PUT_SDB_BLOCK_START(LINE) \
227 fprintf (asm_out_file, \
228 "\t.def\t.bb%s\t.val\t*%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
229 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
231 #define PUT_SDB_BLOCK_END(LINE) \
232 fprintf (asm_out_file, \
233 "\t.def\t.eb%s\t.val\t*%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
234 SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
236 #define PUT_SDB_EPILOGUE_END(NAME)
238 /* Output type in decimal not in octal as done in sdbout.c */
239 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%d%s", a, SDB_DELIM)
241 #undef FUNCTION_PROLOGUE
242 #define FUNCTION_PROLOGUE(FILE, SIZE) \
244 register int regno; \
245 register int mask = 0; \
246 int num_saved_regs = 0, first = 1; \
247 extern char call_used_regs[]; \
248 int fsize = ((SIZE) + 3) & -4; \
251 if (frame_pointer_needed) \
253 /* Adding negative number is faster on the 68040. */ \
254 if (fsize < 0x8000 && !TARGET_68040) \
256 fprintf (FILE, "\tlink %s,#%d\n", \
257 reg_names[FRAME_POINTER_REGNUM], -fsize); \
259 else if (TARGET_68020) \
261 fprintf (FILE, "\tlink %s,#%d\n", \
262 reg_names[FRAME_POINTER_REGNUM], -fsize); \
266 fprintf (FILE, "\tlink %s,#0\n\tadd.l #%d,sp\n", \
267 reg_names[FRAME_POINTER_REGNUM], -fsize); \
272 /* Adding negative number is faster on the 68040. */ \
273 if (fsize + 4 < 0x8000) \
275 fprintf (FILE, "\tadd.w #%d,sp\n", - (fsize + 4)); \
279 fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
282 for (regno = 23; regno >= 16; regno--) \
283 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
285 fprintf (FILE, "\tfmovem.x %s", reg_names[regno]); \
288 else fprintf (FILE, "/%s", reg_names[regno]); \
289 if (!first) fprintf (FILE, ",-(sp)\n"); \
292 for (regno = 0; regno < 16; regno++) \
293 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
295 mask |= 1 << (15 - regno); \
298 if (frame_pointer_needed) \
300 mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM)); \
305 if (num_saved_regs <= 2) \
307 /* Store each separately in the same order moveml uses. \
308 Using two movel instructions instead of a single moveml \
309 is about 15% faster for the 68020 and 68030 at no expense \
314 /* Undo the work from above. */ \
315 for (i = 0; i< 16; i++) \
316 if (mask & (1 << i)) \
317 fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - i]); \
322 for (regno = 0; regno < 16; regno++) \
323 if (mask & (1 << regno)) \
325 fprintf (FILE, "\tmovem.l %s", reg_names[15 - regno]); \
328 else fprintf (FILE, "/%s", reg_names[15 - regno]); \
329 fprintf (FILE, ",-(sp)\n"); \
331 if (flag_pic && current_function_uses_pic_offset_table) \
333 fprintf (FILE, "\tmove.l #__GLOBAL_OFFSET_TABLE_, %s\n", \
334 reg_names[PIC_OFFSET_TABLE_REGNUM]); \
335 fprintf (FILE, "\tlea.l (pc,%s.l),%s\n", \
336 reg_names[PIC_OFFSET_TABLE_REGNUM], \
337 reg_names[PIC_OFFSET_TABLE_REGNUM]); \
342 #undef FUNCTION_EPILOGUE
343 #define FUNCTION_EPILOGUE(FILE, SIZE) \
345 register int regno; \
346 register int mask, fmask; \
347 register int nregs; \
348 int offset, foffset, fpoffset, first = 1; \
349 extern char call_used_regs[]; \
350 int fsize = ((SIZE) + 3) & -4; \
352 rtx insn = get_last_insn (); \
354 /* If the last insn was a BARRIER, we don't have to write any code. */ \
355 if (GET_CODE (insn) == NOTE) \
356 insn = prev_nonnote_insn (insn); \
357 if (insn && GET_CODE (insn) == BARRIER) \
359 /* Output just a no-op so that debuggers don't get confused \
360 about which function the pc is in at this address. */ \
361 fprintf (FILE, "\tnop\n"); \
365 nregs = 0; fmask = 0; fpoffset = 0; \
366 for (regno = 16; regno < 24; regno++) \
367 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
370 fmask |= 1 << (23 - regno); \
372 foffset = fpoffset + nregs * 12; \
373 nregs = 0; mask = 0; \
374 if (frame_pointer_needed) \
375 regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
376 for (regno = 0; regno < 16; regno++) \
377 if (regs_ever_live[regno] && ! call_used_regs[regno]) \
380 mask |= 1 << regno; \
382 offset = foffset + nregs * 4; \
383 if (offset + fsize >= 0x8000 \
384 && frame_pointer_needed \
385 && (mask || fmask || fpoffset)) \
387 fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
388 fsize = 0, big = 1; \
392 /* Restore each separately in the same order moveml does. \
393 Using two movel instructions instead of a single moveml \
394 is about 15% faster for the 68020 and 68030 at no expense \
399 /* Undo the work from above. */ \
400 for (i = 0; i< 16; i++) \
401 if (mask & (1 << i)) \
405 fprintf (FILE, "\tmove.l -%d(%s,a0.l),%s\n", \
407 reg_names[FRAME_POINTER_REGNUM], \
410 else if (! frame_pointer_needed) \
412 fprintf (FILE, "\tmove.l (sp)+,%s\n", \
417 fprintf (FILE, "\tmove.l -%d(%s),%s\n", \
419 reg_names[FRAME_POINTER_REGNUM], \
422 offset = offset - 4; \
428 for (regno = 0; regno < 16; regno++) \
429 if (mask & (1 << regno)) \
430 if (first && big) { \
431 fprintf (FILE, "\tmovem.l -%d(%s,a0.l),%s", \
433 reg_names[FRAME_POINTER_REGNUM], \
437 else if (first && ! frame_pointer_needed) { \
438 fprintf (FILE, "\tmovem.l (sp)+,%s", \
440 reg_names[FRAME_POINTER_REGNUM], \
445 fprintf (FILE, "\tmovem.l -%d(%s),%s", \
447 reg_names[FRAME_POINTER_REGNUM], \
452 fprintf (FILE, "/%s", reg_names[regno]); \
453 fprintf (FILE, "\n"); \
458 for (regno = 16; regno < 24; regno++) \
459 if (fmask & (1 << (23 - regno))) \
460 if (first && big) { \
461 fprintf (FILE, "\tfmovem.x -%d(%s,a0.l),%s", \
463 reg_names[FRAME_POINTER_REGNUM], \
467 else if (first && ! frame_pointer_needed) { \
468 fprintf (FILE, "\tfmovem.x (sp)+,%s", \
470 reg_names[FRAME_POINTER_REGNUM], \
475 fprintf (FILE, "\tfmovem.x -%d(%s),%s", \
477 reg_names[FRAME_POINTER_REGNUM], \
481 else fprintf (FILE, "/%s", reg_names[regno]); \
482 fprintf (FILE, "\n"); \
484 if (frame_pointer_needed) \
485 fprintf (FILE, "\tunlk %s\n", \
486 reg_names[FRAME_POINTER_REGNUM]); \
489 if (fsize + 4 < 0x8000) \
491 fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
495 fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
498 if (current_function_pops_args) \
499 fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
501 fprintf (FILE, "\trts\n"); \
504 /* Translate Motorola opcodes such as `jbeq'
505 into VERSAdos opcodes such as `beq'.
506 Change `fbeq' to `fbseq', `fbne' to `fbsneq'.
509 #undef ASM_OUTPUT_OPCODE
510 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
511 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
513 while (*(PTR) != ' ') \
514 { putc (*(PTR), (FILE)); ++(PTR); } \
516 else if ((PTR)[0] == 'f') \
518 if (!strncmp ((PTR), "fbeq", 4)) \
519 { fprintf ((FILE), "fbseq"); (PTR) += 4; } \
520 else if (!strncmp ((PTR), "fbne", 4)) \
521 { fprintf ((FILE), "fbsneq"); (PTR) += 4; } \
523 else if ((PTR)[0] == 'b' && (PTR)[1] == 'f') \
526 if ((s = (char*)strchr ((PTR), '{'))) \
527 while (*s != '}') { \
529 /* hack, I replace it with R ie nothing */ \
535 /* This is how to output a `long double' extended real constant. */
536 #undef ASM_OUTPUT_LONG_DOUBLE
537 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
539 REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
540 if (sizeof (int) == sizeof (long)) \
541 fprintf (FILE, "\tdc.l $%x,$%x,$%x\n", l[0], l[1], l[2]); \
543 fprintf (FILE, "\tdc.l $%lx,$%lx,$%lx\n", l[0], l[1], l[2]); \
546 #undef ASM_OUTPUT_DOUBLE
548 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
549 do { char dstr[30]; \
550 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
551 fprintf (FILE, "\tdc.d %s\n", dstr); \
554 #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
556 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
557 fprintf (FILE, "\tdc.l $%x,$%x\n", l[0], l[1]); \
561 /* This is how to output an assembler line defining a `float' constant. */
562 #undef ASM_OUTPUT_FLOAT
563 #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
565 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
566 if (sizeof (int) == sizeof (long)) \
567 fprintf (FILE, "\tdc.l $%x\n", l); \
569 fprintf (FILE, "\tdc.l $%lx\n", l); \
572 /* This is how to output an assembler line defining an `int' constant. */
573 #undef ASM_OUTPUT_INT
574 #define ASM_OUTPUT_INT(FILE,VALUE) \
575 ( fprintf (FILE, "\tdc.l "), \
576 output_addr_const (FILE, (VALUE)), \
577 fprintf (FILE, "\n"))
579 /* Likewise for `char' and `short' constants. */
580 #undef ASM_OUTPUT_SHORT
581 #define ASM_OUTPUT_SHORT(FILE,VALUE) \
582 ( fprintf (FILE, "\tdc.w "), \
583 output_addr_const (FILE, (VALUE)), \
584 fprintf (FILE, "\n"))
586 #undef ASM_OUTPUT_CHAR
587 #define ASM_OUTPUT_CHAR(FILE,VALUE) \
588 ( fprintf (FILE, "\tdc.b "), \
589 output_addr_const (FILE, (VALUE)), \
590 fprintf (FILE, "\n"))
592 /* This is how to output an assembler line for a numeric constant byte. */
593 #undef ASM_OUTPUT_BYTE
594 #define ASM_OUTPUT_BYTE(FILE,VALUE) \
595 fprintf (FILE, "\tdc.b $%x\n", (VALUE))
597 /* This is how to output an element of a case-vector that is absolute.
598 (The 68000 does not use such vectors,
599 but we must define this macro anyway.) */
600 #undef ASM_OUTPUT_ADDR_VEC_ELT
601 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
602 asm_fprintf (FILE, "\tdc.l %LL%d\n", VALUE)
604 /* This is how to output an element of a case-vector that is relative. */
605 #undef ASM_OUTPUT_ADDR_DIFF_ELT
606 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
607 asm_fprintf (FILE, "\tdc.w %LL%d-%LL%d\n", VALUE, REL)
609 /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
610 keep switch tables in the text section. */
611 #define JUMP_TABLES_IN_TEXT_SECTION 1
613 /* Output a float value (represented as a C double) as an immediate operand.
614 This macro is a 68k-specific macro. */
615 #undef ASM_OUTPUT_FLOAT_OPERAND
616 #define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
621 REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
622 asm_fprintf ((FILE), "%I%s", dstr); \
627 REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
628 if (sizeof (int) == sizeof (long)) \
629 asm_fprintf ((FILE), "%I$%x", l); \
631 asm_fprintf ((FILE), "%I$%lx", l); \
635 /* Output a double value (represented as a C double) as an immediate operand.
636 This macro is a 68k-specific macro. */
637 #undef ASM_OUTPUT_DOUBLE_OPERAND
638 #define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
639 do { char dstr[30]; \
640 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
641 asm_fprintf (FILE, "%I%s", dstr); \
644 /* Note, long double immediate operands are not actually
645 generated by m68k.md. */
646 #undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
647 #define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \
648 do { char dstr[30]; \
649 REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
650 asm_fprintf (FILE, "%I%s", dstr); \
653 #undef ASM_OUTPUT_COMMON
654 #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
655 ( fputs ("\t.comm ", (FILE)), \
656 assemble_name ((FILE), (NAME)), \
657 fprintf ((FILE), ",%u\n", (ROUNDED)))
659 #undef ASM_OUTPUT_LOCAL
660 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
662 int align = exact_log2 (ROUNDED); \
663 /*fprintf ((FILE), "\tsection 14\n"); */ \
665 ASM_OUTPUT_ALIGN ((FILE), align) \
666 ASM_OUTPUT_LABEL ((FILE), (NAME)); \
667 fprintf ((FILE), "\tdcb.b %u,0\n", (ROUNDED)); \
668 /* fprintf ((FILE), "\tsection 10\n"); */ \
671 #undef PRINT_OPERAND_ADDRESS
672 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
673 { register rtx reg1, reg2, breg, ireg; \
674 register rtx addr = ADDR; \
676 switch (GET_CODE (addr)) \
679 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
682 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
685 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
688 reg1 = 0; reg2 = 0; \
689 ireg = 0; breg = 0; \
691 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
693 offset = XEXP (addr, 0); \
694 addr = XEXP (addr, 1); \
696 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
698 offset = XEXP (addr, 1); \
699 addr = XEXP (addr, 0); \
701 if (GET_CODE (addr) != PLUS) ; \
702 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
704 reg1 = XEXP (addr, 0); \
705 addr = XEXP (addr, 1); \
707 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
709 reg1 = XEXP (addr, 1); \
710 addr = XEXP (addr, 0); \
712 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
714 reg1 = XEXP (addr, 0); \
715 addr = XEXP (addr, 1); \
717 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
719 reg1 = XEXP (addr, 1); \
720 addr = XEXP (addr, 0); \
722 else if (GET_CODE (XEXP (addr, 0)) == REG) \
724 reg1 = XEXP (addr, 0); \
725 addr = XEXP (addr, 1); \
727 else if (GET_CODE (XEXP (addr, 1)) == REG) \
729 reg1 = XEXP (addr, 1); \
730 addr = XEXP (addr, 0); \
732 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
733 || GET_CODE (addr) == SIGN_EXTEND) \
734 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
735 /* for OLD_INDEXING \
736 else if (GET_CODE (addr) == PLUS) \
738 if (GET_CODE (XEXP (addr, 0)) == REG) \
740 reg2 = XEXP (addr, 0); \
741 addr = XEXP (addr, 1); \
743 else if (GET_CODE (XEXP (addr, 1)) == REG) \
745 reg2 = XEXP (addr, 1); \
746 addr = XEXP (addr, 0); \
750 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
751 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
752 || GET_CODE (reg1) == MULT)) \
753 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
754 { breg = reg2; ireg = reg1; } \
755 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
756 { breg = reg1; ireg = reg2; } \
757 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
759 if (GET_CODE (ireg) == MULT) \
760 { scale = INTVAL (XEXP (ireg, 1)); \
761 ireg = XEXP (ireg, 0); } \
762 if (GET_CODE (ireg) == SIGN_EXTEND) \
763 fprintf (FILE, "(.L%d,pc,%s.w", \
764 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
765 reg_names[REGNO (XEXP (ireg, 0))]); \
767 fprintf (FILE, "(.L%d,pc,%s.l", \
768 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
769 reg_names[REGNO (ireg)]); \
770 if (scale != 1) fprintf (FILE, "*%d", scale); \
773 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF \
774 && ! (flag_pic && breg == pic_offset_table_rtx)) \
776 fprintf (FILE, "(.L%d,pc,%s.l", \
777 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
778 reg_names[REGNO (breg)]); \
781 if (ireg != 0 || breg != 0) \
788 output_addr_const (FILE, addr); \
791 fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
794 if (ireg != 0 && GET_CODE (ireg) == MULT) \
795 { scale = INTVAL (XEXP (ireg, 1)); \
796 ireg = XEXP (ireg, 0); } \
797 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
798 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
799 else if (ireg != 0) \
800 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
801 if (scale != 1) fprintf (FILE, "*%d", scale); \
805 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
806 { fprintf (FILE, "(.L%d,pc,%s.w)", \
807 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
808 reg_names[REGNO (reg1)]); \
811 if (GET_CODE (addr) == CONST_INT \
812 && INTVAL (addr) < 0x8000 \
813 && INTVAL (addr) >= -0x8000) \
814 fprintf (FILE, "%d.w", INTVAL (addr)); \
816 output_addr_const (FILE, addr); \
820 #endif /* ! use gas */