* config/tc-mips.c (append_insn): Correctly handle mips16 case
[binutils.git] / bfd / elf32-i860.c
blob453256018884217b48f2190abdbad2d3437887cf
1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
5 Full i860 support contributed by Jason Eckhardt <jle@cygnus.com>.
7 This file is part of BFD, the Binary File Descriptor library.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "libbfd.h"
26 #include "elf-bfd.h"
27 #include "elf/i860.h"
29 /* special_function for R_860_PC26 relocation. */
30 static bfd_reloc_status_type
31 i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
32 arelent *reloc_entry,
33 asymbol *symbol,
34 void *data ATTRIBUTE_UNUSED,
35 asection *input_section,
36 bfd *output_bfd,
37 char **error_message ATTRIBUTE_UNUSED)
39 bfd_vma insn;
40 bfd_vma relocation;
41 bfd_byte *addr;
43 if (output_bfd != NULL
44 && (symbol->flags & BSF_SECTION_SYM) == 0
45 && (! reloc_entry->howto->partial_inplace
46 || reloc_entry->addend == 0))
48 reloc_entry->address += input_section->output_offset;
49 return bfd_reloc_ok;
52 /* Used elf32-mips.c as an example. */
53 if (bfd_is_und_section (symbol->section)
54 && output_bfd == (bfd *) NULL)
55 return bfd_reloc_undefined;
57 if (bfd_is_com_section (symbol->section))
58 relocation = 0;
59 else
60 relocation = symbol->value;
62 relocation += symbol->section->output_section->vma;
63 relocation += symbol->section->output_offset;
64 relocation += reloc_entry->addend;
66 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
67 return bfd_reloc_outofrange;
69 /* Adjust for PC-relative relocation. */
70 relocation -= (input_section->output_section->vma
71 + input_section->output_offset
72 + reloc_entry->address
73 + 4);
75 /* Check for target out of range. */
76 if ((bfd_signed_vma)relocation > (0x3ffffff << 2)
77 || (bfd_signed_vma)relocation < (-0x4000000 << 2))
78 return bfd_reloc_outofrange;
80 addr = (bfd_byte *) data + reloc_entry->address;
81 insn = bfd_get_32 (abfd, addr);
83 relocation >>= reloc_entry->howto->rightshift;
84 insn = (insn & ~reloc_entry->howto->dst_mask)
85 | (relocation & reloc_entry->howto->dst_mask);
87 bfd_put_32 (abfd, (bfd_vma) insn, addr);
89 return bfd_reloc_ok;
92 /* special_function for R_860_PC16 relocation. */
93 static bfd_reloc_status_type
94 i860_howto_pc16_reloc (bfd *abfd,
95 arelent *reloc_entry,
96 asymbol *symbol,
97 void *data,
98 asection *input_section,
99 bfd *output_bfd,
100 char **error_message ATTRIBUTE_UNUSED)
102 bfd_vma insn;
103 bfd_vma relocation;
104 bfd_byte *addr;
106 if (output_bfd != NULL
107 && (symbol->flags & BSF_SECTION_SYM) == 0
108 && (! reloc_entry->howto->partial_inplace
109 || reloc_entry->addend == 0))
111 reloc_entry->address += input_section->output_offset;
112 return bfd_reloc_ok;
115 /* Used elf32-mips.c as an example. */
116 if (bfd_is_und_section (symbol->section)
117 && output_bfd == (bfd *) NULL)
118 return bfd_reloc_undefined;
120 if (bfd_is_com_section (symbol->section))
121 relocation = 0;
122 else
123 relocation = symbol->value;
125 relocation += symbol->section->output_section->vma;
126 relocation += symbol->section->output_offset;
127 relocation += reloc_entry->addend;
129 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
130 return bfd_reloc_outofrange;
132 /* Adjust for PC-relative relocation. */
133 relocation -= (input_section->output_section->vma
134 + input_section->output_offset
135 + reloc_entry->address
136 + 4);
138 /* Check for target out of range. */
139 if ((bfd_signed_vma)relocation > (0x7fff << 2)
140 || (bfd_signed_vma)relocation < (-0x8000 << 2))
141 return bfd_reloc_outofrange;
143 addr = (bfd_byte *) data + reloc_entry->address;
144 insn = bfd_get_32 (abfd, addr);
146 relocation >>= reloc_entry->howto->rightshift;
147 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
148 & reloc_entry->howto->dst_mask;
149 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
151 bfd_put_32 (abfd, (bfd_vma) insn, addr);
153 return bfd_reloc_ok;
156 /* special_function for R_860_HIGHADJ relocation. */
157 static bfd_reloc_status_type
158 i860_howto_highadj_reloc (bfd *abfd,
159 arelent *reloc_entry,
160 asymbol *symbol,
161 void *data,
162 asection *input_section,
163 bfd *output_bfd,
164 char **error_message ATTRIBUTE_UNUSED)
166 bfd_vma insn;
167 bfd_vma relocation;
168 bfd_byte *addr;
170 if (output_bfd != NULL
171 && (symbol->flags & BSF_SECTION_SYM) == 0
172 && (! reloc_entry->howto->partial_inplace
173 || reloc_entry->addend == 0))
175 reloc_entry->address += input_section->output_offset;
176 return bfd_reloc_ok;
179 /* Used elf32-mips.c as an example. */
180 if (bfd_is_und_section (symbol->section)
181 && output_bfd == (bfd *) NULL)
182 return bfd_reloc_undefined;
184 if (bfd_is_com_section (symbol->section))
185 relocation = 0;
186 else
187 relocation = symbol->value;
189 relocation += symbol->section->output_section->vma;
190 relocation += symbol->section->output_offset;
191 relocation += reloc_entry->addend;
192 relocation += 0x8000;
194 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
195 return bfd_reloc_outofrange;
197 addr = (bfd_byte *) data + reloc_entry->address;
198 insn = bfd_get_32 (abfd, addr);
200 relocation = ((relocation >> 16) & 0xffff);
202 insn = (insn & 0xffff0000) | relocation;
204 bfd_put_32 (abfd, (bfd_vma) insn, addr);
206 return bfd_reloc_ok;
209 /* special_function for R_860_SPLITn relocations. */
210 static bfd_reloc_status_type
211 i860_howto_splitn_reloc (bfd *abfd,
212 arelent *reloc_entry,
213 asymbol *symbol,
214 void *data,
215 asection *input_section,
216 bfd *output_bfd,
217 char **error_message ATTRIBUTE_UNUSED)
219 bfd_vma insn;
220 bfd_vma relocation;
221 bfd_byte *addr;
223 if (output_bfd != NULL
224 && (symbol->flags & BSF_SECTION_SYM) == 0
225 && (! reloc_entry->howto->partial_inplace
226 || reloc_entry->addend == 0))
228 reloc_entry->address += input_section->output_offset;
229 return bfd_reloc_ok;
232 /* Used elf32-mips.c as an example. */
233 if (bfd_is_und_section (symbol->section)
234 && output_bfd == (bfd *) NULL)
235 return bfd_reloc_undefined;
237 if (bfd_is_com_section (symbol->section))
238 relocation = 0;
239 else
240 relocation = symbol->value;
242 relocation += symbol->section->output_section->vma;
243 relocation += symbol->section->output_offset;
244 relocation += reloc_entry->addend;
246 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
247 return bfd_reloc_outofrange;
249 addr = (bfd_byte *) data + reloc_entry->address;
250 insn = bfd_get_32 (abfd, addr);
252 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
253 & reloc_entry->howto->dst_mask;
254 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
256 bfd_put_32 (abfd, (bfd_vma) insn, addr);
258 return bfd_reloc_ok;
261 /* This howto table is preliminary. */
262 static reloc_howto_type elf32_i860_howto_table [] =
264 /* This relocation does nothing. */
265 HOWTO (R_860_NONE, /* type */
266 0, /* rightshift */
267 2, /* size (0 = byte, 1 = short, 2 = long) */
268 32, /* bitsize */
269 FALSE, /* pc_relative */
270 0, /* bitpos */
271 complain_overflow_bitfield, /* complain_on_overflow */
272 bfd_elf_generic_reloc, /* special_function */
273 "R_860_NONE", /* name */
274 FALSE, /* partial_inplace */
275 0, /* src_mask */
276 0, /* dst_mask */
277 FALSE), /* pcrel_offset */
279 /* A 32-bit absolute relocation. */
280 HOWTO (R_860_32, /* type */
281 0, /* rightshift */
282 2, /* size (0 = byte, 1 = short, 2 = long) */
283 32, /* bitsize */
284 FALSE, /* pc_relative */
285 0, /* bitpos */
286 complain_overflow_bitfield, /* complain_on_overflow */
287 bfd_elf_generic_reloc, /* special_function */
288 "R_860_32", /* name */
289 FALSE, /* partial_inplace */
290 0xffffffff, /* src_mask */
291 0xffffffff, /* dst_mask */
292 FALSE), /* pcrel_offset */
294 HOWTO (R_860_COPY, /* type */
295 0, /* rightshift */
296 2, /* size (0 = byte, 1 = short, 2 = long) */
297 32, /* bitsize */
298 FALSE, /* pc_relative */
299 0, /* bitpos */
300 complain_overflow_bitfield, /* complain_on_overflow */
301 bfd_elf_generic_reloc, /* special_function */
302 "R_860_COPY", /* name */
303 TRUE, /* partial_inplace */
304 0xffffffff, /* src_mask */
305 0xffffffff, /* dst_mask */
306 FALSE), /* pcrel_offset */
308 HOWTO (R_860_GLOB_DAT, /* type */
309 0, /* rightshift */
310 2, /* size (0 = byte, 1 = short, 2 = long) */
311 32, /* bitsize */
312 FALSE, /* pc_relative */
313 0, /* bitpos */
314 complain_overflow_bitfield, /* complain_on_overflow */
315 bfd_elf_generic_reloc, /* special_function */
316 "R_860_GLOB_DAT", /* name */
317 TRUE, /* partial_inplace */
318 0xffffffff, /* src_mask */
319 0xffffffff, /* dst_mask */
320 FALSE), /* pcrel_offset */
322 HOWTO (R_860_JUMP_SLOT, /* type */
323 0, /* rightshift */
324 2, /* size (0 = byte, 1 = short, 2 = long) */
325 32, /* bitsize */
326 FALSE, /* pc_relative */
327 0, /* bitpos */
328 complain_overflow_bitfield, /* complain_on_overflow */
329 bfd_elf_generic_reloc, /* special_function */
330 "R_860_JUMP_SLOT", /* name */
331 TRUE, /* partial_inplace */
332 0xffffffff, /* src_mask */
333 0xffffffff, /* dst_mask */
334 FALSE), /* pcrel_offset */
336 HOWTO (R_860_RELATIVE, /* type */
337 0, /* rightshift */
338 2, /* size (0 = byte, 1 = short, 2 = long) */
339 32, /* bitsize */
340 FALSE, /* pc_relative */
341 0, /* bitpos */
342 complain_overflow_bitfield, /* complain_on_overflow */
343 bfd_elf_generic_reloc, /* special_function */
344 "R_860_RELATIVE", /* name */
345 TRUE, /* partial_inplace */
346 0xffffffff, /* src_mask */
347 0xffffffff, /* dst_mask */
348 FALSE), /* pcrel_offset */
350 /* A 26-bit PC-relative relocation. */
351 HOWTO (R_860_PC26, /* type */
352 2, /* rightshift */
353 2, /* size (0 = byte, 1 = short, 2 = long) */
354 26, /* bitsize */
355 TRUE, /* pc_relative */
356 0, /* bitpos */
357 complain_overflow_bitfield, /* complain_on_overflow */
358 i860_howto_pc26_reloc, /* special_function */
359 "R_860_PC26", /* name */
360 FALSE, /* partial_inplace */
361 0x3ffffff, /* src_mask */
362 0x3ffffff, /* dst_mask */
363 TRUE), /* pcrel_offset */
365 HOWTO (R_860_PLT26, /* type */
366 0, /* rightshift */
367 2, /* size (0 = byte, 1 = short, 2 = long) */
368 26, /* bitsize */
369 TRUE, /* pc_relative */
370 0, /* bitpos */
371 complain_overflow_bitfield, /* complain_on_overflow */
372 bfd_elf_generic_reloc, /* special_function */
373 "R_860_PLT26", /* name */
374 TRUE, /* partial_inplace */
375 0xffffffff, /* src_mask */
376 0xffffffff, /* dst_mask */
377 TRUE), /* pcrel_offset */
379 /* A 16-bit PC-relative relocation. */
380 HOWTO (R_860_PC16, /* type */
381 2, /* rightshift */
382 2, /* size (0 = byte, 1 = short, 2 = long) */
383 16, /* bitsize */
384 TRUE, /* pc_relative */
385 0, /* bitpos */
386 complain_overflow_bitfield, /* complain_on_overflow */
387 i860_howto_pc16_reloc, /* special_function */
388 "R_860_PC16", /* name */
389 FALSE, /* partial_inplace */
390 0x1f07ff, /* src_mask */
391 0x1f07ff, /* dst_mask */
392 TRUE), /* pcrel_offset */
394 HOWTO (R_860_LOW0, /* type */
395 0, /* rightshift */
396 2, /* size (0 = byte, 1 = short, 2 = long) */
397 16, /* bitsize */
398 FALSE, /* pc_relative */
399 0, /* bitpos */
400 complain_overflow_dont, /* complain_on_overflow */
401 bfd_elf_generic_reloc, /* special_function */
402 "R_860_LOW0", /* name */
403 FALSE, /* partial_inplace */
404 0xffff, /* src_mask */
405 0xffff, /* dst_mask */
406 FALSE), /* pcrel_offset */
408 HOWTO (R_860_SPLIT0, /* type */
409 0, /* rightshift */
410 2, /* size (0 = byte, 1 = short, 2 = long) */
411 16, /* bitsize */
412 FALSE, /* pc_relative */
413 0, /* bitpos */
414 complain_overflow_dont, /* complain_on_overflow */
415 i860_howto_splitn_reloc, /* special_function */
416 "R_860_SPLIT0", /* name */
417 FALSE, /* partial_inplace */
418 0x1f07ff, /* src_mask */
419 0x1f07ff, /* dst_mask */
420 FALSE), /* pcrel_offset */
422 HOWTO (R_860_LOW1, /* type */
423 0, /* rightshift */
424 2, /* size (0 = byte, 1 = short, 2 = long) */
425 16, /* bitsize */
426 FALSE, /* pc_relative */
427 0, /* bitpos */
428 complain_overflow_dont, /* complain_on_overflow */
429 bfd_elf_generic_reloc, /* special_function */
430 "R_860_LOW1", /* name */
431 FALSE, /* partial_inplace */
432 0xfffe, /* src_mask */
433 0xfffe, /* dst_mask */
434 FALSE), /* pcrel_offset */
436 HOWTO (R_860_SPLIT1, /* type */
437 0, /* rightshift */
438 2, /* size (0 = byte, 1 = short, 2 = long) */
439 16, /* bitsize */
440 FALSE, /* pc_relative */
441 0, /* bitpos */
442 complain_overflow_dont, /* complain_on_overflow */
443 i860_howto_splitn_reloc, /* special_function */
444 "R_860_SPLIT1", /* name */
445 FALSE, /* partial_inplace */
446 0x1f07fe, /* src_mask */
447 0x1f07fe, /* dst_mask */
448 FALSE), /* pcrel_offset */
450 HOWTO (R_860_LOW2, /* type */
451 0, /* rightshift */
452 2, /* size (0 = byte, 1 = short, 2 = long) */
453 16, /* bitsize */
454 FALSE, /* pc_relative */
455 0, /* bitpos */
456 complain_overflow_dont, /* complain_on_overflow */
457 bfd_elf_generic_reloc, /* special_function */
458 "R_860_LOW2", /* name */
459 FALSE, /* partial_inplace */
460 0xfffc, /* src_mask */
461 0xfffc, /* dst_mask */
462 FALSE), /* pcrel_offset */
464 HOWTO (R_860_SPLIT2, /* type */
465 0, /* rightshift */
466 2, /* size (0 = byte, 1 = short, 2 = long) */
467 16, /* bitsize */
468 FALSE, /* pc_relative */
469 0, /* bitpos */
470 complain_overflow_dont, /* complain_on_overflow */
471 i860_howto_splitn_reloc, /* special_function */
472 "R_860_SPLIT2", /* name */
473 FALSE, /* partial_inplace */
474 0x1f07fc, /* src_mask */
475 0x1f07fc, /* dst_mask */
476 FALSE), /* pcrel_offset */
478 HOWTO (R_860_LOW3, /* type */
479 0, /* rightshift */
480 2, /* size (0 = byte, 1 = short, 2 = long) */
481 16, /* bitsize */
482 FALSE, /* pc_relative */
483 0, /* bitpos */
484 complain_overflow_dont, /* complain_on_overflow */
485 bfd_elf_generic_reloc, /* special_function */
486 "R_860_LOW3", /* name */
487 FALSE, /* partial_inplace */
488 0xfff8, /* src_mask */
489 0xfff8, /* dst_mask */
490 FALSE), /* pcrel_offset */
492 HOWTO (R_860_LOGOT0, /* type */
493 0, /* rightshift */
494 2, /* size (0 = byte, 1 = short, 2 = long) */
495 16, /* bitsize */
496 FALSE, /* pc_relative */
497 0, /* bitpos */
498 complain_overflow_dont, /* complain_on_overflow */
499 bfd_elf_generic_reloc, /* special_function */
500 "R_860_LOGOT0", /* name */
501 FALSE, /* partial_inplace */
502 0, /* src_mask */
503 0xffff, /* dst_mask */
504 TRUE), /* pcrel_offset */
506 HOWTO (R_860_SPGOT0, /* type */
507 0, /* rightshift */
508 2, /* size (0 = byte, 1 = short, 2 = long) */
509 16, /* bitsize */
510 FALSE, /* pc_relative */
511 0, /* bitpos */
512 complain_overflow_dont, /* complain_on_overflow */
513 bfd_elf_generic_reloc, /* special_function */
514 "R_860_SPGOT0", /* name */
515 FALSE, /* partial_inplace */
516 0, /* src_mask */
517 0xffff, /* dst_mask */
518 TRUE), /* pcrel_offset */
520 HOWTO (R_860_LOGOT1, /* type */
521 0, /* rightshift */
522 2, /* size (0 = byte, 1 = short, 2 = long) */
523 16, /* bitsize */
524 FALSE, /* pc_relative */
525 0, /* bitpos */
526 complain_overflow_dont, /* complain_on_overflow */
527 bfd_elf_generic_reloc, /* special_function */
528 "R_860_LOGOT1", /* name */
529 FALSE, /* partial_inplace */
530 0, /* src_mask */
531 0xffff, /* dst_mask */
532 TRUE), /* pcrel_offset */
534 HOWTO (R_860_SPGOT1, /* type */
535 0, /* rightshift */
536 2, /* size (0 = byte, 1 = short, 2 = long) */
537 16, /* bitsize */
538 FALSE, /* pc_relative */
539 0, /* bitpos */
540 complain_overflow_dont, /* complain_on_overflow */
541 bfd_elf_generic_reloc, /* special_function */
542 "R_860_SPGOT1", /* name */
543 FALSE, /* partial_inplace */
544 0, /* src_mask */
545 0xffff, /* dst_mask */
546 TRUE), /* pcrel_offset */
548 HOWTO (R_860_LOGOTOFF0, /* type */
549 0, /* rightshift */
550 2, /* size (0 = byte, 1 = short, 2 = long) */
551 32, /* bitsize */
552 FALSE, /* pc_relative */
553 0, /* bitpos */
554 complain_overflow_dont, /* complain_on_overflow */
555 bfd_elf_generic_reloc, /* special_function */
556 "R_860_LOGOTOFF0", /* name */
557 TRUE, /* partial_inplace */
558 0xffffffff, /* src_mask */
559 0xffffffff, /* dst_mask */
560 FALSE), /* pcrel_offset */
562 HOWTO (R_860_SPGOTOFF0, /* type */
563 0, /* rightshift */
564 2, /* size (0 = byte, 1 = short, 2 = long) */
565 32, /* bitsize */
566 FALSE, /* pc_relative */
567 0, /* bitpos */
568 complain_overflow_dont, /* complain_on_overflow */
569 bfd_elf_generic_reloc, /* special_function */
570 "R_860_SPGOTOFF0", /* name */
571 TRUE, /* partial_inplace */
572 0xffffffff, /* src_mask */
573 0xffffffff, /* dst_mask */
574 FALSE), /* pcrel_offset */
576 HOWTO (R_860_LOGOTOFF1, /* type */
577 0, /* rightshift */
578 2, /* size (0 = byte, 1 = short, 2 = long) */
579 32, /* bitsize */
580 FALSE, /* pc_relative */
581 0, /* bitpos */
582 complain_overflow_dont, /* complain_on_overflow */
583 bfd_elf_generic_reloc, /* special_function */
584 "R_860_LOGOTOFF1", /* name */
585 TRUE, /* partial_inplace */
586 0xffffffff, /* src_mask */
587 0xffffffff, /* dst_mask */
588 FALSE), /* pcrel_offset */
590 HOWTO (R_860_SPGOTOFF1, /* type */
591 0, /* rightshift */
592 2, /* size (0 = byte, 1 = short, 2 = long) */
593 32, /* bitsize */
594 FALSE, /* pc_relative */
595 0, /* bitpos */
596 complain_overflow_dont, /* complain_on_overflow */
597 bfd_elf_generic_reloc, /* special_function */
598 "R_860_SPGOTOFF1", /* name */
599 TRUE, /* partial_inplace */
600 0xffffffff, /* src_mask */
601 0xffffffff, /* dst_mask */
602 FALSE), /* pcrel_offset */
604 HOWTO (R_860_LOGOTOFF2, /* type */
605 0, /* rightshift */
606 2, /* size (0 = byte, 1 = short, 2 = long) */
607 32, /* bitsize */
608 FALSE, /* pc_relative */
609 0, /* bitpos */
610 complain_overflow_dont, /* complain_on_overflow */
611 bfd_elf_generic_reloc, /* special_function */
612 "R_860_LOGOTOFF2", /* name */
613 TRUE, /* partial_inplace */
614 0xffffffff, /* src_mask */
615 0xffffffff, /* dst_mask */
616 FALSE), /* pcrel_offset */
618 HOWTO (R_860_LOGOTOFF3, /* type */
619 0, /* rightshift */
620 2, /* size (0 = byte, 1 = short, 2 = long) */
621 32, /* bitsize */
622 FALSE, /* pc_relative */
623 0, /* bitpos */
624 complain_overflow_dont, /* complain_on_overflow */
625 bfd_elf_generic_reloc, /* special_function */
626 "R_860_LOGOTOFF3", /* name */
627 TRUE, /* partial_inplace */
628 0xffffffff, /* src_mask */
629 0xffffffff, /* dst_mask */
630 FALSE), /* pcrel_offset */
632 HOWTO (R_860_LOPC, /* type */
633 0, /* rightshift */
634 2, /* size (0 = byte, 1 = short, 2 = long) */
635 16, /* bitsize */
636 TRUE, /* pc_relative */
637 0, /* bitpos */
638 complain_overflow_bitfield, /* complain_on_overflow */
639 bfd_elf_generic_reloc, /* special_function */
640 "R_860_LOPC", /* name */
641 FALSE, /* partial_inplace */
642 0xffff, /* src_mask */
643 0xffff, /* dst_mask */
644 TRUE), /* pcrel_offset */
646 HOWTO (R_860_HIGHADJ, /* type */
647 0, /* rightshift */
648 2, /* size (0 = byte, 1 = short, 2 = long) */
649 16, /* bitsize */
650 FALSE, /* pc_relative */
651 0, /* bitpos */
652 complain_overflow_dont, /* complain_on_overflow */
653 i860_howto_highadj_reloc, /* special_function */
654 "R_860_HIGHADJ", /* name */
655 FALSE, /* partial_inplace */
656 0xffff, /* src_mask */
657 0xffff, /* dst_mask */
658 FALSE), /* pcrel_offset */
660 HOWTO (R_860_HAGOT, /* type */
661 0, /* rightshift */
662 2, /* size (0 = byte, 1 = short, 2 = long) */
663 16, /* bitsize */
664 FALSE, /* pc_relative */
665 0, /* bitpos */
666 complain_overflow_dont, /* complain_on_overflow */
667 bfd_elf_generic_reloc, /* special_function */
668 "R_860_HAGOT", /* name */
669 FALSE, /* partial_inplace */
670 0, /* src_mask */
671 0xffff, /* dst_mask */
672 TRUE), /* pcrel_offset */
674 HOWTO (R_860_HAGOTOFF, /* type */
675 0, /* rightshift */
676 2, /* size (0 = byte, 1 = short, 2 = long) */
677 32, /* bitsize */
678 FALSE, /* pc_relative */
679 0, /* bitpos */
680 complain_overflow_dont, /* complain_on_overflow */
681 bfd_elf_generic_reloc, /* special_function */
682 "R_860_HAGOTOFF", /* name */
683 TRUE, /* partial_inplace */
684 0xffffffff, /* src_mask */
685 0xffffffff, /* dst_mask */
686 FALSE), /* pcrel_offset */
688 HOWTO (R_860_HAPC, /* type */
689 0, /* rightshift */
690 2, /* size (0 = byte, 1 = short, 2 = long) */
691 16, /* bitsize */
692 TRUE, /* pc_relative */
693 0, /* bitpos */
694 complain_overflow_bitfield, /* complain_on_overflow */
695 bfd_elf_generic_reloc, /* special_function */
696 "R_860_HAPC", /* name */
697 FALSE, /* partial_inplace */
698 0xffff, /* src_mask */
699 0xffff, /* dst_mask */
700 TRUE), /* pcrel_offset */
702 HOWTO (R_860_HIGH, /* type */
703 16, /* rightshift */
704 2, /* size (0 = byte, 1 = short, 2 = long) */
705 16, /* bitsize */
706 FALSE, /* pc_relative */
707 0, /* bitpos */
708 complain_overflow_dont, /* complain_on_overflow */
709 bfd_elf_generic_reloc, /* special_function */
710 "R_860_HIGH", /* name */
711 FALSE, /* partial_inplace */
712 0xffff, /* src_mask */
713 0xffff, /* dst_mask */
714 FALSE), /* pcrel_offset */
716 HOWTO (R_860_HIGOT, /* type */
717 0, /* rightshift */
718 2, /* size (0 = byte, 1 = short, 2 = long) */
719 16, /* bitsize */
720 FALSE, /* pc_relative */
721 0, /* bitpos */
722 complain_overflow_dont, /* complain_on_overflow */
723 bfd_elf_generic_reloc, /* special_function */
724 "R_860_HIGOT", /* name */
725 FALSE, /* partial_inplace */
726 0, /* src_mask */
727 0xffff, /* dst_mask */
728 TRUE), /* pcrel_offset */
730 HOWTO (R_860_HIGOTOFF, /* type */
731 0, /* rightshift */
732 2, /* size (0 = byte, 1 = short, 2 = long) */
733 32, /* bitsize */
734 FALSE, /* pc_relative */
735 0, /* bitpos */
736 complain_overflow_dont, /* complain_on_overflow */
737 bfd_elf_generic_reloc, /* special_function */
738 "R_860_HIGOTOFF", /* name */
739 TRUE, /* partial_inplace */
740 0xffffffff, /* src_mask */
741 0xffffffff, /* dst_mask */
742 FALSE), /* pcrel_offset */
745 static unsigned char elf_code_to_howto_index[R_860_max + 1];
747 static reloc_howto_type *
748 lookup_howto (unsigned int rtype)
750 static int initialized = 0;
751 int i;
752 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
753 / sizeof (elf32_i860_howto_table[0]));
755 if (! initialized)
757 initialized = 1;
758 memset (elf_code_to_howto_index, 0xff,
759 sizeof (elf_code_to_howto_index));
760 for (i = 0; i < howto_tbl_size; i++)
761 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
764 BFD_ASSERT (rtype <= R_860_max);
765 i = elf_code_to_howto_index[rtype];
766 if (i >= howto_tbl_size)
767 return 0;
768 return elf32_i860_howto_table + i;
771 /* Given a BFD reloc, return the matching HOWTO structure. */
772 static reloc_howto_type *
773 elf32_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
774 bfd_reloc_code_real_type code)
776 unsigned int rtype;
778 switch (code)
780 case BFD_RELOC_NONE:
781 rtype = R_860_NONE;
782 break;
783 case BFD_RELOC_32:
784 rtype = R_860_32;
785 break;
786 case BFD_RELOC_860_COPY:
787 rtype = R_860_COPY;
788 break;
789 case BFD_RELOC_860_GLOB_DAT:
790 rtype = R_860_GLOB_DAT;
791 break;
792 case BFD_RELOC_860_JUMP_SLOT:
793 rtype = R_860_JUMP_SLOT;
794 break;
795 case BFD_RELOC_860_RELATIVE:
796 rtype = R_860_RELATIVE;
797 break;
798 case BFD_RELOC_860_PC26:
799 rtype = R_860_PC26;
800 break;
801 case BFD_RELOC_860_PLT26:
802 rtype = R_860_PLT26;
803 break;
804 case BFD_RELOC_860_PC16:
805 rtype = R_860_PC16;
806 break;
807 case BFD_RELOC_860_LOW0:
808 rtype = R_860_LOW0;
809 break;
810 case BFD_RELOC_860_SPLIT0:
811 rtype = R_860_SPLIT0;
812 break;
813 case BFD_RELOC_860_LOW1:
814 rtype = R_860_LOW1;
815 break;
816 case BFD_RELOC_860_SPLIT1:
817 rtype = R_860_SPLIT1;
818 break;
819 case BFD_RELOC_860_LOW2:
820 rtype = R_860_LOW2;
821 break;
822 case BFD_RELOC_860_SPLIT2:
823 rtype = R_860_SPLIT2;
824 break;
825 case BFD_RELOC_860_LOW3:
826 rtype = R_860_LOW3;
827 break;
828 case BFD_RELOC_860_LOGOT0:
829 rtype = R_860_LOGOT0;
830 break;
831 case BFD_RELOC_860_SPGOT0:
832 rtype = R_860_SPGOT0;
833 break;
834 case BFD_RELOC_860_LOGOT1:
835 rtype = R_860_LOGOT1;
836 break;
837 case BFD_RELOC_860_SPGOT1:
838 rtype = R_860_SPGOT1;
839 break;
840 case BFD_RELOC_860_LOGOTOFF0:
841 rtype = R_860_LOGOTOFF0;
842 break;
843 case BFD_RELOC_860_SPGOTOFF0:
844 rtype = R_860_SPGOTOFF0;
845 break;
846 case BFD_RELOC_860_LOGOTOFF1:
847 rtype = R_860_LOGOTOFF1;
848 break;
849 case BFD_RELOC_860_SPGOTOFF1:
850 rtype = R_860_SPGOTOFF1;
851 break;
852 case BFD_RELOC_860_LOGOTOFF2:
853 rtype = R_860_LOGOTOFF2;
854 break;
855 case BFD_RELOC_860_LOGOTOFF3:
856 rtype = R_860_LOGOTOFF3;
857 break;
858 case BFD_RELOC_860_LOPC:
859 rtype = R_860_LOPC;
860 break;
861 case BFD_RELOC_860_HIGHADJ:
862 rtype = R_860_HIGHADJ;
863 break;
864 case BFD_RELOC_860_HAGOT:
865 rtype = R_860_HAGOT;
866 break;
867 case BFD_RELOC_860_HAGOTOFF:
868 rtype = R_860_HAGOTOFF;
869 break;
870 case BFD_RELOC_860_HAPC:
871 rtype = R_860_HAPC;
872 break;
873 case BFD_RELOC_860_HIGH:
874 rtype = R_860_HIGH;
875 break;
876 case BFD_RELOC_860_HIGOT:
877 rtype = R_860_HIGOT;
878 break;
879 case BFD_RELOC_860_HIGOTOFF:
880 rtype = R_860_HIGOTOFF;
881 break;
882 default:
883 rtype = 0;
884 break;
886 return lookup_howto (rtype);
889 /* Given a ELF reloc, return the matching HOWTO structure. */
890 static void
891 elf32_i860_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
892 arelent *bfd_reloc,
893 Elf_Internal_Rela *elf_reloc)
895 bfd_reloc->howto
896 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc->r_info));
899 /* Specialized relocation handler for R_860_SPLITn. These relocations
900 involves a 16-bit field that is split into two contiguous parts. */
901 static bfd_reloc_status_type
902 elf32_i860_relocate_splitn (bfd *input_bfd,
903 Elf_Internal_Rela *rello,
904 bfd_byte *contents,
905 bfd_vma value)
907 bfd_vma insn;
908 reloc_howto_type *howto;
909 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
910 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
912 /* Relocate. */
913 value += rello->r_addend;
915 /* Separate the fields and insert. */
916 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
917 insn = (insn & ~howto->dst_mask) | value;
919 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
920 return bfd_reloc_ok;
923 /* Specialized relocation handler for R_860_PC16. This relocation
924 involves a 16-bit, PC-relative field that is split into two contiguous
925 parts. */
926 static bfd_reloc_status_type
927 elf32_i860_relocate_pc16 (bfd *input_bfd,
928 asection *input_section,
929 Elf_Internal_Rela *rello,
930 bfd_byte *contents,
931 bfd_vma value)
933 bfd_vma insn;
934 reloc_howto_type *howto;
935 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
936 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
938 /* Adjust for PC-relative relocation. */
939 value -= (input_section->output_section->vma
940 + input_section->output_offset);
941 value -= rello->r_offset;
943 /* Relocate. */
944 value += rello->r_addend;
946 /* Adjust the value by 4, then separate the fields and insert. */
947 value = (value - 4) >> howto->rightshift;
948 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
949 insn = (insn & ~howto->dst_mask) | value;
951 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
952 return bfd_reloc_ok;
956 /* Specialized relocation handler for R_860_PC26. This relocation
957 involves a 26-bit, PC-relative field which must be adjusted by 4. */
958 static bfd_reloc_status_type
959 elf32_i860_relocate_pc26 (bfd *input_bfd,
960 asection *input_section,
961 Elf_Internal_Rela *rello,
962 bfd_byte *contents,
963 bfd_vma value)
965 bfd_vma insn;
966 reloc_howto_type *howto;
967 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
968 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
970 /* Adjust for PC-relative relocation. */
971 value -= (input_section->output_section->vma
972 + input_section->output_offset);
973 value -= rello->r_offset;
975 /* Relocate. */
976 value += rello->r_addend;
978 /* Adjust value by 4 and insert the field. */
979 value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
980 insn = (insn & ~howto->dst_mask) | value;
982 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
983 return bfd_reloc_ok;
987 /* Specialized relocation handler for R_860_HIGHADJ. */
988 static bfd_reloc_status_type
989 elf32_i860_relocate_highadj (bfd *input_bfd,
990 Elf_Internal_Rela *rel,
991 bfd_byte *contents,
992 bfd_vma value)
994 bfd_vma insn;
996 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
998 value += rel->r_addend;
999 value += 0x8000;
1000 value = ((value >> 16) & 0xffff);
1002 insn = (insn & 0xffff0000) | value;
1004 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
1005 return bfd_reloc_ok;
1008 /* Perform a single relocation. By default we use the standard BFD
1009 routines. However, we handle some specially. */
1010 static bfd_reloc_status_type
1011 i860_final_link_relocate (reloc_howto_type *howto,
1012 bfd *input_bfd,
1013 asection *input_section,
1014 bfd_byte *contents,
1015 Elf_Internal_Rela *rel,
1016 bfd_vma relocation)
1018 return _bfd_final_link_relocate (howto, input_bfd, input_section,
1019 contents, rel->r_offset, relocation,
1020 rel->r_addend);
1023 /* Relocate an i860 ELF section.
1025 This is boiler-plate code copied from fr30.
1027 The RELOCATE_SECTION function is called by the new ELF backend linker
1028 to handle the relocations for a section.
1030 The relocs are always passed as Rela structures; if the section
1031 actually uses Rel structures, the r_addend field will always be
1032 zero.
1034 This function is responsible for adjusting the section contents as
1035 necessary, and (if using Rela relocs and generating a relocatable
1036 output file) adjusting the reloc addend as necessary.
1038 This function does not have to worry about setting the reloc
1039 address or the reloc symbol index.
1041 LOCAL_SYMS is a pointer to the swapped in local symbols.
1043 LOCAL_SECTIONS is an array giving the section in the input file
1044 corresponding to the st_shndx field of each local symbol.
1046 The global hash table entry for the global symbols can be found
1047 via elf_sym_hashes (input_bfd).
1049 When generating relocatable output, this function must handle
1050 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1051 going to be the section symbol corresponding to the output
1052 section, which means that the addend must be adjusted
1053 accordingly. */
1054 static bfd_boolean
1055 elf32_i860_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1056 struct bfd_link_info *info,
1057 bfd *input_bfd,
1058 asection *input_section,
1059 bfd_byte *contents,
1060 Elf_Internal_Rela *relocs,
1061 Elf_Internal_Sym *local_syms,
1062 asection **local_sections)
1064 Elf_Internal_Shdr *symtab_hdr;
1065 struct elf_link_hash_entry **sym_hashes;
1066 Elf_Internal_Rela *rel;
1067 Elf_Internal_Rela *relend;
1069 if (info->relocatable)
1070 return TRUE;
1072 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1073 sym_hashes = elf_sym_hashes (input_bfd);
1074 relend = relocs + input_section->reloc_count;
1076 for (rel = relocs; rel < relend; rel ++)
1078 reloc_howto_type * howto;
1079 unsigned long r_symndx;
1080 Elf_Internal_Sym * sym;
1081 asection * sec;
1082 struct elf_link_hash_entry * h;
1083 bfd_vma relocation;
1084 bfd_reloc_status_type r;
1085 const char * name = NULL;
1086 int r_type;
1088 r_type = ELF32_R_TYPE (rel->r_info);
1089 r_symndx = ELF32_R_SYM (rel->r_info);
1091 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
1092 h = NULL;
1093 sym = NULL;
1094 sec = NULL;
1096 if (r_symndx < symtab_hdr->sh_info)
1098 sym = local_syms + r_symndx;
1099 sec = local_sections [r_symndx];
1100 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1102 name = bfd_elf_string_from_elf_section
1103 (input_bfd, symtab_hdr->sh_link, sym->st_name);
1104 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1106 else
1108 bfd_boolean unresolved_reloc, warned;
1110 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1111 r_symndx, symtab_hdr, sym_hashes,
1112 h, sec, relocation,
1113 unresolved_reloc, warned);
1116 switch (r_type)
1118 default:
1119 r = i860_final_link_relocate (howto, input_bfd, input_section,
1120 contents, rel, relocation);
1121 break;
1123 case R_860_HIGHADJ:
1124 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
1125 relocation);
1126 break;
1128 case R_860_PC16:
1129 r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
1130 contents, relocation);
1131 break;
1133 case R_860_PC26:
1134 r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
1135 contents, relocation);
1136 break;
1138 case R_860_SPLIT0:
1139 case R_860_SPLIT1:
1140 case R_860_SPLIT2:
1141 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1142 relocation);
1143 break;
1145 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1146 case R_860_COPY:
1147 case R_860_GLOB_DAT:
1148 case R_860_JUMP_SLOT:
1149 case R_860_RELATIVE:
1150 case R_860_PLT26:
1151 case R_860_LOGOT0:
1152 case R_860_SPGOT0:
1153 case R_860_LOGOT1:
1154 case R_860_SPGOT1:
1155 case R_860_LOGOTOFF0:
1156 case R_860_SPGOTOFF0:
1157 case R_860_LOGOTOFF1:
1158 case R_860_SPGOTOFF1:
1159 case R_860_LOGOTOFF2:
1160 case R_860_LOGOTOFF3:
1161 case R_860_LOPC:
1162 case R_860_HAGOT:
1163 case R_860_HAGOTOFF:
1164 case R_860_HAPC:
1165 case R_860_HIGOT:
1166 case R_860_HIGOTOFF:
1167 r = bfd_reloc_notsupported;
1168 break;
1171 if (r != bfd_reloc_ok)
1173 const char * msg = (const char *) NULL;
1175 switch (r)
1177 case bfd_reloc_overflow:
1178 r = info->callbacks->reloc_overflow
1179 (info, (h ? &h->root : NULL), name, howto->name,
1180 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
1181 break;
1183 case bfd_reloc_undefined:
1184 r = info->callbacks->undefined_symbol
1185 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1186 break;
1188 case bfd_reloc_outofrange:
1189 msg = _("internal error: out of range error");
1190 break;
1192 case bfd_reloc_notsupported:
1193 msg = _("internal error: unsupported relocation error");
1194 break;
1196 case bfd_reloc_dangerous:
1197 msg = _("internal error: dangerous relocation");
1198 break;
1200 default:
1201 msg = _("internal error: unknown error");
1202 break;
1205 if (msg)
1206 r = info->callbacks->warning
1207 (info, msg, name, input_bfd, input_section, rel->r_offset);
1209 if (! r)
1210 return FALSE;
1214 return TRUE;
1217 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1218 generate labels of the form ".ep.function_name" to denote the end of a
1219 function prolog. These should be local.
1220 ??? Do any other SVR4 compilers have this convention? If so, this should
1221 be added to the generic routine. */
1222 static bfd_boolean
1223 elf32_i860_is_local_label_name (bfd *abfd, const char *name)
1225 if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1226 return TRUE;
1228 return _bfd_elf_is_local_label_name (abfd, name);
1231 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1232 #define TARGET_BIG_NAME "elf32-i860"
1233 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1234 #define TARGET_LITTLE_NAME "elf32-i860-little"
1235 #define ELF_ARCH bfd_arch_i860
1236 #define ELF_MACHINE_CODE EM_860
1237 #define ELF_MAXPAGESIZE 4096
1239 #define elf_backend_rela_normal 1
1240 #define elf_info_to_howto_rel NULL
1241 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1242 #define elf_backend_relocate_section elf32_i860_relocate_section
1243 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1244 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1246 #include "elf32-target.h"