2000-08-21 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_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;
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
729 /* Specialized relocation handler for R_860_PC16.  This relocation
730    involves a 16-bit, PC-relative field that is split into two contiguous
731    parts.  */
732 static bfd_reloc_status_type
733 elf32_i860_relocate_pc16 (input_bfd, input_section, rello, contents, value)
734      bfd *input_bfd;
735      asection *input_section;
736      Elf_Internal_Rela *rello;
737      bfd_byte *contents;
738      bfd_vma value;
739 {
740   bfd_vma insn;
741   reloc_howto_type *howto;
742   howto  = lookup_howto (ELF32_R_TYPE (rello->r_info));
743   insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
744
745   /* Adjust for PC-relative relocation.  */
746   value -= (input_section->output_section->vma
747             + input_section->output_offset);
748   value -= rello->r_offset;
749
750   /* Relocate.  */
751   value += rello->r_addend;
752
753   /* Separate the fields and insert.  */
754   value = (((value & 0xf8) << 5) | (value & 0x7ff)) & howto->dst_mask;
755   insn = (insn & ~howto->dst_mask) | value;
756
757   bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
758   return bfd_reloc_ok;
759
760 }
761
762
763 /* Specialized relocation handler for R_860_HIGHADJ.  */
764 static bfd_reloc_status_type
765 elf32_i860_relocate_highadj (input_bfd, rel, contents, value)
766      bfd *input_bfd;
767      Elf_Internal_Rela *rel;
768      bfd_byte *contents;
769      bfd_vma value;
770 {
771   bfd_vma insn;
772
773   insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
774
775   value += ((rel->r_addend & 0x8000) << 1);
776   value += rel->r_addend;
777   value = ((value >> 16) & 0xffff);
778
779   insn = (insn & 0xffff0000) | value;
780
781   bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
782   return bfd_reloc_ok;
783 }
784
785
786 /* Perform a single relocation.  By default we use the standard BFD
787    routines. However, we handle some specially.  */
788 static bfd_reloc_status_type
789 i860_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
790      reloc_howto_type *  howto;
791      bfd *               input_bfd;
792      asection *          input_section;
793      bfd_byte *          contents;
794      Elf_Internal_Rela * rel;
795      bfd_vma             relocation;
796 {
797   return _bfd_final_link_relocate (howto, input_bfd, input_section,
798                                    contents, rel->r_offset, relocation,
799                                    rel->r_addend);
800 }
801
802
803 /* Relocate an i860 ELF section.
804
805    This is boiler-plate code copied from fr30.
806    There is some attempt to make this function usable for many architectures,
807    both USE_REL and USE_RELA ['twould be nice if such a critter existed],
808    if only to serve as a learning tool.
809
810    The RELOCATE_SECTION function is called by the new ELF backend linker
811    to handle the relocations for a section.
812
813    The relocs are always passed as Rela structures; if the section
814    actually uses Rel structures, the r_addend field will always be
815    zero.
816
817    This function is responsible for adjusting the section contents as
818    necessary, and (if using Rela relocs and generating a relocateable
819    output file) adjusting the reloc addend as necessary.
820
821    This function does not have to worry about setting the reloc
822    address or the reloc symbol index.
823
824    LOCAL_SYMS is a pointer to the swapped in local symbols.
825
826    LOCAL_SECTIONS is an array giving the section in the input file
827    corresponding to the st_shndx field of each local symbol.
828
829    The global hash table entry for the global symbols can be found
830    via elf_sym_hashes (input_bfd).
831
832    When generating relocateable output, this function must handle
833    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
834    going to be the section symbol corresponding to the output
835    section, which means that the addend must be adjusted
836    accordingly.  */
837 static boolean
838 elf32_i860_relocate_section (output_bfd, info, input_bfd, input_section,
839                              contents, relocs, local_syms, local_sections)
840      bfd *                   output_bfd ATTRIBUTE_UNUSED;
841      struct bfd_link_info *  info;
842      bfd *                   input_bfd;
843      asection *              input_section;
844      bfd_byte *              contents;
845      Elf_Internal_Rela *     relocs;
846      Elf_Internal_Sym *      local_syms;
847      asection **             local_sections;
848 {
849   Elf_Internal_Shdr *           symtab_hdr;
850   struct elf_link_hash_entry ** sym_hashes;
851   Elf_Internal_Rela *           rel;
852   Elf_Internal_Rela *           relend;
853
854   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
855   sym_hashes = elf_sym_hashes (input_bfd);
856   relend     = relocs + input_section->reloc_count;
857
858   for (rel = relocs; rel < relend; rel ++)
859     {
860       reloc_howto_type *           howto;
861       unsigned long                r_symndx;
862       Elf_Internal_Sym *           sym;
863       asection *                   sec;
864       struct elf_link_hash_entry * h;
865       bfd_vma                      relocation;
866       bfd_reloc_status_type        r;
867       const char *                 name = NULL;
868       int                          r_type;
869       
870       r_type = ELF32_R_TYPE (rel->r_info);
871      
872 #if 0
873       if (   r_type == R_860_GNU_VTINHERIT
874           || r_type == R_860_GNU_VTENTRY)
875         continue;
876 #endif
877       
878       r_symndx = ELF32_R_SYM (rel->r_info);
879
880       if (info->relocateable)
881         {
882           /* This is a relocateable link.  We don't have to change
883              anything, unless the reloc is against a section symbol,
884              in which case we have to adjust according to where the
885              section symbol winds up in the output section.  */
886           if (r_symndx < symtab_hdr->sh_info)
887             {
888               sym = local_syms + r_symndx;
889               
890               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
891                 {
892                   sec = local_sections [r_symndx];
893                   rel->r_addend += sec->output_offset + sym->st_value;
894                 }
895             }
896
897           continue;
898         }
899
900       /* This is a final link.  */
901       howto  = lookup_howto (ELF32_R_TYPE (rel->r_info));
902       h      = NULL;
903       sym    = NULL;
904       sec    = NULL;
905       
906       if (r_symndx < symtab_hdr->sh_info)
907         {
908           sym = local_syms + r_symndx;
909           sec = local_sections [r_symndx];
910           relocation = (sec->output_section->vma
911                         + sec->output_offset
912                         + sym->st_value);
913           
914           name = bfd_elf_string_from_elf_section
915             (input_bfd, symtab_hdr->sh_link, sym->st_name);
916           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
917         }
918       else
919         {
920           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
921           
922           while (h->root.type == bfd_link_hash_indirect
923                  || h->root.type == bfd_link_hash_warning)
924             h = (struct elf_link_hash_entry *) h->root.u.i.link;
925
926           name = h->root.root.string;
927           
928           if (h->root.type == bfd_link_hash_defined
929               || h->root.type == bfd_link_hash_defweak)
930             {
931               sec = h->root.u.def.section;
932               relocation = (h->root.u.def.value
933                             + sec->output_section->vma
934                             + sec->output_offset);
935             }
936           else if (h->root.type == bfd_link_hash_undefweak)
937             {
938               relocation = 0;
939             }
940           else
941             {
942               if (! ((*info->callbacks->undefined_symbol)
943                      (info, h->root.root.string, input_bfd,
944                       input_section, rel->r_offset, true)))
945                 return false;
946               relocation = 0;
947             }
948         }
949    
950       switch (r_type)
951         {
952         default:
953           r = i860_final_link_relocate (howto, input_bfd, input_section,
954                                         contents, rel, relocation);
955           break;
956
957         case R_860_HIGHADJ:
958           r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
959                                            relocation);
960           break;
961
962         case R_860_PC16:
963           r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
964                                         contents, relocation);
965           break;
966
967         case R_860_SPLIT0:
968         case R_860_SPLIT1:
969         case R_860_SPLIT2:
970           r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
971                                           relocation);
972           break;
973
974         /* We do not yet handle GOT/PLT/Dynamic relocations.  */
975         case R_860_COPY:
976         case R_860_GLOB_DAT:
977         case R_860_JUMP_SLOT:
978         case R_860_RELATIVE:
979         case R_860_PLT26:
980         case R_860_LOGOT0:
981         case R_860_SPGOT0:
982         case R_860_LOGOT1:
983         case R_860_SPGOT1:
984         case R_860_LOGOTOFF0:
985         case R_860_SPGOTOFF0:
986         case R_860_LOGOTOFF1:
987         case R_860_SPGOTOFF1:
988         case R_860_LOGOTOFF2:
989         case R_860_LOGOTOFF3:
990         case R_860_LOPC:
991         case R_860_HAGOT:
992         case R_860_HAGOTOFF:
993         case R_860_HAPC:
994         case R_860_HIGOT:
995         case R_860_HIGOTOFF:
996           r = bfd_reloc_notsupported;
997           break;
998         } 
999
1000       if (r != bfd_reloc_ok)
1001         {
1002           const char * msg = (const char *) NULL;
1003
1004           switch (r)
1005             {
1006             case bfd_reloc_overflow:
1007               r = info->callbacks->reloc_overflow
1008                 (info, name, howto->name, (bfd_vma) 0,
1009                  input_bfd, input_section, rel->r_offset);
1010               break;
1011               
1012             case bfd_reloc_undefined:
1013               r = info->callbacks->undefined_symbol
1014                 (info, name, input_bfd, input_section, rel->r_offset, true);
1015               break;
1016               
1017             case bfd_reloc_outofrange:
1018               msg = _("internal error: out of range error");
1019               break;
1020
1021             case bfd_reloc_notsupported:
1022               msg = _("internal error: unsupported relocation error");
1023               break;
1024
1025             case bfd_reloc_dangerous:
1026               msg = _("internal error: dangerous relocation");
1027               break;
1028
1029             default:
1030               msg = _("internal error: unknown error");
1031               break;
1032             }
1033
1034           if (msg)
1035             r = info->callbacks->warning
1036               (info, msg, name, input_bfd, input_section, rel->r_offset);
1037
1038           if (! r)
1039             return false;
1040         }
1041     }
1042
1043   return true;
1044 }
1045
1046
1047 \f
1048 #define TARGET_BIG_SYM          bfd_elf32_i860_vec
1049 #define TARGET_BIG_NAME         "elf32-i860"
1050 #define TARGET_LITTLE_SYM       bfd_elf32_i860_little_vec
1051 #define TARGET_LITTLE_NAME      "elf32-i860-little"
1052 #define ELF_ARCH                bfd_arch_i860
1053 #define ELF_MACHINE_CODE        EM_860
1054 #define ELF_MAXPAGESIZE         4096
1055
1056 #define elf_info_to_howto_rel                   NULL
1057 #define elf_info_to_howto                       elf32_i860_info_to_howto_rela
1058 #define elf_backend_relocate_section            elf32_i860_relocate_section
1059 #define bfd_elf32_bfd_reloc_type_lookup         elf32_i860_reloc_type_lookup
1060
1061 #include "elf32-target.h"