OSDN Git Service

* config/s390/s390.c (s390_optimize_prolog): Do not save/restore
[pf3gnuchains/gcc-fork.git] / gcc / config / m68k / crds.h
1 /* Definitions of target machine for GNU compiler;
2    Charles River Data Systems UNiverse/32.
3    Copyright (C) 1987, 1993, 1994, 1996, 1997, 1998, 1999, 2000
4    Free Software Foundation, Inc.
5    Contributed by Gary E. Miller (Gary_Edmunds_Miller@cup.portal.com)
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 #define MOTOROLA                /* Use Motorola syntax rather than "MIT" */
25 #define SGS                     /* Uses SGS assembler */
26 #define SGS_SWITCH_TABLES       /* Different switch table handling */
27 #define SGS_NO_LI               /* Suppress jump table label usage */
28 #define CRDS                    /* Charles River Data Systems assembler */
29
30 #include "m68k/m68k.h"
31
32 /* Without STRUCTURE_SIZE_BOUNDARY, we can't ensure that structures are
33    aligned such that we can correctly extract bitfields from them.
34    Someone should check whether the usual compiler on the crds machine
35    provides the equivalent behavior of STRUCTURE_SIZE_BOUNDARY.  */
36 /* Set to 16 because all other m68k targets have it so */
37 #define STRUCTURE_SIZE_BOUNDARY 16
38
39 /* See m68k.h.  0 means 680[01]0 with no 68881.  */
40
41 #undef TARGET_DEFAULT
42 #define TARGET_DEFAULT 0
43
44 /* Don't try using XFmode.  */
45 #undef LONG_DOUBLE_TYPE_SIZE
46 #define LONG_DOUBLE_TYPE_SIZE 64
47
48 /* special flags to the unos assembler.  */
49
50 #undef ASM_SPEC
51 #define ASM_SPEC "-g"
52
53 #undef LIB_SPEC
54 #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}"
55
56 #undef STARTFILE_SPEC
57 #define STARTFILE_SPEC  \
58   "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}"
59
60 /* CC1 spec */
61 #if 0
62 /* c.sac only used in _s_call_r() in libunos.a and malloc() in libmalloc.a */
63 /* so we do not need to bother ! */
64 #define CC1_SPEC "-fpcc-struct-return"
65 #endif
66
67 /* -O2 for MAX optimization */
68 #undef CC1_SPEC
69 #define CC1_SPEC "%{O2:-fstrength-reduce}"
70
71 /* Make output for SDB.  */
72
73 /* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */
74
75 /* UNOS need stack probe :-( */
76
77 #if 0
78 #define HAVE_probe 1
79 #define gen_probe()  gen_rtx_ASM_INPUT (VOIDmode, "tstb -2048(sp)\t;probe\n")
80 #else
81 #undef NEED_PROBE
82 #define NEED_PROBE (-2048)
83 #endif
84
85 /* use memcpy, memset instead of bcopy, etc.  */
86
87 #define TARGET_MEM_FUNCTIONS
88
89 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
90    This will control the use of inline 68881 insns in certain macros.  */
91
92 #undef CPP_SPEC
93 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
94
95 /* Names to predefine in the preprocessor for this target machine.  */
96
97 #undef CPP_PREDEFINES
98 #define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix -D__motorola__ -Asystem=unix  -Acpu=m68k -Amachine=m68k"
99
100 /* Register in which address to store a structure value
101    is passed to a function.  */
102 /* unos uses ".comm c.sac" returns &c.sac in d0 */
103 /* make pointer to c.sac ?
104 #undef STRUCT_VALUE_REGNUM
105 #define STRUCT_VALUE gen_rtx_MEM (Pmode, gen_rtx( , , ) )
106 */
107
108 #define BSS_SECTION_ASM_OP "\t.bss"
109
110 /* Specify how to pad function arguments.
111    Value should be `upward', `downward' or `none'.
112    Same as the default, except no padding for large or variable-size args.  */
113
114 #define FUNCTION_ARG_PADDING(MODE, TYPE)                                \
115   (((MODE) == BLKmode                                                   \
116     ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE))   == INTEGER_CST          \
117        && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT)     \
118     : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY)                          \
119    ? downward : none)
120
121 /* Override parts of m68k.h to fit the CRuDS assembler.  */
122
123 #undef TARGET_VERSION 
124 #define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)");
125
126 /* Specify extra dir to search for include files.  */
127 #define SYSTEM_INCLUDE_DIR "/include"
128
129 /* Control the assembler format that we output.  */
130
131 /* Output at beginning of assembler file.  */
132
133 #undef ASM_FILE_START
134 #define ASM_FILE_START(FILE)    \
135   fprintf (FILE, ";#NO_APP\n");
136
137 /* Output to assembler file text saying following lines
138    may contain character constants, extra white space, comments, etc.  */
139
140 #undef ASM_APP_ON
141 #define ASM_APP_ON ";#APP\n"
142
143 /* Output to assembler file text saying following lines
144    no longer contain unusual constructs.  */
145
146 #undef ASM_APP_OFF 
147 #define ASM_APP_OFF ";#NO_APP\n"
148
149 /* The prefix for immediate operands.  */
150
151 #undef IMMEDIATE_PREFIX
152 #define IMMEDIATE_PREFIX "$"
153
154 /*unos has no .skip :-( */
155 #undef ASM_OUTPUT_SKIP
156 #define ASM_OUTPUT_SKIP(FILE,SIZE)              \
157     fprintf (FILE, "\t. = . + %u\n", (SIZE));   
158
159 /* This says how to output an assembler line
160    to define a local common symbol.  */
161 /* should use bss_section instead of data_section but this makes casm die ? */
162
163 #undef ASM_OUTPUT_LOCAL
164 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
165 { data_section ();                              \
166   if ((SIZE) > 1) fprintf (FILE, "\t.even\n");  \
167   assemble_name ((FILE), (NAME));               \
168   fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));}
169
170 /* This is how to output an insn to push a register on the stack.
171    It need not be very fast code.  */
172
173 #undef ASM_OUTPUT_REG_PUSH
174 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO)  \
175   fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO])
176
177 /* This is how to output an insn to pop a register from the stack.
178    It need not be very fast code.  */
179
180 #undef ASM_OUTPUT_REG_POP
181 #define ASM_OUTPUT_REG_POP(FILE,REGNO)  \
182   fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO])
183
184 #undef  ASM_OUTPUT_ASCII
185 #define  ASM_OUTPUT_ASCII(FILE, P , SIZE)                               \
186 do {  size_t i, limit = (SIZE);                                         \
187           fprintf ((FILE), "\t.ascii \"");                              \
188           for (i = 0; i < limit; i++)                                   \
189             {                                                           \
190               register int c = (P)[i];                                  \
191               if (i != 0 && (i / 200) * 200 == i)                       \
192                 fprintf ((FILE), "\"\n\t.ascii \"");                    \
193               if (c >= ' ' && c < 0177) {                               \
194                 if (c != '\"' && c != '\\') {                           \
195                   putc (c, (FILE));                                     \
196                   continue;                                             \
197                 }                                                       \
198                }                                                        \
199                /* brain dead asm doesn't understand char escapes */     \
200                fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c);     \
201             }                                                           \
202           fprintf ((FILE), "\"\n");                                     \
203  } while (0)
204
205
206 /* Change all JBxx to Bxx.  Also change all DBRA to DBF.
207    Also change divs.l, etc., to divs, etc.  But don't change divsl.l.  */
208
209 #define ASM_OUTPUT_OPCODE(FILE, PTR)                    \
210 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b')               \
211     { ++(PTR); }                                        \
212   else if ((PTR)[0] == 'd')                             \
213     {                                                   \
214       if (!strncmp ((PTR), "dbra", 4))                  \
215         { fprintf ((FILE), "dbf"); (PTR) += 4; }        \
216       else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ')  \
217         { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; }   \
218     }                                                   \
219 }
220
221
222 #if 0
223 /* Print operand X (an rtx) in assembler syntax to file FILE.
224    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
225    For `%' followed by punctuation, CODE is the punctuation and X is null.
226
227    On the 68000, we use several CODE characters:
228    '.' for dot needed in Motorola-style opcode names.
229    '-' for an operand pushing on the stack:
230        sp@-, -(sp) or -(%sp) depending on the style of syntax.
231    '+' for an operand pushing on the stack:
232        sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
233    '@' for a reference to the top word on the stack:
234        sp@, (sp) or (%sp) depending on the style of syntax.
235    '#' for an immediate operand prefix (# in MIT and Motorola syntax
236        but & in SGS syntax, $ in unos syntax).
237    '!' for the fpcr register (used in some float-to-fixed conversions).
238
239    'b' for byte insn (no effect, on the Sun; this is for the ISI).
240    'd' to force memory addressing to be absolute, not relative.
241    'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
242    'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
243        than directly).  Second part of 'y' below.
244    'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
245        or print pair of registers as rx:ry.
246    'y' for a FPA insn (print pair of registers as rx:ry).  This also outputs
247        CONST_DOUBLE's as SunFPA constant RAM registers if
248        possible, so it should not be used except for the SunFPA.  */
249
250 #undef PRINT_OPERAND_PUNCT_VALID_P
251 #define PRINT_OPERAND_PUNCT_VALID_P(CODE)                               \
252   ((CODE) == '.' || (CODE) == '#' || (CODE) == '-'                      \
253    || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
254
255 #undef PRINT_OPERAND
256 #define PRINT_OPERAND(FILE, X, CODE)  \
257 { int i;                                                                \
258   if (CODE == '.') ;                                                    \
259   else if (CODE == '#') fprintf (FILE, "$");                            \
260   else if (CODE == '-') fprintf (FILE, "-(sp)");                        \
261   else if (CODE == '+') fprintf (FILE, "(sp)+");                        \
262   else if (CODE == '@') fprintf (FILE, "(sp)");                         \
263   else if (CODE == '!') fprintf (FILE, "fpcr");                         \
264   else if (CODE == '/')                                                 \
265     ;                                                                   \
266   else if (GET_CODE (X) == REG)                                         \
267     { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode)     \
268         fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \
269       else                                                              \
270         fprintf (FILE, "%s", reg_names[REGNO (X)]);                     \
271     }                                                                   \
272   else if (GET_CODE (X) == MEM)                                         \
273     {                                                                   \
274       output_address (XEXP (X, 0));                                     \
275       if (CODE == 'd' && ! TARGET_68020                                 \
276           && CONSTANT_ADDRESS_P (XEXP (X, 0)))                          \
277         /* fprintf (FILE, ".l") */;                                     \
278     }                                                                   \
279   else if ((CODE == 'y' || CODE == 'w')                                 \
280            && GET_CODE(X) == CONST_DOUBLE                               \
281            && (i = standard_sun_fpa_constant_p (X)))                    \
282     fprintf (FILE, "%%%d", i & 0x1ff);                                  \
283   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode)      \
284     { REAL_VALUE_TYPE r; long l;                                        \
285       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
286       if (CODE == 'f')                                                  \
287         ASM_OUTPUT_FLOAT_OPERAND (CODE, FILE, r);                       \
288       else                                                              \
289         { REAL_VALUE_TO_TARGET_SINGLE (r, l);                           \
290           fprintf (FILE, "$0x%lx", l); } }                              \
291   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode)      \
292     { REAL_VALUE_TYPE r;                                                \
293       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
294       ASM_OUTPUT_DOUBLE_OPERAND (FILE, r); }                            \
295   else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode)      \
296     { REAL_VALUE_TYPE r;                                                \
297       REAL_VALUE_FROM_CONST_DOUBLE (r, X);                              \
298       ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); }                       \
299   else { putc ('$', FILE); output_addr_const (FILE, X); }}
300 #endif
301 \f
302 /* Note that this contains a kludge that knows that the only reason
303    we have an address (plus (label_ref...) (reg...))
304    is in the insn before a tablejump, and we know that m68k.md
305    generates a label LInnn: on such an insn.  */
306 #undef PRINT_OPERAND_ADDRESS
307 #define PRINT_OPERAND_ADDRESS(FILE, ADDR)  \
308 { register rtx reg1, reg2, breg, ireg;                                  \
309   register rtx addr = ADDR;                                             \
310   rtx offset;                                                           \
311   switch (GET_CODE (addr))                                              \
312     {                                                                   \
313     case REG:                                                           \
314       fprintf (FILE, "(%s)", reg_names[REGNO (addr)]);                  \
315       break;                                                            \
316     case PRE_DEC:                                                       \
317       fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);       \
318       break;                                                            \
319     case POST_INC:                                                      \
320       fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);       \
321       break;                                                            \
322     case PLUS:                                                          \
323       reg1 = 0; reg2 = 0;                                               \
324       ireg = 0; breg = 0;                                               \
325       offset = 0;                                                       \
326       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))                          \
327         {                                                               \
328           offset = XEXP (addr, 0);                                      \
329           addr = XEXP (addr, 1);                                        \
330         }                                                               \
331       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))                     \
332         {                                                               \
333           offset = XEXP (addr, 1);                                      \
334           addr = XEXP (addr, 0);                                        \
335         }                                                               \
336       if (GET_CODE (addr) != PLUS) ;                                    \
337       else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)                \
338         {                                                               \
339           reg1 = XEXP (addr, 0);                                        \
340           addr = XEXP (addr, 1);                                        \
341         }                                                               \
342       else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)                \
343         {                                                               \
344           reg1 = XEXP (addr, 1);                                        \
345           addr = XEXP (addr, 0);                                        \
346         }                                                               \
347       else if (GET_CODE (XEXP (addr, 0)) == MULT)                       \
348         {                                                               \
349           reg1 = XEXP (addr, 0);                                        \
350           addr = XEXP (addr, 1);                                        \
351         }                                                               \
352       else if (GET_CODE (XEXP (addr, 1)) == MULT)                       \
353         {                                                               \
354           reg1 = XEXP (addr, 1);                                        \
355           addr = XEXP (addr, 0);                                        \
356         }                                                               \
357       else if (GET_CODE (XEXP (addr, 0)) == REG)                        \
358         {                                                               \
359           reg1 = XEXP (addr, 0);                                        \
360           addr = XEXP (addr, 1);                                        \
361         }                                                               \
362       else if (GET_CODE (XEXP (addr, 1)) == REG)                        \
363         {                                                               \
364           reg1 = XEXP (addr, 1);                                        \
365           addr = XEXP (addr, 0);                                        \
366         }                                                               \
367       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT             \
368           || GET_CODE (addr) == SIGN_EXTEND)                            \
369         { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; }     \
370       if (offset != 0) { if (addr != 0) abort (); addr = offset; }      \
371       if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND                      \
372                     || GET_CODE (reg1) == MULT))                        \
373           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))         \
374         { breg = reg2; ireg = reg1; }                                   \
375       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))         \
376         { breg = reg1; ireg = reg2; }                                   \
377       if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF)       \
378         { int scale = 1;                                                \
379           if (GET_CODE (ireg) == MULT)                                  \
380             { scale = INTVAL (XEXP (ireg, 1));                          \
381               ireg = XEXP (ireg, 0); }                                  \
382           if (GET_CODE (ireg) == SIGN_EXTEND)                           \
383             fprintf (FILE, "L%d-LI%d-2(pc,%s.w",                        \
384                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
385                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
386                      reg_names[REGNO (XEXP (ireg, 0))]);                \
387           else                                                          \
388             fprintf (FILE, "L%d-LI%d-2(pc,%s.l",                        \
389                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
390                      CODE_LABEL_NUMBER (XEXP (addr, 0)),                \
391                      reg_names[REGNO (ireg)]);                          \
392           if (scale != 1) fprintf (FILE, ":%d", scale);                 \
393           putc (')', FILE);                                             \
394           break; }                                                      \
395       if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF)       \
396         { fprintf (FILE, "L%d-LI%d-2(pc,%s.l",                          \
397                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
398                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
399                    reg_names[REGNO (breg)]);                            \
400           putc (')', FILE);                                             \
401           break; }                                                      \
402       if (ireg != 0 || breg != 0)                                       \
403         { int scale = 1;                                                \
404           if (breg == 0)                                                \
405             abort ();                                                   \
406           if (addr && GET_CODE (addr) == LABEL_REF) abort ();           \
407           if (addr != 0)                                                \
408             output_addr_const (FILE, addr);                             \
409           fprintf (FILE, "(%s", reg_names[REGNO (breg)]);               \
410           if (breg != 0 && ireg != 0)                                   \
411             putc (',', FILE);                                           \
412           if (ireg != 0 && GET_CODE (ireg) == MULT)                     \
413             { scale = INTVAL (XEXP (ireg, 1));                          \
414               ireg = XEXP (ireg, 0); }                                  \
415           if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)              \
416             fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]);  \
417           else if (ireg != 0)                                           \
418             fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]);            \
419           if (scale != 1) fprintf (FILE, ":%d", scale);                 \
420           putc (')', FILE);                                             \
421           break;                                                        \
422         }                                                               \
423       else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF)               \
424         { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)",                         \
425                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
426                    CODE_LABEL_NUMBER (XEXP (addr, 0)),                  \
427                    reg_names[REGNO (reg1)]);                            \
428           break; }                                                      \
429     default:                                                            \
430       if (GET_CODE (addr) == CONST_INT                                  \
431           && INTVAL (addr) < 0x8000                                     \
432           && INTVAL (addr) >= -0x8000)                                  \
433         fprintf (FILE, "%d", INTVAL (addr));                            \
434       else                                                              \
435         output_addr_const (FILE, addr);                                 \
436     }}
437 \f
438 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
439   do {  fprintf (FILE, "\t; file\t");                   \
440         output_quoted_string (FILE, FILENAME);          \
441         fprintf (FILE, "\n");                           \
442   } while (0)
443
444 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)    \
445   fprintf (FILE, "\t; ln\t%d\n",                        \
446            (sdb_begin_function_line             \
447             ? (LINENO) - sdb_begin_function_line : 1))
448
449 /* Must put address in  %a0 , not  %d0 . -- LGM, 7/15/88 */
450 /* UNOS ?? */
451 #undef FUNCTION_PROFILER
452 #define FUNCTION_PROFILER(FILE, LABEL_NO)       \
453     fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))