1 /* Definitions of target machine for GNU compiler, for Advanced RISC Machines
2 ARM compilation, AOF Assembler.
3 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rearnsha@armltd.co.uk)
6 This file is part of GNU CC.
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 2, or (at your option)
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.
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, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
27 #define LINK_LIBGCC_SPECIAL 1
29 #define LINK_SPEC "%{aof} %{bin} %{aif} %{ihf} %{shl,*} %{reent*} %{split} \
30 %{ov*,*} %{reloc*} -nodebug"
32 #define STARTFILE_SPEC "crtbegin.o%s"
34 #define ENDFILE_SPEC "crtend.o%s"
37 #define ASM_SPEC "%{g -g} -arch 4 \
38 -apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/26bit}}"
42 #define LIB_SPEC "%{Eb: armlib_h.32b%s}%{!Eb: armlib_h.32l%s}"
45 #define LIBGCC_SPEC "libgcc.a%s"
47 /* Dividing the Output into Sections (Text, Data, ...) */
48 /* AOF Assembler syntax is a nightmare when it comes to areas, since once
49 we change from one area to another, we can't go back again. Instead,
50 we must create a new area with the same attributes and add the new output
51 to that. Unfortunately, there is nothing we can do here to guarantee that
52 two areas with the same attributes will be linked adjacently in the
53 resulting executable, so we have to be careful not to do pc-relative
54 addressing across such boundaries. */
55 char *aof_text_section ();
56 #define TEXT_SECTION_ASM_OP aof_text_section ()
58 #define SELECT_RTX_SECTION(MODE,RTX) text_section ();
60 char *aof_data_section ();
61 #define DATA_SECTION_ASM_OP aof_data_section ()
63 #define EXTRA_SECTIONS in_zero_init, in_ctor, in_dtor
65 #define EXTRA_SECTION_FUNCTIONS \
70 #define ZERO_INIT_SECTION \
72 zero_init_section () \
74 static int zero_init_count = 1; \
75 if (in_section != in_zero_init) \
77 fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", \
79 in_section = in_zero_init; \
83 #define CTOR_SECTION \
87 static int ctors_once = 0; \
88 if (in_section != in_ctor) \
93 "Attempt to output more than one ctor section\n"); \
96 fprintf (asm_out_file, "\t%s\n", CTORS_SECTION_ASM_OP); \
97 in_section = in_ctor; \
102 #define DTOR_SECTION \
106 static int dtors_once = 0; \
107 if (in_section != in_dtor) \
112 "Attempt to output more than one dtor section\n"); \
115 fprintf (asm_out_file, "\t%s\n", DTORS_SECTION_ASM_OP); \
116 in_section = in_dtor; \
121 #define CTOR_LIST_BEGIN \
122 asm (CTORS_SECTION_ASM_OP); \
123 extern func_ptr __CTOR_END__[1]; \
124 func_ptr __CTOR_LIST__[1] = {__CTOR_END__};
126 #define CTOR_LIST_END \
127 asm (CTORS_SECTION_ASM_OP); \
128 func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
130 #define DO_GLOBAL_CTORS_BODY \
132 func_ptr *ptr = __CTOR_LIST__ + 1; \
137 #define DTOR_LIST_BEGIN \
138 asm (DTORS_SECTION_ASM_OP); \
139 extern func_ptr __DTOR_END__[1]; \
140 func_ptr __DTOR_LIST__[1] = {__DTOR_END__};
142 #define DTOR_LIST_END \
143 asm (DTORS_SECTION_ASM_OP); \
144 func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
146 #define DO_GLOBAL_DTORS_BODY \
148 func_ptr *ptr = __DTOR_LIST__ + 1; \
153 #define JUMP_TABLES_IN_TEXT_SECTION 1
156 #define ARM_OS_NAME "(generic)"
159 /* For the AOF linker, we need to reference __main to force the standard
160 library to get linked in. */
162 #define ASM_FILE_START(STREAM) \
164 extern char *version_string; \
165 fprintf ((STREAM), "%s Generated by gcc %s for ARM/%s\n", \
166 ASM_COMMENT_START, version_string, ARM_OS_NAME); \
167 fprintf ((STREAM), "__a1\tRN\t0\n"); \
168 fprintf ((STREAM), "__a2\tRN\t1\n"); \
169 fprintf ((STREAM), "__a3\tRN\t2\n"); \
170 fprintf ((STREAM), "__a4\tRN\t3\n"); \
171 fprintf ((STREAM), "__v1\tRN\t4\n"); \
172 fprintf ((STREAM), "__v2\tRN\t5\n"); \
173 fprintf ((STREAM), "__v3\tRN\t6\n"); \
174 fprintf ((STREAM), "__v4\tRN\t7\n"); \
175 fprintf ((STREAM), "__v5\tRN\t8\n"); \
176 fprintf ((STREAM), "__v6\tRN\t9\n"); \
177 fprintf ((STREAM), "__sl\tRN\t10\n"); \
178 fprintf ((STREAM), "__fp\tRN\t11\n"); \
179 fprintf ((STREAM), "__ip\tRN\t12\n"); \
180 fprintf ((STREAM), "__sp\tRN\t13\n"); \
181 fprintf ((STREAM), "__lr\tRN\t14\n"); \
182 fprintf ((STREAM), "__pc\tRN\t15\n"); \
183 fprintf ((STREAM), "__f0\tFN\t0\n"); \
184 fprintf ((STREAM), "__f1\tFN\t1\n"); \
185 fprintf ((STREAM), "__f2\tFN\t2\n"); \
186 fprintf ((STREAM), "__f3\tFN\t3\n"); \
187 fprintf ((STREAM), "__f4\tFN\t4\n"); \
188 fprintf ((STREAM), "__f5\tFN\t5\n"); \
189 fprintf ((STREAM), "__f6\tFN\t6\n"); \
190 fprintf ((STREAM), "__f7\tFN\t7\n"); \
194 /* Some systems use __main in a way incompatible with its use in gcc, in these
195 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
196 give the same symbol without quotes for an alternative entry point. You
197 must define both, or niether. */
198 #define NAME__MAIN "__gccmain"
199 #define SYMBOL__MAIN __gccmain
201 #define ASM_FILE_END(STREAM) \
205 aof_dump_pic_table (STREAM); \
206 aof_dump_imports (STREAM); \
207 fputs ("\tEND\n", (STREAM)); \
210 #define ASM_IDENTIFY_GCC(STREAM) fputs ("|gcc2_compiled.|\n", (STREAM))
212 #define ASM_COMMENT_START ";"
214 #define ASM_APP_ON ""
216 #define ASM_APP_OFF ""
218 #define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
219 ASM_OUTPUT_DOUBLE((STREAM),(VALUE))
221 #define ASM_OUTPUT_DOUBLE(STREAM,VALUE) \
225 REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), l); \
226 REAL_VALUE_TO_DECIMAL ((VALUE), "%.14g", dstr); \
227 fprintf ((STREAM), "\tDCD &%lx, &%lx\t%s double %s\n", \
228 l[0], l[1], ASM_COMMENT_START, dstr); \
231 #define ASM_OUTPUT_FLOAT(STREAM,VALUE) \
235 REAL_VALUE_TO_TARGET_SINGLE ((VALUE), l); \
236 REAL_VALUE_TO_DECIMAL ((VALUE), "%.7g", dstr); \
237 fprintf ((STREAM), "\tDCD &%lx\t%s double %s\n", \
238 l, ASM_COMMENT_START, dstr); \
241 #define ASM_OUTPUT_INT(STREAM,VALUE) \
242 (fprintf ((STREAM), "\tDCD\t"), \
243 output_addr_const ((STREAM), (VALUE)), \
244 fputc ('\n', (STREAM)))
246 #define ASM_OUTPUT_SHORT(STREAM,VALUE) \
247 (fprintf ((STREAM), "\tDCW\t"), \
248 output_addr_const ((STREAM), (VALUE)), \
249 fputc ('\n', (STREAM)))
251 #define ASM_OUTPUT_CHAR(STREAM,VALUE) \
252 (fprintf ((STREAM), "\tDCB\t"), \
253 output_addr_const ((STREAM), (VALUE)), \
254 fputc ('\n', (STREAM)))
256 #define ASM_OUTPUT_BYTE(STREAM,VALUE) \
257 fprintf ((STREAM), "\tDCB\t%d\n", (VALUE))
259 #define ASM_OUTPUT_ASCII(STREAM,PTR,LEN) \
263 fprintf ((STREAM), "\tDCB"); \
264 for (i = 0; i < (LEN); i++) \
265 fprintf ((STREAM), " &%02x%s", \
266 (unsigned ) *(ptr++), \
268 ? ((i & 3) == 3 ? "\n\tDCB" : ",") \
272 #define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n')
274 #define ASM_OPEN_PAREN "("
275 #define ASM_CLOSE_PAREN ")"
277 /* Output of Uninitialized Variables */
279 #define ASM_OUTPUT_COMMON(STREAM,NAME,SIZE,ROUNDED) \
280 (fprintf ((STREAM), "\tAREA "), \
281 assemble_name ((STREAM), (NAME)), \
282 fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \
283 (ROUNDED), ASM_COMMENT_START, SIZE))
285 #define ASM_OUTPUT_LOCAL(STREAM,NAME,SIZE,ROUNDED) \
286 (zero_init_section (), \
287 assemble_name ((STREAM), (NAME)), \
288 fprintf ((STREAM), "\n"), \
289 fprintf ((STREAM), "\t%% %d\t%s size=%d\n", \
290 (ROUNDED), ASM_COMMENT_START, SIZE))
292 /* Output and Generation of Labels */
294 extern int arm_main_function
;
296 #define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
298 fprintf ((STREAM), "\tEXPORT\t"); \
299 assemble_name ((STREAM), (NAME)); \
300 fputc ('\n', (STREAM)); \
301 if ((NAME)[0] == 'm' && ! strcmp ((NAME), "main")) \
302 arm_main_function = 1; \
305 #define ARM_OUTPUT_LABEL(STREAM,NAME) \
307 assemble_name (STREAM,NAME); \
308 fputs ("\n", STREAM); \
311 #define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
313 if (output_bytecode) \
314 BC_OUTPUT_LABEL (STREAM, NAME); \
317 ASM_OUTPUT_LABEL (STREAM, NAME); \
318 if (! TREE_PUBLIC (DECL)) \
320 fputs ("\tKEEP ", STREAM); \
321 ASM_OUTPUT_LABEL (STREAM, NAME); \
323 aof_delete_import ((NAME)); \
327 #define ASM_DECLARE_OBJECT_NAME(STREAM,NAME,DECL) \
329 if (output_bytecode) \
330 BC_OUTPUT_LABEL (STREAM, NAME); \
333 ASM_OUTPUT_LABEL (STREAM, NAME); \
334 if (! TREE_PUBLIC (DECL)) \
336 fputs ("\tKEEP ", STREAM); \
337 ASM_OUTPUT_LABEL (STREAM, NAME); \
339 aof_delete_import ((NAME)); \
343 #define ASM_OUTPUT_EXTERNAL(STREAM,DECL,NAME) \
344 aof_add_import ((NAME))
346 #define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM,SYMREF) \
347 (fprintf ((STREAM), "\tIMPORT\t"), \
348 assemble_name ((STREAM), XSTR ((SYMREF), 0)), \
349 fputc ('\n', (STREAM)))
351 #define ASM_OUTPUT_LABELREF(STREAM,NAME) \
352 fprintf ((STREAM), "|%s|", NAME)
354 #define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
355 sprintf ((STRING), "*|%s..%d|", (PREFIX), (NUM))
357 #define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
358 ((OUTVAR) = (char *) alloca (strlen ((NAME)) + 10), \
359 sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
361 /* How initialization functions are handled */
363 #define CTORS_SECTION_ASM_OP "AREA\t|C$$gnu_ctorsvec|, DATA, READONLY"
364 #define DTORS_SECTION_ASM_OP "AREA\t|C$$gnu_dtorsvec|, DATA, READONLY"
366 #define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
369 fprintf ((STREAM), "\tDCD\t"); \
370 assemble_name ((STREAM), (NAME)); \
371 fputc ('\n', (STREAM)); \
374 #define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
377 fprintf ((STREAM), "\tDCD\t"); \
378 assemble_name ((STREAM), (NAME)); \
379 fputc ('\n', (STREAM)); \
382 /* Output of Assembler Instructions */
384 #define REGISTER_NAMES \
386 "a1", "a2", "a3", "a4", \
387 "v1", "v2", "v3", "v4", \
388 "v5", "v6", "sl", "fp", \
389 "ip", "sp", "lr", "pc", \
390 "f0", "f1", "f2", "f3", \
391 "f4", "f5", "f6", "f7", \
395 #define ADDITIONAL_REGISTER_NAMES \
397 {"r0", 0}, {"a1", 0}, \
398 {"r1", 1}, {"a2", 1}, \
399 {"r2", 2}, {"a3", 2}, \
400 {"r3", 3}, {"a4", 3}, \
401 {"r4", 4}, {"v1", 4}, \
402 {"r5", 5}, {"v2", 5}, \
403 {"r6", 6}, {"v3", 6}, \
404 {"r7", 7}, {"wr", 7}, \
405 {"r8", 8}, {"v5", 8}, \
406 {"r9", 9}, {"v6", 9}, \
407 {"r10", 10}, {"sl", 10}, {"v7", 10}, \
408 {"r11", 11}, {"fp", 11}, \
409 {"r12", 12}, {"ip", 12}, \
410 {"r13", 13}, {"sp", 13}, \
411 {"r14", 14}, {"lr", 14}, \
412 {"r15", 15}, {"pc", 15} \
415 #define REGISTER_PREFIX "__"
416 #define USER_LABEL_PREFIX ""
417 #define LOCAL_LABEL_PREFIX ""
419 /* Output of Dispatch Tables */
421 #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL) \
422 fprintf ((STREAM), "\tb\t|L..%d|\n", (VALUE))
424 #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
425 fprintf ((STREAM), "\tDCD\t|L..%d|\n", (VALUE))
427 /* A label marking the start of a jump table is a data label. */
428 #define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) \
429 fprintf ((STREAM), "\tALIGN\n|%s..%d|\n", (PREFIX), (NUM))
431 /* Assembler Commands for Alignment */
433 #define ASM_OUTPUT_SKIP(STREAM,NBYTES) \
434 fprintf ((STREAM), "\t%%\t%d\n", (NBYTES))
436 #define ASM_OUTPUT_ALIGN(STREAM,POWER) \
438 register int amount = 1 << (POWER); \
440 fprintf ((STREAM), "\tALIGN 2\n"); \
441 else if (amount == 4) \
442 fprintf ((STREAM), "\tALIGN\n"); \
444 fprintf ((STREAM), "\tALIGN %d\n", amount); \
449 #undef DBX_DEBUGGING_INFO