]> Git Repo - binutils.git/blob - bfd/archures.c
This commit was generated by cvs2svn to track changes on a CVS vendor
[binutils.git] / bfd / archures.c
1 /* BFD library support routines for architectures. */
2
3 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Diddler.
6
7 BFD 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 1, or (at your option)
10 any later version.
11
12 BFD 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 BFD; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* $Id$ */
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "archures.h"
26
27 static char *prt_num_mach ();
28 static boolean scan_num_mach ();
29 static char *prt_960_mach ();
30 static boolean scan_960_mach ();
31
32 struct arch_print {
33         enum bfd_architecture arch;
34         char *astr;
35         char *(*mach_print)();
36         boolean (*mach_scan)();
37 } arch_print[] = {
38
39         {bfd_arch_unknown,      "unknown",      prt_num_mach,   scan_num_mach},
40         {bfd_arch_obscure,      "obscure",      prt_num_mach,   scan_num_mach},
41         {bfd_arch_m68k,         "m68k",         prt_num_mach,   scan_num_mach},
42         {bfd_arch_vax,          "vax",          prt_num_mach,   scan_num_mach},
43         {bfd_arch_i960,         "i960",         prt_960_mach,   scan_960_mach},
44         {bfd_arch_a29k,         "a29k",         prt_num_mach,   scan_num_mach},
45         {bfd_arch_sparc,        "sparc",        prt_num_mach,   scan_num_mach},
46         {bfd_arch_mips,         "mips",         prt_num_mach,   scan_num_mach},
47         {bfd_arch_i386,         "i386",         prt_num_mach,   scan_num_mach},
48         {bfd_arch_ns32k,        "ns32k",        prt_num_mach,   scan_num_mach},
49         {bfd_arch_tahoe,        "tahoe",        prt_num_mach,   scan_num_mach},
50         {bfd_arch_i860,         "i860",         prt_num_mach,   scan_num_mach},
51         {bfd_arch_romp,         "romp",         prt_num_mach,   scan_num_mach},
52         {bfd_arch_alliant,      "alliant",      prt_num_mach,   scan_num_mach},
53         {bfd_arch_convex,       "convex",       prt_num_mach,   scan_num_mach},
54         {bfd_arch_m88k,         "m88k",         prt_num_mach,   scan_num_mach},
55         {bfd_arch_pyramid,      "pyramid",      prt_num_mach,   scan_num_mach},
56         {bfd_arch_unknown,      (char *)0,      prt_num_mach,   scan_num_mach},
57 };
58
59 /* Return a printable string representing the architecture and machine
60    type.  The result is only good until the next call to
61    bfd_printable_arch_mach.  */
62
63 char *
64 bfd_printable_arch_mach (arch, machine)
65      enum bfd_architecture arch;
66      unsigned long machine;
67 {
68   struct arch_print *ap;
69
70   for (ap = arch_print; ap->astr; ap++) {
71     if (ap->arch == arch) {
72       if (machine == 0)
73         return ap->astr;
74       return (*ap->mach_print)(ap, machine);
75     }
76   }
77   return "UNKNOWN!";
78 }
79
80 static char *
81 prt_num_mach (ap, machine)
82      struct arch_print *ap;
83      unsigned long machine;
84 {
85   static char result[20];
86
87   sprintf(result, "%s:%ld", ap->astr, (long) machine);
88   return result;
89 }
90
91 /* Scan a string and attempt to turn it into an archive and machine type
92    combination.  */
93
94 boolean
95 bfd_scan_arch_mach (string, archp, machinep)
96      char *string;
97      enum bfd_architecture *archp;
98      unsigned long *machinep;
99 {
100   struct arch_print *ap;
101   int len;
102
103   /* First look for an architecture, possibly followed by machtype. */
104   for (ap = arch_print; ap->astr; ap++) {
105     if (ap->astr[0] != string[0])
106       continue;
107     len = strlen (ap->astr);
108     if (!strncmp (ap->astr, string, len)) {
109       /* We found the architecture, now see about the machine type */
110       if (archp)
111         *archp = ap->arch;
112       if (string[len] != '\0') {
113         if (ap->mach_scan (string+len, ap, archp, machinep, 1))
114           return true;
115       }
116       if (machinep)
117         *machinep = 0;
118       return true;
119     }
120   }
121
122   /* Couldn't find an architecture -- try for just a machine type */
123   for (ap = arch_print; ap->astr; ap++) {
124     if (ap->mach_scan (string, ap, archp, machinep, 0))
125       return true;
126   }
127
128   return false;
129 }
130
131 static boolean
132 scan_num_mach (string, ap, archp, machinep, archspec)
133      char *string;
134      struct arch_print *ap;
135      enum bfd_architecture *archp;
136      unsigned long *machinep;
137      int archspec;
138 {
139   enum bfd_architecture arch;
140   unsigned long machine;
141   char achar;
142
143   if (archspec) {
144
145     /* Architecture already specified, now go for machine type.  */
146     if (string[0] != ':')
147       return false;
148     /* We'll take any valid number that occupies the entire string */
149     if (1 != sscanf (string+1, "%lu%c", &machine, &achar))
150       return false;
151     arch = ap->arch;
152
153   } else {
154
155     /* We couldn't identify an architecture prefix.  Perhaps the entire
156        thing is a machine type.  Be a lot picker.  */
157     if (1 != sscanf (string, "%lu%c", &machine, &achar))
158       return false;
159     switch (machine) {
160     case 68010:
161     case 68020:
162     case 68030:
163     case 68040:
164     case 68332:
165     case 68050:         arch = bfd_arch_m68k; break;
166     case 68000:         arch = bfd_arch_m68k; machine = 0; break;
167
168     case 80960:
169     case 960:           arch = bfd_arch_i960; machine = 0; break;
170
171     case 386:
172     case 80386:         arch = bfd_arch_i386; machine = 0; break;
173     case 486:           arch = bfd_arch_i386; break;
174
175     case 29000:         arch = bfd_arch_a29k; machine = 0; break;
176
177     case 32016:
178     case 32032:
179     case 32132:
180     case 32232:
181     case 32332:
182     case 32432:
183     case 32532:         arch = bfd_arch_ns32k; break;
184     case 32000:         arch = bfd_arch_ns32k; machine = 0; break;
185
186     case 860:
187     case 80860:         arch = bfd_arch_i860; machine = 0; break;
188
189     default:            return false;
190     }
191   }
192
193   if (archp)
194     *archp = arch;
195   if (machinep)
196     *machinep = machine;
197   return true;
198 }
199 \f
200 /* Intel 960 machine variants.  */
201
202 static char *
203 prt_960_mach (ap, machine)
204      struct arch_print *ap;
205      unsigned long machine;
206 {
207   static char result[20];
208   char *str;
209
210   switch (machine) {
211   case bfd_mach_i960_core:      str = "core"; break;
212   case bfd_mach_i960_kb_sb:     str = "kb"; break;
213   case bfd_mach_i960_mc:        str = "mc"; break;
214   case bfd_mach_i960_xa:        str = "xa"; break;
215   case bfd_mach_i960_ca:        str = "ca"; break;
216   case bfd_mach_i960_ka_sa:     str = "ka"; break;
217   default:
218         return prt_num_mach (ap, machine);
219   }
220   sprintf (result, "%s:%s", ap->astr, str);
221   return result;
222 }
223
224 static boolean
225 scan_960_mach (string, ap, archp, machinep, archspec)
226      char *string;
227      struct arch_print *ap;
228      enum bfd_architecture *archp;
229      unsigned long *machinep;
230      int archspec;
231 {
232   unsigned long machine;
233
234   if (!archspec)
235     return false;
236   if (string[0] != ':')
237     return false;
238   string++;
239   if (string[0] == '\0')
240     return false;
241   if (string[0] == 'c' && string[1] == 'o' && string[2] == 'r' &&
242       string[3] == 'e' && string[4] == '\0')
243     machine = bfd_mach_i960_core;
244   else if (string[1] == '\0' || string[2] != '\0')      /* rest are 2-char */
245     return false;
246   else if (string[0] == 'k' && string[1] == 'b')
247     machine = bfd_mach_i960_kb_sb;
248   else if (string[0] == 's' && string[1] == 'b')
249     machine = bfd_mach_i960_kb_sb;
250   else if (string[0] == 'm' && string[1] == 'c')
251     machine = bfd_mach_i960_mc;
252   else if (string[0] == 'x' && string[1] == 'a')
253     machine = bfd_mach_i960_xa;
254   else if (string[0] == 'c' && string[1] == 'a')
255     machine = bfd_mach_i960_ca;
256   else if (string[0] == 'k' && string[1] == 'a')
257     machine = bfd_mach_i960_ka_sa;
258   else if (string[0] == 's' && string[1] == 'a')
259     machine = bfd_mach_i960_ka_sa;
260   else
261     return false;
262
263   if (archp)
264     *archp = ap->arch;
265   if (machinep)
266     *machinep = machine;
267   return true;
268 }
269
270
271 \f
272 /* Determine whether two BFDs' architectures and machine types are
273    compatible.  Return merged architecture and machine type if nonnull
274    pointers.  */
275
276 boolean
277 bfd_arch_compatible (abfd, bbfd, archp, machinep)
278     bfd *abfd;
279     bfd *bbfd;
280     enum bfd_architecture *archp;
281     unsigned long *machinep;
282 {
283   enum bfd_architecture archa, archb;
284   unsigned long macha, machb;
285   int pick_a;
286
287   archa = bfd_get_architecture (abfd);
288   archb = bfd_get_architecture (bbfd);
289   macha = bfd_get_machine (abfd);
290   machb = bfd_get_machine (bbfd);
291
292   if (archb == bfd_arch_unknown)
293         pick_a = 1;
294   else if (archa == bfd_arch_unknown)
295         pick_a = 0;
296   else if (archa != archb)
297         return false;                   /* Not compatible */
298   else {
299     /* Architectures are the same.  Check machine types.  */
300     if (macha == machb)         /* Same machine type */
301       pick_a = 1;
302     else if (machb == 0)        /* B is default */
303       pick_a = 1;
304     else if (macha == 0)        /* A is default */
305       pick_a = 0;
306     else switch (archa) {
307       /* If particular machine types of one architecture are not
308          compatible with each other, this is the place to put those tests
309          (returning false if incompatible).  */
310     case bfd_arch_i960:
311       /* The i960 has to distinct subspecies which may not interbreed:
312          CORE CA          
313          CORE KA KB MC
314          Any architecture on the same line is compatible, the one on
315          the right is the least restrictive.
316          */
317       /* So, if either is a ca then the other must be a be core or ca */
318       if (macha == bfd_mach_i960_ca) {
319         if (machb != bfd_mach_i960_ca &&
320             machb != bfd_mach_i960_core) {
321           return false;
322         }
323         pick_a = 1;
324       }
325       else      if (machb == bfd_mach_i960_ca) {
326         if (macha != bfd_mach_i960_ca &&
327             macha != bfd_mach_i960_core) {
328           return false;
329         }
330         pick_a = 0;
331       }
332       else {
333         /* This must be from the bottom row, so take the higest */
334         pick_a = (macha > machb);
335       }
336          
337          
338
339       break;
340
341       /* For these chips, as far as we care, "lower" numbers are included
342          by "higher" numbers, e.g. merge 68010 and 68020 into 68020,
343          386 and 486 into 486, etc.  This will need to change
344          if&when we care about things like 68332.  */
345     case bfd_arch_m68k:
346     case bfd_arch_ns32k:
347     case bfd_arch_i386:
348       pick_a = (macha > machb);
349       break;
350     
351       /* By default, pick first file's type, for lack of something better.  */
352     default:
353       pick_a = 1;
354     }
355   }
356
357   /* Set result based on our pick */
358   if (!pick_a) {
359     archa = archb;
360     macha = machb;
361   }
362   if (archp)
363     *archp = archa;
364   if (machinep)
365     *machinep = macha;
366
367   return true;
368 }
This page took 0.043724 seconds and 4 git commands to generate.