-y support
[platform/upstream/binutils.git] / ld / ldlnk960.c
1 /* intel coff loader emulation specific stuff
2    Copyright (C) 1991 Free Software Foundation, Inc.
3    Written by Steve Chamberlain steve@cygnus.com
4
5 This file is part of GLD, the Gnu Linker.
6
7 GLD is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GLD is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GLD; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /*
22    $Id$ 
23 */
24
25 #include "bfd.h"
26 #include "sysdep.h"
27
28 /*#include "archures.h"*/
29 #include "ld.h"
30 #include "config.h"
31 #include "ldemul.h"
32 #include "ldmisc.h"
33 #include "ldlang.h"
34 #include "ldfile.h"
35
36 extern  boolean lang_float_flag;
37 extern bfd *output_bfd;
38
39
40
41 extern enum bfd_architecture ldfile_output_architecture;
42 extern unsigned long ldfile_output_machine;
43 extern char *ldfile_output_machine_name;
44
45
46 typedef struct lib_list {
47   char *name;
48   struct lib_list *next;
49 } lib_list_type;
50
51 static lib_list_type *hll_list;
52 static lib_list_type **hll_list_tail = &hll_list;
53
54 static lib_list_type *syslib_list;
55 static lib_list_type **syslib_list_tail = &syslib_list;
56
57
58 static void
59 append(list, name)
60 lib_list_type ***list;
61 char *name;
62 {
63   lib_list_type *element = 
64     (lib_list_type *)(ldmalloc(sizeof(lib_list_type)));
65
66   element->name = name;
67   element->next = (lib_list_type *)NULL;
68   **list = element;
69   *list = &element->next;
70
71 }
72
73 static boolean had_hll = false;
74 static boolean had_hll_name = false;
75 static void
76 lnk960_hll(name)
77 char *name;
78 {
79   had_hll = true;
80   if (name != (char *)NULL) {
81     had_hll_name = true;
82     append(&hll_list_tail, name);
83   }
84 }
85
86 static void 
87 lnk960_syslib(name)
88 char *name;
89 {
90   append(&syslib_list_tail,name);
91 }
92
93
94
95 #ifdef GNU960
96
97 static void 
98 lnk960_before_parse()
99 {
100   static char *env_variables[] = { "G960LIB", "G960BASE", 0 };
101   char **p;
102   char *env ;
103
104   for ( p = env_variables; *p; p++ ){
105     env =  (char *) getenv(*p);
106     if (env) {
107       ldfile_add_library_path(concat(env,"/lib/libcoff",""));
108     }
109   }
110
111   env= (char *) getenv("I960BASE");
112   if ( env ) {
113     ldfile_add_library_path(concat(env,"/lib",""));
114   }
115
116   ldfile_output_architecture = bfd_arch_i960;
117   ldfile_output_machine = bfd_mach_i960_core;
118 }
119
120 #else   /* not GNU960 */
121
122 static void 
123 lnk960_before_parse()
124 {
125   char *name = getenv("I960BASE");
126
127   if (name == (char *)NULL) {
128     name = getenv("G960BASE");
129     if (name == (char *)NULL) {
130       einfo("%P%F I960BASE and G960BASE not set\n");
131     }
132   }
133
134
135   ldfile_add_library_path(concat(name,"/lib",""));
136   ldfile_output_architecture = bfd_arch_i960;
137   ldfile_output_machine = bfd_mach_i960_core;
138 }
139
140 #endif  /* GNU960 */
141
142
143 static void
144 add_on(list, search)
145 lib_list_type *list;
146 lang_input_file_enum_type search;
147 {
148   while (list) {
149     lang_add_input_file(list->name,
150                         search,
151                         (char *)NULL);
152     list = list->next;
153   }
154 }
155 static void lnk960_after_parse()
156 {
157
158   /* If there has been no arch, default to -KB */
159   if (ldfile_output_machine_name[0] ==0) {
160     ldfile_add_arch("KB");
161   }
162
163   /* if there has been no hll list then add our own */
164   
165   if(had_hll && !had_hll_name) {
166     append(&hll_list_tail,"cg");
167     if (ldfile_output_machine == bfd_mach_i960_ka_sa ||
168         ldfile_output_machine == bfd_mach_i960_ca) {
169         {
170           append(&hll_list_tail,"fpg");
171         }
172     }
173   }
174   
175   add_on(hll_list, lang_input_file_is_l_enum);
176   add_on(syslib_list, lang_input_file_is_search_file_enum);
177 }
178
179 static void
180 lnk960_before_allocation()
181 {
182 }
183 static void
184 lnk960_after_allocation()
185 {
186   extern ld_config_type config;
187   if (config.relocateable_output == false) {
188     lang_abs_symbol_at_end_of(".text","_etext");
189     lang_abs_symbol_at_end_of(".data","_edata");
190     lang_abs_symbol_at_beginning_of(".bss","_bss_start");
191     lang_abs_symbol_at_end_of(".bss","_end");
192   }
193 }
194
195
196 static struct
197  {
198    unsigned  long number;
199    char *name; 
200  }
201 machine_table[] = {
202         bfd_mach_i960_core      ,"CORE",
203         bfd_mach_i960_kb_sb     ,"KB",
204         bfd_mach_i960_kb_sb     ,"SB",
205         bfd_mach_i960_mc        ,"MC",
206         bfd_mach_i960_xa        ,"XA",
207         bfd_mach_i960_ca        ,"CA",
208         bfd_mach_i960_ka_sa     ,"KA",
209         bfd_mach_i960_ka_sa     ,"SA",
210
211         bfd_mach_i960_core      ,"core",
212         bfd_mach_i960_kb_sb     ,"kb",
213         bfd_mach_i960_kb_sb     ,"sb",
214         bfd_mach_i960_mc        ,"mc",
215         bfd_mach_i960_xa        ,"xa",
216         bfd_mach_i960_ca        ,"ca",
217         bfd_mach_i960_ka_sa     ,"ka",
218         bfd_mach_i960_ka_sa     ,"sa",
219         0,(char *)NULL
220 };
221
222 static void
223 lnk960_set_output_arch()
224 {
225   /* Set the output architecture and machine if possible */
226   unsigned int i;
227   ldfile_output_machine = bfd_mach_i960_core;
228   for (i= 0; machine_table[i].name != (char*)NULL; i++) {
229     if (strcmp(ldfile_output_machine_name,machine_table[i].name)==0) {
230       ldfile_output_machine = machine_table[i].number;
231       break;
232     }
233   }
234   bfd_set_arch_mach(output_bfd, ldfile_output_architecture, ldfile_output_machine);
235 }
236
237 static char *
238 lnk960_choose_target()
239 {
240 #ifdef GNU960
241
242   return bfd_make_targ_name(BFD_COFF_FORMAT, 0);
243
244 #else
245
246   char *from_outside = getenv(TARGET_ENVIRON);
247   if (from_outside != (char *)NULL)
248     return from_outside;
249 #ifdef LNK960_LITTLE
250   return LNK960_TARGET_LITTLE
251 #else
252   return LNK960_TARGET;
253 #endif
254 #endif
255
256 }
257
258 /* The default script if none is offered */
259 static char *lnk960_script = 
260 #include "ldlnk960.x"
261 ;
262
263
264 static char *lnk960_script_relocateable = 
265 #include "ldlnk960.xr"
266 ;
267
268 static char *lnk960_get_script()
269 {
270   extern ld_config_type config;
271   if (config.relocateable_output) {
272     return lnk960_script_relocateable;
273   }
274   return lnk960_script;
275 }
276 struct ld_emulation_xfer_struct ld_lnk960_emulation = 
277 {
278   lnk960_before_parse,
279   lnk960_syslib,
280   lnk960_hll,
281   lnk960_after_parse,
282   lnk960_after_allocation,
283   lnk960_set_output_arch,
284   lnk960_choose_target,
285   lnk960_before_allocation,
286   lnk960_get_script,
287 };