2000-12-05 Kazu Hirata <kazu@hxi.com>
[external/binutils.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 /* Prototypes.  */
29 static reloc_howto_type *lookup_howto
30   PARAMS ((unsigned int));
31
32 static reloc_howto_type *elf32_i860_reloc_type_lookup
33   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
34
35 static void elf32_i860_info_to_howto_rela
36   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
37
38 static bfd_reloc_status_type elf32_i860_relocate_splitn
39   PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
40
41 static bfd_reloc_status_type elf32_i860_relocate_pc16
42   PARAMS ((bfd *,  asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
43
44 static bfd_reloc_status_type elf32_i860_relocate_pc26
45   PARAMS ((bfd *,  asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
46
47 static bfd_reloc_status_type elf32_i860_relocate_highadj
48   PARAMS ((bfd *,  Elf_Internal_Rela *, bfd_byte *, bfd_vma));
49
50 static boolean elf32_i860_relocate_section
51   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
52            Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
53
54 static bfd_reloc_status_type i860_final_link_relocate
55   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
56            Elf_Internal_Rela *, bfd_vma));
57
58 static boolean elf32_i860_is_local_label_name
59   PARAMS ((bfd *, const char *));
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 /* Given a BFD reloc, return the matching HOWTO structure.  */
574 static reloc_howto_type *
575 elf32_i860_reloc_type_lookup (abfd, code)
576      bfd * abfd ATTRIBUTE_UNUSED;
577      bfd_reloc_code_real_type code;
578 {
579   unsigned int rtype;
580
581   switch (code)
582     {
583     case BFD_RELOC_NONE:
584       rtype = R_860_NONE;
585       break;
586     case BFD_RELOC_32:
587       rtype = R_860_32;
588       break;
589     case BFD_RELOC_860_COPY:
590       rtype = R_860_COPY;
591       break;
592     case BFD_RELOC_860_GLOB_DAT:
593       rtype = R_860_GLOB_DAT;
594       break;
595     case BFD_RELOC_860_JUMP_SLOT:
596       rtype = R_860_JUMP_SLOT;
597       break;
598     case BFD_RELOC_860_RELATIVE:
599       rtype = R_860_RELATIVE;
600       break;
601     case BFD_RELOC_860_PC26:
602       rtype = R_860_PC26;
603       break;
604     case BFD_RELOC_860_PLT26:
605       rtype = R_860_PLT26;
606       break;
607     case BFD_RELOC_860_PC16:
608       rtype = R_860_PC16;
609       break;
610     case BFD_RELOC_860_LOW0:
611       rtype = R_860_LOW0;
612       break;
613     case BFD_RELOC_860_SPLIT0:
614       rtype = R_860_SPLIT0;
615       break;
616     case BFD_RELOC_860_LOW1:
617       rtype = R_860_LOW1;
618       break;
619     case BFD_RELOC_860_SPLIT1:
620       rtype = R_860_SPLIT1;
621       break;
622     case BFD_RELOC_860_LOW2:
623       rtype = R_860_LOW2;
624       break;
625     case BFD_RELOC_860_SPLIT2:
626       rtype = R_860_SPLIT2;
627       break;
628     case BFD_RELOC_860_LOW3:
629       rtype = R_860_LOW3;
630       break;
631     case BFD_RELOC_860_LOGOT0:
632       rtype = R_860_LOGOT0;
633       break;
634     case BFD_RELOC_860_SPGOT0:
635       rtype = R_860_SPGOT0;
636       break;
637     case BFD_RELOC_860_LOGOT1:
638       rtype = R_860_LOGOT1;
639       break;
640     case BFD_RELOC_860_SPGOT1:
641       rtype = R_860_SPGOT1;
642       break;
643     case BFD_RELOC_860_LOGOTOFF0:
644       rtype = R_860_LOGOTOFF0;
645       break;
646     case BFD_RELOC_860_SPGOTOFF0:
647       rtype = R_860_SPGOTOFF0;
648       break;
649     case BFD_RELOC_860_LOGOTOFF1:
650       rtype = R_860_LOGOTOFF1;
651       break;
652     case BFD_RELOC_860_SPGOTOFF1:
653       rtype = R_860_SPGOTOFF1;
654       break;
655     case BFD_RELOC_860_LOGOTOFF2:
656       rtype = R_860_LOGOTOFF2;
657       break;
658     case BFD_RELOC_860_LOGOTOFF3:
659       rtype = R_860_LOGOTOFF3;
660       break;
661     case BFD_RELOC_860_LOPC:
662       rtype = R_860_LOPC;
663       break;
664     case BFD_RELOC_860_HIGHADJ:
665       rtype = R_860_HIGHADJ;
666       break;
667     case BFD_RELOC_860_HAGOT:
668       rtype = R_860_HAGOT;
669       break;
670     case BFD_RELOC_860_HAGOTOFF:
671       rtype = R_860_HAGOTOFF;
672       break;
673     case BFD_RELOC_860_HAPC:
674       rtype = R_860_HAPC;
675       break;
676     case BFD_RELOC_860_HIGH:
677       rtype = R_860_HIGH;
678       break;
679     case BFD_RELOC_860_HIGOT:
680       rtype = R_860_HIGOT;
681       break;
682     case BFD_RELOC_860_HIGOTOFF:
683       rtype = R_860_HIGOTOFF;
684       break;
685     default:
686       rtype = 0;
687       break;
688     }
689   return lookup_howto (rtype);
690 }
691
692 /* Given a ELF reloc, return the matching HOWTO structure.  */
693 static void
694 elf32_i860_info_to_howto_rela (abfd, bfd_reloc, elf_reloc)
695      bfd *abfd ATTRIBUTE_UNUSED;
696      arelent *bfd_reloc;
697      Elf64_Internal_Rela *elf_reloc;
698 {
699   bfd_reloc->howto = lookup_howto (ELF32_R_TYPE (elf_reloc->r_info));
700 }
701
702 \f
703 /* Specialized relocation handler for R_860_SPLITn.  These relocations
704    involves a 16-bit field that is split into two contiguous parts.  */
705 static bfd_reloc_status_type
706 elf32_i860_relocate_splitn (input_bfd, rello, contents, value)
707      bfd *input_bfd;
708      Elf_Internal_Rela *rello;
709      bfd_byte *contents;
710      bfd_vma value;
711 {
712   bfd_vma insn;
713   reloc_howto_type *howto;
714   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
715   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
716
717   /* Relocate.  */
718   value += rello->r_addend;
719
720   /* Separate the fields and insert.  */
721   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
722   insn = (insn & ~howto->dst_mask) | value;
723
724   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
725   return bfd_reloc_ok;
726 }
727
728 /* Specialized relocation handler for R_860_PC16.  This relocation
729    involves a 16-bit, PC-relative field that is split into two contiguous
730    parts.  */
731 static bfd_reloc_status_type
732 elf32_i860_relocate_pc16 (input_bfd, input_section, rello, contents, value)
733      bfd *input_bfd;
734      asection *input_section;
735      Elf_Internal_Rela *rello;
736      bfd_byte *contents;
737      bfd_vma value;
738 {
739   bfd_vma insn;
740   reloc_howto_type *howto;
741   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
742   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
743
744   /* Adjust for PC-relative relocation.  */
745   value -= (input_section->output_section->vma
746             + input_section->output_offset);
747   value -= rello->r_offset;
748
749   /* Relocate.  */
750   value += rello->r_addend;
751
752   /* Separate the fields and insert.  */
753   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
754   insn = (insn & ~howto->dst_mask) | value;
755
756   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
757   return bfd_reloc_ok;
758
759 }
760
761 /* Specialized relocation handler for R_860_PC26.  This relocation
762    involves a 26-bit, PC-relative field which must be adjusted by 4.  */
763 static bfd_reloc_status_type
764 elf32_i860_relocate_pc26 (input_bfd, input_section, rello, contents, value)
765      bfd *input_bfd;
766      asection *input_section;
767      Elf_Internal_Rela *rello;
768      bfd_byte *contents;
769      bfd_vma value;
770 {
771   bfd_vma insn;
772   reloc_howto_type *howto;
773   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
774   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
775
776   /* Adjust for PC-relative relocation.  */
777   value -= (input_section->output_section->vma
778             + input_section->output_offset);
779   value -= rello->r_offset;
780
781   /* Relocate.  */
782   value += rello->r_addend;
783
784   /* Adjust value by 4 and insert the field.  */
785   value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
786   insn = (insn & ~howto->dst_mask) | value;
787
788   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
789   return bfd_reloc_ok;
790
791 }
792
793 /* Specialized relocation handler for R_860_HIGHADJ.  */
794 static bfd_reloc_status_type
795 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
796      bfd *input_bfd;
797      Elf_Internal_Rela *rel;
798      bfd_byte *contents;
799      bfd_vma value;
800 {
801   bfd_vma insn;
802
803   insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
804
805   value += ((rel->r_addend & 0x8000) << 1);
806   value += rel->r_addend;
807   value = ((value >> 16) & 0xffff);
808
809   insn = (insn & 0xffff0000) | value;
810
811   bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
812   return bfd_reloc_ok;
813 }
814
815 /* Perform a single relocation.  By default we use the standard BFD
816    routines. However, we handle some specially.  */
817 static bfd_reloc_status_type
818 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
819      reloc_howto_type *  howto;
820      bfd *               input_bfd;
821      asection *          input_section;
822      bfd_byte *          contents;
823      Elf_Internal_Rela * rel;
824      bfd_vma             relocation;
825 {
826   return _bfd_final_link_relocate (howto, input_bfd, input_section,
827                                    contents, rel->r_offset, relocation,
828                                    rel->r_addend);
829 }
830
831 /* Relocate an i860 ELF section.
832
833    This is boiler-plate code copied from fr30.
834    There is some attempt to make this function usable for many architectures,
835    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
836    if only to serve as a learning tool.
837
838    The RELOCATE_SECTION function is called by the new ELF backend linker
839    to handle the relocations for a section.
840
841    The relocs are always passed as Rela structures; if the section
842    actually uses Rel structures, the r_addend field will always be
843    zero.
844
845    This function is responsible for adjusting the section contents as
846    necessary, and (if using Rela relocs and generating a relocateable
847    output file) adjusting the reloc addend as necessary.
848
849    This function does not have to worry about setting the reloc
850    address or the reloc symbol index.
851
852    LOCAL_SYMS is a pointer to the swapped in local symbols.
853
854    LOCAL_SECTIONS is an array giving the section in the input file
855    corresponding to the st_shndx field of each local symbol.
856
857    The global hash table entry for the global symbols can be found
858    via elf_sym_hashes (input_bfd).
859
860    When generating relocateable output, this function must handle
861    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
862    going to be the section symbol corresponding to the output
863    section, which means that the addend must be adjusted
864    accordingly.  */
865 static boolean
866 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
867                              contents, relocs, local_syms, local_sections)
868      bfd *                   output_bfd ATTRIBUTE_UNUSED;
869      struct bfd_link_info *  info;
870      bfd *                   input_bfd;
871      asection *              input_section;
872      bfd_byte *              contents;
873      Elf_Internal_Rela *     relocs;
874      Elf_Internal_Sym *      local_syms;
875      asection **             local_sections;
876 {
877   Elf_Internal_Shdr *           symtab_hdr;
878   struct elf_link_hash_entry ** sym_hashes;
879   Elf_Internal_Rela *           rel;
880   Elf_Internal_Rela *           relend;
881
882   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
883   sym_hashes = elf_sym_hashes (input_bfd);
884   relend     = relocs + input_section->reloc_count;
885
886   for (rel = relocs; rel < relend; rel ++)
887     {
888       reloc_howto_type *           howto;
889       unsigned long                r_symndx;
890       Elf_Internal_Sym *           sym;
891       asection *                   sec;
892       struct elf_link_hash_entry * h;
893       bfd_vma                      relocation;
894       bfd_reloc_status_type        r;
895       const char *                 name = NULL;
896       int                          r_type;
897
898       r_type = ELF32_R_TYPE (rel->r_info);
899
900 #if 0
901       if (   r_type == R_860_GNU_VTINHERIT
902           || r_type == R_860_GNU_VTENTRY)
903         continue;
904 #endif
905
906       r_symndx = ELF32_R_SYM (rel->r_info);
907
908       if (info->relocateable)
909         {
910           /* This is a relocateable link.  We don't have to change
911              anything, unless the reloc is against a section symbol,
912              in which case we have to adjust according to where the
913              section symbol winds up in the output section.  */
914           if (r_symndx < symtab_hdr->sh_info)
915             {
916               sym = local_syms + r_symndx;
917
918               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
919                 {
920                   sec = local_sections [r_symndx];
921                   rel->r_addend += sec->output_offset + sym->st_value;
922                 }
923             }
924
925           continue;
926         }
927
928       /* This is a final link.  */
929       howto  = lookup_howto (ELF32_R_TYPE (rel->r_info));
930       h      = NULL;
931       sym    = NULL;
932       sec    = NULL;
933
934       if (r_symndx < symtab_hdr->sh_info)
935         {
936           sym = local_syms + r_symndx;
937           sec = local_sections [r_symndx];
938           relocation = (sec->output_section->vma
939                         + sec->output_offset
940                         + sym->st_value);
941
942           name = bfd_elf_string_from_elf_section
943             (input_bfd, symtab_hdr->sh_link, sym->st_name);
944           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
945         }
946       else
947         {
948           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
949
950           while (h->root.type == bfd_link_hash_indirect
951                  || h->root.type == bfd_link_hash_warning)
952             h = (struct elf_link_hash_entry *) h->root.u.i.link;
953
954           name = h->root.root.string;
955
956           if (h->root.type == bfd_link_hash_defined
957               || h->root.type == bfd_link_hash_defweak)
958             {
959               sec = h->root.u.def.section;
960               relocation = (h->root.u.def.value
961                             + sec->output_section->vma
962                             + sec->output_offset);
963             }
964           else if (h->root.type == bfd_link_hash_undefweak)
965             {
966               relocation = 0;
967             }
968           else
969             {
970               if (! ((*info->callbacks->undefined_symbol)
971                      (info, h->root.root.string, input_bfd,
972                       input_section, rel->r_offset, true)))
973                 return false;
974               relocation = 0;
975             }
976         }
977
978       switch (r_type)
979         {
980         default:
981           r = i860_final_link_relocate (howto, input_bfd, input_section,
982                                         contents, rel, relocation);
983           break;
984
985         case R_860_HIGHADJ:
986           r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
987                                            relocation);
988           break;
989
990         case R_860_PC16:
991           r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
992                                         contents, relocation);
993           break;
994
995         case R_860_PC26:
996           r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
997                                         contents, relocation);
998           break;
999
1000         case R_860_SPLIT0:
1001         case R_860_SPLIT1:
1002         case R_860_SPLIT2:
1003           r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1004                                           relocation);
1005           break;
1006
1007         /* We do not yet handle GOT/PLT/Dynamic relocations.  */
1008         case R_860_COPY:
1009         case R_860_GLOB_DAT:
1010         case R_860_JUMP_SLOT:
1011         case R_860_RELATIVE:
1012         case R_860_PLT26:
1013         case R_860_LOGOT0:
1014         case R_860_SPGOT0:
1015         case R_860_LOGOT1:
1016         case R_860_SPGOT1:
1017         case R_860_LOGOTOFF0:
1018         case R_860_SPGOTOFF0:
1019         case R_860_LOGOTOFF1:
1020         case R_860_SPGOTOFF1:
1021         case R_860_LOGOTOFF2:
1022         case R_860_LOGOTOFF3:
1023         case R_860_LOPC:
1024         case R_860_HAGOT:
1025         case R_860_HAGOTOFF:
1026         case R_860_HAPC:
1027         case R_860_HIGOT:
1028         case R_860_HIGOTOFF:
1029           r = bfd_reloc_notsupported;
1030           break;
1031         }
1032
1033       if (r != bfd_reloc_ok)
1034         {
1035           const char * msg = (const char *) NULL;
1036
1037           switch (r)
1038             {
1039             case bfd_reloc_overflow:
1040               r = info->callbacks->reloc_overflow
1041                 (info, name, howto->name, (bfd_vma) 0,
1042                  input_bfd, input_section, rel->r_offset);
1043               break;
1044
1045             case bfd_reloc_undefined:
1046               r = info->callbacks->undefined_symbol
1047                 (info, name, input_bfd, input_section, rel->r_offset, true);
1048               break;
1049
1050             case bfd_reloc_outofrange:
1051               msg = _("internal error: out of range error");
1052               break;
1053
1054             case bfd_reloc_notsupported:
1055               msg = _("internal error: unsupported relocation error");
1056               break;
1057
1058             case bfd_reloc_dangerous:
1059               msg = _("internal error: dangerous relocation");
1060               break;
1061
1062             default:
1063               msg = _("internal error: unknown error");
1064               break;
1065             }
1066
1067           if (msg)
1068             r = info->callbacks->warning
1069               (info, msg, name, input_bfd, input_section, rel->r_offset);
1070
1071           if (! r)
1072             return false;
1073         }
1074     }
1075
1076   return true;
1077 }
1078
1079 /* Return whether a symbol name implies a local label.  SVR4/860 compilers
1080    generate labels of the form ".ep.function_name" to denote the end of a
1081    function prolog. These should be local.
1082    ??? Do any other SVR4 compilers have this convention? If so, this should
1083    be added to the generic routine.  */
1084 static boolean
1085 elf32_i860_is_local_label_name (abfd, name)
1086      bfd *abfd;
1087      const char *name;
1088 {
1089   if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1090     return true;
1091
1092   return _bfd_elf_is_local_label_name (abfd, name);
1093 }
1094
1095 \f
1096 #define TARGET_BIG_SYM          bfd_elf32_i860_vec
1097 #define TARGET_BIG_NAME         "elf32-i860"
1098 #define TARGET_LITTLE_SYM       bfd_elf32_i860_little_vec
1099 #define TARGET_LITTLE_NAME      "elf32-i860-little"
1100 #define ELF_ARCH                bfd_arch_i860
1101 #define ELF_MACHINE_CODE        EM_860
1102 #define ELF_MAXPAGESIZE         4096
1103
1104 #define elf_info_to_howto_rel                   NULL
1105 #define elf_info_to_howto                       elf32_i860_info_to_howto_rela
1106 #define elf_backend_relocate_section            elf32_i860_relocate_section
1107 #define bfd_elf32_bfd_reloc_type_lookup         elf32_i860_reloc_type_lookup
1108 #define bfd_elf32_bfd_is_local_label_name       elf32_i860_is_local_label_name
1109
1110 #include "elf32-target.h"