xref: /dragonfly/contrib/gdb-7/bfd/cpu-i386.c (revision 8af44722)
1 /* BFD support for the Intel 386 architecture.
2    Copyright 1992, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2004, 2005,
3    2007, 2009, 2010, 2011
4    Free Software Foundation, Inc.
5 
6    This file is part of BFD, the Binary File Descriptor library.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22 
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #include "libiberty.h"
27 
28 extern void * bfd_arch_i386_short_nop_fill (bfd_size_type, bfd_boolean,
29 					    bfd_boolean);
30 
31 static const bfd_arch_info_type *
32 bfd_i386_compatible (const bfd_arch_info_type *a,
33 		     const bfd_arch_info_type *b)
34 {
35   const bfd_arch_info_type *compat = bfd_default_compatible (a, b);
36 
37   /* Don't allow mixing x64_32 with x86_64.  */
38   if (compat
39       && (a->mach & bfd_mach_x64_32) != (b->mach & bfd_mach_x64_32))
40     compat = NULL;
41 
42   return compat;
43 }
44 
45 /* Fill the buffer with zero or nop instruction if CODE is TRUE.  Use
46    multi byte nop instructions if LONG_NOP is TRUE.  */
47 
48 static void *
49 bfd_arch_i386_fill (bfd_size_type count, bfd_boolean code,
50 		    bfd_boolean long_nop)
51 {
52   /* nop */
53   static const char nop_1[] = { 0x90 };
54   /* xchg %ax,%ax */
55   static const char nop_2[] = { 0x66, 0x90 };
56   /* nopl (%[re]ax) */
57   static const char nop_3[] = { 0x0f, 0x1f, 0x00 };
58   /* nopl 0(%[re]ax) */
59   static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 };
60   /* nopl 0(%[re]ax,%[re]ax,1) */
61   static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
62   /* nopw 0(%[re]ax,%[re]ax,1) */
63   static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 };
64   /* nopl 0L(%[re]ax) */
65   static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 };
66   /* nopl 0L(%[re]ax,%[re]ax,1) */
67   static const char nop_8[] =
68     { 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
69   /* nopw 0L(%[re]ax,%[re]ax,1) */
70   static const char nop_9[] =
71     { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
72   /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
73   static const char nop_10[] =
74     { 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
75   static const char *const nops[] =
76     { nop_1, nop_2, nop_3, nop_4, nop_5,
77       nop_6, nop_7, nop_8, nop_9, nop_10 };
78   bfd_size_type nop_size = long_nop ? ARRAY_SIZE (nops) : 2;
79 
80   void *fill = bfd_malloc (count);
81   if (fill == NULL)
82     return fill;
83 
84   if (code)
85     {
86       bfd_byte *p = fill;
87       while (count >= nop_size)
88 	{
89 	  memcpy (p, nops[nop_size - 1], nop_size);
90 	  p += nop_size;
91 	  count -= nop_size;
92 	}
93       if (count != 0)
94 	memcpy (p, nops[count - 1], count);
95     }
96   else
97     memset (fill, 0, count);
98 
99   return fill;
100 }
101 
102 /* Fill the buffer with zero or short nop instruction if CODE is TRUE.  */
103 
104 void *
105 bfd_arch_i386_short_nop_fill (bfd_size_type count,
106 			      bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
107 			      bfd_boolean code)
108 {
109   return bfd_arch_i386_fill (count, code, FALSE);
110 }
111 
112 /* Fill the buffer with zero or long nop instruction if CODE is TRUE.  */
113 
114 static void *
115 bfd_arch_i386_long_nop_fill (bfd_size_type count,
116 			     bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
117 			     bfd_boolean code)
118 {
119   return bfd_arch_i386_fill (count, code, TRUE);
120 }
121 
122 static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax =
123 {
124   64, /* 64 bits in a word */
125   64, /* 64 bits in an address */
126   8,  /* 8 bits in a byte */
127   bfd_arch_i386,
128   bfd_mach_x64_32_intel_syntax,
129   "i386:intel",
130   "i386:x64-32:intel",
131   3,
132   FALSE,
133   bfd_i386_compatible,
134   bfd_default_scan,
135   bfd_arch_i386_long_nop_fill,
136   0
137 };
138 
139 static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax =
140 {
141   64, /* 64 bits in a word */
142   64, /* 64 bits in an address */
143   8,  /* 8 bits in a byte */
144   bfd_arch_i386,
145   bfd_mach_x86_64_intel_syntax,
146   "i386:intel",
147   "i386:x86-64:intel",
148   3,
149   FALSE,
150   bfd_i386_compatible,
151   bfd_default_scan,
152   bfd_arch_i386_long_nop_fill,
153   &bfd_x64_32_arch_intel_syntax,
154 };
155 
156 static const bfd_arch_info_type bfd_i386_arch_intel_syntax =
157 {
158   32,	/* 32 bits in a word */
159   32,	/* 32 bits in an address */
160   8,	/* 8 bits in a byte */
161   bfd_arch_i386,
162   bfd_mach_i386_i386_intel_syntax,
163   "i386:intel",
164   "i386:intel",
165   3,
166   TRUE,
167   bfd_i386_compatible,
168   bfd_default_scan,
169   bfd_arch_i386_short_nop_fill,
170   &bfd_x86_64_arch_intel_syntax
171 };
172 
173 static const bfd_arch_info_type i8086_arch =
174 {
175   32,	/* 32 bits in a word */
176   32,	/* 32 bits in an address (well, not really) */
177   8,	/* 8 bits in a byte */
178   bfd_arch_i386,
179   bfd_mach_i386_i8086,
180   "i8086",
181   "i8086",
182   3,
183   FALSE,
184   bfd_i386_compatible,
185   bfd_default_scan,
186   bfd_arch_i386_short_nop_fill,
187   &bfd_i386_arch_intel_syntax
188 };
189 
190 static const bfd_arch_info_type bfd_x64_32_arch =
191 {
192   64, /* 64 bits in a word */
193   64, /* 64 bits in an address */
194   8,  /* 8 bits in a byte */
195   bfd_arch_i386,
196   bfd_mach_x64_32,
197   "i386",
198   "i386:x64-32",
199   3,
200   FALSE,
201   bfd_i386_compatible,
202   bfd_default_scan,
203   bfd_arch_i386_long_nop_fill,
204   &i8086_arch
205 };
206 
207 static const bfd_arch_info_type bfd_x86_64_arch =
208 {
209   64, /* 64 bits in a word */
210   64, /* 64 bits in an address */
211   8,  /* 8 bits in a byte */
212   bfd_arch_i386,
213   bfd_mach_x86_64,
214   "i386",
215   "i386:x86-64",
216   3,
217   FALSE,
218   bfd_i386_compatible,
219   bfd_default_scan,
220   bfd_arch_i386_long_nop_fill,
221   &bfd_x64_32_arch
222 };
223 
224 const bfd_arch_info_type bfd_i386_arch =
225 {
226   32,	/* 32 bits in a word */
227   32,	/* 32 bits in an address */
228   8,	/* 8 bits in a byte */
229   bfd_arch_i386,
230   bfd_mach_i386_i386,
231   "i386",
232   "i386",
233   3,
234   TRUE,
235   bfd_i386_compatible,
236   bfd_default_scan,
237   bfd_arch_i386_short_nop_fill,
238   &bfd_x86_64_arch
239 };
240