|
|
1.1 root 1: /* Definitions of target machine for GNU compiler for m68k targets using
2: assemblers derived from AT&T "SGS" releases.
3: Copyright (C) 1991, 1993 Free Software Foundation, Inc.
4: Written by Fred Fish ([email protected])
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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21:
22: /* Control assembler-syntax conditionals in m68k.md and conditionals in
23: m68k.h. Note that some systems may also require SGS_SWAP_W and/or
24: SGS_SWITCH_TABLES to be defined as well. */
25:
26: #define MOTOROLA /* Use Motorola syntax rather than "MIT" */
27: #define SGS /* Uses SGS assembler */
28: #define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
29:
30: #include "m68k/m68k.h"
31:
32: /* SGS specific assembler pseudo ops. */
33:
34: #define BYTE_ASM_OP ".byte"
35: #define WORD_ASM_OP ".short"
36: #define LONG_ASM_OP ".long"
37: #define SPACE_ASM_OP ".space"
38: #define ALIGN_ASM_OP ".align"
39: #undef GLOBAL_ASM_OP
40: #define GLOBAL_ASM_OP ".global"
41: #define SWBEG_ASM_OP ".swbeg"
42: #define SET_ASM_OP ".set"
43:
44: #define UNALIGNED_SHORT_ASM_OP ".short" /* Used in dwarfout.c */
45: #define UNALIGNED_INT_ASM_OP ".long" /* Used in dwarfout.c */
46:
47: #define ASM_PN_FORMAT "%s_%d" /* Format for private names */
48:
49: /* Here are four prefixes that are used by asm_fprintf to
50: facilitate customization for alternate assembler syntaxes.
51: Machines with no likelihood of an alternate syntax need not
52: define these and need not use asm_fprintf. */
53:
54: /* The prefix for register names. Note that REGISTER_NAMES
55: is supposed to include this prefix. Also note that this is NOT an
56: fprintf format string, it is a literal string */
57:
58: #undef REGISTER_PREFIX
59: #define REGISTER_PREFIX "%"
60:
61: /* The prefix for local (compiler generated) labels.
62: These labels will not appear in the symbol table. */
63:
64: #undef LOCAL_LABEL_PREFIX
65: #define LOCAL_LABEL_PREFIX "."
66:
67: /* The prefix to add to user-visible assembler symbols. */
68:
69: #undef USER_LABEL_PREFIX
70: #define USER_LABEL_PREFIX ""
71:
72: /* The prefix for immediate operands. */
73:
74: #undef IMMEDIATE_PREFIX
75: #define IMMEDIATE_PREFIX "&"
76:
77: /* How to refer to registers in assembler output.
78: This sequence is indexed by compiler's hard-register-number.
79: Motorola format uses different register names than defined in m68k.h.
80: We also take this chance to convert 'a6' to 'fp' */
81:
82: #undef REGISTER_NAMES
83:
84: #ifndef SUPPORT_SUN_FPA
85:
86: #define REGISTER_NAMES \
87: {"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
88: "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
89: "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
90:
91: #else /* SUPPORTED_SUN_FPA */
92:
93: #define REGISTER_NAMES \
94: {"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
95: "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
96: "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", \
97: "%fpa0", "%fpa1", "%fpa2", "%fpa3", "%fpa4", "%fpa5", "%fpa6","%fpa7", \
98: "%fpa8", "%fpa9", "%fpa10","%fpa11","%fpa12","%fpa13","%fpa14","%fpa15", \
99: "%fpa16","%fpa17","%fpa18","%fpa19","%fpa20","%fpa21","%fpa22","%fpa23", \
100: "%fpa24","%fpa25","%fpa26","%fpa27","%fpa28","%fpa29","%fpa30","%fpa31" }
101:
102: #endif /* defined SUPPORT_SUN_FPA */
103:
104: /* When using an SGS assembler, modify the name of the artificial label which
105: identifies this file as having been compiled with gcc, and the macro that
106: emits such a label in the assembly output, to use '%' rather than '.' */
107:
108: #define ASM_IDENTIFY_GCC(FILE) \
109: { fprintf ((FILE), "%s:\n", "gcc2_compiled%"); }
110:
111: /* This is how to output an assembler line defining an `int' constant. */
112: /* The SGS assembler doesn't understand ".word". */
113:
114: #undef ASM_OUTPUT_SHORT
115: #define ASM_OUTPUT_SHORT(FILE,VALUE) \
116: ( fprintf ((FILE), "\t%s ", WORD_ASM_OP), \
117: output_addr_const ((FILE), (VALUE)), \
118: fprintf ((FILE), "\n"))
119:
120: #undef ASM_OUTPUT_LONG_DOUBLE
121: #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
122: do { long l[3]; \
123: REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
124: fprintf ((FILE), "\t%s 0x%x,0x%x,0x%x\n", LONG_ASM_OP, \
125: l[0], l[1], l[2]); \
126: } while (0)
127:
128: /* This is how to output an assembler line defining a `double' constant. */
129:
130: #undef ASM_OUTPUT_DOUBLE
131: #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
132: do { long l[2]; \
133: REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
134: fprintf ((FILE), "\t%s 0x%x,0x%x\n", LONG_ASM_OP, \
135: l[0], l[1]); \
136: } while (0)
137:
138: /* This is how to output an assembler line defining a `float' constant. */
139:
140: #undef ASM_OUTPUT_FLOAT
141: #define ASM_OUTPUT_FLOAT(FILE,VALUE) \
142: do { long l; \
143: REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
144: fprintf ((FILE), "\t%s 0x%x\n", LONG_ASM_OP, l); \
145: } while (0)
146:
147: /* This is how to output an assembler line that says to advance the
148: location counter to a multiple of 2**LOG bytes. */
149:
150: #undef ASM_OUTPUT_ALIGN
151: #define ASM_OUTPUT_ALIGN(FILE,LOG) \
152: if ((LOG) > 0) \
153: fprintf ((FILE), "\t%s \t%u\n", ALIGN_ASM_OP, 1 << (LOG)); \
154: else if ((LOG) > 31) \
155: abort ();
156:
157: /* The routine used to output null terminated string literals. We cannot
158: use the ".string" pseudo op, because it silently truncates strings to
159: 1023 bytes. There is no "partial string op" which works like ".string"
160: but doesn't append a null byte, so we can't chop the input string up
161: into small pieces and use that. Our only remaining alternative is to
162: output the string one byte at a time. */
163:
164: #define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
1.1.1.2 ! root 165: do { \
1.1 root 166: register int sp = 0, lp = 0, ch; \
167: fprintf ((FILE), "\t%s ", BYTE_ASM_OP); \
168: do { \
169: ch = (PTR)[sp]; \
170: if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \
171: { \
172: fprintf ((FILE), "'%c", ch); \
173: } \
174: else \
175: { \
176: fprintf ((FILE), "0x%x", ch); \
177: } \
178: if (++sp < (LEN)) \
179: { \
180: if ((sp % 10) == 0) \
181: { \
182: fprintf ((FILE), "\n\t%s ", BYTE_ASM_OP); \
183: } \
184: else \
185: { \
186: putc (',', (FILE)); \
187: } \
188: } \
189: } while (sp < (LEN)); \
190: putc ('\n', (FILE)); \
1.1.1.2 ! root 191: } while (0)
1.1 root 192:
193:
194: /* SGS based assemblers don't understand #NO_APP and #APP, so just don't
195: bother emitting them. */
196:
197: #undef ASM_APP_ON
198: #define ASM_APP_ON ""
199:
200: #undef ASM_APP_OFF
201: #define ASM_APP_OFF ""
202:
203: /* When using SGS derived assemblers, change the "MIT" or "MOTOROLA"
204: to "SGS/AT&T" */
205:
206: #undef TARGET_VERSION
207: #define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T syntax)");
208:
209: /* Use proper assembler syntax for these macros. */
210: #undef ASM_OUTPUT_REG_PUSH
211: #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
212: asm_fprintf (FILE, "\t%Omove.l %s,-(%Rsp)\n", reg_names[REGNO])
213:
214: #undef ASM_OUTPUT_REG_POP
215: #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
216: asm_fprintf (FILE, "\t%Omove.l (%Rsp)+,%s\n", reg_names[REGNO])
217:
218: #undef ASM_OUTPUT_FLOAT_OPERAND
219: #define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
220: do { long l; \
221: REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
222: asm_fprintf ((FILE), "%I0x%x", l); \
223: } while (0)
224:
225: #undef ASM_OUTPUT_DOUBLE_OPERAND
226: #define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
227: do { long l[2]; \
228: REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
229: asm_fprintf ((FILE), "%I0x%x%08x", l[0], l[1]); \
230: } while (0)
231:
232: /* How to output a block of SIZE zero bytes. Note that the `space' pseudo,
233: when used in the text segment, causes SGS assemblers to output nop insns
234: rather than 0s, so we set ASM_NO_SKIP_IN_TEXT to prevent this. */
235:
236: #define ASM_NO_SKIP_IN_TEXT 1
237:
238: #undef ASM_OUTPUT_SKIP
239: #define ASM_OUTPUT_SKIP(FILE,SIZE) \
240: fprintf (FILE, "\t%s %u\n", SPACE_ASM_OP, (SIZE))
241:
242: /* Translate Motorola opcodes such as `jbeq' into SGS opcodes such
243: as `beq.w'.
244: Delete the `e' in `move...' and `fmove'.
245: Change `ftst' to `ftest'.
246: Change `fbne' to `fbneq'
247: Change `fsne' to `fsneq'
248: Change `divsl' to `tdivs' (32/32 -> 32r:32q)
249: Change `divul' to `tdivu' (32/32 -> 32r:32q)
250: Optionally change swap to swap.w.
251: */
252:
253: #ifdef SGS_SWAP_W
254: #define ASM_OUTPUT_OPCODE(FILE, PTR) \
255: { \
256: extern int flag_pic; \
257: if (!strncmp ((PTR), "jbsr", 4)) \
258: { if (flag_pic) \
259: fprintf ((FILE), "bsr"); \
260: else \
261: fprintf ((FILE), "jsr"); \
262: (PTR) += 4; } \
263: else if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
264: { ++(PTR); \
265: while (*(PTR) != ' ') \
266: { putc (*(PTR), (FILE)); ++(PTR); } \
267: fprintf ((FILE), ".w"); } \
268: else if ((PTR)[0] == 's') \
269: { \
270: if (!strncmp ((PTR), "swap", 4)) \
271: { fprintf ((FILE), "swap.w"); (PTR) += 4; } \
272: } \
273: /* FMOVE ==> FMOV, (and F%& F%$ translations) */ \
274: else if ((PTR)[0] == 'f') \
275: { \
276: if (!strncmp ((PTR), "fmove", 5)) \
277: { fprintf ((FILE), "fmov"); (PTR) += 5; } \
278: else if (!strncmp ((PTR), "ftst", 4)) \
279: { fprintf ((FILE), "ftest"); (PTR) += 4; } \
280: else if (!strncmp ((PTR), "fbne", 4)) \
281: { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
282: else if (!strncmp ((PTR), "fsne", 4)) \
283: { fprintf ((FILE), "fsneq"); (PTR) += 4; } \
284: else if (!strncmp ((PTR), "f%$move", 7)) \
285: { (PTR) += 7; \
286: if (TARGET_68040_ONLY) \
287: fprintf ((FILE), "fsmov"); \
288: else fprintf ((FILE), "fmov"); } \
289: else if (!strncmp ((PTR), "f%&move", 7)) \
290: { (PTR) += 7; \
291: if (TARGET_68040_ONLY) \
292: fprintf ((FILE), "fdmov"); \
293: else fprintf ((FILE), "fmov"); } \
294: } \
295: /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
296: else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
297: && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
298: { fprintf ((FILE), "mov"); (PTR) += 4; \
299: if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
300: || (PTR)[0] == 'c') (PTR)++; } \
301: /* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
302: else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
303: && (PTR)[2] == 'b') \
304: { fprintf ((FILE), "sub"); (PTR) += 3; \
305: if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
306: || (PTR)[0] == 'a') (PTR)++; } \
307: /* CMP, CMPA, CMPI, CMPM ==> CMP */ \
308: else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
309: && (PTR)[2] == 'p') \
310: { fprintf ((FILE), "cmp"); (PTR) += 3; \
311: if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
312: || (PTR)[0] == 'm') (PTR)++; } \
313: /* DIVSL ==> TDIVS */ \
314: else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
315: && (PTR)[2] == 'v' && (PTR)[3] == 's' \
316: && (PTR)[4] == 'l') \
317: { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
318: /* DIVUL ==> TDIVU */ \
319: else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
320: && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
321: && (PTR)[4] == 'l') \
322: { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
323: }
324:
325: #else /* not SGS_SWAP_W */
326:
327: #define ASM_OUTPUT_OPCODE(FILE, PTR) \
328: { \
329: extern int flag_pic; \
330: if (!strncmp ((PTR), "jbsr", 4)) \
331: { if (flag_pic) \
332: fprintf ((FILE), "bsr"); \
333: else \
334: fprintf ((FILE), "jsr"); \
335: (PTR) += 4; } \
336: else if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
337: { ++(PTR); \
338: while (*(PTR) != ' ') \
339: { putc (*(PTR), (FILE)); ++(PTR); } \
340: fprintf ((FILE), ".w"); } \
341: /* FMOVE ==> FMOV, (and F%& F%$ translations) */ \
342: else if ((PTR)[0] == 'f') \
343: { \
344: if (!strncmp ((PTR), "fmove", 5)) \
345: { fprintf ((FILE), "fmov"); (PTR) += 5; } \
346: else if (!strncmp ((PTR), "ftst", 4)) \
347: { fprintf ((FILE), "ftest"); (PTR) += 4; } \
348: else if (!strncmp ((PTR), "fbne", 4)) \
349: { fprintf ((FILE), "fbneq"); (PTR) += 4; } \
350: else if (!strncmp ((PTR), "fsne", 4)) \
351: { fprintf ((FILE), "fsneq"); (PTR) += 4; } \
352: else if (!strncmp ((PTR), "f%$move", 7)) \
353: { (PTR) += 7; \
354: if (TARGET_68040_ONLY) \
355: fprintf ((FILE), "fsmov"); \
356: else fprintf ((FILE), "fmov"); } \
357: else if (!strncmp ((PTR), "f%&move", 7)) \
358: { (PTR) += 7; \
359: if (TARGET_68040_ONLY) \
360: fprintf ((FILE), "fdmov"); \
361: else fprintf ((FILE), "fmov"); } \
362: } \
363: /* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
364: else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
365: && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
366: { fprintf ((FILE), "mov"); (PTR) += 4; \
367: if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \
368: || (PTR)[0] == 'c') (PTR)++; } \
369: /* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
370: else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
371: && (PTR)[2] == 'b') \
372: { fprintf ((FILE), "sub"); (PTR) += 3; \
373: if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \
374: || (PTR)[0] == 'a') (PTR)++; } \
375: /* CMP, CMPA, CMPI, CMPM ==> CMP */ \
376: else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
377: && (PTR)[2] == 'p') \
378: { fprintf ((FILE), "cmp"); (PTR) += 3; \
379: if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
380: || (PTR)[0] == 'm') (PTR)++; } \
381: /* DIVSL ==> TDIVS */ \
382: else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
383: && (PTR)[2] == 'v' && (PTR)[3] == 's' \
384: && (PTR)[4] == 'l') \
385: { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
386: /* DIVUL ==> TDIVU */ \
387: else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
388: && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
389: && (PTR)[4] == 'l') \
390: { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
391: }
392:
393: #endif /* not SGS_SWAP_W */
394:
395: /* This macro outputs the label at the start of a switch table. The
396: ".swbeg <N>" is an assembler directive that causes the switch table
397: size to be inserted into the object code so that disassemblers, for
398: example, can identify that it is the start of a switch table. */
399:
400: #define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
401: fprintf ((FILE), "\t%s &%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1));
402:
403: #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
404: do { \
405: ASM_OUTPUT_BEFORE_CASE_LABEL((FILE),(PREFIX),(NUM),(TABLE)); \
406: ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM)); \
407: } while (0)
408:
409: /* At end of a switch table, define LDnnn iff the symbol LInnn was defined.
410: Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)"
411: fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results
412: we want. This difference can be accommodated by making the assembler
413: define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other
414: string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END
415: macro. */
416:
417: #undef ASM_OUTPUT_CASE_END
418: #define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
419: { if (switch_table_difference_label_flag) \
420: asm_fprintf (FILE, "\t%s %LLD%d,%LL%d-%LLI%d-2.b\n",\
421: SET_ASM_OP, (NUM), (NUM), (NUM)) \
422: switch_table_difference_label_flag = 0; }
423:
424: int switch_table_difference_label_flag;
425:
426: /* This is how to output an element of a case-vector that is relative. */
427:
428: #undef ASM_OUTPUT_ADDR_DIFF_ELT
429: #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
430: asm_fprintf (FILE, "\t%s %LL%d-%LL%d\n", WORD_ASM_OP, VALUE, REL)
431:
432: /* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to
433: keep switch tables in the text section. */
434:
435: #define JUMP_TABLES_IN_TEXT_SECTION 1
436:
437: /* Store in OUTPUT a string (made with alloca) containing
438: an assembler-name for a local static variable named NAME.
439: LABELNO is an integer which is different for each call. */
440:
441: #undef ASM_FORMAT_PRIVATE_NAME
442: #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
443: ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
444: sprintf ((OUTPUT), ASM_PN_FORMAT, (NAME), (LABELNO)))
445:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.