2009-07-02 Tristan Gingold <gingold@adacore.com>
[binutils.git] / bfd / elf32-i860.c
blob41d5e93f6fbd818378e910ba4ca6868c0f6923bc
1 /* Intel i860 specific support for 32-bit ELF.
2 Copyright 1993, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
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 3 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,
22 MA 02110-1301, USA. */
24 #include "sysdep.h"
25 #include "bfd.h"
26 #include "libbfd.h"
27 #include "elf-bfd.h"
28 #include "elf/i860.h"
30 /* special_function for R_860_PC26 relocation. */
31 static bfd_reloc_status_type
32 i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
33 arelent *reloc_entry,
34 asymbol *symbol,
35 void *data ATTRIBUTE_UNUSED,
36 asection *input_section,
37 bfd *output_bfd,
38 char **error_message ATTRIBUTE_UNUSED)
40 bfd_vma insn;
41 bfd_vma relocation;
42 bfd_byte *addr;
44 if (output_bfd != NULL
45 && (symbol->flags & BSF_SECTION_SYM) == 0
46 && (! reloc_entry->howto->partial_inplace
47 || reloc_entry->addend == 0))
49 reloc_entry->address += input_section->output_offset;
50 return bfd_reloc_ok;
53 /* Used elf32-mips.c as an example. */
54 if (bfd_is_und_section (symbol->section)
55 && output_bfd == (bfd *) NULL)
56 return bfd_reloc_undefined;
58 if (bfd_is_com_section (symbol->section))
59 relocation = 0;
60 else
61 relocation = symbol->value;
63 relocation += symbol->section->output_section->vma;
64 relocation += symbol->section->output_offset;
65 relocation += reloc_entry->addend;
67 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
68 return bfd_reloc_outofrange;
70 /* Adjust for PC-relative relocation. */
71 relocation -= (input_section->output_section->vma
72 + input_section->output_offset
73 + reloc_entry->address
74 + 4);
76 /* Check for target out of range. */
77 if ((bfd_signed_vma)relocation > (0x3ffffff << 2)
78 || (bfd_signed_vma)relocation < (-0x4000000 << 2))
79 return bfd_reloc_outofrange;
81 addr = (bfd_byte *) data + reloc_entry->address;
82 insn = bfd_get_32 (abfd, addr);
84 relocation >>= reloc_entry->howto->rightshift;
85 insn = (insn & ~reloc_entry->howto->dst_mask)
86 | (relocation & reloc_entry->howto->dst_mask);
88 bfd_put_32 (abfd, (bfd_vma) insn, addr);
90 return bfd_reloc_ok;
93 /* special_function for R_860_PC16 relocation. */
94 static bfd_reloc_status_type
95 i860_howto_pc16_reloc (bfd *abfd,
96 arelent *reloc_entry,
97 asymbol *symbol,
98 void *data,
99 asection *input_section,
100 bfd *output_bfd,
101 char **error_message ATTRIBUTE_UNUSED)
103 bfd_vma insn;
104 bfd_vma relocation;
105 bfd_byte *addr;
107 if (output_bfd != NULL
108 && (symbol->flags & BSF_SECTION_SYM) == 0
109 && (! reloc_entry->howto->partial_inplace
110 || reloc_entry->addend == 0))
112 reloc_entry->address += input_section->output_offset;
113 return bfd_reloc_ok;
116 /* Used elf32-mips.c as an example. */
117 if (bfd_is_und_section (symbol->section)
118 && output_bfd == (bfd *) NULL)
119 return bfd_reloc_undefined;
121 if (bfd_is_com_section (symbol->section))
122 relocation = 0;
123 else
124 relocation = symbol->value;
126 relocation += symbol->section->output_section->vma;
127 relocation += symbol->section->output_offset;
128 relocation += reloc_entry->addend;
130 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
131 return bfd_reloc_outofrange;
133 /* Adjust for PC-relative relocation. */
134 relocation -= (input_section->output_section->vma
135 + input_section->output_offset
136 + reloc_entry->address
137 + 4);
139 /* Check for target out of range. */
140 if ((bfd_signed_vma)relocation > (0x7fff << 2)
141 || (bfd_signed_vma)relocation < (-0x8000 << 2))
142 return bfd_reloc_outofrange;
144 addr = (bfd_byte *) data + reloc_entry->address;
145 insn = bfd_get_32 (abfd, addr);
147 relocation >>= reloc_entry->howto->rightshift;
148 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
149 & reloc_entry->howto->dst_mask;
150 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
152 bfd_put_32 (abfd, (bfd_vma) insn, addr);
154 return bfd_reloc_ok;
157 /* special_function for R_860_HIGHADJ relocation. */
158 static bfd_reloc_status_type
159 i860_howto_highadj_reloc (bfd *abfd,
160 arelent *reloc_entry,
161 asymbol *symbol,
162 void *data,
163 asection *input_section,
164 bfd *output_bfd,
165 char **error_message ATTRIBUTE_UNUSED)
167 bfd_vma insn;
168 bfd_vma relocation;
169 bfd_byte *addr;
171 if (output_bfd != NULL
172 && (symbol->flags & BSF_SECTION_SYM) == 0
173 && (! reloc_entry->howto->partial_inplace
174 || reloc_entry->addend == 0))
176 reloc_entry->address += input_section->output_offset;
177 return bfd_reloc_ok;
180 /* Used elf32-mips.c as an example. */
181 if (bfd_is_und_section (symbol->section)
182 && output_bfd == (bfd *) NULL)
183 return bfd_reloc_undefined;
185 if (bfd_is_com_section (symbol->section))
186 relocation = 0;
187 else
188 relocation = symbol->value;
190 relocation += symbol->section->output_section->vma;
191 relocation += symbol->section->output_offset;
192 relocation += reloc_entry->addend;
193 relocation += 0x8000;
195 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
196 return bfd_reloc_outofrange;
198 addr = (bfd_byte *) data + reloc_entry->address;
199 insn = bfd_get_32 (abfd, addr);
201 relocation = ((relocation >> 16) & 0xffff);
203 insn = (insn & 0xffff0000) | relocation;
205 bfd_put_32 (abfd, (bfd_vma) insn, addr);
207 return bfd_reloc_ok;
210 /* special_function for R_860_SPLITn relocations. */
211 static bfd_reloc_status_type
212 i860_howto_splitn_reloc (bfd *abfd,
213 arelent *reloc_entry,
214 asymbol *symbol,
215 void *data,
216 asection *input_section,
217 bfd *output_bfd,
218 char **error_message ATTRIBUTE_UNUSED)
220 bfd_vma insn;
221 bfd_vma relocation;
222 bfd_byte *addr;
224 if (output_bfd != NULL
225 && (symbol->flags & BSF_SECTION_SYM) == 0
226 && (! reloc_entry->howto->partial_inplace
227 || reloc_entry->addend == 0))
229 reloc_entry->address += input_section->output_offset;
230 return bfd_reloc_ok;
233 /* Used elf32-mips.c as an example. */
234 if (bfd_is_und_section (symbol->section)
235 && output_bfd == (bfd *) NULL)
236 return bfd_reloc_undefined;
238 if (bfd_is_com_section (symbol->section))
239 relocation = 0;
240 else
241 relocation = symbol->value;
243 relocation += symbol->section->output_section->vma;
244 relocation += symbol->section->output_offset;
245 relocation += reloc_entry->addend;
247 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
248 return bfd_reloc_outofrange;
250 addr = (bfd_byte *) data + reloc_entry->address;
251 insn = bfd_get_32 (abfd, addr);
253 relocation = (((relocation & 0xf800) << 5) | (relocation & 0x7ff))
254 & reloc_entry->howto->dst_mask;
255 insn = (insn & ~reloc_entry->howto->dst_mask) | relocation;
257 bfd_put_32 (abfd, (bfd_vma) insn, addr);
259 return bfd_reloc_ok;
262 /* This howto table is preliminary. */
263 static reloc_howto_type elf32_i860_howto_table [] =
265 /* This relocation does nothing. */
266 HOWTO (R_860_NONE, /* type */
267 0, /* rightshift */
268 2, /* size (0 = byte, 1 = short, 2 = long) */
269 32, /* bitsize */
270 FALSE, /* pc_relative */
271 0, /* bitpos */
272 complain_overflow_bitfield, /* complain_on_overflow */
273 bfd_elf_generic_reloc, /* special_function */
274 "R_860_NONE", /* name */
275 FALSE, /* partial_inplace */
276 0, /* src_mask */
277 0, /* dst_mask */
278 FALSE), /* pcrel_offset */
280 /* A 32-bit absolute relocation. */
281 HOWTO (R_860_32, /* type */
282 0, /* rightshift */
283 2, /* size (0 = byte, 1 = short, 2 = long) */
284 32, /* bitsize */
285 FALSE, /* pc_relative */
286 0, /* bitpos */
287 complain_overflow_bitfield, /* complain_on_overflow */
288 bfd_elf_generic_reloc, /* special_function */
289 "R_860_32", /* name */
290 FALSE, /* partial_inplace */
291 0xffffffff, /* src_mask */
292 0xffffffff, /* dst_mask */
293 FALSE), /* pcrel_offset */
295 HOWTO (R_860_COPY, /* type */
296 0, /* rightshift */
297 2, /* size (0 = byte, 1 = short, 2 = long) */
298 32, /* bitsize */
299 FALSE, /* pc_relative */
300 0, /* bitpos */
301 complain_overflow_bitfield, /* complain_on_overflow */
302 bfd_elf_generic_reloc, /* special_function */
303 "R_860_COPY", /* name */
304 TRUE, /* partial_inplace */
305 0xffffffff, /* src_mask */
306 0xffffffff, /* dst_mask */
307 FALSE), /* pcrel_offset */
309 HOWTO (R_860_GLOB_DAT, /* type */
310 0, /* rightshift */
311 2, /* size (0 = byte, 1 = short, 2 = long) */
312 32, /* bitsize */
313 FALSE, /* pc_relative */
314 0, /* bitpos */
315 complain_overflow_bitfield, /* complain_on_overflow */
316 bfd_elf_generic_reloc, /* special_function */
317 "R_860_GLOB_DAT", /* name */
318 TRUE, /* partial_inplace */
319 0xffffffff, /* src_mask */
320 0xffffffff, /* dst_mask */
321 FALSE), /* pcrel_offset */
323 HOWTO (R_860_JUMP_SLOT, /* type */
324 0, /* rightshift */
325 2, /* size (0 = byte, 1 = short, 2 = long) */
326 32, /* bitsize */
327 FALSE, /* pc_relative */
328 0, /* bitpos */
329 complain_overflow_bitfield, /* complain_on_overflow */
330 bfd_elf_generic_reloc, /* special_function */
331 "R_860_JUMP_SLOT", /* name */
332 TRUE, /* partial_inplace */
333 0xffffffff, /* src_mask */
334 0xffffffff, /* dst_mask */
335 FALSE), /* pcrel_offset */
337 HOWTO (R_860_RELATIVE, /* type */
338 0, /* rightshift */
339 2, /* size (0 = byte, 1 = short, 2 = long) */
340 32, /* bitsize */
341 FALSE, /* pc_relative */
342 0, /* bitpos */
343 complain_overflow_bitfield, /* complain_on_overflow */
344 bfd_elf_generic_reloc, /* special_function */
345 "R_860_RELATIVE", /* name */
346 TRUE, /* partial_inplace */
347 0xffffffff, /* src_mask */
348 0xffffffff, /* dst_mask */
349 FALSE), /* pcrel_offset */
351 /* A 26-bit PC-relative relocation. */
352 HOWTO (R_860_PC26, /* type */
353 2, /* rightshift */
354 2, /* size (0 = byte, 1 = short, 2 = long) */
355 26, /* bitsize */
356 TRUE, /* pc_relative */
357 0, /* bitpos */
358 complain_overflow_bitfield, /* complain_on_overflow */
359 i860_howto_pc26_reloc, /* special_function */
360 "R_860_PC26", /* name */
361 FALSE, /* partial_inplace */
362 0x3ffffff, /* src_mask */
363 0x3ffffff, /* dst_mask */
364 TRUE), /* pcrel_offset */
366 HOWTO (R_860_PLT26, /* type */
367 0, /* rightshift */
368 2, /* size (0 = byte, 1 = short, 2 = long) */
369 26, /* bitsize */
370 TRUE, /* pc_relative */
371 0, /* bitpos */
372 complain_overflow_bitfield, /* complain_on_overflow */
373 bfd_elf_generic_reloc, /* special_function */
374 "R_860_PLT26", /* name */
375 TRUE, /* partial_inplace */
376 0xffffffff, /* src_mask */
377 0xffffffff, /* dst_mask */
378 TRUE), /* pcrel_offset */
380 /* A 16-bit PC-relative relocation. */
381 HOWTO (R_860_PC16, /* type */
382 2, /* rightshift */
383 2, /* size (0 = byte, 1 = short, 2 = long) */
384 16, /* bitsize */
385 TRUE, /* pc_relative */
386 0, /* bitpos */
387 complain_overflow_bitfield, /* complain_on_overflow */
388 i860_howto_pc16_reloc, /* special_function */
389 "R_860_PC16", /* name */
390 FALSE, /* partial_inplace */
391 0x1f07ff, /* src_mask */
392 0x1f07ff, /* dst_mask */
393 TRUE), /* pcrel_offset */
395 HOWTO (R_860_LOW0, /* type */
396 0, /* rightshift */
397 2, /* size (0 = byte, 1 = short, 2 = long) */
398 16, /* bitsize */
399 FALSE, /* pc_relative */
400 0, /* bitpos */
401 complain_overflow_dont, /* complain_on_overflow */
402 bfd_elf_generic_reloc, /* special_function */
403 "R_860_LOW0", /* name */
404 FALSE, /* partial_inplace */
405 0xffff, /* src_mask */
406 0xffff, /* dst_mask */
407 FALSE), /* pcrel_offset */
409 HOWTO (R_860_SPLIT0, /* type */
410 0, /* rightshift */
411 2, /* size (0 = byte, 1 = short, 2 = long) */
412 16, /* bitsize */
413 FALSE, /* pc_relative */
414 0, /* bitpos */
415 complain_overflow_dont, /* complain_on_overflow */
416 i860_howto_splitn_reloc, /* special_function */
417 "R_860_SPLIT0", /* name */
418 FALSE, /* partial_inplace */
419 0x1f07ff, /* src_mask */
420 0x1f07ff, /* dst_mask */
421 FALSE), /* pcrel_offset */
423 HOWTO (R_860_LOW1, /* type */
424 0, /* rightshift */
425 2, /* size (0 = byte, 1 = short, 2 = long) */
426 16, /* bitsize */
427 FALSE, /* pc_relative */
428 0, /* bitpos */
429 complain_overflow_dont, /* complain_on_overflow */
430 bfd_elf_generic_reloc, /* special_function */
431 "R_860_LOW1", /* name */
432 FALSE, /* partial_inplace */
433 0xfffe, /* src_mask */
434 0xfffe, /* dst_mask */
435 FALSE), /* pcrel_offset */
437 HOWTO (R_860_SPLIT1, /* type */
438 0, /* rightshift */
439 2, /* size (0 = byte, 1 = short, 2 = long) */
440 16, /* bitsize */
441 FALSE, /* pc_relative */
442 0, /* bitpos */
443 complain_overflow_dont, /* complain_on_overflow */
444 i860_howto_splitn_reloc, /* special_function */
445 "R_860_SPLIT1", /* name */
446 FALSE, /* partial_inplace */
447 0x1f07fe, /* src_mask */
448 0x1f07fe, /* dst_mask */
449 FALSE), /* pcrel_offset */
451 HOWTO (R_860_LOW2, /* type */
452 0, /* rightshift */
453 2, /* size (0 = byte, 1 = short, 2 = long) */
454 16, /* bitsize */
455 FALSE, /* pc_relative */
456 0, /* bitpos */
457 complain_overflow_dont, /* complain_on_overflow */
458 bfd_elf_generic_reloc, /* special_function */
459 "R_860_LOW2", /* name */
460 FALSE, /* partial_inplace */
461 0xfffc, /* src_mask */
462 0xfffc, /* dst_mask */
463 FALSE), /* pcrel_offset */
465 HOWTO (R_860_SPLIT2, /* type */
466 0, /* rightshift */
467 2, /* size (0 = byte, 1 = short, 2 = long) */
468 16, /* bitsize */
469 FALSE, /* pc_relative */
470 0, /* bitpos */
471 complain_overflow_dont, /* complain_on_overflow */
472 i860_howto_splitn_reloc, /* special_function */
473 "R_860_SPLIT2", /* name */
474 FALSE, /* partial_inplace */
475 0x1f07fc, /* src_mask */
476 0x1f07fc, /* dst_mask */
477 FALSE), /* pcrel_offset */
479 HOWTO (R_860_LOW3, /* type */
480 0, /* rightshift */
481 2, /* size (0 = byte, 1 = short, 2 = long) */
482 16, /* bitsize */
483 FALSE, /* pc_relative */
484 0, /* bitpos */
485 complain_overflow_dont, /* complain_on_overflow */
486 bfd_elf_generic_reloc, /* special_function */
487 "R_860_LOW3", /* name */
488 FALSE, /* partial_inplace */
489 0xfff8, /* src_mask */
490 0xfff8, /* dst_mask */
491 FALSE), /* pcrel_offset */
493 HOWTO (R_860_LOGOT0, /* type */
494 0, /* rightshift */
495 2, /* size (0 = byte, 1 = short, 2 = long) */
496 16, /* bitsize */
497 FALSE, /* pc_relative */
498 0, /* bitpos */
499 complain_overflow_dont, /* complain_on_overflow */
500 bfd_elf_generic_reloc, /* special_function */
501 "R_860_LOGOT0", /* name */
502 FALSE, /* partial_inplace */
503 0, /* src_mask */
504 0xffff, /* dst_mask */
505 TRUE), /* pcrel_offset */
507 HOWTO (R_860_SPGOT0, /* type */
508 0, /* rightshift */
509 2, /* size (0 = byte, 1 = short, 2 = long) */
510 16, /* bitsize */
511 FALSE, /* pc_relative */
512 0, /* bitpos */
513 complain_overflow_dont, /* complain_on_overflow */
514 bfd_elf_generic_reloc, /* special_function */
515 "R_860_SPGOT0", /* name */
516 FALSE, /* partial_inplace */
517 0, /* src_mask */
518 0xffff, /* dst_mask */
519 TRUE), /* pcrel_offset */
521 HOWTO (R_860_LOGOT1, /* type */
522 0, /* rightshift */
523 2, /* size (0 = byte, 1 = short, 2 = long) */
524 16, /* bitsize */
525 FALSE, /* pc_relative */
526 0, /* bitpos */
527 complain_overflow_dont, /* complain_on_overflow */
528 bfd_elf_generic_reloc, /* special_function */
529 "R_860_LOGOT1", /* name */
530 FALSE, /* partial_inplace */
531 0, /* src_mask */
532 0xffff, /* dst_mask */
533 TRUE), /* pcrel_offset */
535 HOWTO (R_860_SPGOT1, /* type */
536 0, /* rightshift */
537 2, /* size (0 = byte, 1 = short, 2 = long) */
538 16, /* bitsize */
539 FALSE, /* pc_relative */
540 0, /* bitpos */
541 complain_overflow_dont, /* complain_on_overflow */
542 bfd_elf_generic_reloc, /* special_function */
543 "R_860_SPGOT1", /* name */
544 FALSE, /* partial_inplace */
545 0, /* src_mask */
546 0xffff, /* dst_mask */
547 TRUE), /* pcrel_offset */
549 HOWTO (R_860_LOGOTOFF0, /* type */
550 0, /* rightshift */
551 2, /* size (0 = byte, 1 = short, 2 = long) */
552 32, /* bitsize */
553 FALSE, /* pc_relative */
554 0, /* bitpos */
555 complain_overflow_dont, /* complain_on_overflow */
556 bfd_elf_generic_reloc, /* special_function */
557 "R_860_LOGOTOFF0", /* name */
558 TRUE, /* partial_inplace */
559 0xffffffff, /* src_mask */
560 0xffffffff, /* dst_mask */
561 FALSE), /* pcrel_offset */
563 HOWTO (R_860_SPGOTOFF0, /* type */
564 0, /* rightshift */
565 2, /* size (0 = byte, 1 = short, 2 = long) */
566 32, /* bitsize */
567 FALSE, /* pc_relative */
568 0, /* bitpos */
569 complain_overflow_dont, /* complain_on_overflow */
570 bfd_elf_generic_reloc, /* special_function */
571 "R_860_SPGOTOFF0", /* name */
572 TRUE, /* partial_inplace */
573 0xffffffff, /* src_mask */
574 0xffffffff, /* dst_mask */
575 FALSE), /* pcrel_offset */
577 HOWTO (R_860_LOGOTOFF1, /* type */
578 0, /* rightshift */
579 2, /* size (0 = byte, 1 = short, 2 = long) */
580 32, /* bitsize */
581 FALSE, /* pc_relative */
582 0, /* bitpos */
583 complain_overflow_dont, /* complain_on_overflow */
584 bfd_elf_generic_reloc, /* special_function */
585 "R_860_LOGOTOFF1", /* name */
586 TRUE, /* partial_inplace */
587 0xffffffff, /* src_mask */
588 0xffffffff, /* dst_mask */
589 FALSE), /* pcrel_offset */
591 HOWTO (R_860_SPGOTOFF1, /* type */
592 0, /* rightshift */
593 2, /* size (0 = byte, 1 = short, 2 = long) */
594 32, /* bitsize */
595 FALSE, /* pc_relative */
596 0, /* bitpos */
597 complain_overflow_dont, /* complain_on_overflow */
598 bfd_elf_generic_reloc, /* special_function */
599 "R_860_SPGOTOFF1", /* name */
600 TRUE, /* partial_inplace */
601 0xffffffff, /* src_mask */
602 0xffffffff, /* dst_mask */
603 FALSE), /* pcrel_offset */
605 HOWTO (R_860_LOGOTOFF2, /* type */
606 0, /* rightshift */
607 2, /* size (0 = byte, 1 = short, 2 = long) */
608 32, /* bitsize */
609 FALSE, /* pc_relative */
610 0, /* bitpos */
611 complain_overflow_dont, /* complain_on_overflow */
612 bfd_elf_generic_reloc, /* special_function */
613 "R_860_LOGOTOFF2", /* name */
614 TRUE, /* partial_inplace */
615 0xffffffff, /* src_mask */
616 0xffffffff, /* dst_mask */
617 FALSE), /* pcrel_offset */
619 HOWTO (R_860_LOGOTOFF3, /* type */
620 0, /* rightshift */
621 2, /* size (0 = byte, 1 = short, 2 = long) */
622 32, /* bitsize */
623 FALSE, /* pc_relative */
624 0, /* bitpos */
625 complain_overflow_dont, /* complain_on_overflow */
626 bfd_elf_generic_reloc, /* special_function */
627 "R_860_LOGOTOFF3", /* name */
628 TRUE, /* partial_inplace */
629 0xffffffff, /* src_mask */
630 0xffffffff, /* dst_mask */
631 FALSE), /* pcrel_offset */
633 HOWTO (R_860_LOPC, /* type */
634 0, /* rightshift */
635 2, /* size (0 = byte, 1 = short, 2 = long) */
636 16, /* bitsize */
637 TRUE, /* pc_relative */
638 0, /* bitpos */
639 complain_overflow_bitfield, /* complain_on_overflow */
640 bfd_elf_generic_reloc, /* special_function */
641 "R_860_LOPC", /* name */
642 FALSE, /* partial_inplace */
643 0xffff, /* src_mask */
644 0xffff, /* dst_mask */
645 TRUE), /* pcrel_offset */
647 HOWTO (R_860_HIGHADJ, /* type */
648 0, /* rightshift */
649 2, /* size (0 = byte, 1 = short, 2 = long) */
650 16, /* bitsize */
651 FALSE, /* pc_relative */
652 0, /* bitpos */
653 complain_overflow_dont, /* complain_on_overflow */
654 i860_howto_highadj_reloc, /* special_function */
655 "R_860_HIGHADJ", /* name */
656 FALSE, /* partial_inplace */
657 0xffff, /* src_mask */
658 0xffff, /* dst_mask */
659 FALSE), /* pcrel_offset */
661 HOWTO (R_860_HAGOT, /* type */
662 0, /* rightshift */
663 2, /* size (0 = byte, 1 = short, 2 = long) */
664 16, /* bitsize */
665 FALSE, /* pc_relative */
666 0, /* bitpos */
667 complain_overflow_dont, /* complain_on_overflow */
668 bfd_elf_generic_reloc, /* special_function */
669 "R_860_HAGOT", /* name */
670 FALSE, /* partial_inplace */
671 0, /* src_mask */
672 0xffff, /* dst_mask */
673 TRUE), /* pcrel_offset */
675 HOWTO (R_860_HAGOTOFF, /* type */
676 0, /* rightshift */
677 2, /* size (0 = byte, 1 = short, 2 = long) */
678 32, /* bitsize */
679 FALSE, /* pc_relative */
680 0, /* bitpos */
681 complain_overflow_dont, /* complain_on_overflow */
682 bfd_elf_generic_reloc, /* special_function */
683 "R_860_HAGOTOFF", /* name */
684 TRUE, /* partial_inplace */
685 0xffffffff, /* src_mask */
686 0xffffffff, /* dst_mask */
687 FALSE), /* pcrel_offset */
689 HOWTO (R_860_HAPC, /* type */
690 0, /* rightshift */
691 2, /* size (0 = byte, 1 = short, 2 = long) */
692 16, /* bitsize */
693 TRUE, /* pc_relative */
694 0, /* bitpos */
695 complain_overflow_bitfield, /* complain_on_overflow */
696 bfd_elf_generic_reloc, /* special_function */
697 "R_860_HAPC", /* name */
698 FALSE, /* partial_inplace */
699 0xffff, /* src_mask */
700 0xffff, /* dst_mask */
701 TRUE), /* pcrel_offset */
703 HOWTO (R_860_HIGH, /* type */
704 16, /* rightshift */
705 2, /* size (0 = byte, 1 = short, 2 = long) */
706 16, /* bitsize */
707 FALSE, /* pc_relative */
708 0, /* bitpos */
709 complain_overflow_dont, /* complain_on_overflow */
710 bfd_elf_generic_reloc, /* special_function */
711 "R_860_HIGH", /* name */
712 FALSE, /* partial_inplace */
713 0xffff, /* src_mask */
714 0xffff, /* dst_mask */
715 FALSE), /* pcrel_offset */
717 HOWTO (R_860_HIGOT, /* type */
718 0, /* rightshift */
719 2, /* size (0 = byte, 1 = short, 2 = long) */
720 16, /* bitsize */
721 FALSE, /* pc_relative */
722 0, /* bitpos */
723 complain_overflow_dont, /* complain_on_overflow */
724 bfd_elf_generic_reloc, /* special_function */
725 "R_860_HIGOT", /* name */
726 FALSE, /* partial_inplace */
727 0, /* src_mask */
728 0xffff, /* dst_mask */
729 TRUE), /* pcrel_offset */
731 HOWTO (R_860_HIGOTOFF, /* type */
732 0, /* rightshift */
733 2, /* size (0 = byte, 1 = short, 2 = long) */
734 32, /* bitsize */
735 FALSE, /* pc_relative */
736 0, /* bitpos */
737 complain_overflow_dont, /* complain_on_overflow */
738 bfd_elf_generic_reloc, /* special_function */
739 "R_860_HIGOTOFF", /* name */
740 TRUE, /* partial_inplace */
741 0xffffffff, /* src_mask */
742 0xffffffff, /* dst_mask */
743 FALSE), /* pcrel_offset */
746 static unsigned char elf_code_to_howto_index[R_860_max + 1];
748 static reloc_howto_type *
749 lookup_howto (unsigned int rtype)
751 static int initialized = 0;
752 int i;
753 int howto_tbl_size = (int) (sizeof (elf32_i860_howto_table)
754 / sizeof (elf32_i860_howto_table[0]));
756 if (! initialized)
758 initialized = 1;
759 memset (elf_code_to_howto_index, 0xff,
760 sizeof (elf_code_to_howto_index));
761 for (i = 0; i < howto_tbl_size; i++)
762 elf_code_to_howto_index[elf32_i860_howto_table[i].type] = i;
765 BFD_ASSERT (rtype <= R_860_max);
766 i = elf_code_to_howto_index[rtype];
767 if (i >= howto_tbl_size)
768 return 0;
769 return elf32_i860_howto_table + i;
772 /* Given a BFD reloc, return the matching HOWTO structure. */
773 static reloc_howto_type *
774 elf32_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
775 bfd_reloc_code_real_type code)
777 unsigned int rtype;
779 switch (code)
781 case BFD_RELOC_NONE:
782 rtype = R_860_NONE;
783 break;
784 case BFD_RELOC_32:
785 rtype = R_860_32;
786 break;
787 case BFD_RELOC_860_COPY:
788 rtype = R_860_COPY;
789 break;
790 case BFD_RELOC_860_GLOB_DAT:
791 rtype = R_860_GLOB_DAT;
792 break;
793 case BFD_RELOC_860_JUMP_SLOT:
794 rtype = R_860_JUMP_SLOT;
795 break;
796 case BFD_RELOC_860_RELATIVE:
797 rtype = R_860_RELATIVE;
798 break;
799 case BFD_RELOC_860_PC26:
800 rtype = R_860_PC26;
801 break;
802 case BFD_RELOC_860_PLT26:
803 rtype = R_860_PLT26;
804 break;
805 case BFD_RELOC_860_PC16:
806 rtype = R_860_PC16;
807 break;
808 case BFD_RELOC_860_LOW0:
809 rtype = R_860_LOW0;
810 break;
811 case BFD_RELOC_860_SPLIT0:
812 rtype = R_860_SPLIT0;
813 break;
814 case BFD_RELOC_860_LOW1:
815 rtype = R_860_LOW1;
816 break;
817 case BFD_RELOC_860_SPLIT1:
818 rtype = R_860_SPLIT1;
819 break;
820 case BFD_RELOC_860_LOW2:
821 rtype = R_860_LOW2;
822 break;
823 case BFD_RELOC_860_SPLIT2:
824 rtype = R_860_SPLIT2;
825 break;
826 case BFD_RELOC_860_LOW3:
827 rtype = R_860_LOW3;
828 break;
829 case BFD_RELOC_860_LOGOT0:
830 rtype = R_860_LOGOT0;
831 break;
832 case BFD_RELOC_860_SPGOT0:
833 rtype = R_860_SPGOT0;
834 break;
835 case BFD_RELOC_860_LOGOT1:
836 rtype = R_860_LOGOT1;
837 break;
838 case BFD_RELOC_860_SPGOT1:
839 rtype = R_860_SPGOT1;
840 break;
841 case BFD_RELOC_860_LOGOTOFF0:
842 rtype = R_860_LOGOTOFF0;
843 break;
844 case BFD_RELOC_860_SPGOTOFF0:
845 rtype = R_860_SPGOTOFF0;
846 break;
847 case BFD_RELOC_860_LOGOTOFF1:
848 rtype = R_860_LOGOTOFF1;
849 break;
850 case BFD_RELOC_860_SPGOTOFF1:
851 rtype = R_860_SPGOTOFF1;
852 break;
853 case BFD_RELOC_860_LOGOTOFF2:
854 rtype = R_860_LOGOTOFF2;
855 break;
856 case BFD_RELOC_860_LOGOTOFF3:
857 rtype = R_860_LOGOTOFF3;
858 break;
859 case BFD_RELOC_860_LOPC:
860 rtype = R_860_LOPC;
861 break;
862 case BFD_RELOC_860_HIGHADJ:
863 rtype = R_860_HIGHADJ;
864 break;
865 case BFD_RELOC_860_HAGOT:
866 rtype = R_860_HAGOT;
867 break;
868 case BFD_RELOC_860_HAGOTOFF:
869 rtype = R_860_HAGOTOFF;
870 break;
871 case BFD_RELOC_860_HAPC:
872 rtype = R_860_HAPC;
873 break;
874 case BFD_RELOC_860_HIGH:
875 rtype = R_860_HIGH;
876 break;
877 case BFD_RELOC_860_HIGOT:
878 rtype = R_860_HIGOT;
879 break;
880 case BFD_RELOC_860_HIGOTOFF:
881 rtype = R_860_HIGOTOFF;
882 break;
883 default:
884 rtype = 0;
885 break;
887 return lookup_howto (rtype);
890 static reloc_howto_type *
891 elf32_i860_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
892 const char *r_name)
894 unsigned int i;
896 for (i = 0;
897 i < (sizeof (elf32_i860_howto_table)
898 / sizeof (elf32_i860_howto_table[0]));
899 i++)
900 if (elf32_i860_howto_table[i].name != NULL
901 && strcasecmp (elf32_i860_howto_table[i].name, r_name) == 0)
902 return &elf32_i860_howto_table[i];
904 return NULL;
907 /* Given a ELF reloc, return the matching HOWTO structure. */
908 static void
909 elf32_i860_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
910 arelent *bfd_reloc,
911 Elf_Internal_Rela *elf_reloc)
913 bfd_reloc->howto
914 = lookup_howto ((unsigned) ELF32_R_TYPE (elf_reloc->r_info));
917 /* Specialized relocation handler for R_860_SPLITn. These relocations
918 involves a 16-bit field that is split into two contiguous parts. */
919 static bfd_reloc_status_type
920 elf32_i860_relocate_splitn (bfd *input_bfd,
921 Elf_Internal_Rela *rello,
922 bfd_byte *contents,
923 bfd_vma value)
925 bfd_vma insn;
926 reloc_howto_type *howto;
927 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
928 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
930 /* Relocate. */
931 value += rello->r_addend;
933 /* Separate the fields and insert. */
934 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
935 insn = (insn & ~howto->dst_mask) | value;
937 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
938 return bfd_reloc_ok;
941 /* Specialized relocation handler for R_860_PC16. This relocation
942 involves a 16-bit, PC-relative field that is split into two contiguous
943 parts. */
944 static bfd_reloc_status_type
945 elf32_i860_relocate_pc16 (bfd *input_bfd,
946 asection *input_section,
947 Elf_Internal_Rela *rello,
948 bfd_byte *contents,
949 bfd_vma value)
951 bfd_vma insn;
952 reloc_howto_type *howto;
953 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
954 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
956 /* Adjust for PC-relative relocation. */
957 value -= (input_section->output_section->vma
958 + input_section->output_offset);
959 value -= rello->r_offset;
961 /* Relocate. */
962 value += rello->r_addend;
964 /* Adjust the value by 4, then separate the fields and insert. */
965 value = (value - 4) >> howto->rightshift;
966 value = (((value & 0xf800) << 5) | (value & 0x7ff)) & howto->dst_mask;
967 insn = (insn & ~howto->dst_mask) | value;
969 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
970 return bfd_reloc_ok;
974 /* Specialized relocation handler for R_860_PC26. This relocation
975 involves a 26-bit, PC-relative field which must be adjusted by 4. */
976 static bfd_reloc_status_type
977 elf32_i860_relocate_pc26 (bfd *input_bfd,
978 asection *input_section,
979 Elf_Internal_Rela *rello,
980 bfd_byte *contents,
981 bfd_vma value)
983 bfd_vma insn;
984 reloc_howto_type *howto;
985 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rello->r_info));
986 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
988 /* Adjust for PC-relative relocation. */
989 value -= (input_section->output_section->vma
990 + input_section->output_offset);
991 value -= rello->r_offset;
993 /* Relocate. */
994 value += rello->r_addend;
996 /* Adjust value by 4 and insert the field. */
997 value = ((value - 4) >> howto->rightshift) & howto->dst_mask;
998 insn = (insn & ~howto->dst_mask) | value;
1000 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
1001 return bfd_reloc_ok;
1005 /* Specialized relocation handler for R_860_HIGHADJ. */
1006 static bfd_reloc_status_type
1007 elf32_i860_relocate_highadj (bfd *input_bfd,
1008 Elf_Internal_Rela *rel,
1009 bfd_byte *contents,
1010 bfd_vma value)
1012 bfd_vma insn;
1014 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
1016 value += rel->r_addend;
1017 value += 0x8000;
1018 value = ((value >> 16) & 0xffff);
1020 insn = (insn & 0xffff0000) | value;
1022 bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
1023 return bfd_reloc_ok;
1026 /* Perform a single relocation. By default we use the standard BFD
1027 routines. However, we handle some specially. */
1028 static bfd_reloc_status_type
1029 i860_final_link_relocate (reloc_howto_type *howto,
1030 bfd *input_bfd,
1031 asection *input_section,
1032 bfd_byte *contents,
1033 Elf_Internal_Rela *rel,
1034 bfd_vma relocation)
1036 return _bfd_final_link_relocate (howto, input_bfd, input_section,
1037 contents, rel->r_offset, relocation,
1038 rel->r_addend);
1041 /* Relocate an i860 ELF section.
1043 This is boiler-plate code copied from fr30.
1045 The RELOCATE_SECTION function is called by the new ELF backend linker
1046 to handle the relocations for a section.
1048 The relocs are always passed as Rela structures; if the section
1049 actually uses Rel structures, the r_addend field will always be
1050 zero.
1052 This function is responsible for adjusting the section contents as
1053 necessary, and (if using Rela relocs and generating a relocatable
1054 output file) adjusting the reloc addend as necessary.
1056 This function does not have to worry about setting the reloc
1057 address or the reloc symbol index.
1059 LOCAL_SYMS is a pointer to the swapped in local symbols.
1061 LOCAL_SECTIONS is an array giving the section in the input file
1062 corresponding to the st_shndx field of each local symbol.
1064 The global hash table entry for the global symbols can be found
1065 via elf_sym_hashes (input_bfd).
1067 When generating relocatable output, this function must handle
1068 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1069 going to be the section symbol corresponding to the output
1070 section, which means that the addend must be adjusted
1071 accordingly. */
1072 static bfd_boolean
1073 elf32_i860_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
1074 struct bfd_link_info *info,
1075 bfd *input_bfd,
1076 asection *input_section,
1077 bfd_byte *contents,
1078 Elf_Internal_Rela *relocs,
1079 Elf_Internal_Sym *local_syms,
1080 asection **local_sections)
1082 Elf_Internal_Shdr *symtab_hdr;
1083 struct elf_link_hash_entry **sym_hashes;
1084 Elf_Internal_Rela *rel;
1085 Elf_Internal_Rela *relend;
1087 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
1088 sym_hashes = elf_sym_hashes (input_bfd);
1089 relend = relocs + input_section->reloc_count;
1091 for (rel = relocs; rel < relend; rel ++)
1093 reloc_howto_type * howto;
1094 unsigned long r_symndx;
1095 Elf_Internal_Sym * sym;
1096 asection * sec;
1097 struct elf_link_hash_entry * h;
1098 bfd_vma relocation;
1099 bfd_reloc_status_type r;
1100 const char * name = NULL;
1101 int r_type;
1103 r_type = ELF32_R_TYPE (rel->r_info);
1104 r_symndx = ELF32_R_SYM (rel->r_info);
1106 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
1107 h = NULL;
1108 sym = NULL;
1109 sec = NULL;
1111 if (r_symndx < symtab_hdr->sh_info)
1113 sym = local_syms + r_symndx;
1114 sec = local_sections [r_symndx];
1115 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1117 name = bfd_elf_string_from_elf_section
1118 (input_bfd, symtab_hdr->sh_link, sym->st_name);
1119 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
1121 else
1123 bfd_boolean unresolved_reloc, warned;
1125 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1126 r_symndx, symtab_hdr, sym_hashes,
1127 h, sec, relocation,
1128 unresolved_reloc, warned);
1131 if (sec != NULL && elf_discarded_section (sec))
1133 /* For relocs against symbols from removed linkonce sections,
1134 or sections discarded by a linker script, we just want the
1135 section contents zeroed. Avoid any special processing. */
1136 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
1137 rel->r_info = 0;
1138 rel->r_addend = 0;
1139 continue;
1142 if (info->relocatable)
1143 continue;
1145 switch (r_type)
1147 default:
1148 r = i860_final_link_relocate (howto, input_bfd, input_section,
1149 contents, rel, relocation);
1150 break;
1152 case R_860_HIGHADJ:
1153 r = elf32_i860_relocate_highadj (input_bfd, rel, contents,
1154 relocation);
1155 break;
1157 case R_860_PC16:
1158 r = elf32_i860_relocate_pc16 (input_bfd, input_section, rel,
1159 contents, relocation);
1160 break;
1162 case R_860_PC26:
1163 r = elf32_i860_relocate_pc26 (input_bfd, input_section, rel,
1164 contents, relocation);
1165 break;
1167 case R_860_SPLIT0:
1168 case R_860_SPLIT1:
1169 case R_860_SPLIT2:
1170 r = elf32_i860_relocate_splitn (input_bfd, rel, contents,
1171 relocation);
1172 break;
1174 /* We do not yet handle GOT/PLT/Dynamic relocations. */
1175 case R_860_COPY:
1176 case R_860_GLOB_DAT:
1177 case R_860_JUMP_SLOT:
1178 case R_860_RELATIVE:
1179 case R_860_PLT26:
1180 case R_860_LOGOT0:
1181 case R_860_SPGOT0:
1182 case R_860_LOGOT1:
1183 case R_860_SPGOT1:
1184 case R_860_LOGOTOFF0:
1185 case R_860_SPGOTOFF0:
1186 case R_860_LOGOTOFF1:
1187 case R_860_SPGOTOFF1:
1188 case R_860_LOGOTOFF2:
1189 case R_860_LOGOTOFF3:
1190 case R_860_LOPC:
1191 case R_860_HAGOT:
1192 case R_860_HAGOTOFF:
1193 case R_860_HAPC:
1194 case R_860_HIGOT:
1195 case R_860_HIGOTOFF:
1196 r = bfd_reloc_notsupported;
1197 break;
1200 if (r != bfd_reloc_ok)
1202 const char * msg = (const char *) NULL;
1204 switch (r)
1206 case bfd_reloc_overflow:
1207 r = info->callbacks->reloc_overflow
1208 (info, (h ? &h->root : NULL), name, howto->name,
1209 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
1210 break;
1212 case bfd_reloc_undefined:
1213 r = info->callbacks->undefined_symbol
1214 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
1215 break;
1217 case bfd_reloc_outofrange:
1218 msg = _("internal error: out of range error");
1219 break;
1221 case bfd_reloc_notsupported:
1222 msg = _("internal error: unsupported relocation error");
1223 break;
1225 case bfd_reloc_dangerous:
1226 msg = _("internal error: dangerous relocation");
1227 break;
1229 default:
1230 msg = _("internal error: unknown error");
1231 break;
1234 if (msg)
1235 r = info->callbacks->warning
1236 (info, msg, name, input_bfd, input_section, rel->r_offset);
1238 if (! r)
1239 return FALSE;
1243 return TRUE;
1246 /* Return whether a symbol name implies a local label. SVR4/860 compilers
1247 generate labels of the form ".ep.function_name" to denote the end of a
1248 function prolog. These should be local.
1249 ??? Do any other SVR4 compilers have this convention? If so, this should
1250 be added to the generic routine. */
1251 static bfd_boolean
1252 elf32_i860_is_local_label_name (bfd *abfd, const char *name)
1254 if (name[0] == '.' && name[1] == 'e' && name[2] == 'p' && name[3] == '.')
1255 return TRUE;
1257 return _bfd_elf_is_local_label_name (abfd, name);
1260 #define TARGET_BIG_SYM bfd_elf32_i860_vec
1261 #define TARGET_BIG_NAME "elf32-i860"
1262 #define TARGET_LITTLE_SYM bfd_elf32_i860_little_vec
1263 #define TARGET_LITTLE_NAME "elf32-i860-little"
1264 #define ELF_ARCH bfd_arch_i860
1265 #define ELF_MACHINE_CODE EM_860
1266 #define ELF_MAXPAGESIZE 4096
1268 #define elf_backend_rela_normal 1
1269 #define elf_info_to_howto_rel NULL
1270 #define elf_info_to_howto elf32_i860_info_to_howto_rela
1271 #define elf_backend_relocate_section elf32_i860_relocate_section
1272 #define bfd_elf32_bfd_reloc_type_lookup elf32_i860_reloc_type_lookup
1273 #define bfd_elf32_bfd_reloc_name_lookup elf32_i860_reloc_name_lookup
1274 #define bfd_elf32_bfd_is_local_label_name elf32_i860_is_local_label_name
1276 #include "elf32-target.h"