OSDN Git Service

2000-09-02 Jason Eckhardt <jle@cygnus.com>
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf32-i860.c
1 /* Intel i860 specific support for 32-bit ELF.
2    Copyright 1993, 2000 Free Software Foundation, Inc.
3
4    Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/i860.h"
27
28
29 /* Prototypes.  */
30 static reloc_howto_type *lookup_howto
31   PARAMS ((unsigned int));
32
33 static reloc_howto_type *elf32_i860_reloc_type_lookup
34   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
35
36 static void elf32_i860_info_to_howto_rela 
37   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
38
39 static bfd_reloc_status_type elf32_i860_relocate_splitn
40   PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
41
42 static bfd_reloc_status_type elf32_i860_relocate_pc16
43   PARAMS ((bfd *,  asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
44
45 static bfd_reloc_status_type elf32_i860_relocate_highadj
46   PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
47
48 static boolean elf32_i860_relocate_section 
49   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50            Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
51
52 static bfd_reloc_status_type i860_final_link_relocate
53   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
54            Elf_Internal_Rela *, bfd_vma));
55
56 static boolean elf32_i860_is_local_label_name
57   PARAMS ((bfd *, const char *));
58
59
60
61 /* This howto table is preliminary.  */
62 static reloc_howto_type elf32_i860_howto_table [] =
63 {
64   /* This relocation does nothing.  */
65   HOWTO (R_860_NONE,            /* type */
66          0,                     /* rightshift */
67          2,                     /* size (0 = byte, 1 = short, 2 = long) */
68          32,                    /* bitsize */
69          false,                 /* pc_relative */
70          0,                     /* bitpos */
71          complain_overflow_bitfield, /* complain_on_overflow */
72          bfd_elf_generic_reloc, /* special_function */
73          "R_860_NONE",          /* name */
74          false,                 /* partial_inplace */
75          0,                     /* src_mask */
76          0,                     /* dst_mask */
77          false),                /* pcrel_offset */
78
79   /* A 32-bit absolute relocation.  */
80   HOWTO (R_860_32,              /* type */
81          0,                     /* rightshift */
82          2,                     /* size (0 = byte, 1 = short, 2 = long) */
83          32,                    /* bitsize */
84          false,                 /* pc_relative */
85          0,                     /* bitpos */
86          complain_overflow_bitfield, /* complain_on_overflow */
87          bfd_elf_generic_reloc, /* special_function */
88          "R_860_32",            /* name */
89          false,                 /* partial_inplace */
90          0xffffffff,            /* src_mask */
91          0xffffffff,            /* dst_mask */
92          false),                /* pcrel_offset */
93
94   HOWTO (R_860_COPY,            /* type */
95          0,                     /* rightshift */
96          2,                     /* size (0 = byte, 1 = short, 2 = long) */
97          32,                    /* bitsize */
98          false,                 /* pc_relative */
99          0,                     /* bitpos */
100          complain_overflow_bitfield, /* complain_on_overflow */
101          bfd_elf_generic_reloc, /* special_function */
102          "R_860_COPY",          /* name */
103          true,                  /* partial_inplace */
104          0xffffffff,            /* src_mask */
105          0xffffffff,            /* dst_mask */
106          false),                /* pcrel_offset */
107
108   HOWTO (R_860_GLOB_DAT,        /* type */
109          0,                     /* rightshift */
110          2,                     /* size (0 = byte, 1 = short, 2 = long) */
111          32,                    /* bitsize */
112          false,                 /* pc_relative */
113          0,                     /* bitpos */
114          complain_overflow_bitfield, /* complain_on_overflow */
115          bfd_elf_generic_reloc, /* special_function */
116          "R_860_GLOB_DAT",      /* name */
117          true,                  /* partial_inplace */
118          0xffffffff,            /* src_mask */
119          0xffffffff,            /* dst_mask */
120          false),                /* pcrel_offset */
121
122   HOWTO (R_860_JUMP_SLOT,       /* type */
123          0,                     /* rightshift */
124          2,                     /* size (0 = byte, 1 = short, 2 = long) */
125          32,                    /* bitsize */
126          false,                 /* pc_relative */
127          0,                     /* bitpos */
128          complain_overflow_bitfield, /* complain_on_overflow */
129          bfd_elf_generic_reloc, /* special_function */
130          "R_860_JUMP_SLOT",     /* name */
131          true,                  /* partial_inplace */
132          0xffffffff,            /* src_mask */
133          0xffffffff,            /* dst_mask */
134          false),                /* pcrel_offset */
135
136   HOWTO (R_860_RELATIVE,        /* type */
137          0,                     /* rightshift */
138          2,                     /* size (0 = byte, 1 = short, 2 = long) */
139          32,                    /* bitsize */
140          false,                 /* pc_relative */
141          0,                     /* bitpos */
142          complain_overflow_bitfield, /* complain_on_overflow */
143          bfd_elf_generic_reloc, /* special_function */
144          "R_860_RELATIVE",      /* name */
145          true,                  /* partial_inplace */
146          0xffffffff,            /* src_mask */
147          0xffffffff,            /* dst_mask */
148          false),                /* pcrel_offset */
149
150   /* A 26-bit PC-relative relocation.  */
151   HOWTO (R_860_PC26,            /* type */
152          2,                     /* rightshift */
153          2,                     /* size (0 = byte, 1 = short, 2 = long) */
154          26,                    /* bitsize */
155          true,                  /* pc_relative */
156          0,                     /* bitpos */
157          complain_overflow_bitfield, /* complain_on_overflow */
158          bfd_elf_generic_reloc, /* special_function */
159          "R_860_PC26",          /* name */
160          false,                 /* partial_inplace */
161          0x3ffffff,             /* src_mask */
162          0x3ffffff,             /* dst_mask */
163          true),                 /* pcrel_offset */
164
165   HOWTO (R_860_PLT26,           /* type */
166          0,                     /* rightshift */
167          2,                     /* size (0 = byte, 1 = short, 2 = long) */
168          26,                    /* bitsize */
169          true,                  /* pc_relative */
170          0,                     /* bitpos */
171          complain_overflow_bitfield, /* complain_on_overflow */
172          bfd_elf_generic_reloc, /* special_function */
173          "R_860_PLT26",         /* name */
174          true,                  /* partial_inplace */
175          0xffffffff,            /* src_mask */
176          0xffffffff,            /* dst_mask */
177          true),                 /* pcrel_offset */
178
179   /* A 16-bit PC-relative relocation.  */
180   HOWTO (R_860_PC16,            /* type */
181          2,                     /* rightshift */
182          2,                     /* size (0 = byte, 1 = short, 2 = long) */
183          16,                    /* bitsize */
184          true,                  /* pc_relative */
185          0,                     /* bitpos */
186          complain_overflow_bitfield, /* complain_on_overflow */
187          bfd_elf_generic_reloc, /* special_function */
188          "R_860_PC16",          /* name */
189          false,                 /* partial_inplace */
190          0x1f07ff,              /* src_mask */
191          0x1f07ff,              /* dst_mask */
192          true),                 /* pcrel_offset */
193
194   HOWTO (R_860_LOW0,            /* type */
195          0,                     /* rightshift */
196          2,                     /* size (0 = byte, 1 = short, 2 = long) */
197          16,                    /* bitsize */
198          false,                 /* pc_relative */
199          0,                     /* bitpos */
200          complain_overflow_dont, /* complain_on_overflow */
201          bfd_elf_generic_reloc, /* special_function */
202          "R_860_LOW0",          /* name */
203          false,                 /* partial_inplace */
204          0xffff,                /* src_mask */
205          0xffff,                /* dst_mask */
206          false),                /* pcrel_offset */
207
208   HOWTO (R_860_SPLIT0,          /* type */
209          0,                     /* rightshift */
210          2,                     /* size (0 = byte, 1 = short, 2 = long) */
211          16,                    /* bitsize */
212          false,                 /* pc_relative */
213          0,                     /* bitpos */
214          complain_overflow_dont, /* complain_on_overflow */
215          bfd_elf_generic_reloc, /* special_function */
216          "R_860_SPLIT0",        /* name */
217          false,                 /* partial_inplace */
218          0x1f07ff,              /* src_mask */
219          0x1f07ff,              /* dst_mask */
220          false),                /* pcrel_offset */
221
222   HOWTO (R_860_LOW1,            /* type */
223          0,                     /* rightshift */
224          2,                     /* size (0 = byte, 1 = short, 2 = long) */
225          16,                    /* bitsize */
226          false,                 /* pc_relative */
227          0,                     /* bitpos */
228          complain_overflow_dont, /* complain_on_overflow */
229          bfd_elf_generic_reloc, /* special_function */
230          "R_860_LOW1",          /* name */
231          false,                 /* partial_inplace */
232          0xfffe,                /* src_mask */
233          0xfffe,                /* dst_mask */
234          false),                /* pcrel_offset */
235
236   HOWTO (R_860_SPLIT1,          /* type */
237          0,                     /* rightshift */
238          2,                     /* size (0 = byte, 1 = short, 2 = long) */
239          16,                    /* bitsize */
240          false,                 /* pc_relative */
241          0,                     /* bitpos */
242          complain_overflow_dont, /* complain_on_overflow */
243          bfd_elf_generic_reloc, /* special_function */
244          "R_860_SPLIT1",        /* name */
245          false,                 /* partial_inplace */
246          0x1f07fe,              /* src_mask */
247          0x1f07fe,              /* dst_mask */
248          false),                /* pcrel_offset */
249
250   HOWTO (R_860_LOW2,            /* type */
251          0,                     /* rightshift */
252          2,                     /* size (0 = byte, 1 = short, 2 = long) */
253          16,                    /* bitsize */
254          false,                 /* pc_relative */
255          0,                     /* bitpos */
256          complain_overflow_dont, /* complain_on_overflow */
257          bfd_elf_generic_reloc, /* special_function */
258          "R_860_LOW2",          /* name */
259          false,                 /* partial_inplace */
260          0xfffc,                /* src_mask */
261          0xfffc,                /* dst_mask */
262          false),                /* pcrel_offset */
263
264   HOWTO (R_860_SPLIT2,          /* type */
265          0,                     /* rightshift */
266          2,                     /* size (0 = byte, 1 = short, 2 = long) */
267          16,                    /* bitsize */
268          false,                 /* pc_relative */
269          0,                     /* bitpos */
270          complain_overflow_dont, /* complain_on_overflow */
271          bfd_elf_generic_reloc, /* special_function */
272          "R_860_SPLIT2",        /* name */
273          false,                 /* partial_inplace */
274          0x1f07fc,              /* src_mask */
275          0x1f07fc,              /* dst_mask */
276          false),                /* pcrel_offset */
277
278   HOWTO (R_860_LOW3,            /* type */
279          0,                     /* rightshift */
280          2,                     /* size (0 = byte, 1 = short, 2 = long) */
281          16,                    /* bitsize */
282          false,                 /* pc_relative */
283          0,                     /* bitpos */
284          complain_overflow_dont, /* complain_on_overflow */
285          bfd_elf_generic_reloc, /* special_function */
286          "R_860_LOW3",          /* name */
287          false,                 /* partial_inplace */
288          0xfff8,                /* src_mask */
289          0xfff8,                /* dst_mask */
290          false),                /* pcrel_offset */
291
292   HOWTO (R_860_LOGOT0,          /* type */
293          0,                     /* rightshift */
294          2,                     /* size (0 = byte, 1 = short, 2 = long) */
295          16,                    /* bitsize */
296          false,                 /* pc_relative */
297          0,                     /* bitpos */
298          complain_overflow_dont, /* complain_on_overflow */
299          bfd_elf_generic_reloc, /* special_function */
300          "R_860_LOGOT0",        /* name */
301          false,                 /* partial_inplace */
302          0,                     /* src_mask */
303          0xffff,                /* dst_mask */
304          true),                 /* pcrel_offset */
305
306   HOWTO (R_860_SPGOT0,          /* type */
307          0,                     /* rightshift */
308          2,                     /* size (0 = byte, 1 = short, 2 = long) */
309          16,                    /* bitsize */
310          false,                 /* pc_relative */
311          0,                     /* bitpos */
312          complain_overflow_dont, /* complain_on_overflow */
313          bfd_elf_generic_reloc, /* special_function */
314          "R_860_SPGOT0",        /* name */
315          false,                 /* partial_inplace */
316          0,                     /* src_mask */
317          0xffff,                /* dst_mask */
318          true),                 /* pcrel_offset */
319
320   HOWTO (R_860_LOGOT1,          /* type */
321          0,                     /* rightshift */
322          2,                     /* size (0 = byte, 1 = short, 2 = long) */
323          16,                    /* bitsize */
324          false,                 /* pc_relative */
325          0,                     /* bitpos */
326          complain_overflow_dont, /* complain_on_overflow */
327          bfd_elf_generic_reloc, /* special_function */
328          "R_860_LOGOT1",        /* name */
329          false,                 /* partial_inplace */
330          0,                     /* src_mask */
331          0xffff,                /* dst_mask */
332          true),                 /* pcrel_offset */
333
334   HOWTO (R_860_SPGOT1,          /* type */
335          0,                     /* rightshift */
336          2,                     /* size (0 = byte, 1 = short, 2 = long) */
337          16,                    /* bitsize */
338          false,                 /* pc_relative */
339          0,                     /* bitpos */
340          complain_overflow_dont, /* complain_on_overflow */
341          bfd_elf_generic_reloc, /* special_function */
342          "R_860_SPGOT1",        /* name */
343          false,                 /* partial_inplace */
344          0,                     /* src_mask */
345          0xffff,                /* dst_mask */
346          true),                 /* pcrel_offset */
347
348   HOWTO (R_860_LOGOTOFF0,        /* type */
349          0,                     /* rightshift */
350          2,                     /* size (0 = byte, 1 = short, 2 = long) */
351          32,                    /* bitsize */
352          false,                 /* pc_relative */
353          0,                     /* bitpos */
354          complain_overflow_dont, /* complain_on_overflow */
355          bfd_elf_generic_reloc, /* special_function */
356          "R_860_LOGOTOFF0",     /* name */
357          true,                  /* partial_inplace */
358          0xffffffff,            /* src_mask */
359          0xffffffff,            /* dst_mask */
360          false),                /* pcrel_offset */
361
362   HOWTO (R_860_SPGOTOFF0,        /* type */
363          0,                     /* rightshift */
364          2,                     /* size (0 = byte, 1 = short, 2 = long) */
365          32,                    /* bitsize */
366          false,                 /* pc_relative */
367          0,                     /* bitpos */
368          complain_overflow_dont, /* complain_on_overflow */
369          bfd_elf_generic_reloc, /* special_function */
370          "R_860_SPGOTOFF0",     /* name */
371          true,                  /* partial_inplace */
372          0xffffffff,            /* src_mask */
373          0xffffffff,            /* dst_mask */
374          false),                /* pcrel_offset */
375
376   HOWTO (R_860_LOGOTOFF1,        /* type */
377          0,                     /* rightshift */
378          2,                     /* size (0 = byte, 1 = short, 2 = long) */
379          32,                    /* bitsize */
380          false,                 /* pc_relative */
381          0,                     /* bitpos */
382          complain_overflow_dont, /* complain_on_overflow */
383          bfd_elf_generic_reloc, /* special_function */
384          "R_860_LOGOTOFF1",     /* name */
385          true,                  /* partial_inplace */
386          0xffffffff,            /* src_mask */
387          0xffffffff,            /* dst_mask */
388          false),                /* pcrel_offset */
389
390   HOWTO (R_860_SPGOTOFF1,       /* type */
391          0,                     /* rightshift */
392          2,                     /* size (0 = byte, 1 = short, 2 = long) */
393          32,                    /* bitsize */
394          false,                 /* pc_relative */
395          0,                     /* bitpos */
396          complain_overflow_dont, /* complain_on_overflow */
397          bfd_elf_generic_reloc, /* special_function */
398          "R_860_SPGOTOFF1",     /* name */
399          true,                  /* partial_inplace */
400          0xffffffff,            /* src_mask */
401          0xffffffff,            /* dst_mask */
402          false),                /* pcrel_offset */
403
404   HOWTO (R_860_LOGOTOFF2,        /* type */
405          0,                     /* rightshift */
406          2,                     /* size (0 = byte, 1 = short, 2 = long) */
407          32,                    /* bitsize */
408          false,                 /* pc_relative */
409          0,                     /* bitpos */
410          complain_overflow_dont, /* complain_on_overflow */
411          bfd_elf_generic_reloc, /* special_function */
412          "R_860_LOGOTOFF2",     /* name */
413          true,                  /* partial_inplace */
414          0xffffffff,            /* src_mask */
415          0xffffffff,            /* dst_mask */
416          false),                /* pcrel_offset */
417
418   HOWTO (R_860_LOGOTOFF3,        /* type */
419          0,                     /* rightshift */
420          2,                     /* size (0 = byte, 1 = short, 2 = long) */
421          32,                    /* bitsize */
422          false,                 /* pc_relative */
423          0,                     /* bitpos */
424          complain_overflow_dont, /* complain_on_overflow */
425          bfd_elf_generic_reloc, /* special_function */
426          "R_860_LOGOTOFF3",     /* name */
427          true,                  /* partial_inplace */
428          0xffffffff,            /* src_mask */
429          0xffffffff,            /* dst_mask */
430          false),                /* pcrel_offset */
431
432   HOWTO (R_860_LOPC,            /* type */
433          0,                     /* rightshift */
434          2,                     /* size (0 = byte, 1 = short, 2 = long) */
435          16,                    /* bitsize */
436          true,                  /* pc_relative */
437          0,                     /* bitpos */
438          complain_overflow_bitfield, /* complain_on_overflow */
439          bfd_elf_generic_reloc, /* special_function */
440          "R_860_LOPC",          /* name */
441          false,                 /* partial_inplace */
442          0xffff,                /* src_mask */
443          0xffff,                /* dst_mask */
444          true),                 /* pcrel_offset */
445
446   HOWTO (R_860_HIGHADJ,         /* type */
447          0,                     /* rightshift */
448          2,                     /* size (0 = byte, 1 = short, 2 = long) */
449          16,                    /* bitsize */
450          false,                 /* pc_relative */
451          0,                     /* bitpos */
452          complain_overflow_dont, /* complain_on_overflow */
453          bfd_elf_generic_reloc, /* special_function */
454          "R_860_HIGHADJ",       /* name */
455          false,                 /* partial_inplace */
456          0xffff,                /* src_mask */
457          0xffff,                /* dst_mask */
458          false),                /* pcrel_offset */
459
460   HOWTO (R_860_HAGOT,           /* type */
461          0,                     /* rightshift */
462          2,                     /* size (0 = byte, 1 = short, 2 = long) */
463          16,                    /* bitsize */
464          false,                 /* pc_relative */
465          0,                     /* bitpos */
466          complain_overflow_dont, /* complain_on_overflow */
467          bfd_elf_generic_reloc, /* special_function */
468          "R_860_HAGOT",         /* name */
469          false,                 /* partial_inplace */
470          0,                     /* src_mask */
471          0xffff,                /* dst_mask */
472          true),                 /* pcrel_offset */
473
474   HOWTO (R_860_HAGOTOFF,        /* type */
475          0,                     /* rightshift */
476          2,                     /* size (0 = byte, 1 = short, 2 = long) */
477          32,                    /* bitsize */
478          false,                 /* pc_relative */
479          0,                     /* bitpos */
480          complain_overflow_dont, /* complain_on_overflow */
481          bfd_elf_generic_reloc, /* special_function */
482          "R_860_HAGOTOFF",      /* name */
483          true,                  /* partial_inplace */
484          0xffffffff,            /* src_mask */
485          0xffffffff,            /* dst_mask */
486          false),                /* pcrel_offset */
487
488   HOWTO (R_860_HAPC,            /* type */
489          0,                     /* rightshift */
490          2,                     /* size (0 = byte, 1 = short, 2 = long) */
491          16,                    /* bitsize */
492          true,                  /* pc_relative */
493          0,                     /* bitpos */
494          complain_overflow_bitfield, /* complain_on_overflow */
495          bfd_elf_generic_reloc, /* special_function */
496          "R_860_HAPC",          /* name */
497          false,                 /* partial_inplace */
498          0xffff,                /* src_mask */
499          0xffff,                /* dst_mask */
500          true),                 /* pcrel_offset */
501
502   HOWTO (R_860_HIGH,            /* type */
503          16,                    /* rightshift */
504          2,                     /* size (0 = byte, 1 = short, 2 = long) */
505          16,                    /* bitsize */
506          false,                 /* pc_relative */
507          0,                     /* bitpos */
508          complain_overflow_dont, /* complain_on_overflow */
509          bfd_elf_generic_reloc, /* special_function */
510          "R_860_HIGH",          /* name */
511          false,                 /* partial_inplace */
512          0xffff,                /* src_mask */
513          0xffff,                /* dst_mask */
514          false),                /* pcrel_offset */
515
516   HOWTO (R_860_HIGOT,           /* type */
517          0,                     /* rightshift */
518          2,                     /* size (0 = byte, 1 = short, 2 = long) */
519          16,                    /* bitsize */
520          false,                 /* pc_relative */
521          0,                     /* bitpos */
522          complain_overflow_dont, /* complain_on_overflow */
523          bfd_elf_generic_reloc, /* special_function */
524          "R_860_HIGOT",         /* name */
525          false,                 /* partial_inplace */
526          0,                     /* src_mask */
527          0xffff,                /* dst_mask */
528          true),                 /* pcrel_offset */
529
530   HOWTO (R_860_HIGOTOFF,        /* type */
531          0,                     /* rightshift */
532          2,                     /* size (0 = byte, 1 = short, 2 = long) */
533          32,                    /* bitsize */
534          false,                 /* pc_relative */
535          0,                     /* bitpos */
536          complain_overflow_dont, /* complain_on_overflow */
537          bfd_elf_generic_reloc, /* special_function */
538          "R_860_HIGOTOFF",      /* name */
539          true,                  /* partial_inplace */
540          0xffffffff,            /* src_mask */
541          0xffffffff,            /* dst_mask */
542          false),                /* pcrel_offset */
543 };
544
545 \f
546 static unsigned char elf_code_to_howto_index[R_860_max + 1];
547
548 static reloc_howto_type *
549 lookup_howto (rtype)
550      unsigned int rtype;
551 {
552   static int initialized = 0;
553   int i;
554   int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
555                         / sizeof (elf32_i860_howto_table[0]));
556
557   if (! initialized)
558     {
559       initialized = 1;
560       memset (elf_code_to_howto_index, 0xff,
561               sizeof (elf_code_to_howto_index));
562       for (i = 0; i < howto_tbl_size; i++)
563         elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
564     }
565
566   BFD_ASSERT (rtype <= R_860_max);
567   i = elf_code_to_howto_index[rtype];
568   if (i >= howto_tbl_size)
569     return 0;
570   return elf32_i860_howto_table + i;
571 }
572
573
574 /* Given a BFD reloc, return the matching HOWTO structure.  */
575 static reloc_howto_type *
576 elf32_i860_reloc_type_lookup (abfd, code)
577      bfd * abfd ATTRIBUTE_UNUSED;
578      bfd_reloc_code_real_type code;
579 {
580   unsigned int rtype;
581
582   switch (code)
583     {
584     case BFD_RELOC_NONE:
585       rtype = R_860_NONE;
586       break;
587     case BFD_RELOC_32:
588       rtype = R_860_32;
589       break;
590     case BFD_RELOC_860_COPY:
591       rtype = R_860_COPY;
592       break;
593     case BFD_RELOC_860_GLOB_DAT:
594       rtype = R_860_GLOB_DAT; 
595       break;
596     case BFD_RELOC_860_JUMP_SLOT:
597       rtype = R_860_JUMP_SLOT;
598       break;
599     case BFD_RELOC_860_RELATIVE:
600       rtype = R_860_RELATIVE;
601       break;
602     case BFD_RELOC_860_PC26:
603       rtype = R_860_PC26;
604       break;
605     case BFD_RELOC_860_PLT26:
606       rtype = R_860_PLT26;
607       break;
608     case BFD_RELOC_860_PC16:
609       rtype = R_860_PC16;
610       break;
611     case BFD_RELOC_860_LOW0:
612       rtype = R_860_LOW0;
613       break;
614     case BFD_RELOC_860_SPLIT0:
615       rtype = R_860_SPLIT0;
616       break;
617     case BFD_RELOC_860_LOW1:
618       rtype = R_860_LOW1;
619       break;
620     case BFD_RELOC_860_SPLIT1:
621       rtype = R_860_SPLIT1;
622       break;
623     case BFD_RELOC_860_LOW2:
624       rtype = R_860_LOW2;
625       break;
626     case BFD_RELOC_860_SPLIT2:
627       rtype = R_860_SPLIT2;
628       break;
629     case BFD_RELOC_860_LOW3:
630       rtype = R_860_LOW3;
631       break;
632     case BFD_RELOC_860_LOGOT0:
633       rtype = R_860_LOGOT0;
634       break;
635     case BFD_RELOC_860_SPGOT0:
636       rtype = R_860_SPGOT0;
637       break;
638     case BFD_RELOC_860_LOGOT1:
639       rtype = R_860_LOGOT1;
640       break;
641     case BFD_RELOC_860_SPGOT1:
642       rtype = R_860_SPGOT1;
643       break;
644     case BFD_RELOC_860_LOGOTOFF0:
645       rtype = R_860_LOGOTOFF0;
646       break;
647     case BFD_RELOC_860_SPGOTOFF0:
648       rtype = R_860_SPGOTOFF0;
649       break;
650     case BFD_RELOC_860_LOGOTOFF1:
651       rtype = R_860_LOGOTOFF1;
652       break;
653     case BFD_RELOC_860_SPGOTOFF1:
654       rtype = R_860_SPGOTOFF1;
655       break;
656     case BFD_RELOC_860_LOGOTOFF2:
657       rtype = R_860_LOGOTOFF2;
658       break;
659     case BFD_RELOC_860_LOGOTOFF3:
660       rtype = R_860_LOGOTOFF3;
661       break;
662     case BFD_RELOC_860_LOPC:
663       rtype = R_860_LOPC;
664       break;
665     case BFD_RELOC_860_HIGHADJ:
666       rtype = R_860_HIGHADJ;
667       break;
668     case BFD_RELOC_860_HAGOT:
669       rtype = R_860_HAGOT;
670       break;
671     case BFD_RELOC_860_HAGOTOFF:
672       rtype = R_860_HAGOTOFF;
673       break;
674     case BFD_RELOC_860_HAPC:
675       rtype = R_860_HAPC;
676       break;
677     case BFD_RELOC_860_HIGH:
678       rtype = R_860_HIGH;
679       break;
680     case BFD_RELOC_860_HIGOT:
681       rtype = R_860_HIGOT;
682       break;
683     case BFD_RELOC_860_HIGOTOFF:
684       rtype = R_860_HIGOTOFF;
685       break;
686     default:
687       rtype = 0;
688       break;
689     }
690   return lookup_howto (rtype);
691 }
692
693
694 /* Given a ELF reloc, return the matching HOWTO structure.  */
695 static void
696 elf32_i860_info_to_howto_rela (abfd, bfd_reloc, elf_reloc)
697      bfd *abfd ATTRIBUTE_UNUSED;
698      arelent *bfd_reloc;
699      Elf64_Internal_Rela *elf_reloc;
700 {
701   bfd_reloc->howto = lookup_howto (ELF32_R_TYPE (elf_reloc->r_info));
702 }
703
704
705 \f
706 /* Specialized relocation handler for R_860_SPLITn.  These relocations
707    involves a 16-bit field that is split into two contiguous parts.  */
708 static bfd_reloc_status_type
709 elf32_i860_relocate_splitn (input_bfd, rello, contents, value)
710      bfd *input_bfd;
711      Elf_Internal_Rela *rello;
712      bfd_byte *contents;
713      bfd_vma value;
714 {
715   bfd_vma insn;
716   reloc_howto_type *howto;
717   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
718   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
719
720   /* Relocate.  */
721   value += rello->r_addend;
722
723   /* Separate the fields and insert.  */
724   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
725   insn = (insn & ~howto->dst_mask) | value;
726
727   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
728   return bfd_reloc_ok;
729 }
730
731
732 /* Specialized relocation handler for R_860_PC16.  This relocation
733    involves a 16-bit, PC-relative field that is split into two contiguous
734    parts.  */
735 static bfd_reloc_status_type
736 elf32_i860_relocate_pc16 (input_bfd, input_section, rello, contents, value)
737      bfd *input_bfd;
738      asection *input_section;
739      Elf_Internal_Rela *rello;
740      bfd_byte *contents;
741      bfd_vma value;
742 {
743   bfd_vma insn;
744   reloc_howto_type *howto;
745   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
746   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
747
748   /* Adjust for PC-relative relocation.  */
749   value -= (input_section->output_section->vma
750             + input_section->output_offset);
751   value -= rello->r_offset;
752
753   /* Relocate.  */
754   value += rello->r_addend;
755
756   /* Separate the fields and insert.  */
757   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
758   insn = (insn & ~howto->dst_mask) | value;
759
760   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
761   return bfd_reloc_ok;
762
763 }
764
765
766 /* Specialized relocation handler for R_860_HIGHADJ.  */
767 static bfd_reloc_status_type
768 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
769      bfd *input_bfd;
770      Elf_Internal_Rela *rel;
771      bfd_byte *contents;
772      bfd_vma value;
773 {
774   bfd_vma insn;
775
776   insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
777
778   value += ((rel->r_addend & 0x8000) << 1);
779   value += rel->r_addend;
780   value = ((value >> 16) & 0xffff);
781
782   insn = (insn & 0xffff0000) | value;
783
784   bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
785   return bfd_reloc_ok;
786 }
787
788
789 /* Perform a single relocation.  By default we use the standard BFD
790    routines. However, we handle some specially.  */
791 static bfd_reloc_status_type
792 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
793      reloc_howto_type *  howto;
794      bfd *               input_bfd;
795      asection *          input_section;
796      bfd_byte *          contents;
797      Elf_Internal_Rela * rel;
798      bfd_vma             relocation;
799 {
800   return _bfd_final_link_relocate (howto, input_bfd, input_section,
801                                    contents, rel->r_offset, relocation,
802                                    rel->r_addend);
803 }
804
805
806 /* Relocate an i860 ELF section.
807
808    This is boiler-plate code copied from fr30.
809    There is some attempt to make this function usable for many architectures,
810    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
811    if only to serve as a learning tool.
812
813    The RELOCATE_SECTION function is called by the new ELF backend linker
814    to handle the relocations for a section.
815
816    The relocs are always passed as Rela structures; if the section
817    actually uses Rel structures, the r_addend field will always be
818    zero.
819
820    This function is responsible for adjusting the section contents as
821    necessary, and (if using Rela relocs and generating a relocateable
822    output file) adjusting the reloc addend as necessary.
823
824    This function does not have to worry about setting the reloc
825    address or the reloc symbol index.
826
827    LOCAL_SYMS is a pointer to the swapped in local symbols.
828
829    LOCAL_SECTIONS is an array giving the section in the input file
830    corresponding to the st_shndx field of each local symbol.
831
832    The global hash table entry for the global symbols can be found
833    via elf_sym_hashes (input_bfd).
834
835    When generating relocateable output, this function must handle
836    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
837    going to be the section symbol corresponding to the output
838    section, which means that the addend must be adjusted
839    accordingly.  */
840 static boolean
841 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
842                              contents, relocs, local_syms, local_sections)
843      bfd *                   output_bfd ATTRIBUTE_UNUSED;
844      struct bfd_link_info *  info;
845      bfd *                   input_bfd;
846      asection *              input_section;
847      bfd_byte *              contents;
848      Elf_Internal_Rela *     relocs;
849      Elf_Internal_Sym *      local_syms;
850      asection **             local_sections;
851 {
852   Elf_Internal_Shdr *           symtab_hdr;
853   struct elf_link_hash_entry ** sym_hashes;
854   Elf_Internal_Rela *           rel;
855   Elf_Internal_Rela *           relend;
856
857   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
858   sym_hashes = elf_sym_hashes (input_bfd);
859   relend     = relocs + input_section->reloc_count;
860
861   for (rel = relocs; rel < relend; rel ++)
862     {
863       reloc_howto_type *           howto;
864       unsigned long                r_symndx;
865       Elf_Internal_Sym *           sym;
866       asection *                   sec;
867       struct elf_link_hash_entry * h;
868       bfd_vma                      relocation;
869       bfd_reloc_status_type        r;
870       const char *                 name = NULL;
871       int                          r_type;
872       
873       r_type = ELF32_R_TYPE (rel->r_info);
874      
875 #if 0
876       if (   r_type == R_860_GNU_VTINHERIT
877           || r_type == R_860_GNU_VTENTRY)
878         continue;
879 #endif
880       
881       r_symndx = ELF32_R_SYM (rel->r_info);
882
883       if (info->relocateable)
884         {
885           /* This is a relocateable link.  We don't have to change
886              anything, unless the reloc is against a section symbol,
887              in which case we have to adjust according to where the
888              section symbol winds up in the output section.  */
889           if (r_symndx < symtab_hdr->sh_info)
890             {
891               sym = local_syms + r_symndx;
892               
893               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
894                 {
895                   sec = local_sections [r_symndx];
896                   rel->r_addend += sec->output_offset + sym->st_value;
897                 }
898             }
899
900           continue;
901         }
902
903       /* This is a final link.  */
904       howto  = lookup_howto (ELF32_R_TYPE (rel->r_info));
905       h      = NULL;
906       sym    = NULL;
907       sec    = NULL;
908       
909       if (r_symndx < symtab_hdr->sh_info)
910         {
911           sym = local_syms + r_symndx;
912           sec = local_sections [r_symndx];
913           relocation = (sec->output_section->vma
914                         + sec->output_offset
915                         + sym->st_value);
916           
917           name = bfd_elf_string_from_elf_section
918             (input_bfd, symtab_hdr->sh_link, sym->st_name);
919           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
920         }
921       else
922         {
923           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
924           
925           while (h->root.type == bfd_link_hash_indirect
926                  || h->root.type == bfd_link_hash_warning)
927             h = (struct elf_link_hash_entry *) h->root.u.i.link;
928
929           name = h->root.root.string;
930           
931           if (h->root.type == bfd_link_hash_defined
932               || h->root.type == bfd_link_hash_defweak)
933             {
934               sec = h->root.u.def.section;
935               relocation = (h->root.u.def.value
936                             + sec->output_section->vma
937                             + sec->output_offset);
938             }
939           else if (h->root.type == bfd_link_hash_undefweak)
940             {
941               relocation = 0;
942             }
943           else
944             {
945               if (! ((*info->callbacks->undefined_symbol)
946                      (info, h->root.root.string, input_bfd,
947                       input_section, rel->r_offset, true)))
948                 return false;
949               relocation = 0;
950             }
951         }
952    
953       switch (r_type)
954         {
955         default:
956           r = i860_final_link_relocate (howto, input_bfd, input_section,
957                                         contents, rel, relocation);
958           break;
959
960         case R_860_HIGHADJ:
961           r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
962                                            relocation);
963           break;
964
965         case R_860_PC16:
966           r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
967                                         contents, relocation);
968           break;
969
970         case R_860_SPLIT0:
971         case R_860_SPLIT1:
972         case R_860_SPLIT2:
973           r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
974                                           relocation);
975           break;
976
977         /* We do not yet handle GOT/PLT/Dynamic relocations.  */
978         case R_860_COPY:
979         case R_860_GLOB_DAT:
980         case R_860_JUMP_SLOT:
981         case R_860_RELATIVE:
982         case R_860_PLT26:
983         case R_860_LOGOT0:
984         case R_860_SPGOT0:
985         case R_860_LOGOT1:
986         case R_860_SPGOT1:
987         case R_860_LOGOTOFF0:
988         case R_860_SPGOTOFF0:
989         case R_860_LOGOTOFF1:
990         case R_860_SPGOTOFF1:
991         case R_860_LOGOTOFF2:
992         case R_860_LOGOTOFF3:
993         case R_860_LOPC:
994         case R_860_HAGOT:
995         case R_860_HAGOTOFF:
996         case R_860_HAPC:
997         case R_860_HIGOT:
998         case R_860_HIGOTOFF:
999           r = bfd_reloc_notsupported;
1000           break;
1001         } 
1002
1003       if (r != bfd_reloc_ok)
1004         {
1005           const char * msg = (const char *) NULL;
1006
1007           switch (r)
1008             {
1009             case bfd_reloc_overflow:
1010               r = info->callbacks->reloc_overflow
1011                 (info, name, howto->name, (bfd_vma) 0,
1012                  input_bfd, input_section, rel->r_offset);
1013               break;
1014               
1015             case bfd_reloc_undefined:
1016               r = info->callbacks->undefined_symbol
1017                 (info, name, input_bfd, input_section, rel->r_offset, true);
1018               break;
1019               
1020             case bfd_reloc_outofrange:
1021               msg = _("internal error: out of range error");
1022               break;
1023
1024             case bfd_reloc_notsupported:
1025               msg = _("internal error: unsupported relocation error");
1026               break;
1027
1028             case bfd_reloc_dangerous:
1029               msg = _("internal error: dangerous relocation");
1030               break;
1031
1032             default:
1033               msg = _("internal error: unknown error");
1034               break;
1035             }
1036
1037           if (msg)
1038             r = info->callbacks->warning
1039               (info, msg, name, input_bfd, input_section, rel->r_offset);
1040
1041           if (! r)
1042             return false;
1043         }
1044     }
1045
1046   return true;
1047 }
1048
1049
1050 /* Return whether a symbol name implies a local label.  SVR4/860 compilers
1051    generate labels of the form ".ep.function_name" to denote the end of a
1052    function prolog. These should be local.
1053    ??? Do any other SVR4 compilers have this convention? If so, this should
1054    be added to the generic routine.  */
1055 static boolean
1056 elf32_i860_is_local_label_name (abfd, name)
1057      bfd *abfd;
1058      const char *name;
1059 {
1060   if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1061     return true;
1062
1063   return _bfd_elf_is_local_label_name (abfd, name);
1064 }
1065
1066
1067 \f
1068 #define TARGET_BIG_SYM          bfd_elf32_i860_vec
1069 #define TARGET_BIG_NAME         "elf32-i860"
1070 #define TARGET_LITTLE_SYM       bfd_elf32_i860_little_vec
1071 #define TARGET_LITTLE_NAME      "elf32-i860-little"
1072 #define ELF_ARCH                bfd_arch_i860
1073 #define ELF_MACHINE_CODE        EM_860
1074 #define ELF_MAXPAGESIZE         4096
1075
1076 #define elf_info_to_howto_rel                   NULL
1077 #define elf_info_to_howto                       elf32_i860_info_to_howto_rela
1078 #define elf_backend_relocate_section            elf32_i860_relocate_section
1079 #define bfd_elf32_bfd_reloc_type_lookup         elf32_i860_reloc_type_lookup
1080 #define bfd_elf32_bfd_is_local_label_name       elf32_i860_is_local_label_name
1081
1082 #include "elf32-target.h"