15796c8dcSSimon Schubert /* BFD support for the Intel 386 architecture.
25796c8dcSSimon Schubert Copyright 1992, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2004, 2005,
3c50c785cSJohn Marino 2007, 2009, 2010, 2011
45796c8dcSSimon Schubert Free Software Foundation, Inc.
55796c8dcSSimon Schubert
65796c8dcSSimon Schubert This file is part of BFD, the Binary File Descriptor library.
75796c8dcSSimon Schubert
85796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
95796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
105796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
115796c8dcSSimon Schubert (at your option) any later version.
125796c8dcSSimon Schubert
135796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
145796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
155796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
165796c8dcSSimon Schubert GNU General Public License for more details.
175796c8dcSSimon Schubert
185796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
195796c8dcSSimon Schubert along with this program; if not, write to the Free Software
205796c8dcSSimon Schubert Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
215796c8dcSSimon Schubert MA 02110-1301, USA. */
225796c8dcSSimon Schubert
235796c8dcSSimon Schubert #include "sysdep.h"
245796c8dcSSimon Schubert #include "bfd.h"
255796c8dcSSimon Schubert #include "libbfd.h"
26*ef5ccd6cSJohn Marino #include "libiberty.h"
27*ef5ccd6cSJohn Marino
28*ef5ccd6cSJohn Marino extern void * bfd_arch_i386_short_nop_fill (bfd_size_type, bfd_boolean,
29*ef5ccd6cSJohn Marino bfd_boolean);
305796c8dcSSimon Schubert
31c50c785cSJohn Marino static const bfd_arch_info_type *
bfd_i386_compatible(const bfd_arch_info_type * a,const bfd_arch_info_type * b)32c50c785cSJohn Marino bfd_i386_compatible (const bfd_arch_info_type *a,
33c50c785cSJohn Marino const bfd_arch_info_type *b)
34c50c785cSJohn Marino {
35c50c785cSJohn Marino const bfd_arch_info_type *compat = bfd_default_compatible (a, b);
36c50c785cSJohn Marino
37c50c785cSJohn Marino /* Don't allow mixing x64_32 with x86_64. */
38a45ae5f8SJohn Marino if (compat
39a45ae5f8SJohn Marino && (a->mach & bfd_mach_x64_32) != (b->mach & bfd_mach_x64_32))
40c50c785cSJohn Marino compat = NULL;
41c50c785cSJohn Marino
42c50c785cSJohn Marino return compat;
43c50c785cSJohn Marino }
44c50c785cSJohn Marino
45*ef5ccd6cSJohn Marino /* Fill the buffer with zero or nop instruction if CODE is TRUE. Use
46*ef5ccd6cSJohn Marino multi byte nop instructions if LONG_NOP is TRUE. */
47*ef5ccd6cSJohn Marino
48*ef5ccd6cSJohn Marino static void *
bfd_arch_i386_fill(bfd_size_type count,bfd_boolean code,bfd_boolean long_nop)49*ef5ccd6cSJohn Marino bfd_arch_i386_fill (bfd_size_type count, bfd_boolean code,
50*ef5ccd6cSJohn Marino bfd_boolean long_nop)
51*ef5ccd6cSJohn Marino {
52*ef5ccd6cSJohn Marino /* nop */
53*ef5ccd6cSJohn Marino static const char nop_1[] = { 0x90 };
54*ef5ccd6cSJohn Marino /* xchg %ax,%ax */
55*ef5ccd6cSJohn Marino static const char nop_2[] = { 0x66, 0x90 };
56*ef5ccd6cSJohn Marino /* nopl (%[re]ax) */
57*ef5ccd6cSJohn Marino static const char nop_3[] = { 0x0f, 0x1f, 0x00 };
58*ef5ccd6cSJohn Marino /* nopl 0(%[re]ax) */
59*ef5ccd6cSJohn Marino static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 };
60*ef5ccd6cSJohn Marino /* nopl 0(%[re]ax,%[re]ax,1) */
61*ef5ccd6cSJohn Marino static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
62*ef5ccd6cSJohn Marino /* nopw 0(%[re]ax,%[re]ax,1) */
63*ef5ccd6cSJohn Marino static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 };
64*ef5ccd6cSJohn Marino /* nopl 0L(%[re]ax) */
65*ef5ccd6cSJohn Marino static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 };
66*ef5ccd6cSJohn Marino /* nopl 0L(%[re]ax,%[re]ax,1) */
67*ef5ccd6cSJohn Marino static const char nop_8[] =
68*ef5ccd6cSJohn Marino { 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
69*ef5ccd6cSJohn Marino /* nopw 0L(%[re]ax,%[re]ax,1) */
70*ef5ccd6cSJohn Marino static const char nop_9[] =
71*ef5ccd6cSJohn Marino { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
72*ef5ccd6cSJohn Marino /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
73*ef5ccd6cSJohn Marino static const char nop_10[] =
74*ef5ccd6cSJohn Marino { 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
75*ef5ccd6cSJohn Marino static const char *const nops[] =
76*ef5ccd6cSJohn Marino { nop_1, nop_2, nop_3, nop_4, nop_5,
77*ef5ccd6cSJohn Marino nop_6, nop_7, nop_8, nop_9, nop_10 };
78*ef5ccd6cSJohn Marino bfd_size_type nop_size = long_nop ? ARRAY_SIZE (nops) : 2;
79*ef5ccd6cSJohn Marino
80*ef5ccd6cSJohn Marino void *fill = bfd_malloc (count);
81*ef5ccd6cSJohn Marino if (fill == NULL)
82*ef5ccd6cSJohn Marino return fill;
83*ef5ccd6cSJohn Marino
84*ef5ccd6cSJohn Marino if (code)
85*ef5ccd6cSJohn Marino {
86*ef5ccd6cSJohn Marino bfd_byte *p = fill;
87*ef5ccd6cSJohn Marino while (count >= nop_size)
88*ef5ccd6cSJohn Marino {
89*ef5ccd6cSJohn Marino memcpy (p, nops[nop_size - 1], nop_size);
90*ef5ccd6cSJohn Marino p += nop_size;
91*ef5ccd6cSJohn Marino count -= nop_size;
92*ef5ccd6cSJohn Marino }
93*ef5ccd6cSJohn Marino if (count != 0)
94*ef5ccd6cSJohn Marino memcpy (p, nops[count - 1], count);
95*ef5ccd6cSJohn Marino }
96*ef5ccd6cSJohn Marino else
97*ef5ccd6cSJohn Marino memset (fill, 0, count);
98*ef5ccd6cSJohn Marino
99*ef5ccd6cSJohn Marino return fill;
100*ef5ccd6cSJohn Marino }
101*ef5ccd6cSJohn Marino
102*ef5ccd6cSJohn Marino /* Fill the buffer with zero or short nop instruction if CODE is TRUE. */
103*ef5ccd6cSJohn Marino
104*ef5ccd6cSJohn Marino void *
bfd_arch_i386_short_nop_fill(bfd_size_type count,bfd_boolean is_bigendian ATTRIBUTE_UNUSED,bfd_boolean code)105*ef5ccd6cSJohn Marino bfd_arch_i386_short_nop_fill (bfd_size_type count,
106*ef5ccd6cSJohn Marino bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
107*ef5ccd6cSJohn Marino bfd_boolean code)
108*ef5ccd6cSJohn Marino {
109*ef5ccd6cSJohn Marino return bfd_arch_i386_fill (count, code, FALSE);
110*ef5ccd6cSJohn Marino }
111*ef5ccd6cSJohn Marino
112*ef5ccd6cSJohn Marino /* Fill the buffer with zero or long nop instruction if CODE is TRUE. */
113*ef5ccd6cSJohn Marino
114*ef5ccd6cSJohn Marino static void *
bfd_arch_i386_long_nop_fill(bfd_size_type count,bfd_boolean is_bigendian ATTRIBUTE_UNUSED,bfd_boolean code)115*ef5ccd6cSJohn Marino bfd_arch_i386_long_nop_fill (bfd_size_type count,
116*ef5ccd6cSJohn Marino bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
117*ef5ccd6cSJohn Marino bfd_boolean code)
118*ef5ccd6cSJohn Marino {
119*ef5ccd6cSJohn Marino return bfd_arch_i386_fill (count, code, TRUE);
120*ef5ccd6cSJohn Marino }
121*ef5ccd6cSJohn Marino
122c50c785cSJohn Marino static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax =
123c50c785cSJohn Marino {
124c50c785cSJohn Marino 64, /* 64 bits in a word */
125a45ae5f8SJohn Marino 64, /* 64 bits in an address */
126c50c785cSJohn Marino 8, /* 8 bits in a byte */
127c50c785cSJohn Marino bfd_arch_i386,
128c50c785cSJohn Marino bfd_mach_x64_32_intel_syntax,
129c50c785cSJohn Marino "i386:intel",
130c50c785cSJohn Marino "i386:x64-32:intel",
131c50c785cSJohn Marino 3,
132c50c785cSJohn Marino FALSE,
133c50c785cSJohn Marino bfd_i386_compatible,
134c50c785cSJohn Marino bfd_default_scan,
135*ef5ccd6cSJohn Marino bfd_arch_i386_long_nop_fill,
136c50c785cSJohn Marino 0
137c50c785cSJohn Marino };
138c50c785cSJohn Marino
1395796c8dcSSimon Schubert static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax =
1405796c8dcSSimon Schubert {
1415796c8dcSSimon Schubert 64, /* 64 bits in a word */
1425796c8dcSSimon Schubert 64, /* 64 bits in an address */
1435796c8dcSSimon Schubert 8, /* 8 bits in a byte */
1445796c8dcSSimon Schubert bfd_arch_i386,
1455796c8dcSSimon Schubert bfd_mach_x86_64_intel_syntax,
1465796c8dcSSimon Schubert "i386:intel",
1475796c8dcSSimon Schubert "i386:x86-64:intel",
1485796c8dcSSimon Schubert 3,
1495796c8dcSSimon Schubert FALSE,
150c50c785cSJohn Marino bfd_i386_compatible,
1515796c8dcSSimon Schubert bfd_default_scan,
152*ef5ccd6cSJohn Marino bfd_arch_i386_long_nop_fill,
153c50c785cSJohn Marino &bfd_x64_32_arch_intel_syntax,
1545796c8dcSSimon Schubert };
1555796c8dcSSimon Schubert
1565796c8dcSSimon Schubert static const bfd_arch_info_type bfd_i386_arch_intel_syntax =
1575796c8dcSSimon Schubert {
1585796c8dcSSimon Schubert 32, /* 32 bits in a word */
1595796c8dcSSimon Schubert 32, /* 32 bits in an address */
1605796c8dcSSimon Schubert 8, /* 8 bits in a byte */
1615796c8dcSSimon Schubert bfd_arch_i386,
1625796c8dcSSimon Schubert bfd_mach_i386_i386_intel_syntax,
1635796c8dcSSimon Schubert "i386:intel",
1645796c8dcSSimon Schubert "i386:intel",
1655796c8dcSSimon Schubert 3,
1665796c8dcSSimon Schubert TRUE,
167c50c785cSJohn Marino bfd_i386_compatible,
1685796c8dcSSimon Schubert bfd_default_scan,
169*ef5ccd6cSJohn Marino bfd_arch_i386_short_nop_fill,
1705796c8dcSSimon Schubert &bfd_x86_64_arch_intel_syntax
1715796c8dcSSimon Schubert };
1725796c8dcSSimon Schubert
1735796c8dcSSimon Schubert static const bfd_arch_info_type i8086_arch =
1745796c8dcSSimon Schubert {
1755796c8dcSSimon Schubert 32, /* 32 bits in a word */
1765796c8dcSSimon Schubert 32, /* 32 bits in an address (well, not really) */
1775796c8dcSSimon Schubert 8, /* 8 bits in a byte */
1785796c8dcSSimon Schubert bfd_arch_i386,
1795796c8dcSSimon Schubert bfd_mach_i386_i8086,
1805796c8dcSSimon Schubert "i8086",
1815796c8dcSSimon Schubert "i8086",
1825796c8dcSSimon Schubert 3,
1835796c8dcSSimon Schubert FALSE,
184c50c785cSJohn Marino bfd_i386_compatible,
1855796c8dcSSimon Schubert bfd_default_scan,
186*ef5ccd6cSJohn Marino bfd_arch_i386_short_nop_fill,
1875796c8dcSSimon Schubert &bfd_i386_arch_intel_syntax
1885796c8dcSSimon Schubert };
1895796c8dcSSimon Schubert
190c50c785cSJohn Marino static const bfd_arch_info_type bfd_x64_32_arch =
191c50c785cSJohn Marino {
192c50c785cSJohn Marino 64, /* 64 bits in a word */
193a45ae5f8SJohn Marino 64, /* 64 bits in an address */
194c50c785cSJohn Marino 8, /* 8 bits in a byte */
195c50c785cSJohn Marino bfd_arch_i386,
196c50c785cSJohn Marino bfd_mach_x64_32,
197c50c785cSJohn Marino "i386",
198c50c785cSJohn Marino "i386:x64-32",
199c50c785cSJohn Marino 3,
200c50c785cSJohn Marino FALSE,
201c50c785cSJohn Marino bfd_i386_compatible,
202c50c785cSJohn Marino bfd_default_scan,
203*ef5ccd6cSJohn Marino bfd_arch_i386_long_nop_fill,
204c50c785cSJohn Marino &i8086_arch
205c50c785cSJohn Marino };
206c50c785cSJohn Marino
2075796c8dcSSimon Schubert static const bfd_arch_info_type bfd_x86_64_arch =
2085796c8dcSSimon Schubert {
2095796c8dcSSimon Schubert 64, /* 64 bits in a word */
2105796c8dcSSimon Schubert 64, /* 64 bits in an address */
2115796c8dcSSimon Schubert 8, /* 8 bits in a byte */
2125796c8dcSSimon Schubert bfd_arch_i386,
2135796c8dcSSimon Schubert bfd_mach_x86_64,
2145796c8dcSSimon Schubert "i386",
2155796c8dcSSimon Schubert "i386:x86-64",
2165796c8dcSSimon Schubert 3,
2175796c8dcSSimon Schubert FALSE,
218c50c785cSJohn Marino bfd_i386_compatible,
2195796c8dcSSimon Schubert bfd_default_scan,
220*ef5ccd6cSJohn Marino bfd_arch_i386_long_nop_fill,
221c50c785cSJohn Marino &bfd_x64_32_arch
2225796c8dcSSimon Schubert };
2235796c8dcSSimon Schubert
2245796c8dcSSimon Schubert const bfd_arch_info_type bfd_i386_arch =
2255796c8dcSSimon Schubert {
2265796c8dcSSimon Schubert 32, /* 32 bits in a word */
2275796c8dcSSimon Schubert 32, /* 32 bits in an address */
2285796c8dcSSimon Schubert 8, /* 8 bits in a byte */
2295796c8dcSSimon Schubert bfd_arch_i386,
2305796c8dcSSimon Schubert bfd_mach_i386_i386,
2315796c8dcSSimon Schubert "i386",
2325796c8dcSSimon Schubert "i386",
2335796c8dcSSimon Schubert 3,
2345796c8dcSSimon Schubert TRUE,
235c50c785cSJohn Marino bfd_i386_compatible,
2365796c8dcSSimon Schubert bfd_default_scan,
237*ef5ccd6cSJohn Marino bfd_arch_i386_short_nop_fill,
2385796c8dcSSimon Schubert &bfd_x86_64_arch
2395796c8dcSSimon Schubert };
240