OSDN Git Service

50884653b8b64df3b590f3351e294c01900b7854
[pf3gnuchains/gcc-fork.git] / gcc / config / s390 / linux.h
1 /* Definitions for Linux for S/390.
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
4                   Ulrich Weigand (uweigand@de.ibm.com).
5
6 This file is part of GNU CC.
7
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)
11 any later version.
12
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.
17
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.  */
22
23 #ifndef _LINUX_H
24 #define _LINUX_H
25
26 /* Target specific version string.  */
27
28 #ifdef DEFAULT_TARGET_64BIT
29 #undef  TARGET_VERSION
30 #define TARGET_VERSION fprintf (stderr, " (Linux for zSeries)");
31 #else
32 #undef  TARGET_VERSION
33 #define TARGET_VERSION fprintf (stderr, " (Linux for S/390)");
34 #endif
35
36
37 /* Target specific type definitions.  */
38
39 /* ??? Do we really want long as size_t on 31-bit?  */
40 #undef  SIZE_TYPE
41 #define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "long unsigned int")
42 #undef  PTRDIFF_TYPE
43 #define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
44
45 #undef  WCHAR_TYPE
46 #define WCHAR_TYPE "int"
47 #undef  WCHAR_TYPE_SIZE
48 #define WCHAR_TYPE_SIZE 32
49
50
51 /* Target specific preprocessor settings.  */
52
53 #define TARGET_OS_CPP_BUILTINS()                \
54   do                                            \
55     {                                           \
56       builtin_define_std ("linux");             \
57       builtin_define_std ("unix");              \
58       builtin_assert ("system=linux");          \
59       builtin_assert ("system=unix");           \
60       builtin_define ("__ELF__");               \
61       builtin_define ("__gnu_linux__");         \
62       if (flag_pic)                             \
63         {                                       \
64           builtin_define ("__PIC__");           \
65           builtin_define ("__pic__");           \
66         }                                       \
67     }                                           \
68   while (0)
69
70
71 /* Target specific compiler settings.  */
72
73 /* ??? -fcaller-saves sometimes doesn't work.  Fix this! */
74 #undef  CC1_SPEC
75 #define CC1_SPEC "-fno-caller-saves"
76 #undef  CC1PLUS_SPEC
77 #define CC1PLUS_SPEC "-fno-caller-saves"
78
79
80 /* Target specific assembler settings.  */
81
82 #ifdef DEFAULT_TARGET_64BIT
83 #undef  ASM_SPEC
84 #define ASM_SPEC "%{m31:-m31 -Aesa}"
85 #else
86 #undef  ASM_SPEC
87 #define ASM_SPEC "%{m64:-m64 -Aesame}"
88 #endif
89
90
91 /* Target specific linker settings.  */
92
93 #define LINK_ARCH31_SPEC \
94   "-m elf_s390 \
95    %{shared:-shared} \
96    %{!shared: \
97       %{static:-static} \
98       %{!static: \
99         %{rdynamic:-export-dynamic} \
100         %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
101
102 #define LINK_ARCH64_SPEC \
103   "-m elf64_s390 \
104    %{shared:-shared} \
105    %{!shared: \
106       %{static:-static} \
107       %{!static: \
108         %{rdynamic:-export-dynamic} \
109         %{!dynamic-linker:-dynamic-linker /lib/ld64.so.1}}}"
110
111 #ifdef DEFAULT_TARGET_64BIT
112 #undef  LINK_SPEC
113 #define LINK_SPEC "%{m31:%(link_arch31)} %{!m31:%(link_arch64)}"
114 #else
115 #undef  LINK_SPEC
116 #define LINK_SPEC "%{m64:%(link_arch64)} %{!m64:%(link_arch31)}"
117 #endif
118
119
120 /* This macro defines names of additional specifications to put in the specs
121    that can be used in various specifications like CC1_SPEC.  Its definition
122    is an initializer with a subgrouping for each command option.  */
123
124 #define EXTRA_SPECS \
125   { "link_arch31",      LINK_ARCH31_SPEC },     \
126   { "link_arch64",      LINK_ARCH64_SPEC },     \
127
128
129 /* Character to start a comment.  */
130
131 #define ASM_COMMENT_START "#"
132
133
134 /* Assembler pseudos to introduce constants of various size.  */
135
136 #define ASM_DOUBLE "\t.double"
137
138 /* The LOCAL_LABEL_PREFIX variable is used by dbxelf.h.  */
139 #define LOCAL_LABEL_PREFIX "."
140
141 /* Prefix for internally generated assembler labels.  */
142 #define LPREFIX ".L"
143
144
145 /* This is how to output the definition of a user-level label named NAME,
146    such as the label on a static function or variable NAME.  */
147
148 #undef ASM_OUTPUT_LABEL
149 #define ASM_OUTPUT_LABEL(FILE, NAME)     \
150   (assemble_name (FILE, NAME), fputs (":\n", FILE))
151
152 /* Store in OUTPUT a string (made with alloca) containing
153    an assembler-name for a local static variable named NAME.
154    LABELNO is an integer which is different for each call.  */
155
156 #undef ASM_FORMAT_PRIVATE_NAME
157 #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)  \
158 ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),    \
159   sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
160
161
162      /* internal macro to output long */
163 #define _ASM_OUTPUT_LONG(FILE, VALUE)                                   \
164       fprintf (FILE, "\t.long\t0x%lX\n", VALUE);
165
166
167 /* This is how to output an element of a case-vector that is absolute.  */
168
169 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)                    \
170   fprintf (FILE, "%s%s%d\n", integer_asm_op (UNITS_PER_WORD, TRUE), \
171            LPREFIX, VALUE)
172
173 /* This is how to output an element of a case-vector that is relative.  */
174
175 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)                \
176   fprintf (FILE, "%s%s%d-%s%d\n", integer_asm_op (UNITS_PER_WORD, TRUE), \
177            LPREFIX, VALUE, LPREFIX, REL)
178
179
180
181 /* This is how to output an assembler line
182    that says to advance the location counter
183    to a multiple of 2**LOG bytes.  */
184
185 #undef ASM_OUTPUT_ALIGN
186 #define ASM_OUTPUT_ALIGN(FILE, LOG)     \
187     if ((LOG)!=0) fprintf ((FILE), "\t.align\t%d\n", 1<<(LOG))
188
189 /* This is how to output an assembler line
190    that says to advance the location counter by SIZE bytes.  */
191
192 #undef ASM_OUTPUT_SKIP
193 #define ASM_OUTPUT_SKIP(FILE, SIZE)  \
194   fprintf ((FILE), "\t.set\t.,.+%u\n", (SIZE))
195
196 /* This is how to output assembler code to declare an
197    uninitialized external linkage data object.  */
198
199 #undef ASM_OUTPUT_ALIGNED_BSS
200 #define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
201   asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
202
203 /* Output before read-only data.  */
204
205 #define TEXT_SECTION_ASM_OP ".text"
206
207 /* Output before writable (initialized) data.  */
208
209 #define DATA_SECTION_ASM_OP ".data"
210
211 /* Output before writable (uninitialized) data.  */
212
213 #define BSS_SECTION_ASM_OP ".bss"
214
215 /* This is how to output a command to make the user-level label named NAME
216    defined for reference from other files.  */
217
218 #define ASM_GLOBALIZE_LABEL(FILE, NAME)  \
219   (fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
220 \f
221 /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
222    Used for C++ multiple inheritance.  */
223 #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)              \
224 do {                                                                          \
225   if (TARGET_64BIT)                                                           \
226     {                                                                         \
227       if (flag_pic)                                                           \
228         {                                                                     \
229           fprintf (FILE, "\tlarl  1,0f\n");                                   \
230           fprintf (FILE, "\tagf   %d,0(1)\n",                                 \
231                    aggregate_value_p (TREE_TYPE                               \
232                                       (TREE_TYPE (FUNCTION))) ? 3 :2 );       \
233           fprintf (FILE, "\tlarl  1,");                                       \
234           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
235           fprintf (FILE, "@GOTENT\n");                                        \
236           fprintf (FILE, "\tlg    1,0(1)\n");                                 \
237           fprintf (FILE, "\tbr    1\n");                                      \
238           fprintf (FILE, "0:\t.long  ");                                      \
239           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
240           fprintf (FILE, "\n");                                               \
241         }                                                                     \
242       else                                                                    \
243         {                                                                     \
244           fprintf (FILE, "\tlarl  1,0f\n");                                   \
245           fprintf (FILE, "\tagf   %d,0(1)\n",                                 \
246           aggregate_value_p (TREE_TYPE                                        \
247                              (TREE_TYPE (FUNCTION))) ? 3 :2 );                \
248           fprintf (FILE, "\tjg  ");                                           \
249           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
250           fprintf (FILE, "\n");                                               \
251           fprintf (FILE, "0:\t.long  ");                                      \
252           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
253           fprintf (FILE, "\n");                                               \
254         }                                                                     \
255     }                                                                         \
256   else                                                                        \
257     {                                                                         \
258       if (flag_pic)                                                           \
259         {                                                                     \
260           fprintf (FILE, "\tbras  1,0f\n");                                   \
261           fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_-.\n");                \
262           fprintf (FILE, "\t.long  ");                                        \
263           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
264           fprintf (FILE, "@GOT\n");                                           \
265           fprintf (FILE, "\t.long  ");                                        \
266           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
267           fprintf (FILE, "\n");                                               \
268           fprintf (FILE, "0:\tal  %d,8(1)\n",                                 \
269                    aggregate_value_p (TREE_TYPE                               \
270                                       (TREE_TYPE (FUNCTION))) ? 3 : 2 );      \
271           fprintf (FILE, "\tl     0,4(1)\n");                                 \
272           fprintf (FILE, "\tal    1,0(1)\n");                                 \
273           fprintf (FILE, "\talr   1,0\n");                                    \
274           fprintf (FILE, "\tl     1,0(1)\n");                                 \
275           fprintf (FILE, "\tbr    1\n");                                      \
276         } else {                                                              \
277           fprintf (FILE, "\tbras  1,0f\n");                                   \
278           fprintf (FILE, "\t.long  ");                                        \
279           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
280           fprintf (FILE, "-.\n");                                             \
281           fprintf (FILE, "\t.long  ");                                        \
282           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
283           fprintf (FILE, "\n");                                               \
284           fprintf (FILE, "0:\tal  %d,4(1)\n",                                 \
285                    aggregate_value_p (TREE_TYPE                               \
286                                       (TREE_TYPE (FUNCTION))) ? 3 : 2 );      \
287           fprintf (FILE, "\tal    1,0(1)\n");                                 \
288           fprintf (FILE, "\tbr    1\n");                                      \
289        }                                                                      \
290     }                                                                         \
291 } while (0)
292
293 /* Do code reading to identify a signal frame, and set the frame
294    state data appropriately.  See unwind-dw2.c for the structs.  */
295
296 #define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)               \
297   do {                                                                  \
298     unsigned char *pc_ = (CONTEXT)->ra;                                 \
299     long new_cfa_;                                                      \
300     int i_;                                                             \
301                                                                         \
302     typedef struct                                                      \
303       {                                                                 \
304         unsigned long psw_mask;                                         \
305         unsigned long psw_addr;                                         \
306         unsigned long gprs[16];                                         \
307         unsigned int  acrs[16];                                         \
308         unsigned int  fpc;                                              \
309         unsigned int  __pad;                                            \
310         double        fprs[16];                                         \
311       } __attribute__ ((__aligned__ (8))) sigregs_;                     \
312                                                                         \
313     sigregs_ *regs_;                                                    \
314                                                                         \
315     /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn  */                \
316     if (pc_[0] != 0x0a || (pc_[1] != 119 && pc_[1] != 173))             \
317       break;                                                            \
318                                                                         \
319     /* New-style RT frame:                                              \
320         retcode + alignment (8 bytes)                                   \
321         siginfo (128 bytes)                                             \
322         ucontext (contains sigregs)  */                                 \
323     if ((CONTEXT)->ra == (CONTEXT)->cfa)                                \
324       {                                                                 \
325         struct ucontext_                                                \
326           {                                                             \
327             unsigned long     uc_flags;                                 \
328             struct ucontext_ *uc_link;                                  \
329             unsigned long     uc_stack[3];                              \
330             sigregs_          uc_mcontext;                              \
331           } *uc_ = (CONTEXT)->cfa + 8 + 128;                            \
332                                                                         \
333         regs_ = &uc_->uc_mcontext;                                      \
334       }                                                                 \
335                                                                         \
336     /* Old-style RT frame and all non-RT frames:                        \
337         old signal mask (8 bytes)                                       \
338         pointer to sigregs  */                                          \
339     else                                                                \
340       {                                                                 \
341         regs_ = *(sigregs_ **)((CONTEXT)->cfa + 8);                     \
342       }                                                                 \
343                                                                         \
344     new_cfa_ = regs_->gprs[15] + 16*sizeof(long) + 32;                  \
345     (FS)->cfa_how = CFA_REG_OFFSET;                                     \
346     (FS)->cfa_reg = 15;                                                 \
347     (FS)->cfa_offset =                                                  \
348       new_cfa_ - (long) (CONTEXT)->cfa + 16*sizeof(long) + 32;          \
349                                                                         \
350     for (i_ = 0; i_ < 16; i_++)                                         \
351       {                                                                 \
352         (FS)->regs.reg[i_].how = REG_SAVED_OFFSET;                      \
353         (FS)->regs.reg[i_].loc.offset =                                 \
354           (long)&regs_->gprs[i_] - new_cfa_;                            \
355       }                                                                 \
356     for (i_ = 0; i_ < 16; i_++)                                         \
357       {                                                                 \
358         (FS)->regs.reg[16+i_].how = REG_SAVED_OFFSET;                   \
359         (FS)->regs.reg[16+i_].loc.offset =                              \
360           (long)&regs_->fprs[i_] - new_cfa_;                            \
361       }                                                                 \
362                                                                         \
363     /* Load return addr from PSW into dummy register 32.  */            \
364     (FS)->regs.reg[32].how = REG_SAVED_OFFSET;                          \
365     (FS)->regs.reg[32].loc.offset = (long)&regs_->psw_addr - new_cfa_;  \
366     (FS)->retaddr_column = 32;                                          \
367                                                                         \
368     goto SUCCESS;                                                       \
369   } while (0)
370
371 #endif