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