xref: /dflybsd-src/contrib/gdb-7/bfd/cpu-i386.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
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