1*3d8817e4Smiod /* BFD library support routines for architectures.
2*3d8817e4Smiod    Copyright 1990, 1991, 1992, 1993, 1994, 1997, 1998, 2000, 2001, 2002,
3*3d8817e4Smiod    2003, 2004, 2006 Free Software Foundation, Inc.
4*3d8817e4Smiod    Hacked by Steve Chamberlain of Cygnus Support.
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is part of BFD, the Binary File Descriptor library.
7*3d8817e4Smiod 
8*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify
9*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
11*3d8817e4Smiod    (at your option) any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
14*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod    GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod    You should have received a copy of the GNU General Public License
19*3d8817e4Smiod    along with this program; if not, write to the Free Software
20*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21*3d8817e4Smiod 
22*3d8817e4Smiod #include "bfd.h"
23*3d8817e4Smiod #include "sysdep.h"
24*3d8817e4Smiod #include "libbfd.h"
25*3d8817e4Smiod #include "opcode/m68k.h"
26*3d8817e4Smiod 
27*3d8817e4Smiod static const bfd_arch_info_type *
28*3d8817e4Smiod bfd_m68k_compatible (const bfd_arch_info_type *a,
29*3d8817e4Smiod 		     const bfd_arch_info_type *b);
30*3d8817e4Smiod 
31*3d8817e4Smiod #define N(name, print,d,next)  \
32*3d8817e4Smiod {  32, 32, 8, bfd_arch_m68k, name, "m68k",print,2,d,bfd_m68k_compatible,bfd_default_scan, next, }
33*3d8817e4Smiod 
34*3d8817e4Smiod static const bfd_arch_info_type arch_info_struct[] =
35*3d8817e4Smiod   {
36*3d8817e4Smiod     N(bfd_mach_m68000,  "m68k:68000", FALSE, &arch_info_struct[1]),
37*3d8817e4Smiod     N(bfd_mach_m68008,  "m68k:68008", FALSE, &arch_info_struct[2]),
38*3d8817e4Smiod     N(bfd_mach_m68010,  "m68k:68010", FALSE, &arch_info_struct[3]),
39*3d8817e4Smiod     N(bfd_mach_m68020,  "m68k:68020", FALSE, &arch_info_struct[4]),
40*3d8817e4Smiod     N(bfd_mach_m68030,  "m68k:68030", FALSE, &arch_info_struct[5]),
41*3d8817e4Smiod     N(bfd_mach_m68040,  "m68k:68040", FALSE, &arch_info_struct[6]),
42*3d8817e4Smiod     N(bfd_mach_m68060,  "m68k:68060", FALSE, &arch_info_struct[7]),
43*3d8817e4Smiod     N(bfd_mach_cpu32,   "m68k:cpu32", FALSE, &arch_info_struct[8]),
44*3d8817e4Smiod 
45*3d8817e4Smiod     /* Various combinations of CF architecture features */
46*3d8817e4Smiod     N(bfd_mach_mcf_isa_a_nodiv, "m68k:isa-a:nodiv",
47*3d8817e4Smiod       FALSE, &arch_info_struct[9]),
48*3d8817e4Smiod     N(bfd_mach_mcf_isa_a, "m68k:isa-a",
49*3d8817e4Smiod       FALSE, &arch_info_struct[10]),
50*3d8817e4Smiod     N(bfd_mach_mcf_isa_a_mac, "m68k:isa-a:mac",
51*3d8817e4Smiod       FALSE, &arch_info_struct[11]),
52*3d8817e4Smiod     N(bfd_mach_mcf_isa_a_emac, "m68k:isa-a:emac",
53*3d8817e4Smiod       FALSE, &arch_info_struct[12]),
54*3d8817e4Smiod     N(bfd_mach_mcf_isa_aplus, "m68k:isa-aplus",
55*3d8817e4Smiod       FALSE, &arch_info_struct[13]),
56*3d8817e4Smiod     N(bfd_mach_mcf_isa_aplus_mac, "m68k:isa-aplus:mac",
57*3d8817e4Smiod       FALSE, &arch_info_struct[14]),
58*3d8817e4Smiod     N(bfd_mach_mcf_isa_aplus_emac, "m68k:isa-aplus:emac",
59*3d8817e4Smiod       FALSE, &arch_info_struct[15]),
60*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_nousp, "m68k:isa-b:nousp",
61*3d8817e4Smiod       FALSE, &arch_info_struct[16]),
62*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_nousp_mac, "m68k:isa-b:nousp:mac",
63*3d8817e4Smiod       FALSE, &arch_info_struct[17]),
64*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_nousp_emac, "m68k:isa-b:nousp:emac",
65*3d8817e4Smiod       FALSE, &arch_info_struct[18]),
66*3d8817e4Smiod     N(bfd_mach_mcf_isa_b, "m68k:isa-b",
67*3d8817e4Smiod       FALSE, &arch_info_struct[19]),
68*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_mac, "m68k:isa-b:mac",
69*3d8817e4Smiod       FALSE, &arch_info_struct[20]),
70*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_emac, "m68k:isa-b:emac",
71*3d8817e4Smiod       FALSE, &arch_info_struct[21]),
72*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_float, "m68k:isa-b:float",
73*3d8817e4Smiod       FALSE, &arch_info_struct[22]),
74*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_float_mac, "m68k:isa-b:float:mac",
75*3d8817e4Smiod       FALSE, &arch_info_struct[23]),
76*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_float_emac, "m68k:isa-b:float:emac",
77*3d8817e4Smiod       FALSE, &arch_info_struct[24]),
78*3d8817e4Smiod 
79*3d8817e4Smiod     /* Legacy names for CF architectures */
80*3d8817e4Smiod     N(bfd_mach_mcf_isa_a_nodiv, "m68k:5200", FALSE, &arch_info_struct[25]),
81*3d8817e4Smiod     N(bfd_mach_mcf_isa_a_mac,"m68k:5206e", FALSE, &arch_info_struct[26]),
82*3d8817e4Smiod     N(bfd_mach_mcf_isa_a_mac, "m68k:5307", FALSE, &arch_info_struct[27]),
83*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_nousp_mac, "m68k:5407", FALSE, &arch_info_struct[28]),
84*3d8817e4Smiod     N(bfd_mach_mcf_isa_aplus_emac, "m68k:528x", FALSE, &arch_info_struct[29]),
85*3d8817e4Smiod     N(bfd_mach_mcf_isa_aplus_emac, "m68k:521x", FALSE, &arch_info_struct[30]),
86*3d8817e4Smiod     N(bfd_mach_mcf_isa_a_emac, "m68k:5249", FALSE, &arch_info_struct[31]),
87*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_float_emac, "m68k:547x",
88*3d8817e4Smiod       FALSE, &arch_info_struct[32]),
89*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_float_emac, "m68k:548x",
90*3d8817e4Smiod       FALSE, &arch_info_struct[33]),
91*3d8817e4Smiod     N(bfd_mach_mcf_isa_b_float_emac, "m68k:cfv4e", FALSE, 0),
92*3d8817e4Smiod   };
93*3d8817e4Smiod 
94*3d8817e4Smiod const bfd_arch_info_type bfd_m68k_arch =
95*3d8817e4Smiod   N(0, "m68k", TRUE, &arch_info_struct[0]);
96*3d8817e4Smiod 
97*3d8817e4Smiod /* Table indexed by bfd_mach_arch number indicating which
98*3d8817e4Smiod    architectural features are supported.  */
99*3d8817e4Smiod static const unsigned m68k_arch_features[] =
100*3d8817e4Smiod {
101*3d8817e4Smiod   0,
102*3d8817e4Smiod   m68000|m68881|m68851,
103*3d8817e4Smiod   m68000|m68881|m68851,
104*3d8817e4Smiod   m68010|m68881|m68851,
105*3d8817e4Smiod   m68020|m68881|m68851,
106*3d8817e4Smiod   m68030|m68881|m68851,
107*3d8817e4Smiod   m68040|m68881|m68851,
108*3d8817e4Smiod   m68060|m68881|m68851,
109*3d8817e4Smiod   cpu32|m68881,
110*3d8817e4Smiod   mcfisa_a,
111*3d8817e4Smiod   mcfisa_a|mcfhwdiv,
112*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfmac,
113*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfemac,
114*3d8817e4Smiod   mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp,
115*3d8817e4Smiod   mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp|mcfmac,
116*3d8817e4Smiod   mcfisa_a|mcfisa_aa|mcfhwdiv|mcfusp|mcfemac,
117*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b,
118*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfmac,
119*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfemac,
120*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp,
121*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|mcfmac,
122*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|mcfemac,
123*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|cfloat,
124*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|cfloat|mcfmac,
125*3d8817e4Smiod   mcfisa_a|mcfhwdiv|mcfisa_b|mcfusp|cfloat|mcfemac,
126*3d8817e4Smiod };
127*3d8817e4Smiod 
128*3d8817e4Smiod /* Return the count of bits set in MASK  */
129*3d8817e4Smiod static unsigned
bit_count(unsigned mask)130*3d8817e4Smiod bit_count (unsigned mask)
131*3d8817e4Smiod {
132*3d8817e4Smiod   unsigned ix;
133*3d8817e4Smiod 
134*3d8817e4Smiod   for (ix = 0; mask; ix++)
135*3d8817e4Smiod     /* Clear the LSB set */
136*3d8817e4Smiod     mask ^= mask & -mask;
137*3d8817e4Smiod   return ix;
138*3d8817e4Smiod }
139*3d8817e4Smiod 
140*3d8817e4Smiod /* Return the architectural features supported by MACH */
141*3d8817e4Smiod 
142*3d8817e4Smiod unsigned
bfd_m68k_mach_to_features(int mach)143*3d8817e4Smiod bfd_m68k_mach_to_features (int mach)
144*3d8817e4Smiod {
145*3d8817e4Smiod   if ((unsigned)mach
146*3d8817e4Smiod       >= sizeof (m68k_arch_features) / sizeof (m68k_arch_features[0]))
147*3d8817e4Smiod     mach = 0;
148*3d8817e4Smiod   return m68k_arch_features[mach];
149*3d8817e4Smiod }
150*3d8817e4Smiod 
151*3d8817e4Smiod /* Return the bfd machine that most closely represents the
152*3d8817e4Smiod    architectural features.  We find the machine with the smallest
153*3d8817e4Smiod    number of additional features.  If there is no such machine, we
154*3d8817e4Smiod    find the one with the smallest number of missing features.  */
155*3d8817e4Smiod 
bfd_m68k_features_to_mach(unsigned features)156*3d8817e4Smiod int bfd_m68k_features_to_mach (unsigned features)
157*3d8817e4Smiod {
158*3d8817e4Smiod   int superset = 0, subset = 0;
159*3d8817e4Smiod   unsigned extra = 99, missing = 99;
160*3d8817e4Smiod   unsigned ix;
161*3d8817e4Smiod 
162*3d8817e4Smiod   for (ix = 0;
163*3d8817e4Smiod        ix != sizeof (m68k_arch_features) / sizeof (m68k_arch_features[0]);
164*3d8817e4Smiod        ix++)
165*3d8817e4Smiod     {
166*3d8817e4Smiod       unsigned this_extra, this_missing;
167*3d8817e4Smiod 
168*3d8817e4Smiod       if (m68k_arch_features[ix] == features)
169*3d8817e4Smiod 	return ix;
170*3d8817e4Smiod       this_extra = bit_count (m68k_arch_features[ix] & ~features);
171*3d8817e4Smiod       if (this_extra < extra)
172*3d8817e4Smiod 	{
173*3d8817e4Smiod 	  extra = this_extra;
174*3d8817e4Smiod 	  superset = ix;
175*3d8817e4Smiod 	}
176*3d8817e4Smiod 
177*3d8817e4Smiod       this_missing = bit_count (features & ~m68k_arch_features[ix]);
178*3d8817e4Smiod       if (this_missing < missing)
179*3d8817e4Smiod 	{
180*3d8817e4Smiod 	  missing = this_missing;
181*3d8817e4Smiod 	  superset = ix;
182*3d8817e4Smiod 	}
183*3d8817e4Smiod     }
184*3d8817e4Smiod   return superset ? superset : subset;
185*3d8817e4Smiod }
186*3d8817e4Smiod 
187*3d8817e4Smiod static const bfd_arch_info_type *
bfd_m68k_compatible(const bfd_arch_info_type * a,const bfd_arch_info_type * b)188*3d8817e4Smiod bfd_m68k_compatible (const bfd_arch_info_type *a,
189*3d8817e4Smiod 		     const bfd_arch_info_type *b)
190*3d8817e4Smiod {
191*3d8817e4Smiod   if (a->arch != b->arch)
192*3d8817e4Smiod     return NULL;
193*3d8817e4Smiod 
194*3d8817e4Smiod   if (a->bits_per_word != b->bits_per_word)
195*3d8817e4Smiod     return NULL;
196*3d8817e4Smiod 
197*3d8817e4Smiod   if (!a->mach)
198*3d8817e4Smiod     return b;
199*3d8817e4Smiod   if (!b->mach)
200*3d8817e4Smiod     return a;
201*3d8817e4Smiod 
202*3d8817e4Smiod   if (a->mach <= bfd_mach_m68060 && b->mach <= bfd_mach_m68060)
203*3d8817e4Smiod     /* Merge m68k machine. */
204*3d8817e4Smiod     return a->mach > b->mach ? a : b;
205*3d8817e4Smiod   else if (a->mach >= bfd_mach_mcf_isa_a_nodiv
206*3d8817e4Smiod 	   && b->mach >= bfd_mach_mcf_isa_a_nodiv)
207*3d8817e4Smiod     {
208*3d8817e4Smiod       /* Merge cf machine.  */
209*3d8817e4Smiod       unsigned features = (bfd_m68k_mach_to_features (a->mach)
210*3d8817e4Smiod 			   | bfd_m68k_mach_to_features (b->mach));
211*3d8817e4Smiod 
212*3d8817e4Smiod       /* ISA A+ and ISA B are incompatible.  */
213*3d8817e4Smiod       if ((~features & (mcfisa_aa | mcfisa_b)) == 0)
214*3d8817e4Smiod 	return NULL;
215*3d8817e4Smiod 
216*3d8817e4Smiod       /* MAC and EMAC code cannot be merged.  */
217*3d8817e4Smiod       if ((~features & (mcfmac | mcfemac)) == 0)
218*3d8817e4Smiod 	return NULL;
219*3d8817e4Smiod 
220*3d8817e4Smiod       return bfd_lookup_arch (a->arch, bfd_m68k_features_to_mach (features));
221*3d8817e4Smiod     }
222*3d8817e4Smiod   else
223*3d8817e4Smiod     /* They are incompatible.  */
224*3d8817e4Smiod     return NULL;
225*3d8817e4Smiod }
226