* varasm.c (assemble_real): Use REAL_VALUE_TO_x and assemble_integer
[official-gcc.git] / gcc / config / m68k / crds.h
blob03faa9fbba3cf3e6ef2ea6b5bff35d6295ff6ced
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)
7 This file is part of GNU CC.
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.
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.
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. */
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 */
30 #include "m68k/m68k.h"
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
39 /* See m68k.h. 0 means 680[01]0 with no 68881. */
41 #undef TARGET_DEFAULT
42 #define TARGET_DEFAULT 0
44 /* Don't try using XFmode. */
45 #undef LONG_DOUBLE_TYPE_SIZE
46 #define LONG_DOUBLE_TYPE_SIZE 64
48 /* special flags to the unos assembler. */
50 #undef ASM_SPEC
51 #define ASM_SPEC "-g"
53 #undef LIB_SPEC
54 #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}"
56 #undef STARTFILE_SPEC
57 #define STARTFILE_SPEC \
58 "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}"
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
67 /* -O2 for MAX optimization */
68 #undef CC1_SPEC
69 #define CC1_SPEC "%{O2:-fstrength-reduce}"
71 /* cpp has to support a #sccs directive for the /usr/include files */
73 #define SCCS_DIRECTIVE
75 /* Make output for SDB. */
77 /* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */
79 /* UNOS need stack probe :-( */
81 #if 0
82 #define HAVE_probe 1
83 #define gen_probe() gen_rtx_ASM_INPUT (VOIDmode, "tstb -2048(sp)\t;probe\n")
84 #else
85 #undef NEED_PROBE
86 #define NEED_PROBE (-2048)
87 #endif
89 /* use memcpy, memset instead of bcopy, etc. */
91 #define TARGET_MEM_FUNCTIONS
93 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
94 This will control the use of inline 68881 insns in certain macros. */
96 #undef CPP_SPEC
97 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
99 /* Names to predefine in the preprocessor for this target machine. */
101 #undef CPP_PREDEFINES
102 #define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix -D__motorola__ -Asystem=unix -Acpu=m68k -Amachine=m68k"
104 /* Register in which address to store a structure value
105 is passed to a function. */
106 /* unos uses ".comm c.sac" returns &c.sac in d0 */
107 /* make pointer to c.sac ?
108 #undef STRUCT_VALUE_REGNUM
109 #define STRUCT_VALUE gen_rtx_MEM (Pmode, gen_rtx( , , ) )
112 #define BSS_SECTION_ASM_OP "\t.bss"
114 /* Specify how to pad function arguments.
115 Value should be `upward', `downward' or `none'.
116 Same as the default, except no padding for large or variable-size args. */
118 #define FUNCTION_ARG_PADDING(MODE, TYPE) \
119 (((MODE) == BLKmode \
120 ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
121 && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \
122 : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \
123 ? downward : none)
125 /* Override parts of m68k.h to fit the CRuDS assembler. */
127 #undef TARGET_VERSION
128 #define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)");
130 /* Specify extra dir to search for include files. */
131 #define SYSTEM_INCLUDE_DIR "/include"
133 /* Control the assembler format that we output. */
135 /* Output at beginning of assembler file. */
137 #undef ASM_FILE_START
138 #define ASM_FILE_START(FILE) \
139 fprintf (FILE, ";#NO_APP\n");
141 /* Output to assembler file text saying following lines
142 may contain character constants, extra white space, comments, etc. */
144 #undef ASM_APP_ON
145 #define ASM_APP_ON ";#APP\n"
147 /* Output to assembler file text saying following lines
148 no longer contain unusual constructs. */
150 #undef ASM_APP_OFF
151 #define ASM_APP_OFF ";#NO_APP\n"
153 /* The prefix for immediate operands. */
155 #undef IMMEDIATE_PREFIX
156 #define IMMEDIATE_PREFIX "$"
158 /*unos has no .skip :-( */
159 #undef ASM_OUTPUT_SKIP
160 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
161 fprintf (FILE, "\t. = . + %u\n", (SIZE));
163 /* This says how to output an assembler line
164 to define a local common symbol. */
165 /* should use bss_section instead of data_section but this makes casm die ? */
167 #undef ASM_OUTPUT_LOCAL
168 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
169 { data_section (); \
170 if ((SIZE) > 1) fprintf (FILE, "\t.even\n"); \
171 assemble_name ((FILE), (NAME)); \
172 fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));}
174 /* This is how to output an insn to push a register on the stack.
175 It need not be very fast code. */
177 #undef ASM_OUTPUT_REG_PUSH
178 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
179 fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO])
181 /* This is how to output an insn to pop a register from the stack.
182 It need not be very fast code. */
184 #undef ASM_OUTPUT_REG_POP
185 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
186 fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO])
188 #undef ASM_OUTPUT_ASCII
189 #define ASM_OUTPUT_ASCII(FILE, P , SIZE) \
190 do { size_t i, limit = (SIZE); \
191 fprintf ((FILE), "\t.ascii \""); \
192 for (i = 0; i < limit; i++) \
194 register int c = (P)[i]; \
195 if (i != 0 && (i / 200) * 200 == i) \
196 fprintf ((FILE), "\"\n\t.ascii \""); \
197 if (c >= ' ' && c < 0177) { \
198 if (c != '\"' && c != '\\') { \
199 putc (c, (FILE)); \
200 continue; \
203 /* brain dead asm doesn't understand char escapes */ \
204 fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c); \
206 fprintf ((FILE), "\"\n"); \
207 } while (0)
210 /* Change all JBxx to Bxx. Also change all DBRA to DBF.
211 Also change divs.l, etc., to divs, etc. But don't change divsl.l. */
213 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
214 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
215 { ++(PTR); } \
216 else if ((PTR)[0] == 'd') \
218 if (!strncmp ((PTR), "dbra", 4)) \
219 { fprintf ((FILE), "dbf"); (PTR) += 4; } \
220 else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ') \
221 { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; } \
226 #if 0
227 /* Print operand X (an rtx) in assembler syntax to file FILE.
228 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
229 For `%' followed by punctuation, CODE is the punctuation and X is null.
231 On the 68000, we use several CODE characters:
232 '.' for dot needed in Motorola-style opcode names.
233 '-' for an operand pushing on the stack:
234 sp@-, -(sp) or -(%sp) depending on the style of syntax.
235 '+' for an operand pushing on the stack:
236 sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
237 '@' for a reference to the top word on the stack:
238 sp@, (sp) or (%sp) depending on the style of syntax.
239 '#' for an immediate operand prefix (# in MIT and Motorola syntax
240 but & in SGS syntax, $ in unos syntax).
241 '!' for the fpcr register (used in some float-to-fixed conversions).
243 'b' for byte insn (no effect, on the Sun; this is for the ISI).
244 'd' to force memory addressing to be absolute, not relative.
245 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
246 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
247 than directly). Second part of 'y' below.
248 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
249 or print pair of registers as rx:ry.
250 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
251 CONST_DOUBLE's as SunFPA constant RAM registers if
252 possible, so it should not be used except for the SunFPA. */
254 #undef PRINT_OPERAND_PUNCT_VALID_P
255 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
256 ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \
257 || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
259 #undef PRINT_OPERAND
260 #define PRINT_OPERAND(FILE, X, CODE) \
261 { int i; \
262 if (CODE == '.') ; \
263 else if (CODE == '#') fprintf (FILE, "$"); \
264 else if (CODE == '-') fprintf (FILE, "-(sp)"); \
265 else if (CODE == '+') fprintf (FILE, "(sp)+"); \
266 else if (CODE == '@') fprintf (FILE, "(sp)"); \
267 else if (CODE == '!') fprintf (FILE, "fpcr"); \
268 else if (CODE == '/') \
270 else if (GET_CODE (X) == REG) \
271 { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \
272 fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \
273 else \
274 fprintf (FILE, "%s", reg_names[REGNO (X)]); \
276 else if (GET_CODE (X) == MEM) \
278 output_address (XEXP (X, 0)); \
279 if (CODE == 'd' && ! TARGET_68020 \
280 && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
281 /* fprintf (FILE, ".l") */; \
283 else if ((CODE == 'y' || CODE == 'w') \
284 && GET_CODE(X) == CONST_DOUBLE \
285 && (i = standard_sun_fpa_constant_p (X))) \
286 fprintf (FILE, "%%%d", i & 0x1ff); \
287 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
288 { REAL_VALUE_TYPE r; long l; \
289 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
290 if (CODE == 'f') \
291 ASM_OUTPUT_FLOAT_OPERAND (CODE, FILE, r); \
292 else \
293 { REAL_VALUE_TO_TARGET_SINGLE (r, l); \
294 fprintf (FILE, "$0x%lx", l); } } \
295 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
296 { REAL_VALUE_TYPE r; \
297 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
298 ASM_OUTPUT_DOUBLE_OPERAND (FILE, r); } \
299 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
300 { REAL_VALUE_TYPE r; \
301 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
302 ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
303 else { putc ('$', FILE); output_addr_const (FILE, X); }}
304 #endif
306 /* Note that this contains a kludge that knows that the only reason
307 we have an address (plus (label_ref...) (reg...))
308 is in the insn before a tablejump, and we know that m68k.md
309 generates a label LInnn: on such an insn. */
310 #undef PRINT_OPERAND_ADDRESS
311 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
312 { register rtx reg1, reg2, breg, ireg; \
313 register rtx addr = ADDR; \
314 rtx offset; \
315 switch (GET_CODE (addr)) \
317 case REG: \
318 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
319 break; \
320 case PRE_DEC: \
321 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
322 break; \
323 case POST_INC: \
324 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
325 break; \
326 case PLUS: \
327 reg1 = 0; reg2 = 0; \
328 ireg = 0; breg = 0; \
329 offset = 0; \
330 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
332 offset = XEXP (addr, 0); \
333 addr = XEXP (addr, 1); \
335 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
337 offset = XEXP (addr, 1); \
338 addr = XEXP (addr, 0); \
340 if (GET_CODE (addr) != PLUS) ; \
341 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
343 reg1 = XEXP (addr, 0); \
344 addr = XEXP (addr, 1); \
346 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
348 reg1 = XEXP (addr, 1); \
349 addr = XEXP (addr, 0); \
351 else if (GET_CODE (XEXP (addr, 0)) == MULT) \
353 reg1 = XEXP (addr, 0); \
354 addr = XEXP (addr, 1); \
356 else if (GET_CODE (XEXP (addr, 1)) == MULT) \
358 reg1 = XEXP (addr, 1); \
359 addr = XEXP (addr, 0); \
361 else if (GET_CODE (XEXP (addr, 0)) == REG) \
363 reg1 = XEXP (addr, 0); \
364 addr = XEXP (addr, 1); \
366 else if (GET_CODE (XEXP (addr, 1)) == REG) \
368 reg1 = XEXP (addr, 1); \
369 addr = XEXP (addr, 0); \
371 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
372 || GET_CODE (addr) == SIGN_EXTEND) \
373 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
374 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
375 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
376 || GET_CODE (reg1) == MULT)) \
377 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
378 { breg = reg2; ireg = reg1; } \
379 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
380 { breg = reg1; ireg = reg2; } \
381 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
382 { int scale = 1; \
383 if (GET_CODE (ireg) == MULT) \
384 { scale = INTVAL (XEXP (ireg, 1)); \
385 ireg = XEXP (ireg, 0); } \
386 if (GET_CODE (ireg) == SIGN_EXTEND) \
387 fprintf (FILE, "L%d-LI%d-2(pc,%s.w", \
388 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
389 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
390 reg_names[REGNO (XEXP (ireg, 0))]); \
391 else \
392 fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \
393 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
394 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
395 reg_names[REGNO (ireg)]); \
396 if (scale != 1) fprintf (FILE, ":%d", scale); \
397 putc (')', FILE); \
398 break; } \
399 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
400 { fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \
401 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
402 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
403 reg_names[REGNO (breg)]); \
404 putc (')', FILE); \
405 break; } \
406 if (ireg != 0 || breg != 0) \
407 { int scale = 1; \
408 if (breg == 0) \
409 abort (); \
410 if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
411 if (addr != 0) \
412 output_addr_const (FILE, addr); \
413 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
414 if (breg != 0 && ireg != 0) \
415 putc (',', FILE); \
416 if (ireg != 0 && GET_CODE (ireg) == MULT) \
417 { scale = INTVAL (XEXP (ireg, 1)); \
418 ireg = XEXP (ireg, 0); } \
419 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
420 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
421 else if (ireg != 0) \
422 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
423 if (scale != 1) fprintf (FILE, ":%d", scale); \
424 putc (')', FILE); \
425 break; \
427 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
428 { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)", \
429 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
430 CODE_LABEL_NUMBER (XEXP (addr, 0)), \
431 reg_names[REGNO (reg1)]); \
432 break; } \
433 default: \
434 if (GET_CODE (addr) == CONST_INT \
435 && INTVAL (addr) < 0x8000 \
436 && INTVAL (addr) >= -0x8000) \
437 fprintf (FILE, "%d", INTVAL (addr)); \
438 else \
439 output_addr_const (FILE, addr); \
442 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
443 do { fprintf (FILE, "\t; file\t"); \
444 output_quoted_string (FILE, FILENAME); \
445 fprintf (FILE, "\n"); \
446 } while (0)
448 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
449 fprintf (FILE, "\t; ln\t%d\n", \
450 (sdb_begin_function_line \
451 ? (LINENO) - sdb_begin_function_line : 1))
453 /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
454 /* UNOS ?? */
455 #undef FUNCTION_PROFILER
456 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
457 fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))