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