1 /* BFD back-end for National Semiconductor's CR16 ELF
2 Copyright 2007 Free Software Foundation, Inc.
3 Written by M R Swami Reddy.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
25 #include "libiberty.h"
29 /* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type. */
33 bfd_reloc_code_real_type bfd_reloc_enum
; /* BFD relocation enum. */
34 unsigned short cr16_reloc_type
; /* CR16 relocation type. */
37 static const struct cr16_reloc_map cr16_reloc_map
[R_CR16_MAX
] =
39 {BFD_RELOC_NONE
, R_CR16_NONE
},
40 {BFD_RELOC_CR16_NUM8
, R_CR16_NUM8
},
41 {BFD_RELOC_CR16_NUM16
, R_CR16_NUM16
},
42 {BFD_RELOC_CR16_NUM32
, R_CR16_NUM32
},
43 {BFD_RELOC_CR16_NUM32a
, R_CR16_NUM32a
},
44 {BFD_RELOC_CR16_REGREL4
, R_CR16_REGREL4
},
45 {BFD_RELOC_CR16_REGREL4a
, R_CR16_REGREL4a
},
46 {BFD_RELOC_CR16_REGREL14
, R_CR16_REGREL14
},
47 {BFD_RELOC_CR16_REGREL14a
, R_CR16_REGREL14a
},
48 {BFD_RELOC_CR16_REGREL16
, R_CR16_REGREL16
},
49 {BFD_RELOC_CR16_REGREL20
, R_CR16_REGREL20
},
50 {BFD_RELOC_CR16_REGREL20a
, R_CR16_REGREL20a
},
51 {BFD_RELOC_CR16_ABS20
, R_CR16_ABS20
},
52 {BFD_RELOC_CR16_ABS24
, R_CR16_ABS24
},
53 {BFD_RELOC_CR16_IMM4
, R_CR16_IMM4
},
54 {BFD_RELOC_CR16_IMM8
, R_CR16_IMM8
},
55 {BFD_RELOC_CR16_IMM16
, R_CR16_IMM16
},
56 {BFD_RELOC_CR16_IMM20
, R_CR16_IMM20
},
57 {BFD_RELOC_CR16_IMM24
, R_CR16_IMM24
},
58 {BFD_RELOC_CR16_IMM32
, R_CR16_IMM32
},
59 {BFD_RELOC_CR16_IMM32a
, R_CR16_IMM32a
},
60 {BFD_RELOC_CR16_DISP4
, R_CR16_DISP4
},
61 {BFD_RELOC_CR16_DISP8
, R_CR16_DISP8
},
62 {BFD_RELOC_CR16_DISP16
, R_CR16_DISP16
},
63 {BFD_RELOC_CR16_DISP24
, R_CR16_DISP24
},
64 {BFD_RELOC_CR16_DISP24a
, R_CR16_DISP24a
},
65 {BFD_RELOC_CR16_SWITCH8
, R_CR16_SWITCH8
},
66 {BFD_RELOC_CR16_SWITCH16
, R_CR16_SWITCH16
},
67 {BFD_RELOC_CR16_SWITCH32
, R_CR16_SWITCH32
}
70 static reloc_howto_type cr16_elf_howto_table
[] =
72 HOWTO (R_CR16_NONE
, /* type */
76 FALSE
, /* pc_relative */
78 complain_overflow_dont
, /* complain_on_overflow */
79 bfd_elf_generic_reloc
, /* special_function */
80 "R_CR16_NONE", /* name */
81 FALSE
, /* partial_inplace */
84 FALSE
), /* pcrel_offset */
86 HOWTO (R_CR16_NUM8
, /* type */
90 FALSE
, /* pc_relative */
92 complain_overflow_bitfield
,/* complain_on_overflow */
93 bfd_elf_generic_reloc
, /* special_function */
94 "R_CR16_NUM8", /* name */
95 FALSE
, /* partial_inplace */
98 FALSE
), /* pcrel_offset */
100 HOWTO (R_CR16_NUM16
, /* type */
104 FALSE
, /* pc_relative */
106 complain_overflow_bitfield
,/* complain_on_overflow */
107 bfd_elf_generic_reloc
, /* special_function */
108 "R_CR16_NUM16", /* name */
109 FALSE
, /* partial_inplace */
110 0xffff, /* src_mask */
111 0xffff, /* dst_mask */
112 FALSE
), /* pcrel_offset */
114 HOWTO (R_CR16_NUM32
, /* type */
118 FALSE
, /* pc_relative */
120 complain_overflow_bitfield
,/* complain_on_overflow */
121 bfd_elf_generic_reloc
, /* special_function */
122 "R_CR16_NUM32", /* name */
123 FALSE
, /* partial_inplace */
124 0xffffffff, /* src_mask */
125 0xffffffff, /* dst_mask */
126 FALSE
), /* pcrel_offset */
128 HOWTO (R_CR16_NUM32a
, /* type */
132 FALSE
, /* pc_relative */
134 complain_overflow_bitfield
,/* complain_on_overflow */
135 bfd_elf_generic_reloc
, /* special_function */
136 "R_CR16_NUM32a", /* name */
137 FALSE
, /* partial_inplace */
138 0xffffffff, /* src_mask */
139 0xffffffff, /* dst_mask */
140 FALSE
), /* pcrel_offset */
142 HOWTO (R_CR16_REGREL4
, /* type */
146 FALSE
, /* pc_relative */
148 complain_overflow_bitfield
,/* complain_on_overflow */
149 bfd_elf_generic_reloc
, /* special_function */
150 "R_CR16_REGREL4", /* name */
151 FALSE
, /* partial_inplace */
154 FALSE
), /* pcrel_offset */
156 HOWTO (R_CR16_REGREL4a
, /* type */
160 FALSE
, /* pc_relative */
162 complain_overflow_bitfield
,/* complain_on_overflow */
163 bfd_elf_generic_reloc
, /* special_function */
164 "R_CR16_REGREL4a", /* name */
165 FALSE
, /* partial_inplace */
168 FALSE
), /* pcrel_offset */
170 HOWTO (R_CR16_REGREL14
, /* type */
174 FALSE
, /* pc_relative */
176 complain_overflow_bitfield
,/* complain_on_overflow */
177 bfd_elf_generic_reloc
, /* special_function */
178 "R_CR16_REGREL14", /* name */
179 FALSE
, /* partial_inplace */
180 0x3fff, /* src_mask */
181 0x3fff, /* dst_mask */
182 FALSE
), /* pcrel_offset */
184 HOWTO (R_CR16_REGREL14a
, /* type */
188 FALSE
, /* pc_relative */
190 complain_overflow_bitfield
,/* complain_on_overflow */
191 bfd_elf_generic_reloc
, /* special_function */
192 "R_CR16_REGREL14a", /* name */
193 FALSE
, /* partial_inplace */
194 0x3fff, /* src_mask */
195 0x3fff, /* dst_mask */
196 FALSE
), /* pcrel_offset */
198 HOWTO (R_CR16_REGREL16
, /* type */
202 FALSE
, /* pc_relative */
204 complain_overflow_bitfield
,/* complain_on_overflow */
205 bfd_elf_generic_reloc
, /* special_function */
206 "R_CR16_REGREL16", /* name */
207 FALSE
, /* partial_inplace */
208 0xffff, /* src_mask */
209 0xffff, /* dst_mask */
210 FALSE
), /* pcrel_offset */
212 HOWTO (R_CR16_REGREL20
, /* type */
216 FALSE
, /* pc_relative */
218 complain_overflow_bitfield
,/* complain_on_overflow */
219 bfd_elf_generic_reloc
, /* special_function */
220 "R_CR16_REGREL20", /* name */
221 FALSE
, /* partial_inplace */
222 0xfffff, /* src_mask */
223 0xfffff, /* dst_mask */
224 FALSE
), /* pcrel_offset */
226 HOWTO (R_CR16_REGREL20a
, /* type */
230 FALSE
, /* pc_relative */
232 complain_overflow_bitfield
,/* complain_on_overflow */
233 bfd_elf_generic_reloc
, /* special_function */
234 "R_CR16_REGREL20a", /* name */
235 FALSE
, /* partial_inplace */
236 0xfffff, /* src_mask */
237 0xfffff, /* dst_mask */
238 FALSE
), /* pcrel_offset */
240 HOWTO (R_CR16_ABS20
, /* type */
244 FALSE
, /* pc_relative */
246 complain_overflow_bitfield
,/* complain_on_overflow */
247 bfd_elf_generic_reloc
, /* special_function */
248 "R_CR16_ABS20", /* name */
249 FALSE
, /* partial_inplace */
250 0xfffff, /* src_mask */
251 0xfffff, /* dst_mask */
252 FALSE
), /* pcrel_offset */
254 HOWTO (R_CR16_ABS24
, /* type */
258 FALSE
, /* pc_relative */
260 complain_overflow_bitfield
,/* complain_on_overflow */
261 bfd_elf_generic_reloc
, /* special_function */
262 "R_CR16_ABS24", /* name */
263 FALSE
, /* partial_inplace */
264 0xffffff, /* src_mask */
265 0xffffff, /* dst_mask */
266 FALSE
), /* pcrel_offset */
268 HOWTO (R_CR16_IMM4
, /* type */
272 FALSE
, /* pc_relative */
274 complain_overflow_bitfield
,/* complain_on_overflow */
275 bfd_elf_generic_reloc
, /* special_function */
276 "R_CR16_IMM4", /* name */
277 FALSE
, /* partial_inplace */
280 FALSE
), /* pcrel_offset */
282 HOWTO (R_CR16_IMM8
, /* type */
286 FALSE
, /* pc_relative */
288 complain_overflow_bitfield
,/* complain_on_overflow */
289 bfd_elf_generic_reloc
, /* special_function */
290 "R_CR16_IMM8", /* name */
291 FALSE
, /* partial_inplace */
294 FALSE
), /* pcrel_offset */
296 HOWTO (R_CR16_IMM16
, /* type */
300 FALSE
, /* pc_relative */
302 complain_overflow_bitfield
,/* complain_on_overflow */
303 bfd_elf_generic_reloc
, /* special_function */
304 "R_CR16_IMM16", /* name */
305 FALSE
, /* partial_inplace */
306 0xffff, /* src_mask */
307 0xffff, /* dst_mask */
308 FALSE
), /* pcrel_offset */
310 HOWTO (R_CR16_IMM20
, /* type */
314 FALSE
, /* pc_relative */
316 complain_overflow_bitfield
,/* complain_on_overflow */
317 bfd_elf_generic_reloc
, /* special_function */
318 "R_CR16_IMM20", /* name */
319 FALSE
, /* partial_inplace */
320 0xfffff, /* src_mask */
321 0xfffff, /* dst_mask */
322 FALSE
), /* pcrel_offset */
324 HOWTO (R_CR16_IMM24
, /* type */
328 FALSE
, /* pc_relative */
330 complain_overflow_bitfield
,/* complain_on_overflow */
331 bfd_elf_generic_reloc
, /* special_function */
332 "R_CR16_IMM24", /* name */
333 FALSE
, /* partial_inplace */
334 0xffffff, /* src_mask */
335 0xffffff, /* dst_mask */
336 FALSE
), /* pcrel_offset */
338 HOWTO (R_CR16_IMM32
, /* type */
342 FALSE
, /* pc_relative */
344 complain_overflow_bitfield
,/* complain_on_overflow */
345 bfd_elf_generic_reloc
, /* special_function */
346 "R_CR16_IMM32", /* name */
347 FALSE
, /* partial_inplace */
348 0xffffffff, /* src_mask */
349 0xffffffff, /* dst_mask */
350 FALSE
), /* pcrel_offset */
352 HOWTO (R_CR16_IMM32a
, /* type */
356 FALSE
, /* pc_relative */
358 complain_overflow_bitfield
,/* complain_on_overflow */
359 bfd_elf_generic_reloc
, /* special_function */
360 "R_CR16_IMM32a", /* name */
361 FALSE
, /* partial_inplace */
362 0xffffffff, /* src_mask */
363 0xffffffff, /* dst_mask */
364 FALSE
), /* pcrel_offset */
366 HOWTO (R_CR16_DISP4
, /* type */
368 0, /* size (0 = byte, 1 = short, 2 = long) */
370 TRUE
, /* pc_relative */
372 complain_overflow_unsigned
, /* complain_on_overflow */
373 bfd_elf_generic_reloc
, /* special_function */
374 "R_CR16_DISP4", /* name */
375 FALSE
, /* partial_inplace */
378 FALSE
), /* pcrel_offset */
380 HOWTO (R_CR16_DISP8
, /* type */
382 0, /* size (0 = byte, 1 = short, 2 = long) */
384 TRUE
, /* pc_relative */
386 complain_overflow_unsigned
, /* complain_on_overflow */
387 bfd_elf_generic_reloc
, /* special_function */
388 "R_CR16_DISP8", /* name */
389 FALSE
, /* partial_inplace */
390 0x1ff, /* src_mask */
391 0x1ff, /* dst_mask */
392 FALSE
), /* pcrel_offset */
394 HOWTO (R_CR16_DISP16
, /* type */
395 0, /* rightshift REVIITS: To sync with WinIDEA*/
396 1, /* size (0 = byte, 1 = short, 2 = long) */
398 TRUE
, /* pc_relative */
400 complain_overflow_unsigned
, /* complain_on_overflow */
401 bfd_elf_generic_reloc
, /* special_function */
402 "R_CR16_DISP16", /* name */
403 FALSE
, /* partial_inplace */
404 0x1ffff, /* src_mask */
405 0x1ffff, /* dst_mask */
406 FALSE
), /* pcrel_offset */
407 /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc
408 but its not done, to sync with WinIDEA and CR16 4.1 tools */
409 HOWTO (R_CR16_DISP24
, /* type */
411 2, /* size (0 = byte, 1 = short, 2 = long) */
413 TRUE
, /* pc_relative */
415 complain_overflow_unsigned
, /* complain_on_overflow */
416 bfd_elf_generic_reloc
, /* special_function */
417 "R_CR16_DISP24", /* name */
418 FALSE
, /* partial_inplace */
419 0x1ffffff, /* src_mask */
420 0x1ffffff, /* dst_mask */
421 FALSE
), /* pcrel_offset */
423 HOWTO (R_CR16_DISP24a
, /* type */
425 2, /* size (0 = byte, 1 = short, 2 = long) */
427 TRUE
, /* pc_relative */
429 complain_overflow_unsigned
, /* complain_on_overflow */
430 bfd_elf_generic_reloc
, /* special_function */
431 "R_CR16_DISP24a", /* name */
432 FALSE
, /* partial_inplace */
433 0xffffff, /* src_mask */
434 0xffffff, /* dst_mask */
435 FALSE
), /* pcrel_offset */
437 /* An 8 bit switch table entry. This is generated for an expression
438 such as ``.byte L1 - L2''. The offset holds the difference
439 between the reloc address and L2. */
440 HOWTO (R_CR16_SWITCH8
, /* type */
442 0, /* size (0 = byte, 1 = short, 2 = long) */
444 FALSE
, /* pc_relative */
446 complain_overflow_unsigned
, /* complain_on_overflow */
447 bfd_elf_generic_reloc
, /* special_function */
448 "R_CR16_SWITCH8", /* name */
449 FALSE
, /* partial_inplace */
452 TRUE
), /* pcrel_offset */
454 /* A 16 bit switch table entry. This is generated for an expression
455 such as ``.word L1 - L2''. The offset holds the difference
456 between the reloc address and L2. */
457 HOWTO (R_CR16_SWITCH16
, /* type */
459 1, /* size (0 = byte, 1 = short, 2 = long) */
461 FALSE
, /* pc_relative */
463 complain_overflow_unsigned
, /* complain_on_overflow */
464 bfd_elf_generic_reloc
, /* special_function */
465 "R_CR16_SWITCH16", /* name */
466 FALSE
, /* partial_inplace */
467 0xffff, /* src_mask */
468 0xffff, /* dst_mask */
469 TRUE
), /* pcrel_offset */
471 /* A 32 bit switch table entry. This is generated for an expression
472 such as ``.long L1 - L2''. The offset holds the difference
473 between the reloc address and L2. */
474 HOWTO (R_CR16_SWITCH32
, /* type */
476 2, /* size (0 = byte, 1 = short, 2 = long) */
478 FALSE
, /* pc_relative */
480 complain_overflow_unsigned
, /* complain_on_overflow */
481 bfd_elf_generic_reloc
, /* special_function */
482 "R_CR16_SWITCH32", /* name */
483 FALSE
, /* partial_inplace */
484 0xffffffff, /* src_mask */
485 0xffffffff, /* dst_mask */
486 TRUE
) /* pcrel_offset */
489 /* Retrieve a howto ptr using a BFD reloc_code. */
491 static reloc_howto_type
*
492 elf_cr16_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
493 bfd_reloc_code_real_type code
)
497 for (i
= 0; i
< R_CR16_MAX
; i
++)
498 if (code
== cr16_reloc_map
[i
].bfd_reloc_enum
)
499 return &cr16_elf_howto_table
[cr16_reloc_map
[i
].cr16_reloc_type
];
501 _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code
);
505 static reloc_howto_type
*
506 elf_cr16_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
511 for (i
= 0; ARRAY_SIZE (cr16_elf_howto_table
); i
++)
512 if (cr16_elf_howto_table
[i
].name
!= NULL
513 && strcasecmp (cr16_elf_howto_table
[i
].name
, r_name
) == 0)
514 return cr16_elf_howto_table
+ i
;
519 /* Retrieve a howto ptr using an internal relocation entry. */
522 elf_cr16_info_to_howto (bfd
*abfd ATTRIBUTE_UNUSED
, arelent
*cache_ptr
,
523 Elf_Internal_Rela
*dst
)
525 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
527 BFD_ASSERT (r_type
< (unsigned int) R_CR16_MAX
);
528 cache_ptr
->howto
= &cr16_elf_howto_table
[r_type
];
531 /* Perform a relocation as part of a final link. */
533 static bfd_reloc_status_type
534 cr16_elf_final_link_relocate (reloc_howto_type
*howto
,
536 bfd
*output_bfd ATTRIBUTE_UNUSED
,
537 asection
*input_section
,
542 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
543 asection
*sec ATTRIBUTE_UNUSED
,
544 int is_local ATTRIBUTE_UNUSED
)
546 unsigned short r_type
= howto
->type
;
547 bfd_byte
*hit_data
= contents
+ offset
;
548 bfd_vma reloc_bits
, check
, Rvalue1
;
562 case R_CR16_REGREL4a
:
563 case R_CR16_REGREL14
:
564 case R_CR16_REGREL14a
:
565 case R_CR16_REGREL16
:
566 case R_CR16_REGREL20
:
570 /* 'hit_data' is relative to the start of the instruction, not the
571 relocation offset. Advance it to account for the exact offset. */
591 case R_CR16_SWITCH16
:
592 case R_CR16_SWITCH32
:
593 /* We only care about the addend, where the difference between
594 expressions is kept. */
601 if (howto
->pc_relative
)
603 /* Subtract the address of the section containing the location. */
604 Rvalue
-= (input_section
->output_section
->vma
605 + input_section
->output_offset
);
606 /* Subtract the position of the location within the section. */
610 /* Add in supplied addend. */
613 /* Complain if the bitfield overflows, whether it is considered
614 as signed or unsigned. */
615 check
= Rvalue
>> howto
->rightshift
;
617 /* Assumes two's complement. This expression avoids
618 overflow if howto->bitsize is the number of bits in
620 reloc_bits
= (((1 << (howto
->bitsize
- 1)) - 1) << 1) | 1;
622 if (((bfd_vma
) check
& ~reloc_bits
) != 0
623 && (((bfd_vma
) check
& ~reloc_bits
)
624 != (-(bfd_vma
) 1 & ~reloc_bits
)))
626 /* The above right shift is incorrect for a signed
627 value. See if turning on the upper bits fixes the
629 if (howto
->rightshift
&& (bfd_signed_vma
) Rvalue
< 0)
631 check
|= ((bfd_vma
) - 1
633 >> howto
->rightshift
));
635 if (((bfd_vma
) check
& ~reloc_bits
)
636 != (-(bfd_vma
) 1 & ~reloc_bits
))
637 return bfd_reloc_overflow
;
640 return bfd_reloc_overflow
;
643 /* Drop unwanted bits from the value we are relocating to. */
644 Rvalue
>>= (bfd_vma
) howto
->rightshift
;
646 /* Apply dst_mask to select only relocatable part of the insn. */
647 Rvalue
&= howto
->dst_mask
;
652 if (r_type
== R_CR16_DISP8
)
654 Rvalue1
= bfd_get_16 (input_bfd
, hit_data
);
655 Rvalue
= ((Rvalue1
& 0xf000) | ((Rvalue
<< 4) & 0xf00)
656 | (Rvalue1
& 0x00f0) | (Rvalue
& 0xf));
657 bfd_put_16 (input_bfd
, Rvalue
, hit_data
);
659 else if (r_type
== R_CR16_IMM4
)
661 Rvalue1
= bfd_get_16 (input_bfd
, hit_data
);
662 Rvalue
= (((Rvalue1
& 0xff) << 8) | ((Rvalue
<< 4) & 0xf0)
663 | ((Rvalue1
& 0x0f00) >> 8));
664 bfd_put_16 (input_bfd
, Rvalue
, hit_data
);
666 else if (r_type
== R_CR16_DISP4
)
668 Rvalue1
= bfd_get_16 (input_bfd
, hit_data
);
669 Rvalue
= (Rvalue1
| ((Rvalue
& 0xf) << 4));
670 bfd_put_16 (input_bfd
, Rvalue
, hit_data
);
674 bfd_put_8 (input_bfd
, (unsigned char) Rvalue
, hit_data
);
679 if (r_type
== R_CR16_DISP16
)
681 Rvalue
|= (bfd_get_16 (input_bfd
, hit_data
));
682 Rvalue
= ((Rvalue
& 0xfffe) | ((Rvalue
>> 16) & 0x1));
685 bfd_put_16 (input_bfd
, Rvalue
, hit_data
);
689 if ((r_type
== R_CR16_ABS20
) || (r_type
== R_CR16_IMM20
))
691 bfd_put_16 (input_bfd
, (bfd_get_16 (input_bfd
, hit_data
))
692 | ((Rvalue
>> 16) & 0xf), hit_data
);
693 bfd_put_16 (input_bfd
, (Rvalue
) & 0xffff, hit_data
+ 2);
697 if (r_type
== R_CR16_ABS24
)
699 Rvalue
= ((((Rvalue
>> 20)& 0xf) | (((Rvalue
>> 16) & 0xf) << 8)
700 | (bfd_get_16 (input_bfd
, hit_data
)))
701 | ((Rvalue
& 0xffff) << 16));
703 if (r_type
== R_CR16_DISP24
)
705 Rvalue
= ((((Rvalue
>> 20)& 0xf) | (((Rvalue
>>16) & 0xf) << 8)
706 | (bfd_get_16 (input_bfd
, hit_data
)))
707 | (((Rvalue
& 0xfffe)
708 | ((Rvalue
>> 24) & 0x1)) << 16));
710 else if ((r_type
== R_CR16_IMM32
) ||(r_type
== R_CR16_IMM32a
))
712 Rvalue
= (((Rvalue
>> 16)& 0xffff)
713 | (bfd_get_16 (input_bfd
, hit_data
)))
714 | ((Rvalue
& 0xffff) << 16);
716 else if (r_type
== R_CR16_DISP24a
)
718 Rvalue
= (((Rvalue
& 0xfffffe) | (Rvalue
>> 23)));
719 Rvalue
= ((Rvalue
>> 16) & 0xff) | ((Rvalue
& 0xffff) << 16)
720 | (bfd_get_32 (input_bfd
, hit_data
));
723 bfd_put_32 (input_bfd
, Rvalue
, hit_data
);
728 return bfd_reloc_notsupported
;
734 /* Delete some bytes from a section while relaxing. */
737 elf32_cr16_relax_delete_bytes (struct bfd_link_info
*link_info
, bfd
*abfd
,
738 asection
*sec
, bfd_vma addr
, int count
)
740 Elf_Internal_Shdr
*symtab_hdr
;
741 unsigned int sec_shndx
;
743 Elf_Internal_Rela
*irel
, *irelend
;
744 Elf_Internal_Rela
*irelalign
;
746 Elf_Internal_Sym
*isym
;
747 Elf_Internal_Sym
*isymend
;
748 struct elf_link_hash_entry
**sym_hashes
;
749 struct elf_link_hash_entry
**end_hashes
;
750 struct elf_link_hash_entry
**start_hashes
;
751 unsigned int symcount
;
753 sec_shndx
= _bfd_elf_section_from_bfd_section (abfd
, sec
);
755 contents
= elf_section_data (sec
)->this_hdr
.contents
;
757 /* The deletion must stop at the next ALIGN reloc for an aligment
758 power larger than the number of bytes we are deleting. */
762 irel
= elf_section_data (sec
)->relocs
;
763 irelend
= irel
+ sec
->reloc_count
;
765 /* Actually delete the bytes. */
766 memmove (contents
+ addr
, contents
+ addr
+ count
,
767 (size_t) (toaddr
- addr
- count
));
770 /* Adjust all the relocs. */
771 for (irel
= elf_section_data (sec
)->relocs
; irel
< irelend
; irel
++)
772 /* Get the new reloc address. */
773 if ((irel
->r_offset
> addr
&& irel
->r_offset
< toaddr
))
774 irel
->r_offset
-= count
;
776 /* Adjust the local symbols defined in this section. */
777 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
778 isym
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
779 for (isymend
= isym
+ symtab_hdr
->sh_info
; isym
< isymend
; isym
++)
781 if (isym
->st_shndx
== sec_shndx
782 && isym
->st_value
> addr
783 && isym
->st_value
< toaddr
)
785 /* Adjust the addend of SWITCH relocations in this section,
786 which reference this local symbol. */
787 for (irel
= elf_section_data (sec
)->relocs
; irel
< irelend
; irel
++)
789 unsigned long r_symndx
;
790 Elf_Internal_Sym
*rsym
;
791 bfd_vma addsym
, subsym
;
793 /* Skip if not a SWITCH relocation. */
794 if (ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_SWITCH8
795 && ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_SWITCH16
796 && ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_SWITCH32
)
799 r_symndx
= ELF32_R_SYM (irel
->r_info
);
800 rsym
= (Elf_Internal_Sym
*) symtab_hdr
->contents
+ r_symndx
;
802 /* Skip if not the local adjusted symbol. */
806 addsym
= isym
->st_value
;
807 subsym
= addsym
- irel
->r_addend
;
809 /* Fix the addend only when -->> (addsym > addr >= subsym). */
811 irel
->r_addend
-= count
;
816 isym
->st_value
-= count
;
820 /* Now adjust the global symbols defined in this section. */
821 symcount
= (symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
)
822 - symtab_hdr
->sh_info
);
823 sym_hashes
= start_hashes
= elf_sym_hashes (abfd
);
824 end_hashes
= sym_hashes
+ symcount
;
826 for (; sym_hashes
< end_hashes
; sym_hashes
++)
828 struct elf_link_hash_entry
*sym_hash
= *sym_hashes
;
830 /* The '--wrap SYMBOL' option is causing a pain when the object file,
831 containing the definition of __wrap_SYMBOL, includes a direct
832 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
833 the same symbol (which is __wrap_SYMBOL), but still exist as two
834 different symbols in 'sym_hashes', we don't want to adjust
835 the global symbol __wrap_SYMBOL twice.
836 This check is only relevant when symbols are being wrapped. */
837 if (link_info
->wrap_hash
!= NULL
)
839 struct elf_link_hash_entry
**cur_sym_hashes
;
841 /* Loop only over the symbols whom been already checked. */
842 for (cur_sym_hashes
= start_hashes
; cur_sym_hashes
< sym_hashes
;
844 /* If the current symbol is identical to 'sym_hash', that means
845 the symbol was already adjusted (or at least checked). */
846 if (*cur_sym_hashes
== sym_hash
)
849 /* Don't adjust the symbol again. */
850 if (cur_sym_hashes
< sym_hashes
)
854 if ((sym_hash
->root
.type
== bfd_link_hash_defined
855 || sym_hash
->root
.type
== bfd_link_hash_defweak
)
856 && sym_hash
->root
.u
.def
.section
== sec
857 && sym_hash
->root
.u
.def
.value
> addr
858 && sym_hash
->root
.u
.def
.value
< toaddr
)
859 sym_hash
->root
.u
.def
.value
-= count
;
865 /* Relocate a CR16 ELF section. */
868 elf32_cr16_relocate_section (bfd
*output_bfd
, struct bfd_link_info
*info
,
869 bfd
*input_bfd
, asection
*input_section
,
870 bfd_byte
*contents
, Elf_Internal_Rela
*relocs
,
871 Elf_Internal_Sym
*local_syms
,
872 asection
**local_sections
)
874 Elf_Internal_Shdr
*symtab_hdr
;
875 struct elf_link_hash_entry
**sym_hashes
;
876 Elf_Internal_Rela
*rel
, *relend
;
878 if (info
->relocatable
)
881 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
882 sym_hashes
= elf_sym_hashes (input_bfd
);
885 relend
= relocs
+ input_section
->reloc_count
;
886 for (; rel
< relend
; rel
++)
889 reloc_howto_type
*howto
;
890 unsigned long r_symndx
;
891 Elf_Internal_Sym
*sym
;
893 struct elf_link_hash_entry
*h
;
895 bfd_reloc_status_type r
;
897 r_symndx
= ELF32_R_SYM (rel
->r_info
);
898 r_type
= ELF32_R_TYPE (rel
->r_info
);
899 howto
= cr16_elf_howto_table
+ (r_type
);
904 if (r_symndx
< symtab_hdr
->sh_info
)
906 sym
= local_syms
+ r_symndx
;
907 sec
= local_sections
[r_symndx
];
908 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
912 bfd_boolean unresolved_reloc
, warned
;
914 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
915 r_symndx
, symtab_hdr
, sym_hashes
,
917 unresolved_reloc
, warned
);
920 r
= cr16_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
922 contents
, rel
->r_offset
,
923 relocation
, rel
->r_addend
,
924 info
, sec
, h
== NULL
);
926 if (r
!= bfd_reloc_ok
)
929 const char *msg
= NULL
;
932 name
= h
->root
.root
.string
;
935 name
= (bfd_elf_string_from_elf_section
936 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
937 if (name
== NULL
|| *name
== '\0')
938 name
= bfd_section_name (input_bfd
, sec
);
943 case bfd_reloc_overflow
:
944 if (!((*info
->callbacks
->reloc_overflow
)
945 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
946 (bfd_vma
) 0, input_bfd
, input_section
,
951 case bfd_reloc_undefined
:
952 if (!((*info
->callbacks
->undefined_symbol
)
953 (info
, name
, input_bfd
, input_section
,
954 rel
->r_offset
, TRUE
)))
958 case bfd_reloc_outofrange
:
959 msg
= _("internal error: out of range error");
962 case bfd_reloc_notsupported
:
963 msg
= _("internal error: unsupported relocation error");
966 case bfd_reloc_dangerous
:
967 msg
= _("internal error: dangerous error");
971 msg
= _("internal error: unknown error");
975 if (!((*info
->callbacks
->warning
)
976 (info
, msg
, name
, input_bfd
, input_section
,
987 /* This is a version of bfd_generic_get_relocated_section_contents
988 which uses elf32_cr16_relocate_section. */
991 elf32_cr16_get_relocated_section_contents (bfd
*output_bfd
,
992 struct bfd_link_info
*link_info
,
993 struct bfd_link_order
*link_order
,
995 bfd_boolean relocatable
,
998 Elf_Internal_Shdr
*symtab_hdr
;
999 asection
*input_section
= link_order
->u
.indirect
.section
;
1000 bfd
*input_bfd
= input_section
->owner
;
1001 asection
**sections
= NULL
;
1002 Elf_Internal_Rela
*internal_relocs
= NULL
;
1003 Elf_Internal_Sym
*isymbuf
= NULL
;
1005 /* We only need to handle the case of relaxing, or of having a
1006 particular set of section contents, specially. */
1008 || elf_section_data (input_section
)->this_hdr
.contents
== NULL
)
1009 return bfd_generic_get_relocated_section_contents (output_bfd
, link_info
,
1014 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
1016 memcpy (data
, elf_section_data (input_section
)->this_hdr
.contents
,
1017 (size_t) input_section
->size
);
1019 if ((input_section
->flags
& SEC_RELOC
) != 0
1020 && input_section
->reloc_count
> 0)
1022 Elf_Internal_Sym
*isym
;
1023 Elf_Internal_Sym
*isymend
;
1027 internal_relocs
= _bfd_elf_link_read_relocs (input_bfd
, input_section
,
1029 if (internal_relocs
== NULL
)
1032 if (symtab_hdr
->sh_info
!= 0)
1034 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
1035 if (isymbuf
== NULL
)
1036 isymbuf
= bfd_elf_get_elf_syms (input_bfd
, symtab_hdr
,
1037 symtab_hdr
->sh_info
, 0,
1039 if (isymbuf
== NULL
)
1043 amt
= symtab_hdr
->sh_info
;
1044 amt
*= sizeof (asection
*);
1045 sections
= bfd_malloc (amt
);
1046 if (sections
== NULL
&& amt
!= 0)
1049 isymend
= isymbuf
+ symtab_hdr
->sh_info
;
1050 for (isym
= isymbuf
, secpp
= sections
; isym
< isymend
; ++isym
, ++secpp
)
1054 if (isym
->st_shndx
== SHN_UNDEF
)
1055 isec
= bfd_und_section_ptr
;
1056 else if (isym
->st_shndx
== SHN_ABS
)
1057 isec
= bfd_abs_section_ptr
;
1058 else if (isym
->st_shndx
== SHN_COMMON
)
1059 isec
= bfd_com_section_ptr
;
1061 isec
= bfd_section_from_elf_index (input_bfd
, isym
->st_shndx
);
1066 if (! elf32_cr16_relocate_section (output_bfd
, link_info
, input_bfd
,
1067 input_section
, data
, internal_relocs
,
1071 if (sections
!= NULL
)
1074 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
1076 if (elf_section_data (input_section
)->relocs
!= internal_relocs
)
1077 free (internal_relocs
);
1083 if (sections
!= NULL
)
1086 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
1088 if (internal_relocs
!= NULL
1089 && elf_section_data (input_section
)->relocs
!= internal_relocs
)
1090 free (internal_relocs
);
1094 /* This function handles relaxing for the CR16.
1096 There's quite a few relaxing opportunites available on the CR16:
1098 * bcond:24 -> bcond:16 2 bytes
1099 * bcond:16 -> bcond:8 2 bytes
1100 * arithmetic imm32 -> arithmetic imm20/imm16 2 bytes
1101 * arithmetic imm20/imm16 -> arithmetic imm4 2 bytes
1103 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
1106 elf32_cr16_relax_section (bfd
*abfd
, asection
*sec
,
1107 struct bfd_link_info
*link_info
, bfd_boolean
*again
)
1109 Elf_Internal_Shdr
*symtab_hdr
;
1110 Elf_Internal_Rela
*internal_relocs
;
1111 Elf_Internal_Rela
*irel
, *irelend
;
1112 bfd_byte
*contents
= NULL
;
1113 Elf_Internal_Sym
*isymbuf
= NULL
;
1115 /* Assume nothing changes. */
1118 /* We don't have to do anything for a relocatable link, if
1119 this section does not have relocs, or if this is not a
1121 if (link_info
->relocatable
1122 || (sec
->flags
& SEC_RELOC
) == 0
1123 || sec
->reloc_count
== 0
1124 || (sec
->flags
& SEC_CODE
) == 0)
1127 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
1129 /* Get a copy of the native relocations. */
1130 internal_relocs
= _bfd_elf_link_read_relocs (abfd
, sec
, NULL
, NULL
,
1131 link_info
->keep_memory
);
1132 if (internal_relocs
== NULL
)
1135 /* Walk through them looking for relaxing opportunities. */
1136 irelend
= internal_relocs
+ sec
->reloc_count
;
1137 for (irel
= internal_relocs
; irel
< irelend
; irel
++)
1141 /* If this isn't something that can be relaxed, then ignore
1143 if (ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_DISP16
1144 && ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_DISP24
1145 && ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_IMM32
1146 && ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_IMM20
1147 && ELF32_R_TYPE (irel
->r_info
) != (int) R_CR16_IMM16
)
1150 /* Get the section contents if we haven't done so already. */
1151 if (contents
== NULL
)
1153 /* Get cached copy if it exists. */
1154 if (elf_section_data (sec
)->this_hdr
.contents
!= NULL
)
1155 contents
= elf_section_data (sec
)->this_hdr
.contents
;
1156 /* Go get them off disk. */
1157 else if (!bfd_malloc_and_get_section (abfd
, sec
, &contents
))
1161 /* Read this BFD's local symbols if we haven't done so already. */
1162 if (isymbuf
== NULL
&& symtab_hdr
->sh_info
!= 0)
1164 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
1165 if (isymbuf
== NULL
)
1166 isymbuf
= bfd_elf_get_elf_syms (abfd
, symtab_hdr
,
1167 symtab_hdr
->sh_info
, 0,
1169 if (isymbuf
== NULL
)
1173 /* Get the value of the symbol referred to by the reloc. */
1174 if (ELF32_R_SYM (irel
->r_info
) < symtab_hdr
->sh_info
)
1176 /* A local symbol. */
1177 Elf_Internal_Sym
*isym
;
1180 isym
= isymbuf
+ ELF32_R_SYM (irel
->r_info
);
1181 if (isym
->st_shndx
== SHN_UNDEF
)
1182 sym_sec
= bfd_und_section_ptr
;
1183 else if (isym
->st_shndx
== SHN_ABS
)
1184 sym_sec
= bfd_abs_section_ptr
;
1185 else if (isym
->st_shndx
== SHN_COMMON
)
1186 sym_sec
= bfd_com_section_ptr
;
1188 sym_sec
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
1189 symval
= (isym
->st_value
1190 + sym_sec
->output_section
->vma
1191 + sym_sec
->output_offset
);
1196 struct elf_link_hash_entry
*h
;
1198 /* An external symbol. */
1199 indx
= ELF32_R_SYM (irel
->r_info
) - symtab_hdr
->sh_info
;
1200 h
= elf_sym_hashes (abfd
)[indx
];
1201 BFD_ASSERT (h
!= NULL
);
1203 if (h
->root
.type
!= bfd_link_hash_defined
1204 && h
->root
.type
!= bfd_link_hash_defweak
)
1205 /* This appears to be a reference to an undefined
1206 symbol. Just ignore it--it will be caught by the
1207 regular reloc processing. */
1210 symval
= (h
->root
.u
.def
.value
1211 + h
->root
.u
.def
.section
->output_section
->vma
1212 + h
->root
.u
.def
.section
->output_offset
);
1215 /* For simplicity of coding, we are going to modify the section
1216 contents, the section relocs, and the BFD symbol table. We
1217 must tell the rest of the code not to free up this
1218 information. It would be possible to instead create a table
1219 of changes which have to be made, as is done in coff-mips.c;
1220 that would be more work, but would require less memory when
1221 the linker is run. */
1223 /* Try to turn a 24 branch/call into a 16bit relative
1225 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_CR16_DISP24
)
1227 bfd_vma value
= symval
;
1229 /* Deal with pc-relative gunk. */
1230 value
-= (sec
->output_section
->vma
+ sec
->output_offset
);
1231 value
-= irel
->r_offset
;
1232 value
+= irel
->r_addend
;
1234 /* See if the value will fit in 16 bits, note the high value is
1235 0xfffe + 2 as the target will be two bytes closer if we are
1237 if ((long) value
< 0x10000 && (long) value
> -0x10002)
1241 /* Get the opcode. */
1242 code
= (unsigned int) bfd_get_32 (abfd
, contents
+ irel
->r_offset
);
1244 /* Verify it's a 'bcond' and fix the opcode. */
1245 if ((code
& 0xffff) == 0x0010)
1247 bfd_put_16 (abfd
, 0x1800 | ((0xf & (code
>> 20)) << 4), contents
+ irel
->r_offset
);
1248 bfd_put_16 (abfd
, value
, contents
+ irel
->r_offset
+ 2);
1253 /* Note that we've changed the relocs, section contents, etc. */
1254 elf_section_data (sec
)->relocs
= internal_relocs
;
1255 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1256 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
1258 /* Fix the relocation's type. */
1259 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1262 /* Delete two bytes of data. */
1263 if (!elf32_cr16_relax_delete_bytes (link_info
, abfd
, sec
,
1264 irel
->r_offset
+ 2, 2))
1267 /* That will change things, so, we should relax again.
1268 Note that this is not required, and it may be slow. */
1273 /* Try to turn a 16-bit pc-relative branch into an
1274 8-bit pc-relative branch. */
1275 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_CR16_DISP16
)
1277 bfd_vma value
= symval
;
1279 /* Deal with pc-relative gunk. */
1280 value
-= (sec
->output_section
->vma
+ sec
->output_offset
);
1281 value
-= irel
->r_offset
;
1282 value
+= irel
->r_addend
;
1284 /* See if the value will fit in 8 bits, note the high value is
1285 0xfc + 2 as the target will be two bytes closer if we are
1287 if ((long) value
< 0xfe && (long) value
> -0x100)
1289 unsigned short code
;
1291 /* Get the opcode. */
1292 code
= (unsigned short) bfd_get_16 (abfd
, contents
+ irel
->r_offset
);
1294 /* Verify it's a 'bcond' opcode. */
1295 if ((code
& 0xff00) == 0x1800)
1297 bfd_put_8 (abfd
, 0x1 | ((0xf & (code
>> 4)) << 4), contents
+ irel
->r_offset
);
1298 bfd_put_8 (abfd
, value
, contents
+ irel
->r_offset
+ 2);
1303 /* Note that we've changed the relocs, section contents, etc. */
1304 elf_section_data (sec
)->relocs
= internal_relocs
;
1305 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1306 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
1308 /* Fix the relocation's type. */
1309 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1312 /* Delete two bytes of data. */
1313 if (!elf32_cr16_relax_delete_bytes (link_info
, abfd
, sec
,
1314 irel
->r_offset
+ 2, 2))
1317 /* That will change things, so, we should relax again.
1318 Note that this is not required, and it may be slow. */
1323 /* Try to turn a 32bit immediate address into
1324 a 20/16bit immediate address. */
1325 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_CR16_IMM32
)
1327 bfd_vma value
= symval
;
1328 unsigned short is_add_mov
= 0;
1330 /* See if the value will fit in 20 bits. */
1331 if ((long) value
< 0xfffff && (long) value
> 0)
1333 unsigned short code
;
1335 /* Get the opcode. */
1336 code
= (unsigned short) bfd_get_16 (abfd
, contents
+ irel
->r_offset
);
1338 /* Verify it's a arithmetic ADDD or MOVD instruction.
1339 For ADDD and MOVD only, convert to IMM32 -> IMM20. */
1340 if (((code
& 0xfff0) == 0x0070) || ((code
& 0xfff0) == 0x0020))
1345 /* Note that we've changed the relocs, section contents,
1347 elf_section_data (sec
)->relocs
= internal_relocs
;
1348 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1349 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
1351 /* Fix the opcode. */
1352 if ((code
& 0xfff0) == 0x0070) /* For movd. */
1353 bfd_put_8 (abfd
, 0x05, contents
+ irel
->r_offset
+ 1);
1354 else /* code == 0x0020 for addd. */
1355 bfd_put_8 (abfd
, 0x04, contents
+ irel
->r_offset
+ 1);
1357 bfd_put_8 (abfd
, (code
& 0xf) << 4, contents
+ irel
->r_offset
);
1360 /* Fix the relocation's type. */
1361 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1363 /* Delete two bytes of data. */
1364 if (!elf32_cr16_relax_delete_bytes (link_info
, abfd
, sec
,
1365 irel
->r_offset
+ 2, 2))
1368 /* That will change things, so, we should relax again.
1369 Note that this is not required, and it may be slow. */
1373 /* See if the value will fit in 16 bits. */
1374 if ((!is_add_mov
) && ((long) value
< 0x7fff && (long) value
> 0))
1376 unsigned short code
;
1378 /* Get the opcode. */
1379 code
= (unsigned short) bfd_get_16 (abfd
, contents
+ irel
->r_offset
);
1381 /* Note that we've changed the relocs, section contents, etc. */
1382 elf_section_data (sec
)->relocs
= internal_relocs
;
1383 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1384 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
1386 /* Fix the opcode. */
1387 if ((code
& 0xf0) == 0x70) /* For movd. */
1388 bfd_put_8 (abfd
, 0x54, contents
+ irel
->r_offset
+ 1);
1389 else if ((code
& 0xf0) == 0x20) /* For addd. */
1390 bfd_put_8 (abfd
, 0x60, contents
+ irel
->r_offset
+ 1);
1391 else if ((code
& 0xf0) == 0x90) /* For cmpd. */
1392 bfd_put_8 (abfd
, 0x56, contents
+ irel
->r_offset
+ 1);
1396 bfd_put_8 (abfd
, 0xb0 | (code
& 0xf), contents
+ irel
->r_offset
);
1398 /* Fix the relocation's type. */
1399 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1402 /* Delete two bytes of data. */
1403 if (!elf32_cr16_relax_delete_bytes (link_info
, abfd
, sec
,
1404 irel
->r_offset
+ 2, 2))
1407 /* That will change things, so, we should relax again.
1408 Note that this is not required, and it may be slow. */
1413 /* Try to turn a 20/16bit immediate address into
1414 a 4bit immediate address. */
1415 if ((ELF32_R_TYPE (irel
->r_info
) == (int) R_CR16_IMM20
)
1416 || (ELF32_R_TYPE (irel
->r_info
) == (int) R_CR16_IMM16
))
1418 bfd_vma value
= symval
;
1420 /* See if the value will fit in 4 bits. */
1421 if ((long) value
< 0xf && (long) value
> 0)
1423 unsigned short code
;
1425 /* Get the opcode. */
1426 code
= (unsigned short) bfd_get_16 (abfd
, contents
+ irel
->r_offset
);
1428 /* Note that we've changed the relocs, section contents, etc. */
1429 elf_section_data (sec
)->relocs
= internal_relocs
;
1430 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1431 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
1433 /* Fix the opcode. */
1434 if (((code
& 0x0f00) == 0x0400) || ((code
& 0x0f00) == 0x0500))
1436 if ((code
& 0x0f00) == 0x0400) /* For movd imm20. */
1437 bfd_put_8 (abfd
, 0x60, contents
+ irel
->r_offset
);
1438 else /* For addd imm20. */
1439 bfd_put_8 (abfd
, 0x54, contents
+ irel
->r_offset
);
1440 bfd_put_8 (abfd
, (code
& 0xf0) >> 4, contents
+ irel
->r_offset
+ 1);
1444 if ((code
& 0xfff0) == 0x56b0) /* For cmpd imm16. */
1445 bfd_put_8 (abfd
, 0x56, contents
+ irel
->r_offset
);
1446 else if ((code
& 0xfff0) == 0x54b0) /* For movd imm16. */
1447 bfd_put_8 (abfd
, 0x54, contents
+ irel
->r_offset
);
1448 else if ((code
& 0xfff0) == 0x58b0) /* For movb imm16. */
1449 bfd_put_8 (abfd
, 0x58, contents
+ irel
->r_offset
);
1450 else if ((code
& 0xfff0) == 0x5Ab0) /* For movw imm16. */
1451 bfd_put_8 (abfd
, 0x5A, contents
+ irel
->r_offset
);
1452 else if ((code
& 0xfff0) == 0x60b0) /* For addd imm16. */
1453 bfd_put_8 (abfd
, 0x60, contents
+ irel
->r_offset
);
1454 else if ((code
& 0xfff0) == 0x30b0) /* For addb imm16. */
1455 bfd_put_8 (abfd
, 0x30, contents
+ irel
->r_offset
);
1456 else if ((code
& 0xfff0) == 0x2Cb0) /* For addub imm16. */
1457 bfd_put_8 (abfd
, 0x2C, contents
+ irel
->r_offset
);
1458 else if ((code
& 0xfff0) == 0x32b0) /* For adduw imm16. */
1459 bfd_put_8 (abfd
, 0x32, contents
+ irel
->r_offset
);
1460 else if ((code
& 0xfff0) == 0x38b0) /* For subb imm16. */
1461 bfd_put_8 (abfd
, 0x38, contents
+ irel
->r_offset
);
1462 else if ((code
& 0xfff0) == 0x3Ab0) /* For subw imm16. */
1463 bfd_put_8 (abfd
, 0x3A, contents
+ irel
->r_offset
);
1464 else if ((code
& 0xfff0) == 0x50b0) /* For cmpb imm16. */
1465 bfd_put_8 (abfd
, 0x50, contents
+ irel
->r_offset
);
1466 else if ((code
& 0xfff0) == 0x52b0) /* For cmpw imm16. */
1467 bfd_put_8 (abfd
, 0x52, contents
+ irel
->r_offset
);
1471 bfd_put_8 (abfd
, (code
& 0xf), contents
+ irel
->r_offset
+ 1);
1474 /* Fix the relocation's type. */
1475 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1478 /* Delete two bytes of data. */
1479 if (!elf32_cr16_relax_delete_bytes (link_info
, abfd
, sec
,
1480 irel
->r_offset
+ 2, 2))
1483 /* That will change things, so, we should relax again.
1484 Note that this is not required, and it may be slow. */
1491 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
1493 if (! link_info
->keep_memory
)
1496 /* Cache the symbols for elf_link_input_bfd. */
1497 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
1500 if (contents
!= NULL
1501 && elf_section_data (sec
)->this_hdr
.contents
!= contents
)
1503 if (! link_info
->keep_memory
)
1506 /* Cache the section contents for elf_link_input_bfd. */
1507 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1510 if (internal_relocs
!= NULL
1511 && elf_section_data (sec
)->relocs
!= internal_relocs
)
1512 free (internal_relocs
);
1518 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
1520 if (contents
!= NULL
1521 && elf_section_data (sec
)->this_hdr
.contents
!= contents
)
1523 if (internal_relocs
!= NULL
1524 && elf_section_data (sec
)->relocs
!= internal_relocs
)
1525 free (internal_relocs
);
1531 elf32_cr16_gc_mark_hook (asection
*sec
,
1532 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
1533 Elf_Internal_Rela
*rel ATTRIBUTE_UNUSED
,
1534 struct elf_link_hash_entry
*h
,
1535 Elf_Internal_Sym
*sym
)
1538 return bfd_section_from_elf_index (sec
->owner
, sym
->st_shndx
);
1540 switch (h
->root
.type
)
1542 case bfd_link_hash_defined
:
1543 case bfd_link_hash_defweak
:
1544 return h
->root
.u
.def
.section
;
1546 case bfd_link_hash_common
:
1547 return h
->root
.u
.c
.p
->section
;
1554 /* Update the got entry reference counts for the section being removed. */
1557 elf32_cr16_gc_sweep_hook (bfd
*abfd ATTRIBUTE_UNUSED
,
1558 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
1559 asection
*sec ATTRIBUTE_UNUSED
,
1560 const Elf_Internal_Rela
*relocs ATTRIBUTE_UNUSED
)
1562 /* We don't support garbage collection of GOT and PLT relocs yet. */
1566 /* Definitions for setting CR16 target vector. */
1567 #define TARGET_LITTLE_SYM bfd_elf32_cr16_vec
1568 #define TARGET_LITTLE_NAME "elf32-cr16"
1569 #define ELF_ARCH bfd_arch_cr16
1570 #define ELF_MACHINE_CODE EM_CR16
1571 #define ELF_MAXPAGESIZE 0x1
1572 #define elf_symbol_leading_char '_'
1574 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16_reloc_type_lookup
1575 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16_reloc_name_lookup
1576 #define elf_info_to_howto elf_cr16_info_to_howto
1577 #define elf_info_to_howto_rel 0
1578 #define elf_backend_relocate_section elf32_cr16_relocate_section
1579 #define bfd_elf32_bfd_relax_section elf32_cr16_relax_section
1580 #define bfd_elf32_bfd_get_relocated_section_contents \
1581 elf32_cr16_get_relocated_section_contents
1582 #define elf_backend_gc_mark_hook elf32_cr16_gc_mark_hook
1583 #define elf_backend_gc_sweep_hook elf32_cr16_gc_sweep_hook
1584 #define elf_backend_can_gc_sections 1
1585 #define elf_backend_rela_normal 1
1587 #include "elf32-target.h"