|
|
1.1 root 1: /* Definitions of target machine for GNU compiler. SONY NEWS-OS 4 version.
2: Copyright (C) 1987, 1989, 1993 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20: #ifndef USE_GAS
21: /* This controls conditionals in m68k.h. */
22: #define MOTOROLA /* Use Motorola syntax rather than "MIT" */
23: #define SGS_NO_LI /* Suppress jump table label usage */
24: #endif
25:
26: #define NO_DOLLAR_IN_LABEL
27: #define NO_DOT_IN_LABEL
28:
29: #include "m68k/m68k.h"
30:
31: /* See m68k.h. 7 means 68020 with 68881. */
32:
33: #define TARGET_DEFAULT 7
34:
35: /* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
36: This will control the use of inline 68881 insns in certain macros. */
37:
38: #define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
39:
40: /* Names to predefine in the preprocessor for this target machine. */
41: /* These are the ones defined by Sony, plus mc68000 for uniformity with
42: GCC on other 68000 systems. */
43:
44: #ifdef MOTOROLA
45: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews700 -D__motorola__ -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
46: #else
47: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews700 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
48: #endif
49:
50: /* These conditionals tested for different submodels,
51: but they were incorrect since they tested the host rather than the target.
52: The choice of model shouldn't actually matter. */
53:
54: #if 0
55: #ifdef news800
56: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews800 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
57: #endif
58: #ifdef news900
59: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews900 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
60: #endif
61: #ifdef news1500
62: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1500 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
63: #endif
64: #ifdef news1700
65: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1700 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
66: #endif
67: #ifdef news1800
68: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1800 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
69: #endif
70: #ifdef news1900
71: #define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1900 -Asystem(unix) -Asystem(bsd) -Acpu(m68k) -Amachine(m68k)"
72: #endif
73: #endif
74:
75: /* Link with libg.a when debugging, for dbx's sake. */
76:
77: #define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} "
78:
79: /* This is BSD, so it wants DBX format. */
80:
81: #define DBX_DEBUGGING_INFO
82:
83: #if 0
84: /* This is to be compatible with types.h.
85: It was found to be necessary with Newsos 3. */
86:
87: #define SIZE_TYPE "long int"
88: #endif
89:
90: /* Override parts of m68k.h to fit Sony's assembler syntax. */
91:
92: #undef BIGGEST_ALIGNMENT
93: #undef CALL_USED_REGISTERS
94: #undef FUNCTION_VALUE
95: #undef LIBCALL_VALUE
96: #undef FUNCTION_PROFILER
97:
98: #ifdef MOTOROLA
99: #undef FUNCTION_PROLOGUE
100: #undef FUNCTION_EPILOGUE
101: #undef REGISTER_NAMES
102: #undef ASM_OUTPUT_REG_PUSH
103: #undef ASM_OUTPUT_REG_POP
104: #undef ASM_OUTPUT_DOUBLE
105: #undef ASM_OUTPUT_SKIP
106: #undef ASM_FORMAT_PRIVATE_NAME
107: #undef PRINT_OPERAND
108: #undef PRINT_OPERAND_ADDRESS
109: #endif
110:
111: #undef ASM_OUTPUT_ALIGN
112:
113: /* There is no point aligning anything to a rounder boundary than this. */
114: #define BIGGEST_ALIGNMENT 32
115:
116: /* A bitfield declared as `int' forces `int' alignment for the struct. */
117: #define PCC_BITFIELD_TYPE_MATTERS 1
118:
119: /* NEWS makes d2, d3, fp2 and fp3 unsaved registers, unlike the Sun system. */
120:
121: #define CALL_USED_REGISTERS \
122: {1, 1, 1, 1, 0, 0, 0, 0, \
123: 1, 1, 0, 0, 0, 0, 0, 1, \
124: 1, 1, 1, 1, 0, 0, 0, 0}
125:
126: /* NEWS returns floats and doubles in fp0, not d0/d1. */
127:
128: #define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
129:
130: #define LIBCALL_VALUE(MODE) \
131: gen_rtx (REG, (MODE), \
132: ((TARGET_68881 \
133: && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode)) \
134: ? 16 : 0))
135:
136: #define ASM_OUTPUT_ALIGN(FILE,LOG) \
137: fprintf (FILE, "\t.align %d\n", (LOG))
138:
139: #ifdef MOTOROLA
140:
141: /* Don't try to define `gcc_compiled.' since the assembler does not
142: accept symbols with periods. This is no real loss since GDB only
143: really needs it for parms passed in registers. */
144: #define ASM_IDENTIFY_GCC(FILE)
145:
146: #define FUNCTION_PROLOGUE(FILE, SIZE) \
147: { register int regno; \
148: register int mask = 0; \
149: extern char call_used_regs[]; \
150: int fsize = ((SIZE) + 3) & -4; \
151: if (frame_pointer_needed) \
152: { if (fsize < 0x8000) \
153: fprintf (FILE, "\tlink fp,#%d\n", -fsize); \
154: else if (TARGET_68020) \
155: fprintf (FILE, "\tlink.l fp,#%d\n", -fsize); \
156: else \
157: fprintf (FILE, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize);\
158: } \
159: else if (fsize) \
160: { \
161: int amt = fsize + 4; \
162: /* Adding negative number is faster on the 68040. */ \
163: if (fsize + 4 < 0x8000) \
164: asm_fprintf (FILE, "\tadd.w %0I%d,%Rsp\n", - amt); \
165: else \
166: asm_fprintf (FILE, "\tadd.l %0I%d,%Rsp\n", - amt); \
167: } \
168: for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
169: if (regs_ever_live[regno] && ! call_used_regs[regno]) \
170: mask |= 1 << (regno - 16); \
171: if (mask != 0) \
172: fprintf (FILE, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff); \
173: mask = 0; \
174: for (regno = 0; regno < 16; regno++) \
175: if (regs_ever_live[regno] && ! call_used_regs[regno]) \
176: mask |= 1 << (15 - regno); \
177: if (frame_pointer_needed) \
178: mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
179: if (exact_log2 (mask) >= 0) \
180: fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
181: else if (mask) fprintf (FILE, "\tmovem.l #0x%x,-(sp)\n", mask); }
182:
183: #define FUNCTION_PROFILER(FILE, LABEL_NO) \
184: fprintf (FILE, "\tmove.l #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
185:
186: #define FUNCTION_EPILOGUE(FILE, SIZE) \
187: { register int regno; \
188: register int mask, fmask; \
189: register int nregs; \
190: int offset, foffset; \
191: extern char call_used_regs[]; \
192: int fsize = ((SIZE) + 3) & -4; \
193: int big = 0; \
194: nregs = 0; fmask = 0; \
195: for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
196: if (regs_ever_live[regno] && ! call_used_regs[regno]) \
197: { nregs++; fmask |= 1 << (23 - regno); } \
198: foffset = nregs * 12; \
199: nregs = 0; mask = 0; \
200: if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
201: for (regno = 0; regno < 16; regno++) \
202: if (regs_ever_live[regno] && ! call_used_regs[regno]) \
203: { nregs++; mask |= 1 << regno; } \
204: offset = foffset + nregs * 4; \
205: if (offset + fsize >= 0x8000 \
206: && frame_pointer_needed \
207: && (mask || fmask)) \
208: { fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
209: fsize = 0, big = 1; } \
210: if (exact_log2 (mask) >= 0) { \
211: if (big) \
212: fprintf (FILE, "\tmove.l (-%d,fp,a0.l),%s\n", \
213: offset + fsize, reg_names[exact_log2 (mask)]); \
214: else if (! frame_pointer_needed) \
215: fprintf (FILE, "\tmove.l (sp)+,%s\n", \
216: reg_names[exact_log2 (mask)]); \
217: else \
218: fprintf (FILE, "\tmove.l (-%d,fp),%s\n", \
219: offset + fsize, reg_names[exact_log2 (mask)]); } \
220: else if (mask) { \
221: if (big) \
222: fprintf (FILE, "\tmovem.l (-%d,fp,a0.l),#0x%x\n", \
223: offset + fsize, mask); \
224: else if (! frame_pointer_needed) \
225: fprintf (FILE, "\tmovem.l (sp)+,#0x%x\n", mask); \
226: else \
227: fprintf (FILE, "\tmovem.l (-%d,fp),#0x%x\n", \
228: offset + fsize, mask); } \
229: if (fmask) { \
230: if (big) \
231: fprintf (FILE, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n", \
232: foffset + fsize, fmask); \
233: else if (! frame_pointer_needed) \
234: fprintf (FILE, "\tfmovem.x (sp)+,#0x%x\n", fmask); \
235: else \
236: fprintf (FILE, "\tfmovem.x (-%d,fp),#0x%x\n", \
237: foffset + fsize, fmask); } \
238: if (frame_pointer_needed) \
239: fprintf (FILE, "\tunlk fp\n"); \
240: else if (fsize) \
241: { \
242: if (fsize + 4 < 0x8000) \
243: fprintf (FILE, "\tadd.w #%d,sp\n", fsize + 4); \
244: else \
245: fprintf (FILE, "\tadd.l #%d,sp\n", fsize + 4); \
246: } \
247: if (current_function_pops_args) \
248: fprintf (FILE, "\trtd #%d\n", current_function_pops_args); \
249: else fprintf (FILE, "\trts\n"); }
250:
251: /* Difference from m68k.h is in `fp' instead of `a6'. */
252:
253: #define REGISTER_NAMES \
254: {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
255: "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
256: "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7"}
257:
258: /* This is how to output an insn to push a register on the stack.
259: It need not be very fast code. */
260:
261: #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
262: fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[REGNO])
263:
264: /* This is how to output an insn to pop a register from the stack.
265: It need not be very fast code. */
266:
267: #define ASM_OUTPUT_REG_POP(FILE,REGNO) \
268: fprintf (FILE, "\tmove.l (sp)+,%s\n", reg_names[REGNO])
269:
270: #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
271: do { char dstr[30]; \
272: REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
273: fprintf (FILE, "\t.double 0d%s\n", dstr); \
274: } while (0)
275:
276: #define ASM_OUTPUT_SKIP(FILE,SIZE) \
277: fprintf (FILE, "\t.space %u\n", (SIZE))
278:
279: #if 0
280: /* The NEWS assembler in version 3.4 complains about fmove.d, but this
281: macro proved not to work right. 3.4 is old, so forget about it. */
282: #define ASM_OUTPUT_OPCODE(FILE, STRING) \
283: { \
284: if (!strncmp (STRING, "fmove.d", 7) \
285: && CONSTANT_P (operands[1])) \
286: { \
287: fprintf (FILE, "fmove.x"); \
288: STRING += 7; \
289: } \
290: }
291: #endif
292:
293: /* Store in OUTPUT a string (made with alloca) containing
294: an assembler-name for a local static variable named NAME.
295: LABELNO is an integer which is different for each call. */
296:
297: #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
298: ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 13), \
299: sprintf ((OUTPUT), "%s$$$%d", (NAME), (LABELNO)))
300:
301: #define PRINT_OPERAND(FILE, X, CODE) \
302: { if (CODE == '.') fprintf (FILE, "."); \
303: else if (CODE == '#') fprintf (FILE, "#"); \
304: else if (CODE == '-') fprintf (FILE, "-(sp)"); \
305: else if (CODE == '+') fprintf (FILE, "(sp)+"); \
306: else if (CODE == '@') fprintf (FILE, "(sp)"); \
307: else if (CODE == '!') fprintf (FILE, "fpcr"); \
308: else if (CODE == '$') {if (TARGET_68040_ONLY) fprintf (FILE, "s");} \
309: else if (CODE == '&') {if (TARGET_68040_ONLY) fprintf (FILE, "d");} \
310: else if (CODE == '/') \
311: ; \
312: else if (GET_CODE (X) == REG) \
313: fprintf (FILE, "%s", reg_names[REGNO (X)]); \
314: else if (GET_CODE (X) == MEM) \
315: output_address (XEXP (X, 0)); \
316: else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
317: { REAL_VALUE_TYPE r; \
318: REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
319: if (CODE == 'f') \
320: { char dstr[30]; \
321: REAL_VALUE_TO_DECIMAL (r, "%.9e", dstr); \
322: fprintf (FILE, "#0f%s", dstr); \
323: } \
324: else \
325: { long l; \
326: REAL_VALUE_TO_TARGET_SINGLE (r, l); \
327: fprintf (FILE, "#0x%x", l); \
328: }} \
329: else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \
330: { REAL_VALUE_TYPE r; \
331: REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
332: ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
333: else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
334: { REAL_VALUE_TYPE r; char dstr[30]; \
335: REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
336: REAL_VALUE_TO_DECIMAL (r, "%.20e", dstr ); \
337: fprintf (FILE, "#0d%s", dstr); } \
338: else if (CODE == 'b') output_addr_const (FILE, X); \
339: else { putc ('#', FILE); output_addr_const (FILE, X); }}
340:
341: #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
342: { register rtx reg1, reg2, breg, ireg; \
343: register rtx addr = ADDR; \
344: rtx offset; \
345: switch (GET_CODE (addr)) \
346: { \
347: case REG: \
348: fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
349: break; \
350: case PRE_DEC: \
351: fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
352: break; \
353: case POST_INC: \
354: fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
355: break; \
356: case PLUS: \
357: reg1 = 0; reg2 = 0; \
358: ireg = 0; breg = 0; \
359: offset = 0; \
360: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
361: { \
362: offset = XEXP (addr, 0); \
363: addr = XEXP (addr, 1); \
364: } \
365: else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
366: { \
367: offset = XEXP (addr, 1); \
368: addr = XEXP (addr, 0); \
369: } \
370: if (GET_CODE (addr) != PLUS) ; \
371: else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
372: { \
373: reg1 = XEXP (addr, 0); \
374: addr = XEXP (addr, 1); \
375: } \
376: else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
377: { \
378: reg1 = XEXP (addr, 1); \
379: addr = XEXP (addr, 0); \
380: } \
381: else if (GET_CODE (XEXP (addr, 0)) == MULT) \
382: { \
383: reg1 = XEXP (addr, 0); \
384: addr = XEXP (addr, 1); \
385: } \
386: else if (GET_CODE (XEXP (addr, 1)) == MULT) \
387: { \
388: reg1 = XEXP (addr, 1); \
389: addr = XEXP (addr, 0); \
390: } \
391: else if (GET_CODE (XEXP (addr, 0)) == REG) \
392: { \
393: reg1 = XEXP (addr, 0); \
394: addr = XEXP (addr, 1); \
395: } \
396: else if (GET_CODE (XEXP (addr, 1)) == REG) \
397: { \
398: reg1 = XEXP (addr, 1); \
399: addr = XEXP (addr, 0); \
400: } \
401: if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
402: || GET_CODE (addr) == SIGN_EXTEND) \
403: { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
404: if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
405: if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
406: || GET_CODE (reg1) == MULT)) \
407: || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
408: { breg = reg2; ireg = reg1; } \
409: else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
410: { breg = reg1; ireg = reg2; } \
411: if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
412: { int scale = 1; \
413: if (GET_CODE (ireg) == MULT) \
414: { scale = INTVAL (XEXP (ireg, 1)); \
415: ireg = XEXP (ireg, 0); } \
416: if (GET_CODE (ireg) == SIGN_EXTEND) \
417: fprintf (FILE, "(L%d.b,pc,%s.w", \
418: CODE_LABEL_NUMBER (XEXP (addr, 0)), \
419: reg_names[REGNO (XEXP (ireg, 0))]); \
420: else \
421: fprintf (FILE, "(L%d.b,pc,%s.l", \
422: CODE_LABEL_NUMBER (XEXP (addr, 0)), \
423: reg_names[REGNO (ireg)]); \
424: if (scale != 1) fprintf (FILE, "*%d", scale); \
425: putc (')', FILE); \
426: break; } \
427: if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
428: { fprintf (FILE, "(L%d.b,pc,%s.l", \
429: CODE_LABEL_NUMBER (XEXP (addr, 0)), \
430: reg_names[REGNO (breg)]); \
431: putc (')', FILE); \
432: break; } \
433: if (ireg != 0 || breg != 0) \
434: { int scale = 1; \
435: if (breg == 0) \
436: abort (); \
437: if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
438: fprintf (FILE, "("); \
439: if (addr != 0) { \
440: output_addr_const (FILE, addr); \
441: putc (',', FILE); } \
442: fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
443: if (ireg != 0) \
444: putc (',', FILE); \
445: if (ireg != 0 && GET_CODE (ireg) == MULT) \
446: { scale = INTVAL (XEXP (ireg, 1)); \
447: ireg = XEXP (ireg, 0); } \
448: if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
449: fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
450: else if (ireg != 0) \
451: fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
452: if (scale != 1) fprintf (FILE, "*%d", scale); \
453: putc (')', FILE); \
454: break; \
455: } \
456: else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
457: { fprintf (FILE, "(L%d.b,pc,%s.l)", \
458: CODE_LABEL_NUMBER (XEXP (addr, 0)), \
459: reg_names[REGNO (reg1)]); \
460: break; } \
461: default: \
462: if (GET_CODE (addr) == CONST_INT \
463: && INTVAL (addr) < 0x8000 \
464: && INTVAL (addr) >= -0x8000) \
465: fprintf (FILE, "%d.w", INTVAL (addr)); \
466: else \
467: output_addr_const (FILE, addr); \
468: }}
469:
470: #else /* Using GAS, which uses the MIT assembler syntax, like a Sun. */
471:
472: #define FUNCTION_PROFILER(FILE, LABEL_NO) \
473: fprintf (FILE, "\tmovl #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
474:
475: #endif /* MOTOROLA */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.