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