]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf32-cr16.c
Switch sources over to use the GPL version 3
[thirdparty/binutils-gdb.git] / bfd / elf32-cr16.c
CommitLineData
3d3d428f
NC
1/* BFD back-end for National Semiconductor's CR16 ELF
2 Copyright 2007 Free Software Foundation, Inc.
3 Written by M R Swami Reddy.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
3d3d428f
NC
10 (at your option) any later version.
11
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.
16
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. */
20
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"
28
29/* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type. */
30
31struct cr16_reloc_map
32{
33 bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum. */
34 unsigned short cr16_reloc_type; /* CR16 relocation type. */
35};
36
37static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] =
38{
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};
66
67static reloc_howto_type cr16_elf_howto_table[] =
68{
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 */
82
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 */
96
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 */
110
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 */
124
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 */
138
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 */
152
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 */
166
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 */
180
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 */
194
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 */
208
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 */
222
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 */
236
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 */
250
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 */
264
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 */
278
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 */
292
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 */
306
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 */
320
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 */
334
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 */
348
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 */
362
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 */
376
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 */
390
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 */
419
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 */
433};
434
435/* Retrieve a howto ptr using a BFD reloc_code. */
436
437static reloc_howto_type *
438elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
439 bfd_reloc_code_real_type code)
440{
441 unsigned int i;
442
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];
446
447 _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code);
448 return NULL;
449}
450
451static reloc_howto_type *
452elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
453 const char *r_name)
454{
455 unsigned int i;
456
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;
461
462 return NULL;
463}
464
465/* Retrieve a howto ptr using an internal relocation entry. */
466
467static void
468elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
469 Elf_Internal_Rela *dst)
470{
471 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
472
473 BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
474 cache_ptr->howto = &cr16_elf_howto_table[r_type];
475}
476
477/* Perform a relocation as part of a final link. */
478
479static bfd_reloc_status_type
480cr16_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)
491{
492 unsigned short r_type = howto->type;
493 bfd_byte *hit_data = contents + offset;
494 bfd_vma reloc_bits, check, Rvalue1;
495
496 switch (r_type)
497 {
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;
518
519 case R_CR16_NONE:
520 return bfd_reloc_ok;
521 break;
522
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;
529
530 default:
531 break;
532 }
533
534 if (howto->pc_relative)
535 {
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;
541 }
542
543 /* Add in supplied addend. */
544 Rvalue += addend;
545
546 /* Complain if the bitfield overflows, whether it is considered
547 as signed or unsigned. */
548 check = Rvalue >> howto->rightshift;
549
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;
554
555 if (((bfd_vma) check & ~reloc_bits) != 0
556 && (((bfd_vma) check & ~reloc_bits)
557 != (-(bfd_vma) 1 & ~reloc_bits)))
558 {
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)
563 {
564 check |= ((bfd_vma) - 1
565 & ~((bfd_vma) - 1
566 >> howto->rightshift));
567
568 if (((bfd_vma) check & ~reloc_bits)
569 != (-(bfd_vma) 1 & ~reloc_bits))
570 return bfd_reloc_overflow;
571 }
572 else
573 return bfd_reloc_overflow;
574 }
575
576 /* Drop unwanted bits from the value we are relocating to. */
577 Rvalue >>= (bfd_vma) howto->rightshift;
578
579 /* Apply dst_mask to select only relocatable part of the insn. */
580 Rvalue &= howto->dst_mask;
581
582 switch (howto->size)
583 {
584 case 0:
585 if ((r_type == R_CR16_IMM4)
586 || (r_type == R_CR16_DISP4)
587 || (r_type == R_CR16_DISP8))
588 {
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);
593 }
594 break;
595
596 case 1:
597 if (r_type == R_CR16_DISP16)
598 {
599 Rvalue |= (bfd_get_16 (input_bfd, hit_data));
600 Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
601
602 bfd_put_16 (input_bfd, Rvalue, hit_data);
603 }
604 break;
605
606 case 2:
607 if (r_type == R_CR16_ABS20)
608 {
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);
613
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);
622 }
623 else if (r_type == R_CR16_ABS24)
624 {
625 Rvalue = ((((Rvalue >> 20)& 0xf)
626 | (((Rvalue >> 16) & 0xf) << 8)
627 | (bfd_get_16 (input_bfd, hit_data)))
628 | ((Rvalue & 0xffff) << 16));
629
630 bfd_put_32 (input_bfd, Rvalue, hit_data);
631 }
632 else if (r_type == R_CR16_DISP24)
633 {
634 Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf)<<8)
635 | (bfd_get_16 (input_bfd, hit_data)))
636 | (((Rvalue & 0xfffE) | ((Rvalue >> 24) & 0x1)) << 16));
637
638 bfd_put_32 (input_bfd, Rvalue, hit_data);
639 }
640 else if ((r_type == R_CR16_IMM32) || (r_type == R_CR16_IMM32a))
641 {
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);
646 }
647 else if (r_type == R_CR16_DISP24a)
648 {
649 Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
650 Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
651 | (bfd_get_32 (input_bfd, hit_data));
652
653 bfd_put_32 (input_bfd, Rvalue, hit_data);
654 }
655 else if ((r_type == R_CR16_NUM32) || (r_type == R_CR16_NUM32a))
656 {
657 bfd_put_32 (input_bfd, Rvalue, hit_data);
658 }
659 break;
660
661 default:
662 return bfd_reloc_notsupported;
663 }
664
665 return bfd_reloc_ok;
666}
667
668/* Delete some bytes from a section while relaxing. */
669
670static bfd_boolean
671elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
672 asection *sec, bfd_vma addr, int count)
673{
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;
686
687 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
688
689 contents = elf_section_data (sec)->this_hdr.contents;
690
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;
695
696 irel = elf_section_data (sec)->relocs;
697 irelend = irel + sec->reloc_count;
698
699 /* Actually delete the bytes. */
700 memmove (contents + addr, contents + addr + count,
701 (size_t) (toaddr - addr - count));
702 sec->size -= count;
703
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;
709
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++)
714 {
715 if (isym->st_shndx == sec_shndx
716 && isym->st_value > addr
717 && isym->st_value < toaddr)
718 {
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++)
722 {
723 unsigned long r_symndx;
724 Elf_Internal_Sym *rsym;
725 bfd_vma addsym, subsym;
726
727 r_symndx = ELF32_R_SYM (irel->r_info);
728 rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
729
730 /* Skip if not the local adjusted symbol. */
731 if (rsym != isym)
732 continue;
733
734 addsym = isym->st_value;
735 subsym = addsym - irel->r_addend;
736
737 /* Fix the addend only when -->> (addsym > addr >= subsym). */
738 if (subsym <= addr)
739 irel->r_addend -= count;
740 else
741 continue;
742 }
743
744 isym->st_value -= count;
745 }
746 }
747
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;
753
754 for (; sym_hashes < end_hashes; sym_hashes++)
755 {
756 struct elf_link_hash_entry *sym_hash = *sym_hashes;
757
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)
766 {
767 struct elf_link_hash_entry **cur_sym_hashes;
768
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;
776
777 /* Don't adjust the symbol again. */
778 if (cur_sym_hashes < sym_hashes)
779 continue;
780 }
781
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;
788 }
789
790 return TRUE;
791}
792
793/* Relocate a CR16 ELF section. */
794
795static bfd_boolean
796elf32_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)
801{
802 Elf_Internal_Shdr *symtab_hdr;
803 struct elf_link_hash_entry **sym_hashes;
804 Elf_Internal_Rela *rel, *relend;
805
806 if (info->relocatable)
807 return TRUE;
808
809 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
810 sym_hashes = elf_sym_hashes (input_bfd);
811
812 rel = relocs;
813 relend = relocs + input_section->reloc_count;
814 for (; rel < relend; rel++)
815 {
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;
824
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);
828
829 h = NULL;
830 sym = NULL;
831 sec = NULL;
832 if (r_symndx < symtab_hdr->sh_info)
833 {
834 sym = local_syms + r_symndx;
835 sec = local_sections[r_symndx];
836 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
837 }
838 else
839 {
840 bfd_boolean unresolved_reloc, warned;
841
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);
846 }
847
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);
853
854 if (r != bfd_reloc_ok)
855 {
856 const char *name;
857 const char *msg = NULL;
858
859 if (h != NULL)
860 name = h->root.root.string;
861 else
862 {
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);
867 }
868
869 switch (r)
870 {
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;
878
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;
885
886 case bfd_reloc_outofrange:
887 msg = _("internal error: out of range error");
888 goto common_error;
889
890 case bfd_reloc_notsupported:
891 msg = _("internal error: unsupported relocation error");
892 goto common_error;
893
894 case bfd_reloc_dangerous:
895 msg = _("internal error: dangerous error");
896 goto common_error;
897
898 default:
899 msg = _("internal error: unknown error");
900 /* Fall through. */
901
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;
908 }
909 }
910 }
911
912 return TRUE;
913}
914
915/* This is a version of bfd_generic_get_relocated_section_contents
916 which uses elf32_cr16_relocate_section. */
917
918static bfd_byte *
919elf32_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)
925{
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;
932
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);
941
942 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
943
944 memcpy (data, elf_section_data (input_section)->this_hdr.contents,
945 (size_t) input_section->size);
946
947 if ((input_section->flags & SEC_RELOC) != 0
948 && input_section->reloc_count > 0)
949 {
950 Elf_Internal_Sym *isym;
951 Elf_Internal_Sym *isymend;
952 asection **secpp;
953 bfd_size_type amt;
954
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;
959
960 if (symtab_hdr->sh_info != 0)
961 {
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;
969 }
970
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;
976
977 isymend = isymbuf + symtab_hdr->sh_info;
978 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
979 {
980 asection *isec;
981
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);
990
991 *secpp = isec;
992 }
993
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;
998
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);
1006 }
1007
1008 return data;
1009
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;
1020}
1021
1022/* This function handles relaxing for the CR16.
1023
1024 There's quite a few relaxing opportunites available on the CR16:
1025
1026 * bcond:24 -> bcond:16 2 bytes
1027 * bcond:16 -> bcond:8 2 bytes
1028 * arithmetic imm32 -> arithmetic imm16 2 bytes
1029
1030 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
1031
1032static bfd_boolean
1033elf32_cr16_relax_section (bfd *abfd, asection *sec,
1034 struct bfd_link_info *link_info, bfd_boolean *again)
1035{
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;
1041
1042 /* Assume nothing changes. */
1043 *again = FALSE;
1044
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;
1053
1054 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1055
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;
1061
1062 /* Walk through them looking for relaxing opportunities. */
1063 irelend = internal_relocs + sec->reloc_count;
1064 for (irel = internal_relocs; irel < irelend; irel++)
1065 {
1066 bfd_vma symval;
1067
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;
1073
1074 /* Get the section contents if we haven't done so already. */
1075 if (contents == NULL)
1076 {
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;
1083 }
1084
1085 /* Read this BFD's local symbols if we haven't done so already. */
1086 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1087 {
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;
1095 }
1096
1097 /* Get the value of the symbol referred to by the reloc. */
1098 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1099 {
1100 /* A local symbol. */
1101 Elf_Internal_Sym *isym;
1102 asection *sym_sec;
1103
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);
1116 }
1117 else
1118 {
1119 unsigned long indx;
1120 struct elf_link_hash_entry *h;
1121
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);
1126
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;
1133
1134 symval = (h->root.u.def.value
1135 + h->root.u.def.section->output_section->vma
1136 + h->root.u.def.section->output_offset);
1137 }
1138
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. */
1146
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)
1150 {
1151 bfd_vma value = symval;
1152
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;
1157
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)
1162 {
1163 unsigned int code;
1164
1165 /* Get the opcode. */
1166 code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset);
1167
1168 /* Verify it's a 'bcond' and fix the opcode. */
1169 if ((code & 0xffff) == 0x0010)
1170 {
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);
1173 }
1174 else
1175 continue;
1176
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;
1181
1182 /* Fix the relocation's type. */
1183 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1184 R_CR16_DISP16);
1185
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;
1190
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;
1194 }
1195 }
1196
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)
1200 {
1201 bfd_vma value = symval;
1202
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;
1207
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)
1212 {
1213 unsigned short code;
1214
1215 /* Get the opcode. */
1216 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1217
1218 /* Verify it's a 'bcond' opcode. */
1219 if ((code & 0xff00) == 0x1800)
1220 {
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);
1223 }
1224 else
1225 continue;
1226
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;
1231
1232 /* Fix the relocation's type. */
1233 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1234 R_CR16_DISP8);
1235
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;
1240
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;
1244 }
1245 }
1246
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)
1251 {
1252 bfd_vma value = symval;
1253
1254 /* See if the value will fit in 20 bits. */
1255 if ((long) value < 0x7ffff && (long) value > -0x80000)
1256 {
1257 unsigned short code;
1258
1259 /* Get the opcode. */
1260 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1261
1262 /* Verify it's a 'arithmetic double'. */
1263 if ((code & 0xfff0) != 0x0070)
1264 continue;
1265
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;
1270
1271 /* Fix the opcode. */
1272 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1273
1274 /* Fix the relocation's type. */
1275 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1276 R_CR16_IMM20);
1277
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;
1282
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;
1286 }
1287 }
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))
1292 {
1293 bfd_vma value = symval;
1294
1295 /* See if the value will fit in 4 bits. */
1296 if ((long) value < 0x7 && (long) value > -0x8)
1297 {
1298 unsigned short code;
1299
1300 /* Get the opcode. */
1301 code = (unsigned short) bfd_get_8 (abfd, contents + irel->r_offset);
1302
1303 /* Verify it's a 'arithmetic double'. */
1304 if (((code & 0xff) != 0x50) || ((code & 0xff) != 0x45))
1305 continue;
1306
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;
1311
1312 /* Fix the opcode. */
1313 bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
1314
1315 /* Fix the relocation's type. */
1316 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1317 R_CR16_IMM4);
1318
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;
1323
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;
1327 }
1328 }
1329#endif
1330 }
1331
1332 if (isymbuf != NULL
1333 && symtab_hdr->contents != (unsigned char *) isymbuf)
1334 {
1335 if (! link_info->keep_memory)
1336 free (isymbuf);
1337 else
1338 {
1339 /* Cache the symbols for elf_link_input_bfd. */
1340 symtab_hdr->contents = (unsigned char *) isymbuf;
1341 }
1342 }
1343
1344 if (contents != NULL
1345 && elf_section_data (sec)->this_hdr.contents != contents)
1346 {
1347 if (! link_info->keep_memory)
1348 free (contents);
1349 else
1350 {
1351 /* Cache the section contents for elf_link_input_bfd. */
1352 elf_section_data (sec)->this_hdr.contents = contents;
1353 }
1354 }
1355
1356 if (internal_relocs != NULL
1357 && elf_section_data (sec)->relocs != internal_relocs)
1358 free (internal_relocs);
1359
1360 return TRUE;
1361
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);
1372
1373 return FALSE;
1374}
1375
1376static asection *
1377elf32_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)
1382{
1383 if (h == NULL)
1384 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1385
1386 switch (h->root.type)
1387 {
1388 case bfd_link_hash_defined:
1389 case bfd_link_hash_defweak:
1390 return h->root.u.def.section;
1391
1392 case bfd_link_hash_common:
1393 return h->root.u.c.p->section;
1394
1395 default:
1396 return NULL;
1397 }
1398}
1399
1400/* Update the got entry reference counts for the section being removed. */
1401
1402static bfd_boolean
1403elf32_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)
1407{
1408 /* We don't support garbage collection of GOT and PLT relocs yet. */
1409 return TRUE;
1410}
1411
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 '_'
1419
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
1432
1433#include "elf32-target.h"