GCC with patches for Dreamcast
修订版 | beb3b34a38e833681c483638512e3baf1057d140 (tree) |
---|---|
时间 | 1992-01-19 13:47:58 |
作者 | Richard Stallman <rms@gnu....> |
Commiter | Richard Stallman |
Initial revision
From-SVN: r218
@@ -0,0 +1,603 @@ | ||
1 | +/* Definitions of target machine for GNU compiler. | |
2 | + Charles River Data Systems UNiverse/32 | |
3 | + | |
4 | + Written by Gary E. Miller | |
5 | + bug reports to Gary_Edmunds_Miller@cup.portal.com | |
6 | + | |
7 | + Copyright (C) 1987 Free Software Foundation, Inc. | |
8 | + | |
9 | +This file is part of GNU CC. | |
10 | + | |
11 | +GNU CC is free software; you can redistribute it and/or modify | |
12 | +it under the terms of the GNU General Public License as published by | |
13 | +the Free Software Foundation; either version 2, or (at your option) | |
14 | +any later version. | |
15 | + | |
16 | +GNU CC is distributed in the hope that it will be useful, | |
17 | +but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | +GNU General Public License for more details. | |
20 | + | |
21 | +You should have received a copy of the GNU General Public License | |
22 | +along with GNU CC; see the file COPYING. If not, write to | |
23 | +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
24 | + | |
25 | +#define MOTOROLA /* Use Motorola syntax rather than "MIT" */ | |
26 | +#define SGS /* Uses SGS assembler */ | |
27 | +#define SGS_SWITCH_TABLES /* Different switch table handling */ | |
28 | +#define CRDS /* Charles River Data Systems assembler */ | |
29 | + | |
30 | +#include "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 | +#error This doesn't define STRUCTURE_SIZE_BOUNDARY | |
37 | + | |
38 | +/* See m68k.h. 0 means 680[01]0 with no 68881. */ | |
39 | + | |
40 | +#undef TARGET_DEFAULT | |
41 | +#define TARGET_DEFAULT 0 | |
42 | + | |
43 | +/* special flags to the unos assembler. */ | |
44 | + | |
45 | +#undef ASM_SPEC | |
46 | +#define ASM_SPEC "-g" | |
47 | + | |
48 | +#undef LIB_SPEC | |
49 | +#define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}" | |
50 | + | |
51 | +#undef STARTFILE_SPEC | |
52 | +#define STARTFILE_SPEC \ | |
53 | + "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}" | |
54 | + | |
55 | +/* CC1 spec */ | |
56 | +#if 0 | |
57 | +/* c.sac only used in _s_call_r() in libunos.a and malloc() in libmalloc.a */ | |
58 | +/* so we do not need to bother ! */ | |
59 | +#define CC1_SPEC "-fpcc-struct-return" | |
60 | +#endif | |
61 | + | |
62 | +/* -O2 for MAX optimization */ | |
63 | +#undef CC1_SPEC | |
64 | +#define CC1_SPEC "%{O2:-fstrength-reduce}" | |
65 | + | |
66 | +/* cpp has to support a #sccs directive for the /usr/include files */ | |
67 | + | |
68 | +#define SCCS_DIRECTIVE | |
69 | + | |
70 | +/* Make output for SDB. */ | |
71 | + | |
72 | +/* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */ | |
73 | + | |
74 | +/* UNOS has vprintf() */ | |
75 | + | |
76 | +#define HAVE_VPRINTF | |
77 | + | |
78 | +/* UNOS need stack probe :-( */ | |
79 | + | |
80 | +#define HAVE_probe 1 | |
81 | +#define gen_probe() gen_rtx(ASM_INPUT, VOIDmode, "tstb -2048(sp)\t;probe\n") | |
82 | + | |
83 | +/* use memcpy, memset instead of bcopy, etc. */ | |
84 | + | |
85 | +#define TARGET_MEM_FUNCTIONS | |
86 | + | |
87 | +/* Don't try to define `gcc_compiled.' since the assembler might not | |
88 | + accept symbols with periods and GDB doesn't run on this machine anyway. */ | |
89 | +#define ASM_IDENTIFY_GCC(FILE) | |
90 | + | |
91 | +/* Define __HAVE_68881__ in preprocessor if -m68881 is specified. | |
92 | + This will control the use of inline 68881 insns in certain macros. */ | |
93 | + | |
94 | +#undef CPP_SPEC | |
95 | +#define CPP_SPEC "%{m68881:-D__HAVE_68881__}" | |
96 | + | |
97 | +/* Names to predefine in the preprocessor for this target machine. */ | |
98 | + | |
99 | +#undef CPP_PREDEFINES | |
100 | +#define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix" | |
101 | + | |
102 | +/* Register in which address to store a structure value | |
103 | + is passed to a function. */ | |
104 | +/* unos uses ".comm c.sac" returns &c.sac in d0 */ | |
105 | +/* make pointer to c.sac ? | |
106 | +#undef STRUCT_VALUE_REGNUM | |
107 | +#define STRUCT_VALUE gen_rtx(MEM, Pmode, gen_rtx( , , ) ) | |
108 | +*/ | |
109 | + | |
110 | +#define EXTRA_SECTIONS in_bss | |
111 | + | |
112 | +#define EXTRA_SECTION_FUNCTIONS \ | |
113 | +void \ | |
114 | +bss_section () \ | |
115 | +{ \ | |
116 | + if (in_section != in_bss) \ | |
117 | + { \ | |
118 | + fprintf (asm_out_file, ".bss\n"); \ | |
119 | + in_section = in_bss; \ | |
120 | + } \ | |
121 | +} | |
122 | + | |
123 | +/* Specify how to pad function arguments. | |
124 | + Value should be `upward', `downward' or `none'. | |
125 | + Same as the default, except no padding for large or variable-size args. */ | |
126 | + | |
127 | +#define FUNCTION_ARG_PADDING(MODE, TYPE) \ | |
128 | + (((MODE) == BLKmode \ | |
129 | + ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ | |
130 | + && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \ | |
131 | + : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \ | |
132 | + ? downward : none) | |
133 | + | |
134 | +/* Override part of the obstack macros. */ | |
135 | + | |
136 | +#define __PTR_TO_INT(P) ((int)(P)) | |
137 | +#define __INT_TO_PTR(P) ((char *)(P)) | |
138 | + | |
139 | +/* Override parts of m68k.h to fit the CRuDS assembler. */ | |
140 | + | |
141 | +#undef TARGET_VERSION | |
142 | +#define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)"); | |
143 | + | |
144 | +/* Specify extra dir to search for include files. */ | |
145 | +#define SYSTEM_INCLUDE_DIR "/include" | |
146 | + | |
147 | +/* Control the assembler format that we output. */ | |
148 | + | |
149 | +/* Output at beginning of assembler file. */ | |
150 | + | |
151 | +#undef ASM_FILE_START | |
152 | +#define ASM_FILE_START(FILE) \ | |
153 | + fprintf (FILE, ";#NO_APP\n"); | |
154 | + | |
155 | +/* Output to assembler file text saying following lines | |
156 | + may contain character constants, extra white space, comments, etc. */ | |
157 | + | |
158 | +#undef ASM_APP_ON | |
159 | +#define ASM_APP_ON ";#APP\n" | |
160 | + | |
161 | +/* Output to assembler file text saying following lines | |
162 | + no longer contain unusual constructs. */ | |
163 | + | |
164 | +#undef ASM_APP_OFF | |
165 | +#define ASM_APP_OFF ";#NO_APP\n" | |
166 | + | |
167 | +/* This is how to output an assembler line defining a `double' constant. */ | |
168 | + | |
169 | +#undef ASM_OUTPUT_DOUBLE | |
170 | +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ | |
171 | +do { union { double f; long l[2];} tem; \ | |
172 | + tem.f = (VALUE); \ | |
173 | + fprintf (FILE, "\t.long 0x%x, 0x%x\n", tem.l[0], tem.l[1]); \ | |
174 | + } while (0) | |
175 | + | |
176 | +/*unos has no .skip :-( */ | |
177 | +#undef ASM_OUTPUT_SKIP | |
178 | +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ | |
179 | + fprintf (FILE, "\t. = . + %u\n", (SIZE)); | |
180 | + | |
181 | +/* This says how to output an assembler line | |
182 | + to define a local common symbol. */ | |
183 | +/* should use bss_section instead of data_section but this makes casm die ? */ | |
184 | + | |
185 | +#undef ASM_OUTPUT_LOCAL | |
186 | +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ | |
187 | +{ data_section (); \ | |
188 | + if ((SIZE) > 1) fprintf (FILE, "\t.even\n"); \ | |
189 | + assemble_name ((FILE), (NAME)); \ | |
190 | + fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));} | |
191 | + | |
192 | +/* This is how to output an insn to push a register on the stack. | |
193 | + It need not be very fast code. */ | |
194 | + | |
195 | +#undef ASM_OUTPUT_REG_PUSH | |
196 | +#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ | |
197 | + fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO]) | |
198 | + | |
199 | +/* This is how to output an insn to pop a register from the stack. | |
200 | + It need not be very fast code. */ | |
201 | + | |
202 | +#undef ASM_OUTPUT_REG_POP | |
203 | +#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ | |
204 | + fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO]) | |
205 | + | |
206 | +#undef ASM_OUTPUT_ASCII | |
207 | +#define ASM_OUTPUT_ASCII(FILE, P , SIZE) \ | |
208 | +{ int i; \ | |
209 | + fprintf ((FILE), "\t.ascii \""); \ | |
210 | + for (i = 0; i < (SIZE); i++) \ | |
211 | + { \ | |
212 | + register int c = (P)[i]; \ | |
213 | + if (i != 0 && (i / 200) * 200 == i) \ | |
214 | + fprintf ((FILE), "\"\n\t.ascii \""); \ | |
215 | + if (c >= ' ' && c < 0177) { \ | |
216 | + if (c != '\"' && c != '\\') { \ | |
217 | + putc (c, (FILE)); \ | |
218 | + continue; \ | |
219 | + } \ | |
220 | + } \ | |
221 | + /* brain dead asm doesn't understand char escapes */ \ | |
222 | + fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c); \ | |
223 | + } \ | |
224 | + fprintf ((FILE), "\"\n"); \ | |
225 | + } | |
226 | + | |
227 | + | |
228 | +/* Change all JBxx to Bxx. Also change all DBRA to DBF. | |
229 | + Also change divs.l, etc., to divs, etc. But don't change divsl.l. */ | |
230 | + | |
231 | +#define ASM_OUTPUT_OPCODE(FILE, PTR) \ | |
232 | +{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \ | |
233 | + { ++(PTR); } \ | |
234 | + else if ((PTR)[0] == 'd') \ | |
235 | + { \ | |
236 | + if (!strncmp ((PTR), "dbra", 4)) \ | |
237 | + { fprintf ((FILE), "dbf"); (PTR) += 4; } \ | |
238 | + else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ') \ | |
239 | + { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; } \ | |
240 | + } \ | |
241 | +} | |
242 | + | |
243 | + | |
244 | +/* Print operand X (an rtx) in assembler syntax to file FILE. | |
245 | + CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. | |
246 | + For `%' followed by punctuation, CODE is the punctuation and X is null. | |
247 | + | |
248 | + On the 68000, we use several CODE characters: | |
249 | + '.' for dot needed in Motorola-style opcode names. | |
250 | + '-' for an operand pushing on the stack: | |
251 | + sp@-, -(sp) or -(%sp) depending on the style of syntax. | |
252 | + '+' for an operand pushing on the stack: | |
253 | + sp@+, (sp)+ or (%sp)+ depending on the style of syntax. | |
254 | + '@' for a reference to the top word on the stack: | |
255 | + sp@, (sp) or (%sp) depending on the style of syntax. | |
256 | + '#' for an immediate operand prefix (# in MIT and Motorola syntax | |
257 | + but & in SGS syntax, $ in unos syntax). | |
258 | + '!' for the cc register (used in an `and to cc' insn). | |
259 | + | |
260 | + 'b' for byte insn (no effect, on the Sun; this is for the ISI). | |
261 | + 'd' to force memory addressing to be absolute, not relative. | |
262 | + 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex) | |
263 | + 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather | |
264 | + than directly). Second part of 'y' below. | |
265 | + 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex), | |
266 | + or print pair of registers as rx:ry. | |
267 | + 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs | |
268 | + CONST_DOUBLE's as SunFPA constant RAM registers if | |
269 | + possible, so it should not be used except for the SunFPA. */ | |
270 | + | |
271 | +#undef PRINT_OPERAND_PUNCT_VALID_P | |
272 | +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ | |
273 | + ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \ | |
274 | + || (CODE) == '+' || (CODE) == '@' || (CODE) == '!') | |
275 | + | |
276 | +#undef PRINT_OPERAND | |
277 | +#define PRINT_OPERAND(FILE, X, CODE) \ | |
278 | +{ int i; \ | |
279 | + if (CODE == '.') ; \ | |
280 | + else if (CODE == '#') fprintf (FILE, "$"); \ | |
281 | + else if (CODE == '-') fprintf (FILE, "-(sp)"); \ | |
282 | + else if (CODE == '+') fprintf (FILE, "(sp)+"); \ | |
283 | + else if (CODE == '@') fprintf (FILE, "(sp)"); \ | |
284 | + else if (CODE == '!') fprintf (FILE, "cc"); \ | |
285 | + else if (GET_CODE (X) == REG) \ | |
286 | + { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \ | |
287 | + fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \ | |
288 | + else \ | |
289 | + fprintf (FILE, "%s", reg_names[REGNO (X)]); \ | |
290 | + } \ | |
291 | + else if (GET_CODE (X) == MEM) \ | |
292 | + { \ | |
293 | + output_address (XEXP (X, 0)); \ | |
294 | + if (CODE == 'd' && ! TARGET_68020 \ | |
295 | + && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ | |
296 | + /* fprintf (FILE, ".l") */; \ | |
297 | + } \ | |
298 | + else if ((CODE == 'y' || CODE == 'w') \ | |
299 | + && GET_CODE(X) == CONST_DOUBLE \ | |
300 | + && (i = standard_sun_fpa_constant_p (X))) \ | |
301 | + fprintf (FILE, "%%%d", i & 0x1ff); \ | |
302 | + else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ | |
303 | + { union { double d; int i[2]; } u; \ | |
304 | + union { float f; int i; } u1; \ | |
305 | + u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ | |
306 | + u1.f = u.d; \ | |
307 | + if (CODE == 'f') \ | |
308 | + ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f); \ | |
309 | + else \ | |
310 | + fprintf (FILE, "$0x%x", u1.i); } \ | |
311 | + else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ | |
312 | + { union { double d; int i[2]; } u; \ | |
313 | + u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ | |
314 | + ASM_OUTPUT_DOUBLE_OPERAND (FILE, u.d); } \ | |
315 | + else { putc ('$', FILE); output_addr_const (FILE, X); }} | |
316 | + | |
317 | +/* Note that this contains a kludge that knows that the only reason | |
318 | + we have an address (plus (label_ref...) (reg...)) | |
319 | + is in the insn before a tablejump, and we know that m68k.md | |
320 | + generates a label LInnn: on such an insn. */ | |
321 | +#undef PRINT_OPERAND_ADDRESS | |
322 | +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ | |
323 | +{ register rtx reg1, reg2, breg, ireg; \ | |
324 | + register rtx addr = ADDR; \ | |
325 | + rtx offset; \ | |
326 | + switch (GET_CODE (addr)) \ | |
327 | + { \ | |
328 | + case REG: \ | |
329 | + fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \ | |
330 | + break; \ | |
331 | + case PRE_DEC: \ | |
332 | + fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \ | |
333 | + break; \ | |
334 | + case POST_INC: \ | |
335 | + fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \ | |
336 | + break; \ | |
337 | + case PLUS: \ | |
338 | + reg1 = 0; reg2 = 0; \ | |
339 | + ireg = 0; breg = 0; \ | |
340 | + offset = 0; \ | |
341 | + if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \ | |
342 | + { \ | |
343 | + offset = XEXP (addr, 0); \ | |
344 | + addr = XEXP (addr, 1); \ | |
345 | + } \ | |
346 | + else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \ | |
347 | + { \ | |
348 | + offset = XEXP (addr, 1); \ | |
349 | + addr = XEXP (addr, 0); \ | |
350 | + } \ | |
351 | + if (GET_CODE (addr) != PLUS) ; \ | |
352 | + else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \ | |
353 | + { \ | |
354 | + reg1 = XEXP (addr, 0); \ | |
355 | + addr = XEXP (addr, 1); \ | |
356 | + } \ | |
357 | + else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \ | |
358 | + { \ | |
359 | + reg1 = XEXP (addr, 1); \ | |
360 | + addr = XEXP (addr, 0); \ | |
361 | + } \ | |
362 | + else if (GET_CODE (XEXP (addr, 0)) == MULT) \ | |
363 | + { \ | |
364 | + reg1 = XEXP (addr, 0); \ | |
365 | + addr = XEXP (addr, 1); \ | |
366 | + } \ | |
367 | + else if (GET_CODE (XEXP (addr, 1)) == MULT) \ | |
368 | + { \ | |
369 | + reg1 = XEXP (addr, 1); \ | |
370 | + addr = XEXP (addr, 0); \ | |
371 | + } \ | |
372 | + else if (GET_CODE (XEXP (addr, 0)) == REG) \ | |
373 | + { \ | |
374 | + reg1 = XEXP (addr, 0); \ | |
375 | + addr = XEXP (addr, 1); \ | |
376 | + } \ | |
377 | + else if (GET_CODE (XEXP (addr, 1)) == REG) \ | |
378 | + { \ | |
379 | + reg1 = XEXP (addr, 1); \ | |
380 | + addr = XEXP (addr, 0); \ | |
381 | + } \ | |
382 | + if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \ | |
383 | + || GET_CODE (addr) == SIGN_EXTEND) \ | |
384 | + { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \ | |
385 | + if (offset != 0) { if (addr != 0) abort (); addr = offset; } \ | |
386 | + if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \ | |
387 | + || GET_CODE (reg1) == MULT)) \ | |
388 | + || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \ | |
389 | + { breg = reg2; ireg = reg1; } \ | |
390 | + else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \ | |
391 | + { breg = reg1; ireg = reg2; } \ | |
392 | + if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \ | |
393 | + { int scale = 1; \ | |
394 | + if (GET_CODE (ireg) == MULT) \ | |
395 | + { scale = INTVAL (XEXP (ireg, 1)); \ | |
396 | + ireg = XEXP (ireg, 0); } \ | |
397 | + if (GET_CODE (ireg) == SIGN_EXTEND) \ | |
398 | + fprintf (FILE, "L%d-LI%d-2(pc,%s.w", \ | |
399 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
400 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
401 | + reg_names[REGNO (XEXP (ireg, 0))]); \ | |
402 | + else \ | |
403 | + fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \ | |
404 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
405 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
406 | + reg_names[REGNO (ireg)]); \ | |
407 | + if (scale != 1) fprintf (FILE, ":%d", scale); \ | |
408 | + putc (')', FILE); \ | |
409 | + break; } \ | |
410 | + if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \ | |
411 | + { fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \ | |
412 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
413 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
414 | + reg_names[REGNO (breg)]); \ | |
415 | + putc (')', FILE); \ | |
416 | + break; } \ | |
417 | + if (ireg != 0 || breg != 0) \ | |
418 | + { int scale = 1; \ | |
419 | + if (breg == 0) \ | |
420 | + abort (); \ | |
421 | + if (addr && GET_CODE (addr) == LABEL_REF) abort (); \ | |
422 | + if (addr != 0) \ | |
423 | + output_addr_const (FILE, addr); \ | |
424 | + fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \ | |
425 | + if (breg != 0 && ireg != 0) \ | |
426 | + putc (',', FILE); \ | |
427 | + if (ireg != 0 && GET_CODE (ireg) == MULT) \ | |
428 | + { scale = INTVAL (XEXP (ireg, 1)); \ | |
429 | + ireg = XEXP (ireg, 0); } \ | |
430 | + if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \ | |
431 | + fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \ | |
432 | + else if (ireg != 0) \ | |
433 | + fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \ | |
434 | + if (scale != 1) fprintf (FILE, ":%d", scale); \ | |
435 | + putc (')', FILE); \ | |
436 | + break; \ | |
437 | + } \ | |
438 | + else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \ | |
439 | + { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)", \ | |
440 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
441 | + CODE_LABEL_NUMBER (XEXP (addr, 0)), \ | |
442 | + reg_names[REGNO (reg1)]); \ | |
443 | + break; } \ | |
444 | + default: \ | |
445 | + if (GET_CODE (addr) == CONST_INT \ | |
446 | + && INTVAL (addr) < 0x8000 \ | |
447 | + && INTVAL (addr) >= -0x8000) \ | |
448 | + fprintf (FILE, "%d", INTVAL (addr)); \ | |
449 | + else \ | |
450 | + output_addr_const (FILE, addr); \ | |
451 | + }} | |
452 | + | |
453 | +#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \ | |
454 | + fprintf (FILE, "\t; file\t\"%s\"\n", FILENAME) | |
455 | + | |
456 | +#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \ | |
457 | + fprintf (FILE, "\t; ln\t%d\n", \ | |
458 | + (sdb_begin_function_line \ | |
459 | + ? last_linenum - sdb_begin_function_line : 1)) | |
460 | + | |
461 | +/* This macro generates the assembly code for function entry. | |
462 | + FILE is a stdio stream to output the code to. | |
463 | + SIZE is an int: how many units of temporary storage to allocate. | |
464 | + Refer to the array `regs_ever_live' to determine which registers | |
465 | + to save; `regs_ever_live[I]' is nonzero if register number I | |
466 | + is ever used in the function. This macro is responsible for | |
467 | + knowing which registers should not be saved even if used. */ | |
468 | + | |
469 | +/* Note that the order of the bit mask for fmovem is the opposite | |
470 | + of the order for movem! */ | |
471 | + | |
472 | +#undef FUNCTION_PROLOGUE | |
473 | +#define FUNCTION_PROLOGUE(FILE, SIZE) \ | |
474 | +{ register int regno; \ | |
475 | + register int mask = 0; \ | |
476 | + extern char call_used_regs[]; \ | |
477 | + int fsize = ((SIZE) + 3) & -4; \ | |
478 | + /* unos stack probe */ \ | |
479 | + if ( fsize > 30000 ) { \ | |
480 | + fprintf (FILE, "\tmovel sp,a0\n"); \ | |
481 | + fprintf (FILE, "\taddl $-%d,a0\n", 2048 + fsize); \ | |
482 | + fprintf (FILE, "\ttstb (a0)\n"); \ | |
483 | + } else { \ | |
484 | + fprintf (FILE, "\ttstb -%d(sp)\n", 2048 + fsize); \ | |
485 | + } \ | |
486 | + if (frame_pointer_needed) \ | |
487 | + { if (TARGET_68020 || fsize < 0x8000) \ | |
488 | + fprintf (FILE, "\tlink a6,$%d\n", -fsize); \ | |
489 | + else \ | |
490 | + fprintf (FILE, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize); } \ | |
491 | + for (regno = 24; regno < 56; regno++) \ | |
492 | + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ | |
493 | + fprintf(FILE, "\tfpmoved %s, sp@-\n", \ | |
494 | + reg_names[regno]); \ | |
495 | + for (regno = 16; regno < 24; regno++) \ | |
496 | + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ | |
497 | + mask |= 1 << (regno - 16); \ | |
498 | + if ((mask & 0xff) != 0) \ | |
499 | + fprintf (FILE, "\tfmovem $0x%x,-(sp)\n", mask & 0xff); \ | |
500 | + mask = 0; \ | |
501 | + for (regno = 0; regno < 16; regno++) \ | |
502 | + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ | |
503 | + mask |= 1 << (15 - regno); \ | |
504 | + if (frame_pointer_needed) \ | |
505 | + mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \ | |
506 | + if (exact_log2 (mask) >= 0) \ | |
507 | + fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \ | |
508 | + else if (mask) fprintf (FILE, "\tmovem $0x%x,-(sp)\n", mask); } | |
509 | + | |
510 | +/* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */ | |
511 | +/* UNOS ?? */ | |
512 | +#undef FUNCTION_PROFILER | |
513 | +#define FUNCTION_PROFILER(FILE, LABEL_NO) \ | |
514 | + fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO)) | |
515 | + | |
516 | +/* This macro generates the assembly code for function exit, | |
517 | + on machines that need it. If FUNCTION_EPILOGUE is not defined | |
518 | + then individual return instructions are generated for each | |
519 | + return statement. Args are same as for FUNCTION_PROLOGUE. | |
520 | + | |
521 | + The function epilogue should not depend on the current stack pointer! | |
522 | + It should use the frame pointer only. This is mandatory because | |
523 | + of alloca; we also take advantage of it to omit stack adjustments | |
524 | + before returning. */ | |
525 | + | |
526 | +#undef FUNCTION_EPILOGUE | |
527 | +#define FUNCTION_EPILOGUE(FILE, SIZE) \ | |
528 | +{ register int regno; \ | |
529 | + register int mask, fmask; \ | |
530 | + register int nregs; \ | |
531 | + int offset, foffset, fpoffset; \ | |
532 | + extern char call_used_regs[]; \ | |
533 | + int fsize = ((SIZE) + 3) & -4; \ | |
534 | + int big = 0; \ | |
535 | + nregs = 0; fmask = 0; fpoffset = 0; \ | |
536 | + for (regno = 24 ; regno < 56 ; regno++) \ | |
537 | + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ | |
538 | + nregs++; \ | |
539 | + fpoffset = nregs*8; \ | |
540 | + nregs = 0; \ | |
541 | + for (regno = 16; regno < 24; regno++) \ | |
542 | + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ | |
543 | + { nregs++; fmask |= 1 << (23 - regno); } \ | |
544 | + foffset = fpoffset + nregs * 12; \ | |
545 | + nregs = 0; mask = 0; \ | |
546 | + if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \ | |
547 | + for (regno = 0; regno < 16; regno++) \ | |
548 | + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ | |
549 | + { nregs++; mask |= 1 << regno; } \ | |
550 | + offset = foffset + nregs * 4; \ | |
551 | + if (offset + fsize >= 0x8000 \ | |
552 | + && frame_pointer_needed \ | |
553 | + && (mask || fmask || fpoffset)) \ | |
554 | + { fprintf (FILE, "\tmovel $%d,a0\n", -fsize); \ | |
555 | + fsize = 0, big = 1; } \ | |
556 | + if (exact_log2 (mask) >= 0) { \ | |
557 | + if (big) \ | |
558 | + fprintf (FILE, "\tmovel -%d(a6,a0.l),%s\n", \ | |
559 | + offset + fsize, reg_names[exact_log2 (mask)]); \ | |
560 | + else if (! frame_pointer_needed) \ | |
561 | + fprintf (FILE, "\tmovel (sp)+,%s\n", \ | |
562 | + reg_names[exact_log2 (mask)]); \ | |
563 | + else \ | |
564 | + fprintf (FILE, "\tmovel -%d(a6),%s\n", \ | |
565 | + offset + fsize, reg_names[exact_log2 (mask)]); } \ | |
566 | + else if (mask) { \ | |
567 | + if (big) \ | |
568 | + fprintf (FILE, "\tmovem -%d(a6,a0.l),$0x%x\n", \ | |
569 | + offset + fsize, mask); \ | |
570 | + else if (! frame_pointer_needed) \ | |
571 | + fprintf (FILE, "\tmovem (sp)+,$0x%x\n", mask); \ | |
572 | + else \ | |
573 | + fprintf (FILE, "\tmovem -%d(a6),$0x%x\n", \ | |
574 | + offset + fsize, mask); } \ | |
575 | + if (fmask) { \ | |
576 | + if (big) \ | |
577 | + fprintf (FILE, "\tfmovem -%d(a6,a0.l),$0x%x\n", \ | |
578 | + foffset + fsize, fmask); \ | |
579 | + else if (! frame_pointer_needed) \ | |
580 | + fprintf (FILE, "\tfmovem (sp)+,$0x%x\n", fmask); \ | |
581 | + else \ | |
582 | + fprintf (FILE, "\tfmovem -%d(a6),$0x%x\n", \ | |
583 | + foffset + fsize, fmask); } \ | |
584 | + if (fpoffset != 0) \ | |
585 | + for (regno = 55; regno >= 24; regno--) \ | |
586 | + if (regs_ever_live[regno] && ! call_used_regs[regno]) { \ | |
587 | + if (big) \ | |
588 | + fprintf(FILE, "\tfpmoved -%d(a6,a0.l), %s\n", \ | |
589 | + fpoffset + fsize, reg_names[regno]); \ | |
590 | + else if (! frame_pointer_needed) \ | |
591 | + fprintf(FILE, "\tfpmoved (sp)+, %s\n", \ | |
592 | + reg_names[regno]); \ | |
593 | + else \ | |
594 | + fprintf(FILE, "\tfpmoved -%d(a6), %s\n", \ | |
595 | + fpoffset + fsize, reg_names[regno]); \ | |
596 | + fpoffset -= 8; \ | |
597 | + } \ | |
598 | + if (frame_pointer_needed) \ | |
599 | + fprintf (FILE, "\tunlk a6\n"); \ | |
600 | + if (current_function_pops_args) \ | |
601 | + fprintf (FILE, "\trtd $%d\n", current_function_pops_args); \ | |
602 | + else fprintf (FILE, "\trts\n"); } | |
603 | + |