New port: National Semiconductor's CR16
[binutils.git] / bfd / elf32-cr16.c
blob197bff720085b735037614c5e3402b281c7a7967
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 2 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. */
21 #include "sysdep.h"
22 #include "bfd.h"
23 #include "bfdlink.h"
24 #include "libbfd.h"
25 #include "libiberty.h"
26 #include "elf-bfd.h"
27 #include "elf/cr16.h"
29 /* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type. */
31 struct cr16_reloc_map
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}
67 static reloc_howto_type cr16_elf_howto_table[] =
69 HOWTO (R_CR16_NONE, /* type */
70 0, /* rightshift */
71 2, /* size */
72 32, /* bitsize */
73 FALSE, /* pc_relative */
74 0, /* bitpos */
75 complain_overflow_dont, /* complain_on_overflow */
76 bfd_elf_generic_reloc, /* special_function */
77 "R_CR16_NONE", /* name */
78 FALSE, /* partial_inplace */
79 0, /* src_mask */
80 0, /* dst_mask */
81 FALSE), /* pcrel_offset */
83 HOWTO (R_CR16_NUM8, /* type */
84 0, /* rightshift */
85 0, /* size */
86 8, /* bitsize */
87 FALSE, /* pc_relative */
88 0, /* bitpos */
89 complain_overflow_bitfield,/* complain_on_overflow */
90 bfd_elf_generic_reloc, /* special_function */
91 "R_CR16_NUM8", /* name */
92 FALSE, /* partial_inplace */
93 0xff, /* src_mask */
94 0xff, /* dst_mask */
95 FALSE), /* pcrel_offset */
97 HOWTO (R_CR16_NUM16, /* type */
98 0, /* rightshift */
99 1, /* size */
100 16, /* bitsize */
101 FALSE, /* pc_relative */
102 0, /* bitpos */
103 complain_overflow_bitfield,/* complain_on_overflow */
104 bfd_elf_generic_reloc, /* special_function */
105 "R_CR16_NUM16", /* name */
106 FALSE, /* partial_inplace */
107 0xffff, /* src_mask */
108 0xffff, /* dst_mask */
109 FALSE), /* pcrel_offset */
111 HOWTO (R_CR16_NUM32, /* type */
112 0, /* rightshift */
113 2, /* size */
114 32, /* bitsize */
115 FALSE, /* pc_relative */
116 0, /* bitpos */
117 complain_overflow_bitfield,/* complain_on_overflow */
118 bfd_elf_generic_reloc, /* special_function */
119 "R_CR16_NUM32", /* name */
120 FALSE, /* partial_inplace */
121 0xffffffff, /* src_mask */
122 0xffffffff, /* dst_mask */
123 FALSE), /* pcrel_offset */
125 HOWTO (R_CR16_NUM32a, /* type */
126 1, /* rightshift */
127 2, /* size */
128 32, /* bitsize */
129 FALSE, /* pc_relative */
130 0, /* bitpos */
131 complain_overflow_bitfield,/* complain_on_overflow */
132 bfd_elf_generic_reloc, /* special_function */
133 "R_CR16_NUM32a", /* name */
134 FALSE, /* partial_inplace */
135 0xffffffff, /* src_mask */
136 0xffffffff, /* dst_mask */
137 FALSE), /* pcrel_offset */
139 HOWTO (R_CR16_REGREL4, /* type */
140 0, /* rightshift */
141 0, /* size */
142 4, /* bitsize */
143 FALSE, /* pc_relative */
144 0, /* bitpos */
145 complain_overflow_bitfield,/* complain_on_overflow */
146 bfd_elf_generic_reloc, /* special_function */
147 "R_CR16_REGREL4", /* name */
148 FALSE, /* partial_inplace */
149 0xf, /* src_mask */
150 0xf, /* dst_mask */
151 FALSE), /* pcrel_offset */
153 HOWTO (R_CR16_REGREL4a, /* type */
154 0, /* rightshift */
155 0, /* size */
156 4, /* bitsize */
157 FALSE, /* pc_relative */
158 0, /* bitpos */
159 complain_overflow_bitfield,/* complain_on_overflow */
160 bfd_elf_generic_reloc, /* special_function */
161 "R_CR16_REGREL4a", /* name */
162 FALSE, /* partial_inplace */
163 0xf, /* src_mask */
164 0xf, /* dst_mask */
165 FALSE), /* pcrel_offset */
167 HOWTO (R_CR16_REGREL14, /* type */
168 0, /* rightshift */
169 1, /* size */
170 14, /* bitsize */
171 FALSE, /* pc_relative */
172 0, /* bitpos */
173 complain_overflow_bitfield,/* complain_on_overflow */
174 bfd_elf_generic_reloc, /* special_function */
175 "R_CR16_REGREL14", /* name */
176 FALSE, /* partial_inplace */
177 0x3fff, /* src_mask */
178 0x3fff, /* dst_mask */
179 FALSE), /* pcrel_offset */
181 HOWTO (R_CR16_REGREL14a, /* type */
182 0, /* rightshift */
183 1, /* size */
184 14, /* bitsize */
185 FALSE, /* pc_relative */
186 0, /* bitpos */
187 complain_overflow_bitfield,/* complain_on_overflow */
188 bfd_elf_generic_reloc, /* special_function */
189 "R_CR16_REGREL14a", /* name */
190 FALSE, /* partial_inplace */
191 0x3fff, /* src_mask */
192 0x3fff, /* dst_mask */
193 FALSE), /* pcrel_offset */
195 HOWTO (R_CR16_REGREL16, /* type */
196 0, /* rightshift */
197 1, /* size */
198 16, /* bitsize */
199 FALSE, /* pc_relative */
200 0, /* bitpos */
201 complain_overflow_bitfield,/* complain_on_overflow */
202 bfd_elf_generic_reloc, /* special_function */
203 "R_CR16_REGREL16", /* name */
204 FALSE, /* partial_inplace */
205 0xffff, /* src_mask */
206 0xffff, /* dst_mask */
207 FALSE), /* pcrel_offset */
209 HOWTO (R_CR16_REGREL20, /* type */
210 0, /* rightshift */
211 2, /* size */
212 20, /* bitsize */
213 FALSE, /* pc_relative */
214 0, /* bitpos */
215 complain_overflow_bitfield,/* complain_on_overflow */
216 bfd_elf_generic_reloc, /* special_function */
217 "R_CR16_REGREL20", /* name */
218 FALSE, /* partial_inplace */
219 0xfffff, /* src_mask */
220 0xfffff, /* dst_mask */
221 FALSE), /* pcrel_offset */
223 HOWTO (R_CR16_REGREL20a, /* type */
224 0, /* rightshift */
225 2, /* size */
226 20, /* bitsize */
227 FALSE, /* pc_relative */
228 0, /* bitpos */
229 complain_overflow_bitfield,/* complain_on_overflow */
230 bfd_elf_generic_reloc, /* special_function */
231 "R_CR16_REGREL20a", /* name */
232 FALSE, /* partial_inplace */
233 0xfffff, /* src_mask */
234 0xfffff, /* dst_mask */
235 FALSE), /* pcrel_offset */
237 HOWTO (R_CR16_ABS20, /* type */
238 0, /* rightshift */
239 2, /* size */
240 20, /* bitsize */
241 FALSE, /* pc_relative */
242 0, /* bitpos */
243 complain_overflow_bitfield,/* complain_on_overflow */
244 bfd_elf_generic_reloc, /* special_function */
245 "R_CR16_ABS20", /* name */
246 FALSE, /* partial_inplace */
247 0xfffff, /* src_mask */
248 0xfffff, /* dst_mask */
249 FALSE), /* pcrel_offset */
251 HOWTO (R_CR16_ABS24, /* type */
252 0, /* rightshift */
253 2, /* size */
254 24, /* bitsize */
255 FALSE, /* pc_relative */
256 0, /* bitpos */
257 complain_overflow_bitfield,/* complain_on_overflow */
258 bfd_elf_generic_reloc, /* special_function */
259 "R_CR16_ABS24", /* name */
260 FALSE, /* partial_inplace */
261 0xffffff, /* src_mask */
262 0xffffff, /* dst_mask */
263 FALSE), /* pcrel_offset */
265 HOWTO (R_CR16_IMM4, /* type */
266 0, /* rightshift */
267 0, /* size */
268 4, /* bitsize */
269 FALSE, /* pc_relative */
270 0, /* bitpos */
271 complain_overflow_bitfield,/* complain_on_overflow */
272 bfd_elf_generic_reloc, /* special_function */
273 "R_CR16_IMM4", /* name */
274 FALSE, /* partial_inplace */
275 0xf, /* src_mask */
276 0xf, /* dst_mask */
277 FALSE), /* pcrel_offset */
279 HOWTO (R_CR16_IMM8, /* type */
280 0, /* rightshift */
281 0, /* size */
282 8, /* bitsize */
283 FALSE, /* pc_relative */
284 0, /* bitpos */
285 complain_overflow_bitfield,/* complain_on_overflow */
286 bfd_elf_generic_reloc, /* special_function */
287 "R_CR16_IMM8", /* name */
288 FALSE, /* partial_inplace */
289 0xff, /* src_mask */
290 0xff, /* dst_mask */
291 FALSE), /* pcrel_offset */
293 HOWTO (R_CR16_IMM16, /* type */
294 0, /* rightshift */
295 1, /* size */
296 16, /* bitsize */
297 FALSE, /* pc_relative */
298 0, /* bitpos */
299 complain_overflow_bitfield,/* complain_on_overflow */
300 bfd_elf_generic_reloc, /* special_function */
301 "R_CR16_IMM16", /* name */
302 FALSE, /* partial_inplace */
303 0xffff, /* src_mask */
304 0xffff, /* dst_mask */
305 FALSE), /* pcrel_offset */
307 HOWTO (R_CR16_IMM20, /* type */
308 0, /* rightshift */
309 2, /* size */
310 20, /* bitsize */
311 FALSE, /* pc_relative */
312 0, /* bitpos */
313 complain_overflow_bitfield,/* complain_on_overflow */
314 bfd_elf_generic_reloc, /* special_function */
315 "R_CR16_IMM20", /* name */
316 FALSE, /* partial_inplace */
317 0xfffff, /* src_mask */
318 0xfffff, /* dst_mask */
319 FALSE), /* pcrel_offset */
321 HOWTO (R_CR16_IMM24, /* type */
322 0, /* rightshift */
323 2, /* size */
324 24, /* bitsize */
325 FALSE, /* pc_relative */
326 0, /* bitpos */
327 complain_overflow_bitfield,/* complain_on_overflow */
328 bfd_elf_generic_reloc, /* special_function */
329 "R_CR16_IMM24", /* name */
330 FALSE, /* partial_inplace */
331 0xffffff, /* src_mask */
332 0xffffff, /* dst_mask */
333 FALSE), /* pcrel_offset */
335 HOWTO (R_CR16_IMM32, /* type */
336 0, /* rightshift */
337 2, /* size */
338 32, /* bitsize */
339 FALSE, /* pc_relative */
340 0, /* bitpos */
341 complain_overflow_bitfield,/* complain_on_overflow */
342 bfd_elf_generic_reloc, /* special_function */
343 "R_CR16_IMM32", /* name */
344 FALSE, /* partial_inplace */
345 0xffffffff, /* src_mask */
346 0xffffffff, /* dst_mask */
347 FALSE), /* pcrel_offset */
349 HOWTO (R_CR16_IMM32a, /* type */
350 1, /* rightshift */
351 2, /* size */
352 32, /* bitsize */
353 FALSE, /* pc_relative */
354 0, /* bitpos */
355 complain_overflow_bitfield,/* complain_on_overflow */
356 bfd_elf_generic_reloc, /* special_function */
357 "R_CR16_IMM32a", /* name */
358 FALSE, /* partial_inplace */
359 0xffffffff, /* src_mask */
360 0xffffffff, /* dst_mask */
361 FALSE), /* pcrel_offset */
363 HOWTO (R_CR16_DISP4, /* type */
364 1, /* rightshift */
365 0, /* size (0 = byte, 1 = short, 2 = long) */
366 4, /* bitsize */
367 TRUE, /* pc_relative */
368 0, /* bitpos */
369 complain_overflow_unsigned, /* complain_on_overflow */
370 bfd_elf_generic_reloc, /* special_function */
371 "R_CR16_DISP4", /* name */
372 FALSE, /* partial_inplace */
373 0xf, /* src_mask */
374 0xf, /* dst_mask */
375 FALSE), /* pcrel_offset */
377 HOWTO (R_CR16_DISP8, /* type */
378 1, /* rightshift */
379 0, /* size (0 = byte, 1 = short, 2 = long) */
380 8, /* bitsize */
381 TRUE, /* pc_relative */
382 0, /* bitpos */
383 complain_overflow_unsigned, /* complain_on_overflow */
384 bfd_elf_generic_reloc, /* special_function */
385 "R_CR16_DISP8", /* name */
386 FALSE, /* partial_inplace */
387 0x1ff, /* src_mask */
388 0x1ff, /* dst_mask */
389 FALSE), /* pcrel_offset */
391 HOWTO (R_CR16_DISP16, /* type */
392 0, /* rightshift REVIITS: To sync with WinIDEA*/
393 1, /* size (0 = byte, 1 = short, 2 = long) */
394 16, /* bitsize */
395 TRUE, /* pc_relative */
396 0, /* bitpos */
397 complain_overflow_unsigned, /* complain_on_overflow */
398 bfd_elf_generic_reloc, /* special_function */
399 "R_CR16_DISP16", /* name */
400 FALSE, /* partial_inplace */
401 0x1ffff, /* src_mask */
402 0x1ffff, /* dst_mask */
403 FALSE), /* pcrel_offset */
404 /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc
405 but its not done, to sync with WinIDEA and CR16 4.1 tools */
406 HOWTO (R_CR16_DISP24, /* type */
407 0, /* rightshift */
408 2, /* size (0 = byte, 1 = short, 2 = long) */
409 24, /* bitsize */
410 TRUE, /* pc_relative */
411 0, /* bitpos */
412 complain_overflow_unsigned, /* complain_on_overflow */
413 bfd_elf_generic_reloc, /* special_function */
414 "R_CR16_DISP24", /* name */
415 FALSE, /* partial_inplace */
416 0x1ffffff, /* src_mask */
417 0x1ffffff, /* dst_mask */
418 FALSE), /* pcrel_offset */
420 HOWTO (R_CR16_DISP24a, /* type */
421 0, /* rightshift */
422 2, /* size (0 = byte, 1 = short, 2 = long) */
423 24, /* bitsize */
424 TRUE, /* pc_relative */
425 0, /* bitpos */
426 complain_overflow_unsigned, /* complain_on_overflow */
427 bfd_elf_generic_reloc, /* special_function */
428 "R_CR16_DISP24a", /* name */
429 FALSE, /* partial_inplace */
430 0xffffff, /* src_mask */
431 0xffffff, /* dst_mask */
432 FALSE) /* pcrel_offset */
435 /* Retrieve a howto ptr using a BFD reloc_code. */
437 static reloc_howto_type *
438 elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
439 bfd_reloc_code_real_type code)
441 unsigned int i;
443 for (i = 0; i < R_CR16_MAX; i++)
444 if (code == cr16_reloc_map[i].bfd_reloc_enum)
445 return &cr16_elf_howto_table[cr16_reloc_map[i].cr16_reloc_type];
447 _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code);
448 return NULL;
451 static reloc_howto_type *
452 elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
453 const char *r_name)
455 unsigned int i;
457 for (i = 0; ARRAY_SIZE (cr16_elf_howto_table); i++)
458 if (cr16_elf_howto_table[i].name != NULL
459 && strcasecmp (cr16_elf_howto_table[i].name, r_name) == 0)
460 return cr16_elf_howto_table + i;
462 return NULL;
465 /* Retrieve a howto ptr using an internal relocation entry. */
467 static void
468 elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
469 Elf_Internal_Rela *dst)
471 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
473 BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
474 cache_ptr->howto = &cr16_elf_howto_table[r_type];
477 /* Perform a relocation as part of a final link. */
479 static bfd_reloc_status_type
480 cr16_elf_final_link_relocate (reloc_howto_type *howto,
481 bfd *input_bfd,
482 bfd *output_bfd ATTRIBUTE_UNUSED,
483 asection *input_section,
484 bfd_byte *contents,
485 bfd_vma offset,
486 bfd_vma Rvalue,
487 bfd_vma addend,
488 struct bfd_link_info *info ATTRIBUTE_UNUSED,
489 asection *sec ATTRIBUTE_UNUSED,
490 int is_local ATTRIBUTE_UNUSED)
492 unsigned short r_type = howto->type;
493 bfd_byte *hit_data = contents + offset;
494 bfd_vma reloc_bits, check, Rvalue1;
496 switch (r_type)
498 case R_CR16_IMM4:
499 case R_CR16_IMM8:
500 case R_CR16_IMM16:
501 case R_CR16_IMM20:
502 case R_CR16_IMM32:
503 case R_CR16_IMM32a:
504 case R_CR16_REGREL4:
505 case R_CR16_REGREL4a:
506 case R_CR16_REGREL14:
507 case R_CR16_REGREL14a:
508 case R_CR16_REGREL16:
509 case R_CR16_REGREL20:
510 case R_CR16_ABS20:
511 case R_CR16_ABS24:
512 case R_CR16_DISP16:
513 case R_CR16_DISP24:
514 /* 'hit_data' is relative to the start of the instruction, not the
515 relocation offset. Advance it to account for the exact offset. */
516 hit_data += 2;
517 break;
519 case R_CR16_NONE:
520 return bfd_reloc_ok;
521 break;
523 case R_CR16_DISP4:
524 case R_CR16_DISP8:
525 case R_CR16_DISP24a:
526 /* We only care about the addend, where the difference between
527 expressions is kept. */
528 if (is_local) Rvalue -= -1;
530 default:
531 break;
534 if (howto->pc_relative)
536 /* Subtract the address of the section containing the location. */
537 Rvalue -= (input_section->output_section->vma
538 + input_section->output_offset);
539 /* Subtract the position of the location within the section. */
540 Rvalue -= offset;
543 /* Add in supplied addend. */
544 Rvalue += addend;
546 /* Complain if the bitfield overflows, whether it is considered
547 as signed or unsigned. */
548 check = Rvalue >> howto->rightshift;
550 /* Assumes two's complement. This expression avoids
551 overflow if howto->bitsize is the number of bits in
552 bfd_vma. */
553 reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
555 if (((bfd_vma) check & ~reloc_bits) != 0
556 && (((bfd_vma) check & ~reloc_bits)
557 != (-(bfd_vma) 1 & ~reloc_bits)))
559 /* The above right shift is incorrect for a signed
560 value. See if turning on the upper bits fixes the
561 overflow. */
562 if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
564 check |= ((bfd_vma) - 1
565 & ~((bfd_vma) - 1
566 >> howto->rightshift));
568 if (((bfd_vma) check & ~reloc_bits)
569 != (-(bfd_vma) 1 & ~reloc_bits))
570 return bfd_reloc_overflow;
572 else
573 return bfd_reloc_overflow;
576 /* Drop unwanted bits from the value we are relocating to. */
577 Rvalue >>= (bfd_vma) howto->rightshift;
579 /* Apply dst_mask to select only relocatable part of the insn. */
580 Rvalue &= howto->dst_mask;
582 switch (howto->size)
584 case 0:
585 if ((r_type == R_CR16_IMM4)
586 || (r_type == R_CR16_DISP4)
587 || (r_type == R_CR16_DISP8))
589 Rvalue1 = bfd_get_16 (input_bfd, hit_data);
590 Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00)
591 | (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
592 bfd_put_16 (input_bfd, Rvalue, hit_data);
594 break;
596 case 1:
597 if (r_type == R_CR16_DISP16)
599 Rvalue |= (bfd_get_16 (input_bfd, hit_data));
600 Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
602 bfd_put_16 (input_bfd, Rvalue, hit_data);
604 break;
606 case 2:
607 if (r_type == R_CR16_ABS20)
609 Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16)
610 | (bfd_get_16 (input_bfd, hit_data + 2)))
611 & ~howto->dst_mask);
612 Rvalue |= (bfd_get_16 (input_bfd, hit_data + 2) << 16);
614 /* Relocation on INSTRUCTIONS is different : Instructions are
615 word-addressable, that is, each word itself is arranged according
616 to little-endian convention, whereas the words are arranged with
617 respect to one another in BIG ENDIAN fashion.
618 When there is an immediate value that spans a word boundary,
619 it is split in a big-endian way with respect to the words. */
620 bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data);
621 bfd_put_16 (input_bfd, (Rvalue >> 16)& 0xffff, hit_data + 2);
623 else if (r_type == R_CR16_ABS24)
625 Rvalue = ((((Rvalue >> 20)& 0xf)
626 | (((Rvalue >> 16) & 0xf) << 8)
627 | (bfd_get_16 (input_bfd, hit_data)))
628 | ((Rvalue & 0xffff) << 16));
630 bfd_put_32 (input_bfd, Rvalue, hit_data);
632 else if (r_type == R_CR16_DISP24)
634 Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf)<<8)
635 | (bfd_get_16 (input_bfd, hit_data)))
636 | (((Rvalue & 0xfffE) | ((Rvalue >> 24) & 0x1)) << 16));
638 bfd_put_32 (input_bfd, Rvalue, hit_data);
640 else if ((r_type == R_CR16_IMM32) || (r_type == R_CR16_IMM32a))
642 Rvalue = (((Rvalue >> 16)& 0xffff)
643 | (bfd_get_16 (input_bfd, hit_data)))
644 | ((Rvalue & 0xffff) << 16);
645 bfd_put_32 (input_bfd, Rvalue, hit_data);
647 else if (r_type == R_CR16_DISP24a)
649 Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
650 Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
651 | (bfd_get_32 (input_bfd, hit_data));
653 bfd_put_32 (input_bfd, Rvalue, hit_data);
655 else if ((r_type == R_CR16_NUM32) || (r_type == R_CR16_NUM32a))
657 bfd_put_32 (input_bfd, Rvalue, hit_data);
659 break;
661 default:
662 return bfd_reloc_notsupported;
665 return bfd_reloc_ok;
668 /* Delete some bytes from a section while relaxing. */
670 static bfd_boolean
671 elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
672 asection *sec, bfd_vma addr, int count)
674 Elf_Internal_Shdr *symtab_hdr;
675 unsigned int sec_shndx;
676 bfd_byte *contents;
677 Elf_Internal_Rela *irel, *irelend;
678 Elf_Internal_Rela *irelalign;
679 bfd_vma toaddr;
680 Elf_Internal_Sym *isym;
681 Elf_Internal_Sym *isymend;
682 struct elf_link_hash_entry **sym_hashes;
683 struct elf_link_hash_entry **end_hashes;
684 struct elf_link_hash_entry **start_hashes;
685 unsigned int symcount;
687 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
689 contents = elf_section_data (sec)->this_hdr.contents;
691 /* The deletion must stop at the next ALIGN reloc for an aligment
692 power larger than the number of bytes we are deleting. */
693 irelalign = NULL;
694 toaddr = sec->size;
696 irel = elf_section_data (sec)->relocs;
697 irelend = irel + sec->reloc_count;
699 /* Actually delete the bytes. */
700 memmove (contents + addr, contents + addr + count,
701 (size_t) (toaddr - addr - count));
702 sec->size -= count;
704 /* Adjust all the relocs. */
705 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
706 /* Get the new reloc address. */
707 if ((irel->r_offset > addr && irel->r_offset < toaddr))
708 irel->r_offset -= count;
710 /* Adjust the local symbols defined in this section. */
711 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
712 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
713 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
715 if (isym->st_shndx == sec_shndx
716 && isym->st_value > addr
717 && isym->st_value < toaddr)
719 /* Adjust the addend of SWITCH relocations in this section,
720 which reference this local symbol. */
721 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
723 unsigned long r_symndx;
724 Elf_Internal_Sym *rsym;
725 bfd_vma addsym, subsym;
727 r_symndx = ELF32_R_SYM (irel->r_info);
728 rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
730 /* Skip if not the local adjusted symbol. */
731 if (rsym != isym)
732 continue;
734 addsym = isym->st_value;
735 subsym = addsym - irel->r_addend;
737 /* Fix the addend only when -->> (addsym > addr >= subsym). */
738 if (subsym <= addr)
739 irel->r_addend -= count;
740 else
741 continue;
744 isym->st_value -= count;
748 /* Now adjust the global symbols defined in this section. */
749 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
750 - symtab_hdr->sh_info);
751 sym_hashes = start_hashes = elf_sym_hashes (abfd);
752 end_hashes = sym_hashes + symcount;
754 for (; sym_hashes < end_hashes; sym_hashes++)
756 struct elf_link_hash_entry *sym_hash = *sym_hashes;
758 /* The '--wrap SYMBOL' option is causing a pain when the object file,
759 containing the definition of __wrap_SYMBOL, includes a direct
760 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
761 the same symbol (which is __wrap_SYMBOL), but still exist as two
762 different symbols in 'sym_hashes', we don't want to adjust
763 the global symbol __wrap_SYMBOL twice.
764 This check is only relevant when symbols are being wrapped. */
765 if (link_info->wrap_hash != NULL)
767 struct elf_link_hash_entry **cur_sym_hashes;
769 /* Loop only over the symbols whom been already checked. */
770 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
771 cur_sym_hashes++)
772 /* If the current symbol is identical to 'sym_hash', that means
773 the symbol was already adjusted (or at least checked). */
774 if (*cur_sym_hashes == sym_hash)
775 break;
777 /* Don't adjust the symbol again. */
778 if (cur_sym_hashes < sym_hashes)
779 continue;
782 if ((sym_hash->root.type == bfd_link_hash_defined
783 || sym_hash->root.type == bfd_link_hash_defweak)
784 && sym_hash->root.u.def.section == sec
785 && sym_hash->root.u.def.value > addr
786 && sym_hash->root.u.def.value < toaddr)
787 sym_hash->root.u.def.value -= count;
790 return TRUE;
793 /* Relocate a CR16 ELF section. */
795 static bfd_boolean
796 elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
797 bfd *input_bfd, asection *input_section,
798 bfd_byte *contents, Elf_Internal_Rela *relocs,
799 Elf_Internal_Sym *local_syms,
800 asection **local_sections)
802 Elf_Internal_Shdr *symtab_hdr;
803 struct elf_link_hash_entry **sym_hashes;
804 Elf_Internal_Rela *rel, *relend;
806 if (info->relocatable)
807 return TRUE;
809 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
810 sym_hashes = elf_sym_hashes (input_bfd);
812 rel = relocs;
813 relend = relocs + input_section->reloc_count;
814 for (; rel < relend; rel++)
816 int r_type;
817 reloc_howto_type *howto;
818 unsigned long r_symndx;
819 Elf_Internal_Sym *sym;
820 asection *sec;
821 struct elf_link_hash_entry *h;
822 bfd_vma relocation;
823 bfd_reloc_status_type r;
825 r_symndx = ELF32_R_SYM (rel->r_info);
826 r_type = ELF32_R_TYPE (rel->r_info);
827 howto = cr16_elf_howto_table + (r_type);
829 h = NULL;
830 sym = NULL;
831 sec = NULL;
832 if (r_symndx < symtab_hdr->sh_info)
834 sym = local_syms + r_symndx;
835 sec = local_sections[r_symndx];
836 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
838 else
840 bfd_boolean unresolved_reloc, warned;
842 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
843 r_symndx, symtab_hdr, sym_hashes,
844 h, sec, relocation,
845 unresolved_reloc, warned);
848 r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
849 input_section,
850 contents, rel->r_offset,
851 relocation, rel->r_addend,
852 info, sec, h == NULL);
854 if (r != bfd_reloc_ok)
856 const char *name;
857 const char *msg = NULL;
859 if (h != NULL)
860 name = h->root.root.string;
861 else
863 name = (bfd_elf_string_from_elf_section
864 (input_bfd, symtab_hdr->sh_link, sym->st_name));
865 if (name == NULL || *name == '\0')
866 name = bfd_section_name (input_bfd, sec);
869 switch (r)
871 case bfd_reloc_overflow:
872 if (!((*info->callbacks->reloc_overflow)
873 (info, (h ? &h->root : NULL), name, howto->name,
874 (bfd_vma) 0, input_bfd, input_section,
875 rel->r_offset)))
876 return FALSE;
877 break;
879 case bfd_reloc_undefined:
880 if (!((*info->callbacks->undefined_symbol)
881 (info, name, input_bfd, input_section,
882 rel->r_offset, TRUE)))
883 return FALSE;
884 break;
886 case bfd_reloc_outofrange:
887 msg = _("internal error: out of range error");
888 goto common_error;
890 case bfd_reloc_notsupported:
891 msg = _("internal error: unsupported relocation error");
892 goto common_error;
894 case bfd_reloc_dangerous:
895 msg = _("internal error: dangerous error");
896 goto common_error;
898 default:
899 msg = _("internal error: unknown error");
900 /* Fall through. */
902 common_error:
903 if (!((*info->callbacks->warning)
904 (info, msg, name, input_bfd, input_section,
905 rel->r_offset)))
906 return FALSE;
907 break;
912 return TRUE;
915 /* This is a version of bfd_generic_get_relocated_section_contents
916 which uses elf32_cr16_relocate_section. */
918 static bfd_byte *
919 elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
920 struct bfd_link_info *link_info,
921 struct bfd_link_order *link_order,
922 bfd_byte *data,
923 bfd_boolean relocatable,
924 asymbol **symbols)
926 Elf_Internal_Shdr *symtab_hdr;
927 asection *input_section = link_order->u.indirect.section;
928 bfd *input_bfd = input_section->owner;
929 asection **sections = NULL;
930 Elf_Internal_Rela *internal_relocs = NULL;
931 Elf_Internal_Sym *isymbuf = NULL;
933 /* We only need to handle the case of relaxing, or of having a
934 particular set of section contents, specially. */
935 if (relocatable
936 || elf_section_data (input_section)->this_hdr.contents == NULL)
937 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
938 link_order, data,
939 relocatable,
940 symbols);
942 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
944 memcpy (data, elf_section_data (input_section)->this_hdr.contents,
945 (size_t) input_section->size);
947 if ((input_section->flags & SEC_RELOC) != 0
948 && input_section->reloc_count > 0)
950 Elf_Internal_Sym *isym;
951 Elf_Internal_Sym *isymend;
952 asection **secpp;
953 bfd_size_type amt;
955 internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
956 NULL, NULL, FALSE);
957 if (internal_relocs == NULL)
958 goto error_return;
960 if (symtab_hdr->sh_info != 0)
962 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
963 if (isymbuf == NULL)
964 isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
965 symtab_hdr->sh_info, 0,
966 NULL, NULL, NULL);
967 if (isymbuf == NULL)
968 goto error_return;
971 amt = symtab_hdr->sh_info;
972 amt *= sizeof (asection *);
973 sections = bfd_malloc (amt);
974 if (sections == NULL && amt != 0)
975 goto error_return;
977 isymend = isymbuf + symtab_hdr->sh_info;
978 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
980 asection *isec;
982 if (isym->st_shndx == SHN_UNDEF)
983 isec = bfd_und_section_ptr;
984 else if (isym->st_shndx == SHN_ABS)
985 isec = bfd_abs_section_ptr;
986 else if (isym->st_shndx == SHN_COMMON)
987 isec = bfd_com_section_ptr;
988 else
989 isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
991 *secpp = isec;
994 if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd,
995 input_section, data, internal_relocs,
996 isymbuf, sections))
997 goto error_return;
999 if (sections != NULL)
1000 free (sections);
1001 if (isymbuf != NULL
1002 && symtab_hdr->contents != (unsigned char *) isymbuf)
1003 free (isymbuf);
1004 if (elf_section_data (input_section)->relocs != internal_relocs)
1005 free (internal_relocs);
1008 return data;
1010 error_return:
1011 if (sections != NULL)
1012 free (sections);
1013 if (isymbuf != NULL
1014 && symtab_hdr->contents != (unsigned char *) isymbuf)
1015 free (isymbuf);
1016 if (internal_relocs != NULL
1017 && elf_section_data (input_section)->relocs != internal_relocs)
1018 free (internal_relocs);
1019 return NULL;
1022 /* This function handles relaxing for the CR16.
1024 There's quite a few relaxing opportunites available on the CR16:
1026 * bcond:24 -> bcond:16 2 bytes
1027 * bcond:16 -> bcond:8 2 bytes
1028 * arithmetic imm32 -> arithmetic imm16 2 bytes
1030 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
1032 static bfd_boolean
1033 elf32_cr16_relax_section (bfd *abfd, asection *sec,
1034 struct bfd_link_info *link_info, bfd_boolean *again)
1036 Elf_Internal_Shdr *symtab_hdr;
1037 Elf_Internal_Rela *internal_relocs;
1038 Elf_Internal_Rela *irel, *irelend;
1039 bfd_byte *contents = NULL;
1040 Elf_Internal_Sym *isymbuf = NULL;
1042 /* Assume nothing changes. */
1043 *again = FALSE;
1045 /* We don't have to do anything for a relocatable link, if
1046 this section does not have relocs, or if this is not a
1047 code section. */
1048 if (link_info->relocatable
1049 || (sec->flags & SEC_RELOC) == 0
1050 || sec->reloc_count == 0
1051 || (sec->flags & SEC_CODE) == 0)
1052 return TRUE;
1054 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1056 /* Get a copy of the native relocations. */
1057 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1058 link_info->keep_memory);
1059 if (internal_relocs == NULL)
1060 goto error_return;
1062 /* Walk through them looking for relaxing opportunities. */
1063 irelend = internal_relocs + sec->reloc_count;
1064 for (irel = internal_relocs; irel < irelend; irel++)
1066 bfd_vma symval;
1068 /* If this isn't something that can be relaxed, then ignore
1069 this reloc. */
1070 if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
1071 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24)
1072 continue;
1074 /* Get the section contents if we haven't done so already. */
1075 if (contents == NULL)
1077 /* Get cached copy if it exists. */
1078 if (elf_section_data (sec)->this_hdr.contents != NULL)
1079 contents = elf_section_data (sec)->this_hdr.contents;
1080 /* Go get them off disk. */
1081 else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1082 goto error_return;
1085 /* Read this BFD's local symbols if we haven't done so already. */
1086 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1088 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1089 if (isymbuf == NULL)
1090 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1091 symtab_hdr->sh_info, 0,
1092 NULL, NULL, NULL);
1093 if (isymbuf == NULL)
1094 goto error_return;
1097 /* Get the value of the symbol referred to by the reloc. */
1098 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1100 /* A local symbol. */
1101 Elf_Internal_Sym *isym;
1102 asection *sym_sec;
1104 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1105 if (isym->st_shndx == SHN_UNDEF)
1106 sym_sec = bfd_und_section_ptr;
1107 else if (isym->st_shndx == SHN_ABS)
1108 sym_sec = bfd_abs_section_ptr;
1109 else if (isym->st_shndx == SHN_COMMON)
1110 sym_sec = bfd_com_section_ptr;
1111 else
1112 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1113 symval = (isym->st_value
1114 + sym_sec->output_section->vma
1115 + sym_sec->output_offset);
1117 else
1119 unsigned long indx;
1120 struct elf_link_hash_entry *h;
1122 /* An external symbol. */
1123 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1124 h = elf_sym_hashes (abfd)[indx];
1125 BFD_ASSERT (h != NULL);
1127 if (h->root.type != bfd_link_hash_defined
1128 && h->root.type != bfd_link_hash_defweak)
1129 /* This appears to be a reference to an undefined
1130 symbol. Just ignore it--it will be caught by the
1131 regular reloc processing. */
1132 continue;
1134 symval = (h->root.u.def.value
1135 + h->root.u.def.section->output_section->vma
1136 + h->root.u.def.section->output_offset);
1139 /* For simplicity of coding, we are going to modify the section
1140 contents, the section relocs, and the BFD symbol table. We
1141 must tell the rest of the code not to free up this
1142 information. It would be possible to instead create a table
1143 of changes which have to be made, as is done in coff-mips.c;
1144 that would be more work, but would require less memory when
1145 the linker is run. */
1147 /* Try to turn a 24 branch/call into a 16bit relative
1148 * branch/call. */
1149 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
1151 bfd_vma value = symval;
1153 /* Deal with pc-relative gunk. */
1154 value -= (sec->output_section->vma + sec->output_offset);
1155 value -= irel->r_offset;
1156 value += irel->r_addend;
1158 /* See if the value will fit in 16 bits, note the high value is
1159 0xfffe + 2 as the target will be two bytes closer if we are
1160 able to relax. */
1161 if ((long) value < 0x10000 && (long) value > -0x10002)
1163 unsigned int code;
1165 /* Get the opcode. */
1166 code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset);
1168 /* Verify it's a 'bcond' and fix the opcode. */
1169 if ((code & 0xffff) == 0x0010)
1171 bfd_put_16 (abfd, 0x1800 | ((0xf & (code >>20))<<4), contents + irel->r_offset);
1172 bfd_put_16 (abfd, value, contents + irel->r_offset+2);
1174 else
1175 continue;
1177 /* Note that we've changed the relocs, section contents, etc. */
1178 elf_section_data (sec)->relocs = internal_relocs;
1179 elf_section_data (sec)->this_hdr.contents = contents;
1180 symtab_hdr->contents = (unsigned char *) isymbuf;
1182 /* Fix the relocation's type. */
1183 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1184 R_CR16_DISP16);
1186 /* Delete two bytes of data. */
1187 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1188 irel->r_offset + 2, 2))
1189 goto error_return;
1191 /* That will change things, so, we should relax again.
1192 Note that this is not required, and it may be slow. */
1193 *again = TRUE;
1197 /* Try to turn a 16bit pc-relative branch into an
1198 8bit pc-relative branch. */
1199 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
1201 bfd_vma value = symval;
1203 /* Deal with pc-relative gunk. */
1204 value -= (sec->output_section->vma + sec->output_offset);
1205 value -= irel->r_offset;
1206 value += irel->r_addend;
1208 /* See if the value will fit in 8 bits, note the high value is
1209 0xfc + 2 as the target will be two bytes closer if we are
1210 able to relax. */
1211 if ((long) value < 0xfe && (long) value > -0x100)
1213 unsigned short code;
1215 /* Get the opcode. */
1216 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1218 /* Verify it's a 'bcond' opcode. */
1219 if ((code & 0xff00) == 0x1800)
1221 bfd_put_8 (abfd, 0x1 | ((0xf & (code>>4))<<4), contents + irel->r_offset);
1222 bfd_put_8 (abfd, value, contents + irel->r_offset+2);
1224 else
1225 continue;
1227 /* Note that we've changed the relocs, section contents, etc. */
1228 elf_section_data (sec)->relocs = internal_relocs;
1229 elf_section_data (sec)->this_hdr.contents = contents;
1230 symtab_hdr->contents = (unsigned char *) isymbuf;
1232 /* Fix the relocation's type. */
1233 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1234 R_CR16_DISP8);
1236 /* Delete two bytes of data. */
1237 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1238 irel->r_offset + 2, 2))
1239 goto error_return;
1241 /* That will change things, so, we should relax again.
1242 Note that this is not required, and it may be slow. */
1243 *again = TRUE;
1247 #if 0 // REVISIT: To support IMM relaxation in CR16 target
1248 /* Try to turn a 32bit immediate address into
1249 a 20bit immediate address. */
1250 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
1252 bfd_vma value = symval;
1254 /* See if the value will fit in 20 bits. */
1255 if ((long) value < 0x7ffff && (long) value > -0x80000)
1257 unsigned short code;
1259 /* Get the opcode. */
1260 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1262 /* Verify it's a 'arithmetic double'. */
1263 if ((code & 0xfff0) != 0x0070)
1264 continue;
1266 /* Note that we've changed the relocs, section contents, etc. */
1267 elf_section_data (sec)->relocs = internal_relocs;
1268 elf_section_data (sec)->this_hdr.contents = contents;
1269 symtab_hdr->contents = (unsigned char *) isymbuf;
1271 /* Fix the opcode. */
1272 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1274 /* Fix the relocation's type. */
1275 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1276 R_CR16_IMM20);
1278 /* Delete two bytes of data. */
1279 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1280 irel->r_offset + 2, 2))
1281 goto error_return;
1283 /* That will change things, so, we should relax again.
1284 Note that this is not required, and it may be slow. */
1285 *again = TRUE;
1288 /* Try to turn a 20bit/16bit immediate address into
1289 a 4bit immediate address. */
1290 if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
1291 || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
1293 bfd_vma value = symval;
1295 /* See if the value will fit in 4 bits. */
1296 if ((long) value < 0x7 && (long) value > -0x8)
1298 unsigned short code;
1300 /* Get the opcode. */
1301 code = (unsigned short) bfd_get_8 (abfd, contents + irel->r_offset);
1303 /* Verify it's a 'arithmetic double'. */
1304 if (((code & 0xff) != 0x50) || ((code & 0xff) != 0x45))
1305 continue;
1307 /* Note that we've changed the relocs, section contents, etc. */
1308 elf_section_data (sec)->relocs = internal_relocs;
1309 elf_section_data (sec)->this_hdr.contents = contents;
1310 symtab_hdr->contents = (unsigned char *) isymbuf;
1312 /* Fix the opcode. */
1313 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1315 /* Fix the relocation's type. */
1316 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1317 R_CR16_IMM4);
1319 /* Delete two bytes of data. */
1320 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1321 irel->r_offset + 2, 2))
1322 goto error_return;
1324 /* That will change things, so, we should relax again.
1325 Note that this is not required, and it may be slow. */
1326 *again = TRUE;
1329 #endif
1332 if (isymbuf != NULL
1333 && symtab_hdr->contents != (unsigned char *) isymbuf)
1335 if (! link_info->keep_memory)
1336 free (isymbuf);
1337 else
1339 /* Cache the symbols for elf_link_input_bfd. */
1340 symtab_hdr->contents = (unsigned char *) isymbuf;
1344 if (contents != NULL
1345 && elf_section_data (sec)->this_hdr.contents != contents)
1347 if (! link_info->keep_memory)
1348 free (contents);
1349 else
1351 /* Cache the section contents for elf_link_input_bfd. */
1352 elf_section_data (sec)->this_hdr.contents = contents;
1356 if (internal_relocs != NULL
1357 && elf_section_data (sec)->relocs != internal_relocs)
1358 free (internal_relocs);
1360 return TRUE;
1362 error_return:
1363 if (isymbuf != NULL
1364 && symtab_hdr->contents != (unsigned char *) isymbuf)
1365 free (isymbuf);
1366 if (contents != NULL
1367 && elf_section_data (sec)->this_hdr.contents != contents)
1368 free (contents);
1369 if (internal_relocs != NULL
1370 && elf_section_data (sec)->relocs != internal_relocs)
1371 free (internal_relocs);
1373 return FALSE;
1376 static asection *
1377 elf32_cr16_gc_mark_hook (asection *sec,
1378 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1379 Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1380 struct elf_link_hash_entry *h,
1381 Elf_Internal_Sym *sym)
1383 if (h == NULL)
1384 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1386 switch (h->root.type)
1388 case bfd_link_hash_defined:
1389 case bfd_link_hash_defweak:
1390 return h->root.u.def.section;
1392 case bfd_link_hash_common:
1393 return h->root.u.c.p->section;
1395 default:
1396 return NULL;
1400 /* Update the got entry reference counts for the section being removed. */
1402 static bfd_boolean
1403 elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1404 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1405 asection *sec ATTRIBUTE_UNUSED,
1406 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1408 /* We don't support garbage collection of GOT and PLT relocs yet. */
1409 return TRUE;
1412 /* Definitions for setting CR16 target vector. */
1413 #define TARGET_LITTLE_SYM bfd_elf32_cr16_vec
1414 #define TARGET_LITTLE_NAME "elf32-cr16"
1415 #define ELF_ARCH bfd_arch_cr16
1416 #define ELF_MACHINE_CODE EM_CR16
1417 #define ELF_MAXPAGESIZE 0x1
1418 #define elf_symbol_leading_char '_'
1420 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16_reloc_type_lookup
1421 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16_reloc_name_lookup
1422 #define elf_info_to_howto elf_cr16_info_to_howto
1423 #define elf_info_to_howto_rel 0
1424 #define elf_backend_relocate_section elf32_cr16_relocate_section
1425 #define bfd_elf32_bfd_relax_section elf32_cr16_relax_section
1426 #define bfd_elf32_bfd_get_relocated_section_contents \
1427 elf32_cr16_get_relocated_section_contents
1428 #define elf_backend_gc_mark_hook elf32_cr16_gc_mark_hook
1429 #define elf_backend_gc_sweep_hook elf32_cr16_gc_sweep_hook
1430 #define elf_backend_can_gc_sections 1
1431 #define elf_backend_rela_normal 1
1433 #include "elf32-target.h"