1/* Definitions of target machine for GNU compiler.  HP-UX 68000/68020 version.
2   Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING.  If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.  */
20
21/* Define USE_GAS if GCC is supposed to work with the GNU assembler,
22   GNU linker and GNU debugger using DBX debugging information.
23   (In other words, much of HPUX has been cast aside.)
24   Undefine USE_GAS if you want GCC to feed the HP assembler.  */
25
26/* #define USE_GAS */  /* Use hp320g.h if you want this.  */
27
28/* Control assembler-syntax conditionals in m68k.md.  */
29
30#ifndef USE_GAS
31#define MOTOROLA		/* Use Motorola syntax rather than "MIT" */
32#define SGS			/* Uses SGS assembler */
33#define SGS_CMP_ORDER		/* Takes cmp operands in reverse order */
34#define HPUX_ASM
35
36#if !defined (CROSS_COMPILE) && !defined (NO_BUGS)
37/* The assembler on HP 9k3xx machines running HPUX 8.0 doesn't translate
38   floating point constants behind some operands.  The workaround is to
39   use hex constants.  Reported by Thomas Nau (nau@medizin.uni-ulm.de).  */
40#define AS_BUG_FLOATING_CONSTANT
41/* The assembler on HP 9k3xx machines running HPUX 8.0 doesn't accept
42   labels followed by a text, data, or other section directive.  Reported
43   by Thomas Nau (nau@medizin.uni-ulm.de).  */
44#define AS_BUG_TRAILING_LABEL
45#endif
46
47#endif /* not USE_GAS */
48
49/* gcc.c should find libgcc.a itself rather than expecting linker to.  */
50#define LINK_LIBGCC_SPECIAL
51/* The arguments of -L must be a separate argv element.  */
52#define SPACE_AFTER_L_OPTION
53/* HP/UX doesn't have libg.a.  */
54#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
55
56/* Be compatible with system stddef.h.  */
57#define SIZE_TYPE "unsigned int"
58
59/* Use atexit for static constructors/destructors, instead of defining
60   our own exit function.  */
61#define HAVE_ATEXIT
62
63#include "m68k/m68k.h"
64
65/* See m68k.h.  7 means 68020 with 68881.  */
66
67#ifndef TARGET_DEFAULT
68#define	TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
69#endif
70
71/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
72   This will control the use of inline 68881 insns in certain macros.  */
73
74#ifdef HPUX_ASM
75
76#define ASM_SPEC "%{m68000:+X}%{mc68000:+X}"
77
78#define NO_DOT_IN_LABEL
79
80#if TARGET_DEFAULT & MASK_68881  /* -m68881 is the default */
81
82/* These definitions differ from those used for GAS by defining __HPUX_ASM__.
83   This is needed because some programs, particularly GDB, need to
84   know which assembler is being used so that the correct `asm'
85   instructions can be used. */
86
87#define CPP_SPEC \
88"%{!msoft-float:-D__HAVE_68881__ }\
89%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE} -D__HPUX_ASM__"
90
91#else /* default is -msoft-float */
92
93#define CPP_SPEC \
94"%{m68881:-D__HAVE_68881__ }\
95%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE} -D__HPUX_ASM__"
96
97#endif /* default is -msoft-float */
98
99#else /* not HPUX_ASM */
100
101#if TARGET_DEFAULT & MASK_68881  /* -m68881 is the default */
102
103#define CPP_SPEC \
104"%{!msoft-float:-D__HAVE_68881__ }\
105%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE}"
106
107#else /* default is -msoft-float */
108
109#define CPP_SPEC \
110"%{m68881:-D__HAVE_68881__ }\
111%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE}"
112
113#endif /* default is -msoft-float */
114
115
116/* -m68000 requires special flags to the assembler.  */
117#define ASM_SPEC \
118 "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
119
120/* Tell GCC to put a space after -L when generating such options.  */
121#define SPACE_AFTER_L_OPTION
122
123#endif /* Not HPUX_ASM */
124
125/* Translate -static for HPUX linker.  */
126#define LINK_SPEC "%{static:-a archive}"
127
128/* Names to predefine in the preprocessor for this target machine
129   (for non-strict-ANSI programs only).  */
130/* These are the ones defined by HPUX cc, plus mc68000 for uniformity with
131   GCC on other 68000 systems.  */
132
133#define CPP_PREDEFINES "-Dhp9000s200 -Dhp9000s300 -DPWB -Dhpux -Dunix -D__hp9000s300 -D__hp9000s200 -D__PWB -D__hpux -D__unix -D__motorola__ -Asystem(unix) -Asystem(hpux) -Acpu(m68k) -Amachine(m68k)"
134
135/* Every structure or union's size must be a multiple of 2 bytes.  */
136
137#define STRUCTURE_SIZE_BOUNDARY 16
138
139/* hpux doesn't use static area for struct returns. */
140#undef PCC_STATIC_STRUCT_RETURN
141
142/* Generate calls to memcpy, memcmp and memset.  */
143#define TARGET_MEM_FUNCTIONS
144
145#if 0  /* No longer correct in HPUX version 6.5.  */
146/* Function calls don't save any fp registers on hpux.  */
147#undef CALL_USED_REGISTERS
148#define CALL_USED_REGISTERS						\
149 {1, 1, 0, 0, 0, 0, 0, 0,						\
150  1, 1, 0, 0, 0, 0, 0, 1,						\
151  1, 1, 1, 1, 1, 1, 1, 1}
152#endif /* 0 */
153
154#ifdef HPUX_ASM
155
156/* Override parts of m68k.h to fit the HPUX assembler.  */
157
158#undef TARGET_VERSION
159#undef REGISTER_NAMES
160#undef ASM_OUTPUT_REG_PUSH
161#undef ASM_OUTPUT_REG_POP
162#undef ASM_FILE_START
163#undef ASM_APP_ON
164#undef ASM_APP_OFF
165#undef TEXT_SECTION_ASM_OP
166#undef DATA_SECTION_ASM_OP
167#undef READONLY_DATA_SECTION
168#undef ASM_OUTPUT_DOUBLE
169#undef ASM_OUTPUT_FLOAT
170#undef ASM_OUTPUT_INT
171#undef ASM_OUTPUT_SHORT
172#undef ASM_OUTPUT_CHAR
173#undef ASM_OUTPUT_BYTE
174#undef ASM_OUTPUT_ADDR_VEC_ELT
175#undef ASM_OUTPUT_ADDR_DIFF_ELT
176#undef ASM_OUTPUT_ALIGN
177#undef ASM_OUTPUT_SKIP
178#undef ASM_OUTPUT_COMMON
179#undef ASM_OUTPUT_LOCAL
180#undef ASM_FORMAT_PRIVATE_NAME
181#undef FUNCTION_PROFILER
182#undef ASM_OUTPUT_INTERNAL_LABEL
183#undef GLOBAL_ASM_OP
184#undef IMMEDIATE_PREFIX
185#undef REGISTER_PREFIX
186
187#define TARGET_VERSION fprintf (stderr, " (68k, SGS/hpux syntax)");
188
189#define REGISTER_NAMES \
190{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",	\
191 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",	\
192 "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"}
193
194#define IMMEDIATE_PREFIX        "&"
195#define REGISTER_PREFIX         "%"
196
197#define FUNCTION_PROFILER(FILE, LABEL_NO) \
198   fprintf (FILE, "\tmov.l &LP%d,%%a0\n\tjsr mcount\n", (LABEL_NO));
199
200/* This is how to output an insn to push a register on the stack.
201   It need not be very fast code.  */
202
203#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
204  fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
205
206/* This is how to output an insn to pop a register from the stack.
207   It need not be very fast code.  */
208
209#define ASM_OUTPUT_REG_POP(FILE,REGNO)  \
210  fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
211
212/* For HPUX versions before 6.5, define this macro as empty.  */
213#define ASM_FILE_START(FILE)						\
214  if (TARGET_68020)							\
215    {									\
216      if (TARGET_68881)							\
217	 fprintf (FILE, "\tversion 3\n"); /* 68020 fp regs saved */	\
218      else								\
219	 fprintf (FILE, "\tversion 2\n"); /* 68020 no fp regs saved */	\
220    }									\
221  else									\
222    fprintf (FILE, "\tversion 1\n");	/* 68010 */
223
224#define ASM_APP_ON ""
225
226#define ASM_APP_OFF ""
227
228#ifdef AS_BUG_TRAILING_LABEL
229#define TEXT_SECTION_ASM_OP "\tlalign\t1\ntext"
230#define DATA_SECTION_ASM_OP "\tlalign\t1\ndata"
231#else
232#define TEXT_SECTION_ASM_OP "text"
233#define DATA_SECTION_ASM_OP "data"
234#endif
235#define	ASCII_DATA_ASM_OP "byte"
236
237/* This is the command to make the user-level label named NAME
238   defined for reference from other files.  */
239
240#define GLOBAL_ASM_OP "global"
241
242/* This says how to output an assembler line
243   to define a global common symbol.  */
244
245#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
246( fputs ("\tcomm ", (FILE)),			\
247  assemble_name ((FILE), (NAME)),		\
248  fprintf ((FILE), ",%u\n", (ROUNDED)))
249
250/* This says how to output an assembler line
251   to define a local common symbol.  */
252
253#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
254( fputs ("\tlcomm ", (FILE)),			\
255  assemble_name ((FILE), (NAME)),		\
256  fprintf ((FILE), ",%u,2\n", (ROUNDED)))
257
258/* Store in OUTPUT a string (made with alloca) containing
259   an assembler-name for a local static variable named NAME.
260   LABELNO is an integer which is different for each call.  */
261
262#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)	\
263( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12),	\
264  sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
265
266#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)	\
267do{  if (PREFIX[0] == 'L' && PREFIX[1] == 'I')		\
268    fprintf(FILE, "\tset %s%d,.+2\n", PREFIX, NUM);	\
269  else							\
270    fprintf (FILE, "%s%d:\n", PREFIX, NUM);		\
271} while(0)
272
273#define ASM_OUTPUT_DOUBLE(FILE, VALUE)			\
274  do { char dstr[30];					\
275       REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr);	\
276       fprintf (FILE, "\tdouble 0f%s\n", dstr);		\
277     } while (0)
278
279#define ASM_OUTPUT_FLOAT(FILE, VALUE)			\
280  do { char dstr[30];					\
281       REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr);	\
282       fprintf (FILE, "\tfloat 0f%s\n", dstr);		\
283     } while (0)
284
285#undef ASM_OUTPUT_LONG_DOUBLE
286#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)  				\
287do { long l[3];								\
288     REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l);			\
289     fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]);	\
290   } while (0)
291
292/* This is how to output an assembler line defining an `int' constant.  */
293
294#define ASM_OUTPUT_INT(FILE,VALUE)  \
295( fprintf (FILE, "\tlong "),			\
296  output_addr_const (FILE, (VALUE)),		\
297  fprintf (FILE, "\n"))
298
299/* Likewise for `char' and `short' constants.  */
300
301#define ASM_OUTPUT_SHORT(FILE,VALUE)  \
302( fprintf (FILE, "\tshort "),			\
303  output_addr_const (FILE, (VALUE)),		\
304  fprintf (FILE, "\n"))
305
306#define ASM_OUTPUT_CHAR(FILE,VALUE)  \
307( fprintf (FILE, "\tbyte "),			\
308  output_addr_const (FILE, (VALUE)),		\
309  fprintf (FILE, "\n"))
310
311/* This is how to output an assembler line for a numeric constant byte.  */
312
313#define ASM_OUTPUT_BYTE(FILE,VALUE)  \
314  fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
315
316#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
317  fprintf (FILE, "\tlong L%d\n", VALUE)
318
319#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)  \
320  fprintf (FILE, "\tshort L%d-L%d\n", VALUE, REL)
321
322#define ASM_OUTPUT_ALIGN(FILE,LOG)	\
323  if ((LOG) == 1)			\
324    fprintf (FILE, "\tlalign 2\n");	\
325  else if ((LOG) != 0)			\
326    abort ();
327
328#define ASM_OUTPUT_SKIP(FILE,SIZE)  \
329  fprintf (FILE, "\tspace %u\n", (SIZE))
330
331#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME)
332#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)
333
334/* Output a float value (represented as a C double) as an immediate operand.
335   This macro is a 68k-specific macro.  */
336
337#undef ASM_OUTPUT_FLOAT_OPERAND
338#ifdef AS_BUG_FLOATING_CONSTANT
339#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE)		\
340 do { long l;							\
341      REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);			\
342      fprintf ((FILE), "&0x%lx", l);				\
343     } while (0)
344#else
345#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE)		\
346 do {								\
347      if (CODE == 'f')						\
348        {							\
349          char dstr[30];					\
350          REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr);		\
351          fprintf ((FILE), "&0f%s", dstr);			\
352        }							\
353      else							\
354        {							\
355          long l;						\
356          REAL_VALUE_TO_TARGET_SINGLE (VALUE, l);		\
357          fprintf ((FILE), "&0x%lx", l);			\
358        }							\
359     } while (0)
360#endif /* AS_BUG_FLOATING_CONSTANT */
361
362/* Output a double value (represented as a C double) as an immediate operand.
363   This macro is a 68k-specific macro.  */
364#undef ASM_OUTPUT_DOUBLE_OPERAND
365#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE)				\
366 do { char dstr[30];							\
367      REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr);			\
368      fprintf (FILE, "&0f%s", dstr);					\
369    } while (0)
370
371/* Note, long double immediate operands are not actually
372   generated by m68k.md.  */
373#undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
374#define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE)			\
375 do { char dstr[30];							\
376      REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr);			\
377      fprintf (FILE, "&0f%s", dstr);					\
378    } while (0)
379
380#if 0
381#undef PRINT_OPERAND
382#define PRINT_OPERAND(FILE, X, CODE)  \
383{ if (CODE == '.') fprintf (FILE, ".");					\
384  else if (CODE == '#') fprintf (FILE, "&");				\
385  else if (CODE == '-') fprintf (FILE, "-(%%sp)");			\
386  else if (CODE == '+') fprintf (FILE, "(%%sp)+");			\
387  else if (CODE == '@') fprintf (FILE, "(%%sp)");			\
388  else if (CODE == '!') fprintf (FILE, "%%fpcr");			\
389  else if (CODE == '$') { if (TARGET_68040_ONLY) fprintf (FILE, "s"); } \
390  else if (CODE == '&') { if (TARGET_68040_ONLY) fprintf (FILE, "d"); } \
391  else if (CODE == '/')							\
392    fprintf (FILE, "%%");						\
393  else if (GET_CODE (X) == REG)						\
394    fprintf (FILE, "%s", reg_names[REGNO (X)]);				\
395  else if (GET_CODE (X) == MEM)						\
396    output_address (XEXP (X, 0));					\
397  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode)	\
398    { REAL_VALUE_TYPE r;  long l;					\
399      REAL_VALUE_FROM_CONST_DOUBLE (r, X);				\
400      PRINT_OPERAND_FLOAT (CODE, FILE, r, l); }				\
401  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode)	\
402    { REAL_VALUE_TYPE r;  char dstr[30];				\
403      REAL_VALUE_FROM_CONST_DOUBLE (r, X);				\
404      REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);				\
405      fprintf (FILE, "&0f%s", dstr); }					\
406  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode)	\
407    { REAL_VALUE_TYPE r;  char dstr[30];				\
408      REAL_VALUE_FROM_CONST_DOUBLE (r, X);				\
409      REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);				\
410      fprintf (FILE, "&0f%s", dstr); }					\
411  else { putc ('&', FILE); output_addr_const (FILE, X); }}
412#endif
413
414#undef PRINT_OPERAND_ADDRESS
415#define PRINT_OPERAND_ADDRESS(FILE, ADDR)  \
416{ register rtx reg1, reg2, breg, ireg;					\
417  register rtx addr = ADDR;						\
418  rtx offset;								\
419  switch (GET_CODE (addr))						\
420    {									\
421    case REG:								\
422      fprintf (FILE, "(%s)", reg_names[REGNO (addr)]);			\
423      break;								\
424    case PRE_DEC:							\
425      fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);	\
426      break;								\
427    case POST_INC:							\
428      fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);	\
429      break;								\
430    case PLUS:								\
431      reg1 = 0;	reg2 = 0;						\
432      ireg = 0;	breg = 0;						\
433      offset = 0;							\
434      if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))				\
435	{								\
436	  offset = XEXP (addr, 0);					\
437	  addr = XEXP (addr, 1);					\
438	}								\
439      else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))			\
440	{								\
441	  offset = XEXP (addr, 1);					\
442	  addr = XEXP (addr, 0);					\
443	}								\
444      if (GET_CODE (addr) != PLUS) ;					\
445      else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)		\
446	{								\
447	  reg1 = XEXP (addr, 0);					\
448	  addr = XEXP (addr, 1);					\
449	}								\
450      else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)		\
451	{								\
452	  reg1 = XEXP (addr, 1);					\
453	  addr = XEXP (addr, 0);					\
454	}								\
455      else if (GET_CODE (XEXP (addr, 0)) == MULT)			\
456	{								\
457	  reg1 = XEXP (addr, 0);					\
458	  addr = XEXP (addr, 1);					\
459	}								\
460      else if (GET_CODE (XEXP (addr, 1)) == MULT)			\
461	{								\
462	  reg1 = XEXP (addr, 1);					\
463	  addr = XEXP (addr, 0);					\
464	}								\
465      else if (GET_CODE (XEXP (addr, 0)) == REG)			\
466	{								\
467	  reg1 = XEXP (addr, 0);					\
468	  addr = XEXP (addr, 1);					\
469	}								\
470      else if (GET_CODE (XEXP (addr, 1)) == REG)			\
471	{								\
472	  reg1 = XEXP (addr, 1);					\
473	  addr = XEXP (addr, 0);					\
474	}								\
475      if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT		\
476	  || GET_CODE (addr) == SIGN_EXTEND)				\
477	{ if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; }	\
478/*  for OLD_INDEXING							\
479      else if (GET_CODE (addr) == PLUS)					\
480	{								\
481	  if (GET_CODE (XEXP (addr, 0)) == REG)				\
482	    {								\
483	      reg2 = XEXP (addr, 0);					\
484	      addr = XEXP (addr, 1);					\
485	    }								\
486	  else if (GET_CODE (XEXP (addr, 1)) == REG)			\
487	    {								\
488	      reg2 = XEXP (addr, 1);					\
489	      addr = XEXP (addr, 0);					\
490	    }								\
491	}								\
492  */									\
493      if (offset != 0) { if (addr != 0) abort (); addr = offset; }	\
494      if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND			\
495		    || GET_CODE (reg1) == MULT))			\
496	  || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))		\
497	{ breg = reg2; ireg = reg1; }					\
498      else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))		\
499	{ breg = reg1; ireg = reg2; }					\
500      if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF)	\
501        { int scale = 1;						\
502	  if (GET_CODE (ireg) == MULT)					\
503	    { scale = INTVAL (XEXP (ireg, 1));				\
504	      ireg = XEXP (ireg, 0); }					\
505	  if (GET_CODE (ireg) == SIGN_EXTEND)				\
506	    fprintf (FILE, "L%d-LI%d(%%pc,%s.w",			\
507		     CODE_LABEL_NUMBER (XEXP (addr, 0)),		\
508		     CODE_LABEL_NUMBER (XEXP (addr, 0)),		\
509		     reg_names[REGNO (XEXP (ireg, 0))]); 		\
510	  else								\
511	    fprintf (FILE, "L%d-LI%d(%%pc,%s.l",			\
512		     CODE_LABEL_NUMBER (XEXP (addr, 0)),		\
513		     CODE_LABEL_NUMBER (XEXP (addr, 0)),		\
514		     reg_names[REGNO (ireg)]);				\
515	  if (scale != 1) fprintf (FILE, "*%d", scale);			\
516	  putc (')', FILE);						\
517	  break; }							\
518      if (ireg != 0 || breg != 0)					\
519	{ int scale = 1;						\
520	  if (breg == 0)						\
521	    abort ();							\
522	  if (addr != 0)						\
523	    output_addr_const (FILE, addr);				\
524	  fprintf (FILE, "(%s", reg_names[REGNO (breg)]);		\
525	  if (ireg != 0)						\
526	    putc (',', FILE);						\
527	  if (ireg != 0 && GET_CODE (ireg) == MULT)			\
528	    { scale = INTVAL (XEXP (ireg, 1));				\
529	      ireg = XEXP (ireg, 0); }					\
530	  if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)		\
531	    fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);	\
532	  else if (ireg != 0)						\
533	    fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]);		\
534	  if (scale != 1) fprintf (FILE, "*%d", scale);			\
535	  putc (')', FILE);						\
536	  break;							\
537	}								\
538      else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF)		\
539	{ fprintf (FILE, "L%d-LI%d(%%pc,%s.w)",				\
540		   CODE_LABEL_NUMBER (XEXP (addr, 0)),			\
541		   CODE_LABEL_NUMBER (XEXP (addr, 0)),			\
542		   reg_names[REGNO (reg1)]);				\
543	  break; }							\
544    default:								\
545      if (GET_CODE (addr) == CONST_INT					\
546	  && INTVAL (addr) < 0x8000					\
547	  && INTVAL (addr) >= -0x8000)					\
548	fprintf (FILE, "%d.w", INTVAL (addr));				\
549      else								\
550        output_addr_const (FILE, addr);					\
551    }}
552
553#define	ASM_OUTPUT_ASCII(f, p, size)	\
554do { register int i;			\
555  int inside;				\
556  inside = FALSE;			\
557  for (i = 0; i < (size); i++) {	\
558    if (i % 8 == 0) {			\
559      if (i != 0) {			\
560	if (inside)			\
561	  putc('"', (f));		\
562	putc('\n', (f));		\
563	inside = FALSE;			\
564      }					\
565      fprintf((f), "\t%s ", ASCII_DATA_ASM_OP);	\
566    }					\
567    if ((p)[i] < 32 || (p)[i] == '\\' || (p)[i] == '"' || (p)[i] == 127) {	\
568      if (inside) {			\
569	putc('"', (f));			\
570	inside = FALSE;			\
571      }					\
572      if (i % 8 != 0)			\
573	putc(',', (f));			\
574      fprintf((f), "%d", (p)[i]);	\
575    } else {				\
576      if (!inside) {			\
577	if (i % 8 != 0)			\
578	  putc(',', (f));		\
579	putc('"', (f));			\
580	inside = TRUE;			\
581      }					\
582      putc((p)[i], (f));		\
583    }					\
584  }					\
585  if (inside)				\
586    putc('"', (f));			\
587  putc('\n', (f));			\
588} while (0)
589
590/* Translate Motorola opcodes such as `jbeq'
591   into SGS opcodes such as `beq.w'.
592   Delete the `e' in `move...' and `fmove'.
593   Change `ftst' to `ftest'.  */
594
595#define ASM_OUTPUT_OPCODE(FILE, PTR)			\
596{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b')		\
597    { ++(PTR);						\
598      while (*(PTR) != ' ')				\
599	{ putc (*(PTR), (FILE)); ++(PTR); }		\
600      fprintf ((FILE), ".w"); }				\
601  else if ((PTR)[0] == 'f')				\
602    {							\
603      if (!strncmp ((PTR), "fmove", 5))			\
604	{ fprintf ((FILE), "fmov"); (PTR) += 5; }	\
605      else if (!strncmp ((PTR), "ftst", 4))		\
606	{ fprintf ((FILE), "ftest"); (PTR) += 4; }	\
607    }							\
608  else if ((PTR)[0] == 'm' && (PTR)[1] == 'o'		\
609	   && (PTR)[2] == 'v' && (PTR)[3] == 'e')	\
610    { fprintf ((FILE), "mov"); (PTR) += 4; }		\
611}
612
613/* Prevent output of `gcc_compiled.:'.  */
614
615#define ASM_IDENTIFY_GCC(FILE)
616
617#else /* not HPUX_ASM */
618
619#undef FUNCTION_PROFILER
620
621/* HP-UX needs the call to mcount before the link instruction.
622   Copy the return address onto the stack before the call to fake it out.  */
623#define FUNCTION_PROFILER(FILE, LABEL_NO) \
624  fprintf (FILE, \
625	   "\tmovel a6@(4),sp@-\n\tmovl #LP%d,a0\n\tjsr mcount\n\taddqw #4,sp\n", \
626	   (LABEL_NO));
627
628#endif /* not HPUX_ASM */
629
630/* In m68k svr4, a symbol_ref rtx can be a valid PIC operand if it is an
631   operand of a function call. */
632#undef LEGITIMATE_PIC_OPERAND_P
633#define LEGITIMATE_PIC_OPERAND_P(X) \
634  ((! symbolic_operand (X, VOIDmode) \
635    && ! (GET_CODE (X) == CONST_DOUBLE && CONST_DOUBLE_MEM (X)	\
636	  && GET_CODE (CONST_DOUBLE_MEM (X)) == MEM		\
637	  && symbolic_operand (XEXP (CONST_DOUBLE_MEM (X), 0), VOIDmode))) \
638   || (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
639
640/* hpux8 and later have C++ compatible include files, so do not
641   pretend they are `extern "C"'.  */
642#define NO_IMPLICIT_EXTERN_C
643