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
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"
1434