OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [cpu-arm.c] - Blame information for rev 146

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 khays
/* BFD support for the ARM processor
2
   Copyright 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007,
3
   2009, 2010 Free Software Foundation, Inc.
4
   Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
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
/* This routine is provided two arch_infos and works out which ARM
29
   machine which would be compatible with both and returns a pointer
30
   to its info structure.  */
31
 
32
static const bfd_arch_info_type *
33
compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b)
34
{
35
  /* If a & b are for different architecture we can do nothing.  */
36
  if (a->arch != b->arch)
37
      return NULL;
38
 
39
  /* If a & b are for the same machine then all is well.  */
40
  if (a->mach == b->mach)
41
    return a;
42
 
43
  /* Otherwise if either a or b is the 'default' machine
44
     then it can be polymorphed into the other.  */
45
  if (a->the_default)
46
    return b;
47
 
48
  if (b->the_default)
49
    return a;
50
 
51
  /* So far all newer ARM architecture cores are
52
     supersets of previous cores.  */
53
  if (a->mach < b->mach)
54
    return b;
55
  else if (a->mach > b->mach)
56
    return a;
57
 
58
  /* Never reached!  */
59
  return NULL;
60
}
61
 
62
static struct
63
{
64
  unsigned int mach;
65
  char *       name;
66
}
67
processors[] =
68
{
69
  { bfd_mach_arm_2,  "arm2"     },
70
  { bfd_mach_arm_2a, "arm250"   },
71
  { bfd_mach_arm_2a, "arm3"     },
72
  { bfd_mach_arm_3,  "arm6"     },
73
  { bfd_mach_arm_3,  "arm60"    },
74
  { bfd_mach_arm_3,  "arm600"   },
75
  { bfd_mach_arm_3,  "arm610"   },
76
  { bfd_mach_arm_3,  "arm7"     },
77
  { bfd_mach_arm_3,  "arm710"   },
78
  { bfd_mach_arm_3,  "arm7500"  },
79
  { bfd_mach_arm_3,  "arm7d"    },
80
  { bfd_mach_arm_3,  "arm7di"   },
81
  { bfd_mach_arm_3M, "arm7dm"   },
82
  { bfd_mach_arm_3M, "arm7dmi"  },
83
  { bfd_mach_arm_4T, "arm7tdmi" },
84
  { bfd_mach_arm_4,  "arm8"     },
85
  { bfd_mach_arm_4,  "arm810"   },
86
  { bfd_mach_arm_4,  "arm9"     },
87
  { bfd_mach_arm_4,  "arm920"   },
88
  { bfd_mach_arm_4T, "arm920t"  },
89
  { bfd_mach_arm_4T, "arm9tdmi" },
90
  { bfd_mach_arm_4,  "sa1"      },
91
  { bfd_mach_arm_4,  "strongarm"},
92
  { bfd_mach_arm_4,  "strongarm110" },
93
  { bfd_mach_arm_4,  "strongarm1100" },
94
  { bfd_mach_arm_XScale, "xscale" },
95
  { bfd_mach_arm_ep9312, "ep9312" },
96
  { bfd_mach_arm_iWMMXt, "iwmmxt" },
97
  { bfd_mach_arm_iWMMXt2, "iwmmxt2" }
98
};
99
 
100
static bfd_boolean
101
scan (const struct bfd_arch_info *info, const char *string)
102
{
103
  int  i;
104
 
105
  /* First test for an exact match.  */
106
  if (strcasecmp (string, info->printable_name) == 0)
107
    return TRUE;
108
 
109
  /* Next check for a processor name instead of an Architecture name.  */
110
  for (i = sizeof (processors) / sizeof (processors[0]); i--;)
111
    {
112
      if (strcasecmp (string, processors [i].name) == 0)
113
        break;
114
    }
115
 
116
  if (i != -1 && info->mach == processors [i].mach)
117
    return TRUE;
118
 
119
  /* Finally check for the default architecture.  */
120
  if (strcasecmp (string, "arm") == 0)
121
    return info->the_default;
122
 
123
  return FALSE;
124
}
125
 
126
#define N(number, print, default, next)  \
127
{  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, scan, next }
128
 
129
static const bfd_arch_info_type arch_info_struct[] =
130
{
131
  N (bfd_mach_arm_2,      "armv2",   FALSE, & arch_info_struct[1]),
132
  N (bfd_mach_arm_2a,     "armv2a",  FALSE, & arch_info_struct[2]),
133
  N (bfd_mach_arm_3,      "armv3",   FALSE, & arch_info_struct[3]),
134
  N (bfd_mach_arm_3M,     "armv3m",  FALSE, & arch_info_struct[4]),
135
  N (bfd_mach_arm_4,      "armv4",   FALSE, & arch_info_struct[5]),
136
  N (bfd_mach_arm_4T,     "armv4t",  FALSE, & arch_info_struct[6]),
137
  N (bfd_mach_arm_5,      "armv5",   FALSE, & arch_info_struct[7]),
138
  N (bfd_mach_arm_5T,     "armv5t",  FALSE, & arch_info_struct[8]),
139
  N (bfd_mach_arm_5TE,    "armv5te", FALSE, & arch_info_struct[9]),
140
  N (bfd_mach_arm_XScale, "xscale",  FALSE, & arch_info_struct[10]),
141
  N (bfd_mach_arm_ep9312, "ep9312",  FALSE, & arch_info_struct[11]),
142
  N (bfd_mach_arm_iWMMXt, "iwmmxt",  FALSE, & arch_info_struct[12]),
143
  N (bfd_mach_arm_iWMMXt2, "iwmmxt2", FALSE, NULL)
144
};
145
 
146
const bfd_arch_info_type bfd_arm_arch =
147
  N (0, "arm", TRUE, & arch_info_struct[0]);
148
 
149
/* Support functions used by both the COFF and ELF versions of the ARM port.  */
150
 
151
/* Handle the merging of the 'machine' settings of input file IBFD
152
   and an output file OBFD.  These values actually represent the
153
   different possible ARM architecture variants.
154
   Returns TRUE if they were merged successfully or FALSE otherwise.  */
155
 
156
bfd_boolean
157
bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
158
{
159
  unsigned int in  = bfd_get_mach (ibfd);
160
  unsigned int out = bfd_get_mach (obfd);
161
 
162
  /* If the output architecture is unknown, we now have a value to set.  */
163
  if (out == bfd_mach_arm_unknown)
164
    bfd_set_arch_mach (obfd, bfd_arch_arm, in);
165
 
166
  /* If the input architecture is unknown,
167
     then so must be the output architecture.  */
168
  else if (in == bfd_mach_arm_unknown)
169
    /* FIXME: We ought to have some way to
170
       override this on the command line.  */
171
    bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
172
 
173
  /* If they are the same then nothing needs to be done.  */
174
  else if (out == in)
175
    ;
176
 
177
  /* Otherwise the general principle that a earlier architecture can be
178
     linked with a later architecture to produce a binary that will execute
179
     on the later architecture.
180
 
181
     We fail however if we attempt to link a Cirrus EP9312 binary with an
182
     Intel XScale binary, since these architecture have co-processors which
183
     will not both be present on the same physical hardware.  */
184
  else if (in == bfd_mach_arm_ep9312
185
           && (out == bfd_mach_arm_XScale
186
               || out == bfd_mach_arm_iWMMXt
187
               || out == bfd_mach_arm_iWMMXt2))
188
    {
189
      _bfd_error_handler (_("\
190
error: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
191
                          ibfd, obfd);
192
      bfd_set_error (bfd_error_wrong_format);
193
      return FALSE;
194
    }
195
  else if (out == bfd_mach_arm_ep9312
196
           && (in == bfd_mach_arm_XScale
197
               || in == bfd_mach_arm_iWMMXt
198
               || in == bfd_mach_arm_iWMMXt2))
199
    {
200
      _bfd_error_handler (_("\
201
error: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
202
                          obfd, ibfd);
203
      bfd_set_error (bfd_error_wrong_format);
204
      return FALSE;
205
    }
206
  else if (in > out)
207
    bfd_set_arch_mach (obfd, bfd_arch_arm, in);
208
  /* else
209
     Nothing to do.  */
210
 
211
  return TRUE;
212
}
213
 
214
typedef struct
215
{
216
  unsigned char namesz[4];      /* Size of entry's owner string.  */
217
  unsigned char descsz[4];      /* Size of the note descriptor.  */
218
  unsigned char type[4];        /* Interpretation of the descriptor.  */
219
  char          name[1];        /* Start of the name+desc data.  */
220
} arm_Note;
221
 
222
static bfd_boolean
223
arm_check_note (bfd *abfd,
224
                bfd_byte *buffer,
225
                bfd_size_type buffer_size,
226
                const char *expected_name,
227
                char **description_return)
228
{
229
  unsigned long namesz;
230
  unsigned long descsz;
231
  unsigned long type;
232
  char *        descr;
233
 
234
  if (buffer_size < offsetof (arm_Note, name))
235
    return FALSE;
236
 
237
  /* We have to extract the values this way to allow for a
238
     host whose endian-ness is different from the target.  */
239
  namesz = bfd_get_32 (abfd, buffer);
240
  descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
241
  type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
242
  descr  = (char *) buffer + offsetof (arm_Note, name);
243
 
244
  /* Check for buffer overflow.  */
245
  if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
246
    return FALSE;
247
 
248
  if (expected_name == NULL)
249
    {
250
      if (namesz != 0)
251
        return FALSE;
252
    }
253
  else
254
    {
255
      if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
256
        return FALSE;
257
 
258
      if (strcmp (descr, expected_name) != 0)
259
        return FALSE;
260
 
261
      descr += (namesz + 3) & ~3;
262
    }
263
 
264
  /* FIXME: We should probably check the type as well.  */
265
  (void) type;
266
 
267
  if (description_return != NULL)
268
    * description_return = descr;
269
 
270
  return TRUE;
271
}
272
 
273
#define NOTE_ARCH_STRING        "arch: "
274
 
275
bfd_boolean
276
bfd_arm_update_notes (bfd *abfd, const char *note_section)
277
{
278
  asection *     arm_arch_section;
279
  bfd_size_type  buffer_size;
280
  bfd_byte *     buffer;
281
  char *         arch_string;
282
  char *         expected;
283
 
284
  /* Look for a note section.  If one is present check the architecture
285
     string encoded in it, and set it to the current architecture if it is
286
     different.  */
287
  arm_arch_section = bfd_get_section_by_name (abfd, note_section);
288
 
289
  if (arm_arch_section == NULL)
290
    return TRUE;
291
 
292
  buffer_size = arm_arch_section->size;
293
  if (buffer_size == 0)
294
    return FALSE;
295
 
296
  if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
297
    goto FAIL;
298
 
299
  /* Parse the note.  */
300
  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
301
    goto FAIL;
302
 
303
  /* Check the architecture in the note against the architecture of the bfd.  */
304
  switch (bfd_get_mach (abfd))
305
    {
306
    default:
307
    case bfd_mach_arm_unknown: expected = "unknown"; break;
308
    case bfd_mach_arm_2:       expected = "armv2"; break;
309
    case bfd_mach_arm_2a:      expected = "armv2a"; break;
310
    case bfd_mach_arm_3:       expected = "armv3"; break;
311
    case bfd_mach_arm_3M:      expected = "armv3M"; break;
312
    case bfd_mach_arm_4:       expected = "armv4"; break;
313
    case bfd_mach_arm_4T:      expected = "armv4t"; break;
314
    case bfd_mach_arm_5:       expected = "armv5"; break;
315
    case bfd_mach_arm_5T:      expected = "armv5t"; break;
316
    case bfd_mach_arm_5TE:     expected = "armv5te"; break;
317
    case bfd_mach_arm_XScale:  expected = "XScale"; break;
318
    case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
319
    case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
320
    case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
321
    }
322
 
323
  if (strcmp (arch_string, expected) != 0)
324
    {
325
      strcpy ((char *) buffer + (offsetof (arm_Note, name)
326
                                 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
327
              expected);
328
 
329
      if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
330
                                      (file_ptr) 0, buffer_size))
331
        {
332
          (*_bfd_error_handler)
333
            (_("warning: unable to update contents of %s section in %s"),
334
             note_section, bfd_get_filename (abfd));
335
          goto FAIL;
336
        }
337
    }
338
 
339
  free (buffer);
340
  return TRUE;
341
 
342
 FAIL:
343
  if (buffer != NULL)
344
    free (buffer);
345
  return FALSE;
346
}
347
 
348
 
349
static struct
350
{
351
  const char * string;
352
  unsigned int mach;
353
}
354
architectures[] =
355
{
356
  { "armv2",   bfd_mach_arm_2 },
357
  { "armv2a",  bfd_mach_arm_2a },
358
  { "armv3",   bfd_mach_arm_3 },
359
  { "armv3M",  bfd_mach_arm_3M },
360
  { "armv4",   bfd_mach_arm_4 },
361
  { "armv4t",  bfd_mach_arm_4T },
362
  { "armv5",   bfd_mach_arm_5 },
363
  { "armv5t",  bfd_mach_arm_5T },
364
  { "armv5te", bfd_mach_arm_5TE },
365
  { "XScale",  bfd_mach_arm_XScale },
366
  { "ep9312",  bfd_mach_arm_ep9312 },
367
  { "iWMMXt",  bfd_mach_arm_iWMMXt },
368
  { "iWMMXt2", bfd_mach_arm_iWMMXt2 }
369
};
370
 
371
/* Extract the machine number stored in a note section.  */
372
unsigned int
373
bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
374
{
375
  asection *     arm_arch_section;
376
  bfd_size_type  buffer_size;
377
  bfd_byte *     buffer;
378
  char *         arch_string;
379
  int            i;
380
 
381
  /* Look for a note section.  If one is present check the architecture
382
     string encoded in it, and set it to the current architecture if it is
383
     different.  */
384
  arm_arch_section = bfd_get_section_by_name (abfd, note_section);
385
 
386
  if (arm_arch_section == NULL)
387
    return bfd_mach_arm_unknown;
388
 
389
  buffer_size = arm_arch_section->size;
390
  if (buffer_size == 0)
391
    return bfd_mach_arm_unknown;
392
 
393
  if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
394
    goto FAIL;
395
 
396
  /* Parse the note.  */
397
  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
398
    goto FAIL;
399
 
400
  /* Interpret the architecture string.  */
401
  for (i = ARRAY_SIZE (architectures); i--;)
402
    if (strcmp (arch_string, architectures[i].string) == 0)
403
      {
404
        free (buffer);
405
        return architectures[i].mach;
406
      }
407
 
408
 FAIL:
409
  if (buffer != NULL)
410
    free (buffer);
411
  return bfd_mach_arm_unknown;
412
}
413
 
414
bfd_boolean
415
bfd_is_arm_special_symbol_name (const char * name, int type)
416
{
417
  /* The ARM compiler outputs several obsolete forms.  Recognize them
418
     in addition to the standard $a, $t and $d.  We are somewhat loose
419
     in what we accept here, since the full set is not documented.  */
420
  if (!name || name[0] != '$')
421
    return FALSE;
422
  if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
423
    type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
424
  else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
425
    type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
426
  else if (name[1] >= 'a' && name[1] <= 'z')
427
    type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
428
  else
429
    return FALSE;
430
 
431
  return (type != 0 && (name[2] == 0 || name[2] == '.'));
432
}
433
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.