1 /* Definitions of target machine for GNU compiler.
2 For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
3 Copyright (C) 1990, 1993, 1994, 1996, 1997, 2000, 2002
4 Free Software Foundation, Inc.
5 Contributed by Robert Andersson (ra@intsys.no), International Systems,
8 This file is part of GNU CC.
10 GNU CC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GNU CC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
26 /* This file outputs assembler source suitable for the native Tower as
27 and with sdb debugging symbols. See tower.h for more comments.
29 This file was based on m68k.h, hp320.h and 3b1.h as of the
32 #include "m68k/tower.h"
34 /* Use default settings for system V.3. */
38 /* Names to predefine in the preprocessor for this target machine. */
40 #define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_600 -D__motorola__ -Asystem=unix -Asystem=svr3 -Acpu=m68k -Amachine=m68k"
42 /* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
43 This will control the use of inline 68881 insns in certain macros.
44 Also, define special define used to identify the Tower assembler. */
46 #define CPP_SPEC "-D__TOWER_ASM__ %{m68881:-D__HAVE_68881__}"
48 /* We don't want local labels to start with period.
49 See (*targetm.asm_out.internal_label). */
50 #undef LOCAL_LABEL_PREFIX
51 #define LOCAL_LABEL_PREFIX ""
53 /* The prefix to add to user-visible assembler symbols. */
54 /* We do not want leading underscores. */
56 #undef USER_LABEL_PREFIX
57 #define USER_LABEL_PREFIX ""
59 /* These four macros control how m68k.md is expanded. */
61 #define MOTOROLA /* Use Motorola syntax rather than "MIT" */
62 #define SGS /* Uses SGS assembler */
63 #define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
64 #define SGS_NO_LI /* Suppress jump table label usage */
67 #define INT_OP_GROUP INT_OP_NO_DOT
69 /* Turn on SDB debugging info. */
71 #define SDB_DEBUGGING_INFO 1
73 /* All the ASM_OUTPUT macros need to conform to the Tower as syntax. */
75 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
77 fprintf (FILE, "\tfile\t"); \
78 output_quoted_string (FILE, FILENAME); \
79 fprintf (FILE, "\n"); \
80 fprintf (FILE, "section ~init,\"x\"\n"); \
81 fprintf (FILE, "section ~fini,\"x\"\n"); \
82 fprintf (FILE, "section ~rodata,\"x\"\n"); \
83 fprintf (FILE, "text\n"); \
86 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
87 fprintf (FILE, "\tln\t%d\n", \
88 (sdb_begin_function_line > -1 \
89 ? (LINENO) - sdb_begin_function_line : 1))
91 #undef ASM_OUTPUT_IDENT
92 #define ASM_OUTPUT_IDENT(FILE, NAME) \
93 fprintf (FILE, "\tident\t\"%s\" \n", NAME)
95 #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
96 do { register size_t sp = 0, lp = 0, limit = (LEN); \
97 fprintf ((FILE), "\tbyte\t"); \
99 if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
101 fprintf ((FILE), "'%c", (PTR)[sp]); } \
104 fprintf ((FILE), "0x%x", (PTR)[sp]); } \
108 fprintf ((FILE), "\n\tbyte\t"); } \
110 putc (',', (FILE)); \
112 putc ('\n', (FILE)); } while (0)
114 /* Translate Motorola opcodes such as `jbeq'
115 into SGS/Tower opcodes such as `beq.w'.
116 Change `move' to `mov'.
117 Change `cmpm' to `cmp'.
118 Change `divsl' to `tdivs'.
119 Change `divul' to `tdivu'.
120 Change `ftst' to `ftest'.
121 Change `fmove' to `fmov'. */
123 #define ASM_OUTPUT_OPCODE(FILE, PTR) \
124 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
126 while (*(PTR) != ' ') \
127 { putc (*(PTR), (FILE)); ++(PTR); } \
128 fprintf ((FILE), ".w"); } \
129 else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
130 && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
131 { fprintf ((FILE), "mov"); (PTR) += 4; } \
132 else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
133 && (PTR)[2] == 'p' && (PTR)[3] == 'm') \
134 { fprintf ((FILE), "cmp"); (PTR) += 4; } \
135 else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
136 && (PTR)[2] == 'v' && (PTR)[3] == 's' \
137 && (PTR)[4] == 'l') \
138 { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
139 else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
140 && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
141 && (PTR)[4] == 'l') \
142 { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
143 else if ((PTR)[0] == 'f' && (PTR)[1] == 't' \
144 && (PTR)[2] == 's' && (PTR)[3] == 't') \
145 { fprintf ((FILE), "ftest"); (PTR) += 4; } \
146 else if ((PTR)[0] == 'f' && (PTR)[1] == 'm' \
147 && (PTR)[2] == 'o' && (PTR)[3] == 'v' \
148 && (PTR)[4] == 'e') \
149 { fprintf ((FILE), "fmov"); (PTR) += 5; } \
154 /* Override parts of m68k.h to fit the Tower assembler.
155 This section needs to track changes done to m68k.h in the future. */
157 #undef TARGET_VERSION
158 #define TARGET_VERSION fprintf (stderr, " (68k, Motorola/SGS/Tower32 syntax)");
160 #undef FUNCTION_PROFILER
161 #define FUNCTION_PROFILER(FILE, LABEL_NO) \
162 fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount%%\n", (LABEL_NO))
164 #undef FUNCTION_EXTRA_EPILOGUE
165 #define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
166 { if (current_function_returns_pointer \
167 && ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
168 asm_fprintf (FILE, "\tmov.l %Rd0,%Ra0\n"); }
170 /* This is how to output an insn to push a register on the stack.
171 It need not be very fast code. */
173 #undef ASM_OUTPUT_REG_PUSH
174 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
175 fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
177 /* This is how to output an insn to pop a register from the stack.
178 It need not be very fast code. */
180 #undef ASM_OUTPUT_REG_POP
181 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
182 fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
184 #undef ASM_FILE_START
185 #define ASM_FILE_START(FILE) \
186 ( fprintf (FILE, "#NO_APP\n"), \
187 output_file_directive ((FILE), main_input_filename))
189 #undef TEXT_SECTION_ASM_OP
190 #define TEXT_SECTION_ASM_OP "\ttext"
192 #undef DATA_SECTION_ASM_OP
193 #define DATA_SECTION_ASM_OP "\tdata"
195 /* This says how to output an assembler line to define a global common symbol.
196 We use SIZE rather than ROUNDED, as this is what the native cc does. */
198 #undef ASM_OUTPUT_COMMON
199 #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
200 ( fputs ("\tcomm ", (FILE)), \
201 assemble_name ((FILE), (NAME)), \
202 fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
204 /* This says how to output an assembler line to define a local common symbol.
205 We use SIZE rather than ROUNDED, as this is what the native cc does. */
207 #undef ASM_OUTPUT_LOCAL
208 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
209 ( fputs ("\tlcomm ", (FILE)), \
210 assemble_name ((FILE), (NAME)), \
211 fprintf ((FILE), ",%d\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
213 #define ASM_PN_FORMAT "%s%%%%%lu"
215 /* This is the command to make the user-level label named NAME
216 defined for reference from other files. */
219 #define GLOBAL_ASM_OP "\tglobal\t"
221 #undef ASM_GENERATE_INTERNAL_LABEL
222 #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
223 sprintf ((LABEL), "%s%%%ld", (PREFIX), (long)(NUM))
225 #undef ASM_OUTPUT_CASE_LABEL
226 #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
227 fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
228 XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
230 #undef ASM_OUTPUT_ADDR_VEC_ELT
231 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
232 fprintf (FILE, "\tlong L%%%d\n", (VALUE))
234 #undef ASM_OUTPUT_ADDR_DIFF_ELT
235 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
236 fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
238 #undef ASM_OUTPUT_ALIGN
239 #define ASM_OUTPUT_ALIGN(FILE,LOG) \
242 fprintf (FILE, "\teven\n"); \
243 else if ((LOG) != 0) \
247 #undef ASM_OUTPUT_SKIP
248 #define ASM_OUTPUT_SKIP(FILE,SIZE) \
249 fprintf (FILE, "\tspace %d\n", (SIZE))
251 /* Output a float value (represented as a C double) as an immediate operand.
252 This macro is a 68k-specific macro. */
254 #undef ASM_OUTPUT_FLOAT_OPERAND
255 #define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
257 REAL_VALUE_TO_TARGET_SINGLE (r, l); \
258 /* Use hex representation even if CODE is f. as needs it. */ \
259 fprintf ((FILE), "&0x%lx", l); \
262 /* Output a double value (represented as a C double) as an immediate operand.
263 This macro is a 68k-specific macro. */
264 #undef ASM_OUTPUT_DOUBLE_OPERAND
265 #define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
267 REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
268 fprintf ((FILE), "&0x%lx%08lx", l[0], l[1]); \
273 #define PRINT_OPERAND(FILE, X, CODE) \
274 { if (CODE == '.') fprintf (FILE, "."); \
275 else if (CODE == '#') fprintf (FILE, "&"); \
276 else if (CODE == '-') fprintf (FILE, "-(%%sp)"); \
277 else if (CODE == '+') fprintf (FILE, "(%%sp)+"); \
278 else if (CODE == '@') fprintf (FILE, "(%%sp)"); \
279 else if (CODE == '!') fprintf (FILE, "%%fpcr"); \
280 else if (CODE == '/') \
281 fprintf (FILE, "%%"); \
282 else if (CODE == '$') { if (TARGET_68040_ONLY) fprintf (FILE, "s"); } \
283 else if (CODE == '&') { if (TARGET_68040_ONLY) fprintf (FILE, "d"); } \
284 else if (GET_CODE (X) == REG) \
285 fprintf (FILE, "%s", reg_names[REGNO (X)]); \
286 else if (GET_CODE (X) == MEM) \
287 output_address (XEXP (X, 0)); \
288 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
289 { REAL_VALUE_TYPE r; long l; \
290 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
291 REAL_VALUE_TO_TARGET_SINGLE (r, l); \
292 fprintf (FILE, "&0x%lx", l); } \
293 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
294 { REAL_VALUE_TYPE r; int i[2]; \
295 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
296 REAL_VALUE_TO_TARGET_DOUBLE (r, i); \
297 fprintf (FILE, "&0x%x%08x", i[0], i[1]); } \
298 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
299 { REAL_VALUE_TYPE r; \
300 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
301 ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
302 else { putc ('&', FILE); output_addr_const (FILE, X); }}
305 /* Note that this contains a kludge that knows that the only reason
306 we have an address (plus (label_ref...) (reg...))
307 is in the insn before a tablejump, and we know that the table is
308 exactly 10 bytes away. */
310 #undef PRINT_OPERAND_ADDRESS
311 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
312 { register rtx reg1, reg2, breg, ireg; \
313 register rtx addr = ADDR; \
315 switch (GET_CODE (addr)) \
318 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
321 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
324 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
327 reg1 = 0; reg2 = 0; \
328 ireg = 0; breg = 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 /* for OLD_INDEXING \
375 else if (GET_CODE (addr) == PLUS) \
377 if (GET_CODE (XEXP (addr, 0)) == REG) \
379 reg2 = XEXP (addr, 0); \
380 addr = XEXP (addr, 1); \
382 else if (GET_CODE (XEXP (addr, 1)) == REG) \
384 reg2 = XEXP (addr, 1); \
385 addr = XEXP (addr, 0); \
389 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
390 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
391 || GET_CODE (reg1) == MULT)) \
392 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
393 { breg = reg2; ireg = reg1; } \
394 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
395 { breg = reg1; ireg = reg2; } \
396 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
398 if (GET_CODE (ireg) == MULT) \
399 { scale = INTVAL (XEXP (ireg, 1)); \
400 ireg = XEXP (ireg, 0); } \
401 if (GET_CODE (ireg) == SIGN_EXTEND) \
402 fprintf (FILE, "10(%%pc,%s.w", \
403 reg_names[REGNO (XEXP (ireg, 0))]); \
405 fprintf (FILE, "10(%%pc,%s.l", \
406 reg_names[REGNO (ireg)]); \
407 if (scale != 1) fprintf (FILE, "*%d", scale); \
410 if (ireg != 0 || breg != 0) \
415 output_addr_const (FILE, addr); \
416 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
419 if (ireg != 0 && GET_CODE (ireg) == MULT) \
420 { scale = INTVAL (XEXP (ireg, 1)); \
421 ireg = XEXP (ireg, 0); } \
422 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
423 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
424 else if (ireg != 0) \
425 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
426 if (scale != 1) fprintf (FILE, "*%d", scale); \
430 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
431 { fprintf (FILE, "10(%%pc,%s.w)", \
432 reg_names[REGNO (reg1)]); \
435 output_addr_const (FILE, addr); \
440 /* Override usual definitions of SDB output macros.
441 These definitions differ only in the absence of the period
442 at the beginning of the name of the directive
443 and in the use of `~' as the symbol for the current location. */
445 #define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
446 #define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
447 #define PUT_SDB_VAL(a) \
448 ( fputs ("\tval\t", asm_out_file), \
449 output_addr_const (asm_out_file, (a)), \
450 fputc (';', asm_out_file))
452 #define PUT_SDB_DEF(a) \
453 do { fprintf (asm_out_file, "\tdef\t"); \
454 ASM_OUTPUT_LABELREF (asm_out_file, a); \
455 fprintf (asm_out_file, ";"); } while (0)
457 #define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
458 #define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
459 #define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
460 #define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
461 #define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
462 #define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
463 #define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d;", a)
465 #define PUT_SDB_TAG(a) \
466 do { fprintf (asm_out_file, "\ttag\t"); \
467 ASM_OUTPUT_LABELREF (asm_out_file, a); \
468 fprintf (asm_out_file, ";"); } while (0)
470 #define PUT_SDB_BLOCK_START(LINE) \
471 fprintf (asm_out_file, \
472 "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
475 #define PUT_SDB_BLOCK_END(LINE) \
476 fprintf (asm_out_file, \
477 "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
480 #define PUT_SDB_FUNCTION_START(LINE) \
481 fprintf (asm_out_file, \
482 "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
485 #define PUT_SDB_FUNCTION_END(LINE) \
486 fprintf (asm_out_file, \
487 "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
490 #define PUT_SDB_EPILOGUE_END(NAME) \
491 fprintf (asm_out_file, \
492 "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
495 #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
496 sprintf ((BUFFER), "~%dfake", (NUMBER));
498 #define NO_DOLLAR_IN_LABEL
499 #define NO_DOT_IN_LABEL
501 /* The usual definitions don't work because neither $ nor . is allowed. */
502 #define CONSTRUCTOR_NAME_FORMAT "_GLOBAL_%%I\%%%s"
504 /* Define a few machine-specific details
505 of the implementation of constructors.
507 The __CTORS_LIST__ goes in the .init section. Define CTOR_LIST_BEGIN
508 and CTOR_LIST_END to contribute to the .init section an instruction to
509 push a word containing 0 (or some equivalent of that). */
511 #undef INIT_SECTION_ASM_OP
512 #define INIT_SECTION_ASM_OP "\tsection\t~init"
513 #undef FINI_SECTION_ASM_OP
514 #define FINI_SECTION_ASM_OP "\tsection\t~fini"
515 #undef READONLY_DATA_SECTION_ASM_OP
516 #define READONLY_DATA_SECTION_ASM_OP "\tsection\t~rodata"
518 #define CTOR_LIST_BEGIN \
519 asm (INIT_SECTION_ASM_OP); \
521 #define CTOR_LIST_END CTOR_LIST_BEGIN
523 #define BSS_SECTION_ASM_OP "\tsection\t~bss"
525 #define TARGET_ASM_CONSTRUCTOR m68k_svr3_asm_out_constructor