]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/binutils/bfd/elf32-cr16.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / binutils / bfd / elf32-cr16.c
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
9    the Free Software Foundation; either version 2 of the License, or
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
31 struct 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
37 static 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
67 static 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
437 static reloc_howto_type *
438 elf_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
451 static reloc_howto_type *
452 elf_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
467 static void
468 elf_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
479 static bfd_reloc_status_type
480 cr16_elf_final_link_relocate (reloc_howto_type *howto,
481                               bfd *input_bfd,
482                               bfd *output_bfd ATTRIBUTE_UNUSED,
483                               asection *input_section,
484                               bfd_byte *contents,
485                               bfd_vma offset,
486                               bfd_vma Rvalue,
487                               bfd_vma addend,
488                               struct bfd_link_info *info ATTRIBUTE_UNUSED,
489                               asection *sec ATTRIBUTE_UNUSED,
490                               int is_local ATTRIBUTE_UNUSED)
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
670 static bfd_boolean
671 elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
672                                asection *sec, bfd_vma addr, int count)
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
795 static bfd_boolean
796 elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
797                             bfd *input_bfd, asection *input_section,
798                             bfd_byte *contents, Elf_Internal_Rela *relocs,
799                             Elf_Internal_Sym *local_syms,
800                             asection **local_sections)
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
918 static bfd_byte *
919 elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
920                                            struct bfd_link_info *link_info,
921                                            struct bfd_link_order *link_order,
922                                            bfd_byte *data,
923                                            bfd_boolean relocatable,
924                                            asymbol **symbols)
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
1032 static bfd_boolean
1033 elf32_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
1376 static asection *
1377 elf32_cr16_gc_mark_hook (asection *sec,
1378                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
1379                         Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1380                         struct elf_link_hash_entry *h,
1381                         Elf_Internal_Sym *sym)
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
1402 static bfd_boolean
1403 elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1404                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
1405                          asection *sec ATTRIBUTE_UNUSED,
1406                          const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
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"