2008-09-26 Kai Tietz <kai.tietz@onevision.com>
[binutils.git] / bfd / elf32-cr16.c
blob84130b0caa4b6adc42816a9996bbec1e81e6b881
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. */
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},
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 */
73 0, /* rightshift */
74 2, /* size */
75 32, /* bitsize */
76 FALSE, /* pc_relative */
77 0, /* bitpos */
78 complain_overflow_dont, /* complain_on_overflow */
79 bfd_elf_generic_reloc, /* special_function */
80 "R_CR16_NONE", /* name */
81 FALSE, /* partial_inplace */
82 0, /* src_mask */
83 0, /* dst_mask */
84 FALSE), /* pcrel_offset */
86 HOWTO (R_CR16_NUM8, /* type */
87 0, /* rightshift */
88 0, /* size */
89 8, /* bitsize */
90 FALSE, /* pc_relative */
91 0, /* bitpos */
92 complain_overflow_bitfield,/* complain_on_overflow */
93 bfd_elf_generic_reloc, /* special_function */
94 "R_CR16_NUM8", /* name */
95 FALSE, /* partial_inplace */
96 0xff, /* src_mask */
97 0xff, /* dst_mask */
98 FALSE), /* pcrel_offset */
100 HOWTO (R_CR16_NUM16, /* type */
101 0, /* rightshift */
102 1, /* size */
103 16, /* bitsize */
104 FALSE, /* pc_relative */
105 0, /* bitpos */
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 */
115 0, /* rightshift */
116 2, /* size */
117 32, /* bitsize */
118 FALSE, /* pc_relative */
119 0, /* bitpos */
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 */
129 1, /* rightshift */
130 2, /* size */
131 32, /* bitsize */
132 FALSE, /* pc_relative */
133 0, /* bitpos */
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 */
143 0, /* rightshift */
144 0, /* size */
145 4, /* bitsize */
146 FALSE, /* pc_relative */
147 0, /* bitpos */
148 complain_overflow_bitfield,/* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_CR16_REGREL4", /* name */
151 FALSE, /* partial_inplace */
152 0xf, /* src_mask */
153 0xf, /* dst_mask */
154 FALSE), /* pcrel_offset */
156 HOWTO (R_CR16_REGREL4a, /* type */
157 0, /* rightshift */
158 0, /* size */
159 4, /* bitsize */
160 FALSE, /* pc_relative */
161 0, /* bitpos */
162 complain_overflow_bitfield,/* complain_on_overflow */
163 bfd_elf_generic_reloc, /* special_function */
164 "R_CR16_REGREL4a", /* name */
165 FALSE, /* partial_inplace */
166 0xf, /* src_mask */
167 0xf, /* dst_mask */
168 FALSE), /* pcrel_offset */
170 HOWTO (R_CR16_REGREL14, /* type */
171 0, /* rightshift */
172 1, /* size */
173 14, /* bitsize */
174 FALSE, /* pc_relative */
175 0, /* bitpos */
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 */
185 0, /* rightshift */
186 1, /* size */
187 14, /* bitsize */
188 FALSE, /* pc_relative */
189 0, /* bitpos */
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 */
199 0, /* rightshift */
200 1, /* size */
201 16, /* bitsize */
202 FALSE, /* pc_relative */
203 0, /* bitpos */
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 */
213 0, /* rightshift */
214 2, /* size */
215 20, /* bitsize */
216 FALSE, /* pc_relative */
217 0, /* bitpos */
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 */
227 0, /* rightshift */
228 2, /* size */
229 20, /* bitsize */
230 FALSE, /* pc_relative */
231 0, /* bitpos */
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 */
241 0, /* rightshift */
242 2, /* size */
243 20, /* bitsize */
244 FALSE, /* pc_relative */
245 0, /* bitpos */
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 */
255 0, /* rightshift */
256 2, /* size */
257 24, /* bitsize */
258 FALSE, /* pc_relative */
259 0, /* bitpos */
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 */
269 0, /* rightshift */
270 0, /* size */
271 4, /* bitsize */
272 FALSE, /* pc_relative */
273 0, /* bitpos */
274 complain_overflow_bitfield,/* complain_on_overflow */
275 bfd_elf_generic_reloc, /* special_function */
276 "R_CR16_IMM4", /* name */
277 FALSE, /* partial_inplace */
278 0xf, /* src_mask */
279 0xf, /* dst_mask */
280 FALSE), /* pcrel_offset */
282 HOWTO (R_CR16_IMM8, /* type */
283 0, /* rightshift */
284 0, /* size */
285 8, /* bitsize */
286 FALSE, /* pc_relative */
287 0, /* bitpos */
288 complain_overflow_bitfield,/* complain_on_overflow */
289 bfd_elf_generic_reloc, /* special_function */
290 "R_CR16_IMM8", /* name */
291 FALSE, /* partial_inplace */
292 0xff, /* src_mask */
293 0xff, /* dst_mask */
294 FALSE), /* pcrel_offset */
296 HOWTO (R_CR16_IMM16, /* type */
297 0, /* rightshift */
298 1, /* size */
299 16, /* bitsize */
300 FALSE, /* pc_relative */
301 0, /* bitpos */
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 */
311 0, /* rightshift */
312 2, /* size */
313 20, /* bitsize */
314 FALSE, /* pc_relative */
315 0, /* bitpos */
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 */
325 0, /* rightshift */
326 2, /* size */
327 24, /* bitsize */
328 FALSE, /* pc_relative */
329 0, /* bitpos */
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 */
339 0, /* rightshift */
340 2, /* size */
341 32, /* bitsize */
342 FALSE, /* pc_relative */
343 0, /* bitpos */
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 */
353 1, /* rightshift */
354 2, /* size */
355 32, /* bitsize */
356 FALSE, /* pc_relative */
357 0, /* bitpos */
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 */
367 1, /* rightshift */
368 0, /* size (0 = byte, 1 = short, 2 = long) */
369 4, /* bitsize */
370 TRUE, /* pc_relative */
371 0, /* bitpos */
372 complain_overflow_unsigned, /* complain_on_overflow */
373 bfd_elf_generic_reloc, /* special_function */
374 "R_CR16_DISP4", /* name */
375 FALSE, /* partial_inplace */
376 0xf, /* src_mask */
377 0xf, /* dst_mask */
378 FALSE), /* pcrel_offset */
380 HOWTO (R_CR16_DISP8, /* type */
381 1, /* rightshift */
382 0, /* size (0 = byte, 1 = short, 2 = long) */
383 8, /* bitsize */
384 TRUE, /* pc_relative */
385 0, /* bitpos */
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) */
397 16, /* bitsize */
398 TRUE, /* pc_relative */
399 0, /* bitpos */
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 */
410 0, /* rightshift */
411 2, /* size (0 = byte, 1 = short, 2 = long) */
412 24, /* bitsize */
413 TRUE, /* pc_relative */
414 0, /* bitpos */
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 */
424 0, /* rightshift */
425 2, /* size (0 = byte, 1 = short, 2 = long) */
426 24, /* bitsize */
427 TRUE, /* pc_relative */
428 0, /* bitpos */
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 */
441 0, /* rightshift */
442 0, /* size (0 = byte, 1 = short, 2 = long) */
443 8, /* bitsize */
444 FALSE, /* pc_relative */
445 0, /* bitpos */
446 complain_overflow_unsigned, /* complain_on_overflow */
447 bfd_elf_generic_reloc, /* special_function */
448 "R_CR16_SWITCH8", /* name */
449 FALSE, /* partial_inplace */
450 0xff, /* src_mask */
451 0xff, /* dst_mask */
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 */
458 0, /* rightshift */
459 1, /* size (0 = byte, 1 = short, 2 = long) */
460 16, /* bitsize */
461 FALSE, /* pc_relative */
462 0, /* bitpos */
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 */
475 0, /* rightshift */
476 2, /* size (0 = byte, 1 = short, 2 = long) */
477 32, /* bitsize */
478 FALSE, /* pc_relative */
479 0, /* bitpos */
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)
495 unsigned int i;
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);
502 return NULL;
505 static reloc_howto_type *
506 elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
507 const char *r_name)
509 unsigned int i;
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;
516 return NULL;
519 /* Retrieve a howto ptr using an internal relocation entry. */
521 static void
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,
535 bfd *input_bfd,
536 bfd *output_bfd ATTRIBUTE_UNUSED,
537 asection *input_section,
538 bfd_byte *contents,
539 bfd_vma offset,
540 bfd_vma Rvalue,
541 bfd_vma addend,
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;
550 switch (r_type)
552 case R_CR16_IMM4:
553 case R_CR16_IMM20:
554 case R_CR16_ABS20:
555 break;
557 case R_CR16_IMM8:
558 case R_CR16_IMM16:
559 case R_CR16_IMM32:
560 case R_CR16_IMM32a:
561 case R_CR16_REGREL4:
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:
567 case R_CR16_ABS24:
568 case R_CR16_DISP16:
569 case R_CR16_DISP24:
570 /* 'hit_data' is relative to the start of the instruction, not the
571 relocation offset. Advance it to account for the exact offset. */
572 hit_data += 2;
573 break;
575 case R_CR16_NONE:
576 return bfd_reloc_ok;
577 break;
579 case R_CR16_DISP4:
580 if (is_local)
581 Rvalue += -1;
582 break;
584 case R_CR16_DISP8:
585 case R_CR16_DISP24a:
586 if (is_local)
587 Rvalue -= -1;
588 break;
590 case R_CR16_SWITCH8:
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. */
595 Rvalue = 0;
597 default:
598 break;
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. */
607 Rvalue -= offset;
610 /* Add in supplied addend. */
611 Rvalue += 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
619 bfd_vma. */
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
628 overflow. */
629 if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
631 check |= ((bfd_vma) - 1
632 & ~((bfd_vma) - 1
633 >> howto->rightshift));
635 if (((bfd_vma) check & ~reloc_bits)
636 != (-(bfd_vma) 1 & ~reloc_bits))
637 return bfd_reloc_overflow;
639 else
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;
649 switch (howto->size)
651 case 0:
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);
672 else
674 bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
676 break;
678 case 1:
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);
686 break;
688 case 2:
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);
695 else
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);
725 break;
727 default:
728 return bfd_reloc_notsupported;
731 return bfd_reloc_ok;
734 /* Delete some bytes from a section while relaxing. */
736 static bfd_boolean
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;
742 bfd_byte *contents;
743 Elf_Internal_Rela *irel, *irelend;
744 Elf_Internal_Rela *irelalign;
745 bfd_vma toaddr;
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. */
759 irelalign = NULL;
760 toaddr = sec->size;
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));
768 sec->size -= 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)
797 continue;
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. */
803 if (rsym != isym)
804 continue;
806 addsym = isym->st_value;
807 subsym = addsym - irel->r_addend;
809 /* Fix the addend only when -->> (addsym > addr >= subsym). */
810 if (subsym <= addr)
811 irel->r_addend -= count;
812 else
813 continue;
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;
843 cur_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)
847 break;
849 /* Don't adjust the symbol again. */
850 if (cur_sym_hashes < sym_hashes)
851 continue;
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;
862 return TRUE;
865 /* Relocate a CR16 ELF section. */
867 static bfd_boolean
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)
879 return TRUE;
881 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
882 sym_hashes = elf_sym_hashes (input_bfd);
884 rel = relocs;
885 relend = relocs + input_section->reloc_count;
886 for (; rel < relend; rel++)
888 int r_type;
889 reloc_howto_type *howto;
890 unsigned long r_symndx;
891 Elf_Internal_Sym *sym;
892 asection *sec;
893 struct elf_link_hash_entry *h;
894 bfd_vma relocation;
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);
901 h = NULL;
902 sym = NULL;
903 sec = NULL;
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);
910 else
912 bfd_boolean unresolved_reloc, warned;
914 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
915 r_symndx, symtab_hdr, sym_hashes,
916 h, sec, relocation,
917 unresolved_reloc, warned);
920 r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
921 input_section,
922 contents, rel->r_offset,
923 relocation, rel->r_addend,
924 info, sec, h == NULL);
926 if (r != bfd_reloc_ok)
928 const char *name;
929 const char *msg = NULL;
931 if (h != NULL)
932 name = h->root.root.string;
933 else
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);
941 switch (r)
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,
947 rel->r_offset)))
948 return FALSE;
949 break;
951 case bfd_reloc_undefined:
952 if (!((*info->callbacks->undefined_symbol)
953 (info, name, input_bfd, input_section,
954 rel->r_offset, TRUE)))
955 return FALSE;
956 break;
958 case bfd_reloc_outofrange:
959 msg = _("internal error: out of range error");
960 goto common_error;
962 case bfd_reloc_notsupported:
963 msg = _("internal error: unsupported relocation error");
964 goto common_error;
966 case bfd_reloc_dangerous:
967 msg = _("internal error: dangerous error");
968 goto common_error;
970 default:
971 msg = _("internal error: unknown error");
972 /* Fall through. */
974 common_error:
975 if (!((*info->callbacks->warning)
976 (info, msg, name, input_bfd, input_section,
977 rel->r_offset)))
978 return FALSE;
979 break;
984 return TRUE;
987 /* This is a version of bfd_generic_get_relocated_section_contents
988 which uses elf32_cr16_relocate_section. */
990 static bfd_byte *
991 elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
992 struct bfd_link_info *link_info,
993 struct bfd_link_order *link_order,
994 bfd_byte *data,
995 bfd_boolean relocatable,
996 asymbol **symbols)
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. */
1007 if (relocatable
1008 || elf_section_data (input_section)->this_hdr.contents == NULL)
1009 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1010 link_order, data,
1011 relocatable,
1012 symbols);
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;
1024 asection **secpp;
1025 bfd_size_type amt;
1027 internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
1028 NULL, NULL, FALSE);
1029 if (internal_relocs == NULL)
1030 goto error_return;
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,
1038 NULL, NULL, NULL);
1039 if (isymbuf == NULL)
1040 goto error_return;
1043 amt = symtab_hdr->sh_info;
1044 amt *= sizeof (asection *);
1045 sections = bfd_malloc (amt);
1046 if (sections == NULL && amt != 0)
1047 goto error_return;
1049 isymend = isymbuf + symtab_hdr->sh_info;
1050 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
1052 asection *isec;
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;
1060 else
1061 isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
1063 *secpp = isec;
1066 if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd,
1067 input_section, data, internal_relocs,
1068 isymbuf, sections))
1069 goto error_return;
1071 if (sections != NULL)
1072 free (sections);
1073 if (isymbuf != NULL
1074 && symtab_hdr->contents != (unsigned char *) isymbuf)
1075 free (isymbuf);
1076 if (elf_section_data (input_section)->relocs != internal_relocs)
1077 free (internal_relocs);
1080 return data;
1082 error_return:
1083 if (sections != NULL)
1084 free (sections);
1085 if (isymbuf != NULL
1086 && symtab_hdr->contents != (unsigned char *) isymbuf)
1087 free (isymbuf);
1088 if (internal_relocs != NULL
1089 && elf_section_data (input_section)->relocs != internal_relocs)
1090 free (internal_relocs);
1091 return NULL;
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. */
1105 static bfd_boolean
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. */
1116 *again = FALSE;
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
1120 code section. */
1121 if (link_info->relocatable
1122 || (sec->flags & SEC_RELOC) == 0
1123 || sec->reloc_count == 0
1124 || (sec->flags & SEC_CODE) == 0)
1125 return TRUE;
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)
1133 goto error_return;
1135 /* Walk through them looking for relaxing opportunities. */
1136 irelend = internal_relocs + sec->reloc_count;
1137 for (irel = internal_relocs; irel < irelend; irel++)
1139 bfd_vma symval;
1141 /* If this isn't something that can be relaxed, then ignore
1142 this reloc. */
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)
1148 continue;
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))
1158 goto error_return;
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,
1168 NULL, NULL, NULL);
1169 if (isymbuf == NULL)
1170 goto error_return;
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;
1178 asection *sym_sec;
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;
1187 else
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);
1193 else
1195 unsigned long indx;
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. */
1208 continue;
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
1224 branch/call. */
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
1236 able to relax. */
1237 if ((long) value < 0x10000 && (long) value > -0x10002)
1239 unsigned int code;
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);
1250 else
1251 continue;
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),
1260 R_CR16_DISP16);
1262 /* Delete two bytes of data. */
1263 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1264 irel->r_offset + 2, 2))
1265 goto error_return;
1267 /* That will change things, so, we should relax again.
1268 Note that this is not required, and it may be slow. */
1269 *again = TRUE;
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
1286 able to relax. */
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);
1300 else
1301 continue;
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),
1310 R_CR16_DISP8);
1312 /* Delete two bytes of data. */
1313 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1314 irel->r_offset + 2, 2))
1315 goto error_return;
1317 /* That will change things, so, we should relax again.
1318 Note that this is not required, and it may be slow. */
1319 *again = TRUE;
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))
1341 is_add_mov = 1;
1343 if (is_add_mov)
1345 /* Note that we've changed the relocs, section contents,
1346 etc. */
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),
1362 R_CR16_IMM20);
1363 /* Delete two bytes of data. */
1364 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1365 irel->r_offset + 2, 2))
1366 goto error_return;
1368 /* That will change things, so, we should relax again.
1369 Note that this is not required, and it may be slow. */
1370 *again = TRUE;
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);
1393 else
1394 continue;
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),
1400 R_CR16_IMM16);
1402 /* Delete two bytes of data. */
1403 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1404 irel->r_offset + 2, 2))
1405 goto error_return;
1407 /* That will change things, so, we should relax again.
1408 Note that this is not required, and it may be slow. */
1409 *again = TRUE;
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);
1442 else
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);
1468 else
1469 continue;
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),
1476 R_CR16_IMM4);
1478 /* Delete two bytes of data. */
1479 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1480 irel->r_offset + 2, 2))
1481 goto error_return;
1483 /* That will change things, so, we should relax again.
1484 Note that this is not required, and it may be slow. */
1485 *again = TRUE;
1490 if (isymbuf != NULL
1491 && symtab_hdr->contents != (unsigned char *) isymbuf)
1493 if (! link_info->keep_memory)
1494 free (isymbuf);
1495 else
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)
1504 free (contents);
1505 else
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);
1514 return TRUE;
1516 error_return:
1517 if (isymbuf != NULL
1518 && symtab_hdr->contents != (unsigned char *) isymbuf)
1519 free (isymbuf);
1520 if (contents != NULL
1521 && elf_section_data (sec)->this_hdr.contents != contents)
1522 free (contents);
1523 if (internal_relocs != NULL
1524 && elf_section_data (sec)->relocs != internal_relocs)
1525 free (internal_relocs);
1527 return FALSE;
1530 static asection *
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)
1537 if (h == NULL)
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;
1549 default:
1550 return NULL;
1554 /* Update the got entry reference counts for the section being removed. */
1556 static bfd_boolean
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. */
1563 return TRUE;
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_MACHINE_ALT1 EM_CR16_OLD
1572 #define ELF_MAXPAGESIZE 0x1
1573 #define elf_symbol_leading_char '_'
1575 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16_reloc_type_lookup
1576 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16_reloc_name_lookup
1577 #define elf_info_to_howto elf_cr16_info_to_howto
1578 #define elf_info_to_howto_rel 0
1579 #define elf_backend_relocate_section elf32_cr16_relocate_section
1580 #define bfd_elf32_bfd_relax_section elf32_cr16_relax_section
1581 #define bfd_elf32_bfd_get_relocated_section_contents \
1582 elf32_cr16_get_relocated_section_contents
1583 #define elf_backend_gc_mark_hook elf32_cr16_gc_mark_hook
1584 #define elf_backend_gc_sweep_hook elf32_cr16_gc_sweep_hook
1585 #define elf_backend_can_gc_sections 1
1586 #define elf_backend_rela_normal 1
1588 #include "elf32-target.h"