Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / gcc / config / i386 / next.h
1 /* Target definitions for GNU compiler for Intel x86 CPU running NeXTSTEP
2    Copyright (C) 1993, 1995, 1996, 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
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)
9 any later version.
10
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.
15
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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 #include "i386/gas.h"
22 #include "nextstep.h"
23
24 /* By default, target has a 80387, with IEEE FP.  */
25
26 #undef  TARGET_DEFAULT
27 #define TARGET_DEFAULT  (MASK_80387 | MASK_IEEE_FP)
28
29 /* Implicit library calls should use memcpy, not bcopy, etc.  */
30
31 #define TARGET_MEM_FUNCTIONS
32
33 /* Machines that use the AT&T assembler syntax
34    also return floating point values in an FP register.
35    Define how to find the value returned by a function.
36    VALTYPE is the data type of the value (as a tree).
37    If the precise function being called is known, FUNC is its FUNCTION_DECL;
38    otherwise, FUNC is 0.  */
39
40 #undef  VALUE_REGNO
41 #define VALUE_REGNO(MODE) \
42   ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode     \
43    ? FIRST_FLOAT_REG : 0)
44
45 /* 1 if N is a possible register number for a function value. */
46
47 #undef  FUNCTION_VALUE_REGNO_P
48 #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG)
49
50 #ifdef REAL_VALUE_TO_TARGET_LONG_DOUBLE
51 #undef  ASM_OUTPUT_LONG_DOUBLE
52 #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)                              \
53   do {                                                                  \
54     long hex[3];                                                        \
55     REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, hex);                      \
56     if (sizeof (int) == sizeof (long))                                  \
57       fprintf (FILE, "\t.long 0x%x\n\t.long 0x%x\n\t.long 0x%x\n",      \
58                 hex[0], hex[1], hex[2]);                                \
59     else                                                                \
60       fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n\t.long 0x%lx\n",   \
61                 hex[0], hex[1], hex[2]);                                \
62   } while (0)
63 #endif
64
65 #ifdef REAL_VALUE_TO_TARGET_DOUBLE
66 #undef  ASM_OUTPUT_DOUBLE
67 #define ASM_OUTPUT_DOUBLE(FILE,VALUE)                                   \
68   do {                                                                  \
69     long hex[2];                                                        \
70     REAL_VALUE_TO_TARGET_DOUBLE (VALUE, hex);                           \
71     if (sizeof (int) == sizeof (long))                                  \
72       fprintf (FILE, "\t.long 0x%x\n\t.long 0x%x\n", hex[0], hex[1]);   \
73     else                                                                \
74       fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n", hex[0], hex[1]); \
75   } while (0)
76 #endif
77
78 /* This is how to output an assembler line defining a `float' constant.  */
79
80 #ifdef REAL_VALUE_TO_TARGET_SINGLE
81 #undef  ASM_OUTPUT_FLOAT
82 #define ASM_OUTPUT_FLOAT(FILE,VALUE)                                    \
83   do {                                                                  \
84     long hex;                                                           \
85     REAL_VALUE_TO_TARGET_SINGLE (VALUE, hex);                           \
86     if (sizeof (int) == sizeof (long))                                  \
87       fprintf (FILE, "\t.long 0x%x\n", hex);                            \
88     else                                                                \
89       fprintf (FILE, "\t.long 0x%lx\n", hex);                           \
90   } while (0)
91 #endif
92
93 /* A C statement or statements which output an assembler instruction
94    opcode to the stdio stream STREAM.  The macro-operand PTR is a
95    variable of type `char *' which points to the opcode name in its
96    "internal" form--the form that is written in the machine description.
97
98    GAS version 1.38.1 doesn't understand the `repz' opcode mnemonic.
99    So use `repe' instead.  */
100
101 #undef  ASM_OUTPUT_OPCODE
102 #define ASM_OUTPUT_OPCODE(STREAM, PTR)  \
103 {                                                       \
104   if ((PTR)[0] == 'r'                                   \
105       && (PTR)[1] == 'e'                                \
106       && (PTR)[2] == 'p')                               \
107     {                                                   \
108       if ((PTR)[3] == 'z')                              \
109         {                                               \
110           fprintf (STREAM, "repe");                     \
111           (PTR) += 4;                                   \
112         }                                               \
113       else if ((PTR)[3] == 'n' && (PTR)[4] == 'z')      \
114         {                                               \
115           fprintf (STREAM, "repne");                    \
116           (PTR) += 5;                                   \
117         }                                               \
118     }                                                   \
119 }
120
121 /* Define macro used to output shift-double opcodes when the shift
122    count is in %cl.  Some assemblers require %cl as an argument;
123    some don't.
124
125    GAS requires the %cl argument, so override unx386.h. */
126
127 #undef  SHIFT_DOUBLE_OMITS_COUNT
128 #define SHIFT_DOUBLE_OMITS_COUNT 0
129
130 /* Print opcodes the way that GAS expects them. */
131 #define GAS_MNEMONICS 1
132
133 /* Names to predefine in the preprocessor for this target machine.  */
134
135 #undef  CPP_PREDEFINES
136 #define CPP_PREDEFINES "-Di386 -DNeXT -Dunix -D__MACH__ -D__LITTLE_ENDIAN__ -D__ARCHITECTURE__=\"i386\" -Asystem(unix) -Asystem(mach) -Acpu(i386) -Amachine(i386)"
137
138 /* This accounts for the return pc and saved fp on the i386. */
139
140 #define OBJC_FORWARDING_STACK_OFFSET 8
141 #define OBJC_FORWARDING_MIN_OFFSET 8
142
143 /* We do not want a dot in internal labels.  */
144
145 #undef LPREFIX
146 #define LPREFIX "L"
147
148 #undef  ASM_GENERATE_INTERNAL_LABEL
149 #define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER)  \
150     sprintf ((BUF), "*%s%d", (PREFIX), (NUMBER))
151
152 #undef ASM_OUTPUT_INTERNAL_LABEL
153 #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)      \
154   fprintf (FILE, "%s%d:\n", PREFIX, NUM)
155
156 /* Output to assembler file text saying following lines
157    may contain character constants, extra white space, comments, etc.  */
158
159 #undef  ASM_APP_ON
160 #define ASM_APP_ON "#APP\n"
161
162 /* Output to assembler file text saying following lines
163    no longer contain unusual constructs.  */
164
165 #undef  ASM_APP_OFF
166 #define ASM_APP_OFF "#NO_APP\n"
167
168 #undef  ASM_OUTPUT_REG_PUSH
169 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
170   fprintf (FILE, "\tpushl %se%s\n", "%", reg_names[REGNO])
171
172 #undef  ASM_OUTPUT_REG_POP
173 #define ASM_OUTPUT_REG_POP(FILE,REGNO)  \
174   fprintf (FILE, "\tpopl %se%s\n", "%", reg_names[REGNO])
175
176 /* This is being overridden because the default i386 configuration
177    generates calls to "_mcount".  NeXT system libraries all use
178    "mcount".  */
179
180 #undef  FUNCTION_PROFILER
181 #define FUNCTION_PROFILER(FILE, LABELNO)                                \
182 {                                                                       \
183   if (flag_pic)                                                         \
184     {                                                                   \
185       fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n",              \
186                LPREFIX, (LABELNO));                                     \
187       fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n");                    \
188     }                                                                   \
189   else                                                                  \
190     {                                                                   \
191       fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO));      \
192       fprintf (FILE, "\tcall mcount\n");                                \
193     }                                                                   \
194 }
195
196 /* BEGIN Calling Convention CHANGES */
197
198 /* These changes violate the Intel/Unix ABI.  Specifically, they
199    change the way that space for a block return value is passed to a
200    function.  The ABI says that the pointer is passed on the stack.
201    We change to pass the pointer in %ebx.  This makes the NeXT
202    Objective-C forwarding mechanism possible to implement on an i386.  */
203
204 /* Do NOT pass address of structure values on the stack.  */
205
206 #undef  STRUCT_VALUE_INCOMING
207 #undef  STRUCT_VALUE
208
209 /* Pass them in %ebx.  */
210
211 #undef  STRUCT_VALUE_REGNUM
212 #define STRUCT_VALUE_REGNUM 3
213
214 /* Because we are passing the pointer in a register, we don't need to
215    rely on the callee to pop it.  */
216
217 #undef  RETURN_POPS_ARGS
218 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE)                          \
219   ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE          \
220    ? 0                                                          \
221    : (TARGET_RTD                                                \
222       && (TYPE_ARG_TYPES (FUNTYPE) == 0                         \
223           || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \
224               == void_type_node))) ? (SIZE) : 0)
225
226 /* END Calling Convention CHANGES */
227
228 /* NeXT still uses old binutils that don't insert nops by default
229    when the .align directive demands to insert extra space in the text
230    segment.  */
231 #undef ASM_OUTPUT_ALIGN
232 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
233   if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))