Support arch-dependent fill
[external/binutils.git] / bfd / cpu-i386.c
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_fill (bfd_size_type, bfd_boolean, bfd_boolean);
29
30 static const bfd_arch_info_type *
31 bfd_i386_compatible (const bfd_arch_info_type *a,
32                      const bfd_arch_info_type *b)
33 {
34   const bfd_arch_info_type *compat = bfd_default_compatible (a, b);
35
36   /* Don't allow mixing x64_32 with x86_64.  */
37   if (compat
38       && (a->mach & bfd_mach_x64_32) != (b->mach & bfd_mach_x64_32))
39     compat = NULL;
40
41   return compat;
42 }
43
44 /* Fill the buffer with zero or nop instruction if CODE is TRUE.  */
45
46 void *
47 bfd_arch_i386_fill (bfd_size_type count,
48                     bfd_boolean is_bigendian ATTRIBUTE_UNUSED,
49                     bfd_boolean code)
50 {
51   /* nop */
52   static const char nop_1[] = { 0x90 }; 
53   /* nopw */
54   static const char nop_2[] = { 0x66, 0x90 };
55   /* nopl (%[re]ax) */
56   static const char nop_3[] = { 0x0f, 0x1f, 0x00 };
57   /* nopl 0(%[re]ax) */
58   static const char nop_4[] = { 0x0f, 0x1f, 0x40, 0x00 };
59   /* nopl 0(%[re]ax,%[re]ax,1) */
60   static const char nop_5[] = { 0x0f, 0x1f, 0x44, 0x00, 0x00 };
61   /* nopw 0(%[re]ax,%[re]ax,1) */
62   static const char nop_6[] = { 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 };
63   /* nopl 0L(%[re]ax) */
64   static const char nop_7[] = { 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 };
65   /* nopl 0L(%[re]ax,%[re]ax,1) */
66   static const char nop_8[] =
67     { 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00};
68   /* nopw 0L(%[re]ax,%[re]ax,1) */
69   static const char nop_9[] =
70     { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
71   /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
72   static const char nop_10[] =
73     { 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
74   static const char *const nops[] =
75     { nop_1, nop_2, nop_3, nop_4, nop_5,
76       nop_6, nop_7, nop_8, nop_9, nop_10 };
77
78   void *fill = bfd_malloc (count);
79   if (fill == NULL)
80     return fill;
81
82   if (code)
83     {
84       bfd_byte *p = fill;
85       while (count >= ARRAY_SIZE (nops))
86         {
87           memcpy (p, nops[ARRAY_SIZE (nops) - 1], ARRAY_SIZE (nops));
88           p += ARRAY_SIZE (nops);
89           count -= ARRAY_SIZE (nops);
90         }
91       if (count != 0)
92         memcpy (p, nops[count - 1], count);
93     }
94   else
95     memset (fill, 0, count);
96
97   return fill;
98 }
99
100 static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax =
101 {
102   64, /* 64 bits in a word */
103   64, /* 64 bits in an address */
104   8,  /* 8 bits in a byte */
105   bfd_arch_i386,
106   bfd_mach_x64_32_intel_syntax,
107   "i386:intel",
108   "i386:x64-32:intel",
109   3,
110   FALSE,
111   bfd_i386_compatible,
112   bfd_default_scan,
113   bfd_arch_i386_fill,
114   0
115 };
116
117 static const bfd_arch_info_type bfd_x86_64_arch_intel_syntax =
118 {
119   64, /* 64 bits in a word */
120   64, /* 64 bits in an address */
121   8,  /* 8 bits in a byte */
122   bfd_arch_i386,
123   bfd_mach_x86_64_intel_syntax,
124   "i386:intel",
125   "i386:x86-64:intel",
126   3,
127   FALSE,
128   bfd_i386_compatible,
129   bfd_default_scan,
130   bfd_arch_i386_fill,
131   &bfd_x64_32_arch_intel_syntax,
132 };
133
134 static const bfd_arch_info_type bfd_i386_arch_intel_syntax =
135 {
136   32,   /* 32 bits in a word */
137   32,   /* 32 bits in an address */
138   8,    /* 8 bits in a byte */
139   bfd_arch_i386,
140   bfd_mach_i386_i386_intel_syntax,
141   "i386:intel",
142   "i386:intel",
143   3,
144   TRUE,
145   bfd_i386_compatible,
146   bfd_default_scan,
147   bfd_arch_i386_fill,
148   &bfd_x86_64_arch_intel_syntax
149 };
150
151 static const bfd_arch_info_type i8086_arch =
152 {
153   32,   /* 32 bits in a word */
154   32,   /* 32 bits in an address (well, not really) */
155   8,    /* 8 bits in a byte */
156   bfd_arch_i386,
157   bfd_mach_i386_i8086,
158   "i8086",
159   "i8086",
160   3,
161   FALSE,
162   bfd_i386_compatible,
163   bfd_default_scan,
164   bfd_arch_i386_fill,
165   &bfd_i386_arch_intel_syntax
166 };
167
168 static const bfd_arch_info_type bfd_x64_32_arch =
169 {
170   64, /* 64 bits in a word */
171   64, /* 64 bits in an address */
172   8,  /* 8 bits in a byte */
173   bfd_arch_i386,
174   bfd_mach_x64_32,
175   "i386",
176   "i386:x64-32",
177   3,
178   FALSE,
179   bfd_i386_compatible,
180   bfd_default_scan,
181   bfd_arch_i386_fill,
182   &i8086_arch
183 };
184
185 static const bfd_arch_info_type bfd_x86_64_arch =
186 {
187   64, /* 64 bits in a word */
188   64, /* 64 bits in an address */
189   8,  /* 8 bits in a byte */
190   bfd_arch_i386,
191   bfd_mach_x86_64,
192   "i386",
193   "i386:x86-64",
194   3,
195   FALSE,
196   bfd_i386_compatible,
197   bfd_default_scan,
198   bfd_arch_i386_fill,
199   &bfd_x64_32_arch
200 };
201
202 const bfd_arch_info_type bfd_i386_arch =
203 {
204   32,   /* 32 bits in a word */
205   32,   /* 32 bits in an address */
206   8,    /* 8 bits in a byte */
207   bfd_arch_i386,
208   bfd_mach_i386_i386,
209   "i386",
210   "i386",
211   3,
212   TRUE,
213   bfd_i386_compatible,
214   bfd_default_scan,
215   bfd_arch_i386_fill,
216   &bfd_x86_64_arch
217 };