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 279

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 166 khays
{  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \
128
   scan, bfd_arch_default_fill, next }
129 14 khays
 
130
static const bfd_arch_info_type arch_info_struct[] =
131
{
132
  N (bfd_mach_arm_2,      "armv2",   FALSE, & arch_info_struct[1]),
133
  N (bfd_mach_arm_2a,     "armv2a",  FALSE, & arch_info_struct[2]),
134
  N (bfd_mach_arm_3,      "armv3",   FALSE, & arch_info_struct[3]),
135
  N (bfd_mach_arm_3M,     "armv3m",  FALSE, & arch_info_struct[4]),
136
  N (bfd_mach_arm_4,      "armv4",   FALSE, & arch_info_struct[5]),
137
  N (bfd_mach_arm_4T,     "armv4t",  FALSE, & arch_info_struct[6]),
138
  N (bfd_mach_arm_5,      "armv5",   FALSE, & arch_info_struct[7]),
139
  N (bfd_mach_arm_5T,     "armv5t",  FALSE, & arch_info_struct[8]),
140
  N (bfd_mach_arm_5TE,    "armv5te", FALSE, & arch_info_struct[9]),
141
  N (bfd_mach_arm_XScale, "xscale",  FALSE, & arch_info_struct[10]),
142
  N (bfd_mach_arm_ep9312, "ep9312",  FALSE, & arch_info_struct[11]),
143
  N (bfd_mach_arm_iWMMXt, "iwmmxt",  FALSE, & arch_info_struct[12]),
144
  N (bfd_mach_arm_iWMMXt2, "iwmmxt2", FALSE, NULL)
145
};
146
 
147
const bfd_arch_info_type bfd_arm_arch =
148
  N (0, "arm", TRUE, & arch_info_struct[0]);
149
 
150
/* Support functions used by both the COFF and ELF versions of the ARM port.  */
151
 
152
/* Handle the merging of the 'machine' settings of input file IBFD
153
   and an output file OBFD.  These values actually represent the
154
   different possible ARM architecture variants.
155
   Returns TRUE if they were merged successfully or FALSE otherwise.  */
156
 
157
bfd_boolean
158
bfd_arm_merge_machines (bfd *ibfd, bfd *obfd)
159
{
160
  unsigned int in  = bfd_get_mach (ibfd);
161
  unsigned int out = bfd_get_mach (obfd);
162
 
163
  /* If the output architecture is unknown, we now have a value to set.  */
164
  if (out == bfd_mach_arm_unknown)
165
    bfd_set_arch_mach (obfd, bfd_arch_arm, in);
166
 
167
  /* If the input architecture is unknown,
168
     then so must be the output architecture.  */
169
  else if (in == bfd_mach_arm_unknown)
170
    /* FIXME: We ought to have some way to
171
       override this on the command line.  */
172
    bfd_set_arch_mach (obfd, bfd_arch_arm, bfd_mach_arm_unknown);
173
 
174
  /* If they are the same then nothing needs to be done.  */
175
  else if (out == in)
176
    ;
177
 
178
  /* Otherwise the general principle that a earlier architecture can be
179
     linked with a later architecture to produce a binary that will execute
180
     on the later architecture.
181
 
182
     We fail however if we attempt to link a Cirrus EP9312 binary with an
183
     Intel XScale binary, since these architecture have co-processors which
184
     will not both be present on the same physical hardware.  */
185
  else if (in == bfd_mach_arm_ep9312
186
           && (out == bfd_mach_arm_XScale
187
               || out == bfd_mach_arm_iWMMXt
188
               || out == bfd_mach_arm_iWMMXt2))
189
    {
190
      _bfd_error_handler (_("\
191
error: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
192
                          ibfd, obfd);
193
      bfd_set_error (bfd_error_wrong_format);
194
      return FALSE;
195
    }
196
  else if (out == bfd_mach_arm_ep9312
197
           && (in == bfd_mach_arm_XScale
198
               || in == bfd_mach_arm_iWMMXt
199
               || in == bfd_mach_arm_iWMMXt2))
200
    {
201
      _bfd_error_handler (_("\
202
error: %B is compiled for the EP9312, whereas %B is compiled for XScale"),
203
                          obfd, ibfd);
204
      bfd_set_error (bfd_error_wrong_format);
205
      return FALSE;
206
    }
207
  else if (in > out)
208
    bfd_set_arch_mach (obfd, bfd_arch_arm, in);
209
  /* else
210
     Nothing to do.  */
211
 
212
  return TRUE;
213
}
214
 
215
typedef struct
216
{
217
  unsigned char namesz[4];      /* Size of entry's owner string.  */
218
  unsigned char descsz[4];      /* Size of the note descriptor.  */
219
  unsigned char type[4];        /* Interpretation of the descriptor.  */
220
  char          name[1];        /* Start of the name+desc data.  */
221
} arm_Note;
222
 
223
static bfd_boolean
224
arm_check_note (bfd *abfd,
225
                bfd_byte *buffer,
226
                bfd_size_type buffer_size,
227
                const char *expected_name,
228
                char **description_return)
229
{
230
  unsigned long namesz;
231
  unsigned long descsz;
232
  unsigned long type;
233
  char *        descr;
234
 
235
  if (buffer_size < offsetof (arm_Note, name))
236
    return FALSE;
237
 
238
  /* We have to extract the values this way to allow for a
239
     host whose endian-ness is different from the target.  */
240
  namesz = bfd_get_32 (abfd, buffer);
241
  descsz = bfd_get_32 (abfd, buffer + offsetof (arm_Note, descsz));
242
  type   = bfd_get_32 (abfd, buffer + offsetof (arm_Note, type));
243
  descr  = (char *) buffer + offsetof (arm_Note, name);
244
 
245
  /* Check for buffer overflow.  */
246
  if (namesz + descsz + offsetof (arm_Note, name) > buffer_size)
247
    return FALSE;
248
 
249
  if (expected_name == NULL)
250
    {
251
      if (namesz != 0)
252
        return FALSE;
253
    }
254
  else
255
    {
256
      if (namesz != ((strlen (expected_name) + 1 + 3) & ~3))
257
        return FALSE;
258
 
259
      if (strcmp (descr, expected_name) != 0)
260
        return FALSE;
261
 
262
      descr += (namesz + 3) & ~3;
263
    }
264
 
265
  /* FIXME: We should probably check the type as well.  */
266
  (void) type;
267
 
268
  if (description_return != NULL)
269
    * description_return = descr;
270
 
271
  return TRUE;
272
}
273
 
274
#define NOTE_ARCH_STRING        "arch: "
275
 
276
bfd_boolean
277
bfd_arm_update_notes (bfd *abfd, const char *note_section)
278
{
279
  asection *     arm_arch_section;
280
  bfd_size_type  buffer_size;
281
  bfd_byte *     buffer;
282
  char *         arch_string;
283
  char *         expected;
284
 
285
  /* Look for a note section.  If one is present check the architecture
286
     string encoded in it, and set it to the current architecture if it is
287
     different.  */
288
  arm_arch_section = bfd_get_section_by_name (abfd, note_section);
289
 
290
  if (arm_arch_section == NULL)
291
    return TRUE;
292
 
293
  buffer_size = arm_arch_section->size;
294
  if (buffer_size == 0)
295
    return FALSE;
296
 
297
  if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
298
    goto FAIL;
299
 
300
  /* Parse the note.  */
301
  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
302
    goto FAIL;
303
 
304
  /* Check the architecture in the note against the architecture of the bfd.  */
305
  switch (bfd_get_mach (abfd))
306
    {
307
    default:
308
    case bfd_mach_arm_unknown: expected = "unknown"; break;
309
    case bfd_mach_arm_2:       expected = "armv2"; break;
310
    case bfd_mach_arm_2a:      expected = "armv2a"; break;
311
    case bfd_mach_arm_3:       expected = "armv3"; break;
312
    case bfd_mach_arm_3M:      expected = "armv3M"; break;
313
    case bfd_mach_arm_4:       expected = "armv4"; break;
314
    case bfd_mach_arm_4T:      expected = "armv4t"; break;
315
    case bfd_mach_arm_5:       expected = "armv5"; break;
316
    case bfd_mach_arm_5T:      expected = "armv5t"; break;
317
    case bfd_mach_arm_5TE:     expected = "armv5te"; break;
318
    case bfd_mach_arm_XScale:  expected = "XScale"; break;
319
    case bfd_mach_arm_ep9312:  expected = "ep9312"; break;
320
    case bfd_mach_arm_iWMMXt:  expected = "iWMMXt"; break;
321
    case bfd_mach_arm_iWMMXt2: expected = "iWMMXt2"; break;
322
    }
323
 
324
  if (strcmp (arch_string, expected) != 0)
325
    {
326
      strcpy ((char *) buffer + (offsetof (arm_Note, name)
327
                                 + ((strlen (NOTE_ARCH_STRING) + 3) & ~3)),
328
              expected);
329
 
330
      if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
331
                                      (file_ptr) 0, buffer_size))
332
        {
333
          (*_bfd_error_handler)
334
            (_("warning: unable to update contents of %s section in %s"),
335
             note_section, bfd_get_filename (abfd));
336
          goto FAIL;
337
        }
338
    }
339
 
340
  free (buffer);
341
  return TRUE;
342
 
343
 FAIL:
344
  if (buffer != NULL)
345
    free (buffer);
346
  return FALSE;
347
}
348
 
349
 
350
static struct
351
{
352
  const char * string;
353
  unsigned int mach;
354
}
355
architectures[] =
356
{
357
  { "armv2",   bfd_mach_arm_2 },
358
  { "armv2a",  bfd_mach_arm_2a },
359
  { "armv3",   bfd_mach_arm_3 },
360
  { "armv3M",  bfd_mach_arm_3M },
361
  { "armv4",   bfd_mach_arm_4 },
362
  { "armv4t",  bfd_mach_arm_4T },
363
  { "armv5",   bfd_mach_arm_5 },
364
  { "armv5t",  bfd_mach_arm_5T },
365
  { "armv5te", bfd_mach_arm_5TE },
366
  { "XScale",  bfd_mach_arm_XScale },
367
  { "ep9312",  bfd_mach_arm_ep9312 },
368
  { "iWMMXt",  bfd_mach_arm_iWMMXt },
369
  { "iWMMXt2", bfd_mach_arm_iWMMXt2 }
370
};
371
 
372
/* Extract the machine number stored in a note section.  */
373
unsigned int
374
bfd_arm_get_mach_from_notes (bfd *abfd, const char *note_section)
375
{
376
  asection *     arm_arch_section;
377
  bfd_size_type  buffer_size;
378
  bfd_byte *     buffer;
379
  char *         arch_string;
380
  int            i;
381
 
382
  /* Look for a note section.  If one is present check the architecture
383
     string encoded in it, and set it to the current architecture if it is
384
     different.  */
385
  arm_arch_section = bfd_get_section_by_name (abfd, note_section);
386
 
387
  if (arm_arch_section == NULL)
388
    return bfd_mach_arm_unknown;
389
 
390
  buffer_size = arm_arch_section->size;
391
  if (buffer_size == 0)
392
    return bfd_mach_arm_unknown;
393
 
394
  if (!bfd_malloc_and_get_section (abfd, arm_arch_section, &buffer))
395
    goto FAIL;
396
 
397
  /* Parse the note.  */
398
  if (! arm_check_note (abfd, buffer, buffer_size, NOTE_ARCH_STRING, & arch_string))
399
    goto FAIL;
400
 
401
  /* Interpret the architecture string.  */
402
  for (i = ARRAY_SIZE (architectures); i--;)
403
    if (strcmp (arch_string, architectures[i].string) == 0)
404
      {
405
        free (buffer);
406
        return architectures[i].mach;
407
      }
408
 
409
 FAIL:
410
  if (buffer != NULL)
411
    free (buffer);
412
  return bfd_mach_arm_unknown;
413
}
414
 
415
bfd_boolean
416
bfd_is_arm_special_symbol_name (const char * name, int type)
417
{
418
  /* The ARM compiler outputs several obsolete forms.  Recognize them
419
     in addition to the standard $a, $t and $d.  We are somewhat loose
420
     in what we accept here, since the full set is not documented.  */
421
  if (!name || name[0] != '$')
422
    return FALSE;
423
  if (name[1] == 'a' || name[1] == 't' || name[1] == 'd')
424
    type &= BFD_ARM_SPECIAL_SYM_TYPE_MAP;
425
  else if (name[1] == 'm' || name[1] == 'f' || name[1] == 'p')
426
    type &= BFD_ARM_SPECIAL_SYM_TYPE_TAG;
427
  else if (name[1] >= 'a' && name[1] <= 'z')
428
    type &= BFD_ARM_SPECIAL_SYM_TYPE_OTHER;
429
  else
430
    return FALSE;
431
 
432
  return (type != 0 && (name[2] == 0 || name[2] == '.'));
433
}
434
 

powered by: WebSVN 2.1.0

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