Various CR16 fixes
[platform/upstream/binutils.git] / 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 3 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   {BFD_RELOC_CR16_SWITCH8,   R_CR16_SWITCH8},
66   {BFD_RELOC_CR16_SWITCH16,  R_CR16_SWITCH16},
67   {BFD_RELOC_CR16_SWITCH32,  R_CR16_SWITCH32}
68 };
69
70 static reloc_howto_type cr16_elf_howto_table[] =
71 {
72   HOWTO (R_CR16_NONE,              /* type */
73          0,                        /* rightshift */
74          2,                        /* size */
75          32,                       /* bitsize */
76          FALSE,                    /* pc_relative */
77          0,                        /* bitpos */
78          complain_overflow_dont,   /* complain_on_overflow */
79          bfd_elf_generic_reloc,    /* special_function */
80          "R_CR16_NONE",            /* name */
81          FALSE,                    /* partial_inplace */
82          0,                        /* src_mask */
83          0,                        /* dst_mask */
84          FALSE),                   /* pcrel_offset */
85
86   HOWTO (R_CR16_NUM8,              /* type */
87          0,                        /* rightshift */
88          0,                        /* size */
89          8,                        /* bitsize */
90          FALSE,                    /* pc_relative */
91          0,                        /* bitpos */
92          complain_overflow_bitfield,/* complain_on_overflow */
93          bfd_elf_generic_reloc,    /* special_function */
94          "R_CR16_NUM8",            /* name */
95          FALSE,                    /* partial_inplace */
96          0xff,                     /* src_mask */
97          0xff,                     /* dst_mask */
98          FALSE),                   /* pcrel_offset */
99
100   HOWTO (R_CR16_NUM16,             /* type */
101          0,                        /* rightshift */
102          1,                        /* size */
103          16,                       /* bitsize */
104          FALSE,                    /* pc_relative */
105          0,                        /* bitpos */
106          complain_overflow_bitfield,/* complain_on_overflow */
107          bfd_elf_generic_reloc,    /* special_function */
108          "R_CR16_NUM16",           /* name */
109          FALSE,                    /* partial_inplace */
110          0xffff,                   /* src_mask */
111          0xffff,                   /* dst_mask */
112          FALSE),                   /* pcrel_offset */
113
114   HOWTO (R_CR16_NUM32,             /* type */
115          0,                        /* rightshift */
116          2,                        /* size */
117          32,                       /* bitsize */
118          FALSE,                    /* pc_relative */
119          0,                        /* bitpos */
120          complain_overflow_bitfield,/* complain_on_overflow */
121          bfd_elf_generic_reloc,    /* special_function */
122          "R_CR16_NUM32",           /* name */
123          FALSE,                    /* partial_inplace */
124          0xffffffff,               /* src_mask */
125          0xffffffff,               /* dst_mask */
126          FALSE),                   /* pcrel_offset */
127
128   HOWTO (R_CR16_NUM32a,            /* type */
129          1,                        /* rightshift */
130          2,                        /* size */
131          32,                       /* bitsize */
132          FALSE,                    /* pc_relative */
133          0,                        /* bitpos */
134          complain_overflow_bitfield,/* complain_on_overflow */
135          bfd_elf_generic_reloc,    /* special_function */
136          "R_CR16_NUM32a",          /* name */
137          FALSE,                    /* partial_inplace */
138          0xffffffff,               /* src_mask */
139          0xffffffff,               /* dst_mask */
140          FALSE),                   /* pcrel_offset */
141
142   HOWTO (R_CR16_REGREL4,           /* type */
143          0,                        /* rightshift */
144          0,                        /* size */
145          4,                        /* bitsize */
146          FALSE,                    /* pc_relative */
147          0,                        /* bitpos */
148          complain_overflow_bitfield,/* complain_on_overflow */
149          bfd_elf_generic_reloc,    /* special_function */
150          "R_CR16_REGREL4",         /* name */
151          FALSE,                    /* partial_inplace */
152          0xf,                      /* src_mask */
153          0xf,                      /* dst_mask */
154          FALSE),                   /* pcrel_offset */
155
156   HOWTO (R_CR16_REGREL4a,          /* type */
157          0,                        /* rightshift */
158          0,                        /* size */
159          4,                        /* bitsize */
160          FALSE,                    /* pc_relative */
161          0,                        /* bitpos */
162          complain_overflow_bitfield,/* complain_on_overflow */
163          bfd_elf_generic_reloc,    /* special_function */
164          "R_CR16_REGREL4a",        /* name */
165          FALSE,                    /* partial_inplace */
166          0xf,                      /* src_mask */
167          0xf,                      /* dst_mask */
168          FALSE),                   /* pcrel_offset */
169
170   HOWTO (R_CR16_REGREL14,          /* type */
171          0,                        /* rightshift */
172          1,                        /* size */
173          14,                       /* bitsize */
174          FALSE,                    /* pc_relative */
175          0,                        /* bitpos */
176          complain_overflow_bitfield,/* complain_on_overflow */
177          bfd_elf_generic_reloc,    /* special_function */
178          "R_CR16_REGREL14",        /* name */
179          FALSE,                    /* partial_inplace */
180          0x3fff,                   /* src_mask */
181          0x3fff,                   /* dst_mask */
182          FALSE),                   /* pcrel_offset */
183
184   HOWTO (R_CR16_REGREL14a,         /* type */
185          0,                        /* rightshift */
186          1,                        /* size */
187          14,                       /* bitsize */
188          FALSE,                    /* pc_relative */
189          0,                        /* bitpos */
190          complain_overflow_bitfield,/* complain_on_overflow */
191          bfd_elf_generic_reloc,    /* special_function */
192          "R_CR16_REGREL14a",       /* name */
193          FALSE,                    /* partial_inplace */
194          0x3fff,                   /* src_mask */
195          0x3fff,                   /* dst_mask */
196          FALSE),                   /* pcrel_offset */
197
198   HOWTO (R_CR16_REGREL16,          /* type */
199          0,                        /* rightshift */
200          1,                        /* size */
201          16,                       /* bitsize */
202          FALSE,                    /* pc_relative */
203          0,                        /* bitpos */
204          complain_overflow_bitfield,/* complain_on_overflow */
205          bfd_elf_generic_reloc,    /* special_function */
206          "R_CR16_REGREL16",        /* name */
207          FALSE,                    /* partial_inplace */
208          0xffff,                   /* src_mask */
209          0xffff,                   /* dst_mask */
210          FALSE),                   /* pcrel_offset */
211
212   HOWTO (R_CR16_REGREL20,          /* type */
213          0,                        /* rightshift */
214          2,                        /* size */
215          20,                       /* bitsize */
216          FALSE,                    /* pc_relative */
217          0,                        /* bitpos */
218          complain_overflow_bitfield,/* complain_on_overflow */
219          bfd_elf_generic_reloc,    /* special_function */
220          "R_CR16_REGREL20",        /* name */
221          FALSE,                    /* partial_inplace */
222          0xfffff,                  /* src_mask */
223          0xfffff,                  /* dst_mask */
224          FALSE),                   /* pcrel_offset */
225
226   HOWTO (R_CR16_REGREL20a,         /* type */
227          0,                        /* rightshift */
228          2,                        /* size */
229          20,                       /* bitsize */
230          FALSE,                    /* pc_relative */
231          0,                        /* bitpos */
232          complain_overflow_bitfield,/* complain_on_overflow */
233          bfd_elf_generic_reloc,    /* special_function */
234          "R_CR16_REGREL20a",       /* name */
235          FALSE,                    /* partial_inplace */
236          0xfffff,                  /* src_mask */
237          0xfffff,                  /* dst_mask */
238          FALSE),                   /* pcrel_offset */
239
240   HOWTO (R_CR16_ABS20,             /* type */
241          0,                        /* rightshift */
242          2,                        /* size */
243          20,                       /* bitsize */
244          FALSE,                    /* pc_relative */
245          0,                        /* bitpos */
246          complain_overflow_bitfield,/* complain_on_overflow */
247          bfd_elf_generic_reloc,    /* special_function */
248          "R_CR16_ABS20",           /* name */
249          FALSE,                    /* partial_inplace */
250          0xfffff,                  /* src_mask */
251          0xfffff,                  /* dst_mask */
252          FALSE),                   /* pcrel_offset */
253
254   HOWTO (R_CR16_ABS24,             /* type */
255          0,                        /* rightshift */
256          2,                        /* size */
257          24,                       /* bitsize */
258          FALSE,                    /* pc_relative */
259          0,                        /* bitpos */
260          complain_overflow_bitfield,/* complain_on_overflow */
261          bfd_elf_generic_reloc,    /* special_function */
262          "R_CR16_ABS24",           /* name */
263          FALSE,                    /* partial_inplace */
264          0xffffff,                 /* src_mask */
265          0xffffff,                 /* dst_mask */
266          FALSE),                   /* pcrel_offset */
267
268   HOWTO (R_CR16_IMM4,              /* type */
269          0,                        /* rightshift */
270          0,                        /* size */
271          4,                        /* bitsize */
272          FALSE,                    /* pc_relative */
273          0,                        /* bitpos */
274          complain_overflow_bitfield,/* complain_on_overflow */
275          bfd_elf_generic_reloc,    /* special_function */
276          "R_CR16_IMM4",            /* name */
277          FALSE,                    /* partial_inplace */
278          0xf,                      /* src_mask */
279          0xf,                      /* dst_mask */
280          FALSE),                   /* pcrel_offset */
281
282   HOWTO (R_CR16_IMM8,              /* type */
283          0,                        /* rightshift */
284          0,                        /* size */
285          8,                        /* bitsize */
286          FALSE,                    /* pc_relative */
287          0,                        /* bitpos */
288          complain_overflow_bitfield,/* complain_on_overflow */
289          bfd_elf_generic_reloc,    /* special_function */
290          "R_CR16_IMM8",            /* name */
291          FALSE,                    /* partial_inplace */
292          0xff,                     /* src_mask */
293          0xff,                     /* dst_mask */
294          FALSE),                   /* pcrel_offset */
295
296   HOWTO (R_CR16_IMM16,             /* type */
297          0,                        /* rightshift */
298          1,                        /* size */
299          16,                       /* bitsize */
300          FALSE,                    /* pc_relative */
301          0,                        /* bitpos */
302          complain_overflow_bitfield,/* complain_on_overflow */
303          bfd_elf_generic_reloc,    /* special_function */
304          "R_CR16_IMM16",           /* name */
305          FALSE,                    /* partial_inplace */
306          0xffff,                   /* src_mask */
307          0xffff,                   /* dst_mask */
308          FALSE),                   /* pcrel_offset */
309
310   HOWTO (R_CR16_IMM20,             /* type */
311          0,                        /* rightshift */
312          2,                        /* size */
313          20,                       /* bitsize */
314          FALSE,                    /* pc_relative */
315          0,                        /* bitpos */
316          complain_overflow_bitfield,/* complain_on_overflow */
317          bfd_elf_generic_reloc,    /* special_function */
318          "R_CR16_IMM20",           /* name */
319          FALSE,                    /* partial_inplace */
320          0xfffff,                  /* src_mask */
321          0xfffff,                  /* dst_mask */
322          FALSE),                   /* pcrel_offset */
323
324   HOWTO (R_CR16_IMM24,             /* type */
325          0,                        /* rightshift */
326          2,                        /* size */
327          24,                       /* bitsize */
328          FALSE,                    /* pc_relative */
329          0,                        /* bitpos */
330          complain_overflow_bitfield,/* complain_on_overflow */
331          bfd_elf_generic_reloc,    /* special_function */
332          "R_CR16_IMM24",           /* name */
333          FALSE,                    /* partial_inplace */
334          0xffffff,                 /* src_mask */
335          0xffffff,                 /* dst_mask */
336          FALSE),                   /* pcrel_offset */
337
338   HOWTO (R_CR16_IMM32,             /* type */
339          0,                        /* rightshift */
340          2,                        /* size */
341          32,                       /* bitsize */
342          FALSE,                    /* pc_relative */
343          0,                        /* bitpos */
344          complain_overflow_bitfield,/* complain_on_overflow */
345          bfd_elf_generic_reloc,    /* special_function */
346          "R_CR16_IMM32",           /* name */
347          FALSE,                    /* partial_inplace */
348          0xffffffff,               /* src_mask */
349          0xffffffff,               /* dst_mask */
350          FALSE),                   /* pcrel_offset */
351
352   HOWTO (R_CR16_IMM32a,            /* type */
353          1,                        /* rightshift */
354          2,                        /* size */
355          32,                       /* bitsize */
356          FALSE,                    /* pc_relative */
357          0,                        /* bitpos */
358          complain_overflow_bitfield,/* complain_on_overflow */
359          bfd_elf_generic_reloc,    /* special_function */
360          "R_CR16_IMM32a",          /* name */
361          FALSE,                    /* partial_inplace */
362          0xffffffff,               /* src_mask */
363          0xffffffff,               /* dst_mask */
364          FALSE),                   /* pcrel_offset */
365
366   HOWTO (R_CR16_DISP4,             /* type */
367          1,                        /* rightshift */
368          0,                        /* size (0 = byte, 1 = short, 2 = long) */
369          4,                        /* bitsize */
370          TRUE,                     /* pc_relative */
371          0,                        /* bitpos */
372          complain_overflow_unsigned, /* complain_on_overflow */
373          bfd_elf_generic_reloc,    /* special_function */
374          "R_CR16_DISP4",           /* name */
375          FALSE,                    /* partial_inplace */
376          0xf,                      /* src_mask */
377          0xf,                      /* dst_mask */
378          FALSE),                   /* pcrel_offset */
379
380   HOWTO (R_CR16_DISP8,             /* type */
381          1,                        /* rightshift */
382          0,                        /* size (0 = byte, 1 = short, 2 = long) */
383          8,                        /* bitsize */
384          TRUE,                     /* pc_relative */
385          0,                        /* bitpos */
386          complain_overflow_unsigned, /* complain_on_overflow */
387          bfd_elf_generic_reloc,    /* special_function */
388          "R_CR16_DISP8",           /* name */
389          FALSE,                    /* partial_inplace */
390          0x1ff,                    /* src_mask */
391          0x1ff,                    /* dst_mask */
392          FALSE),                   /* pcrel_offset */
393
394   HOWTO (R_CR16_DISP16,            /* type */
395          0,                        /* rightshift REVIITS: To sync with WinIDEA*/
396          1,                        /* size (0 = byte, 1 = short, 2 = long) */
397          16,                       /* bitsize */
398          TRUE,                     /* pc_relative */
399          0,                        /* bitpos */
400          complain_overflow_unsigned, /* complain_on_overflow */
401          bfd_elf_generic_reloc,    /* special_function */
402          "R_CR16_DISP16",          /* name */
403          FALSE,                    /* partial_inplace */
404          0x1ffff,                  /* src_mask */
405          0x1ffff,                  /* dst_mask */
406          FALSE),                   /* pcrel_offset */
407   /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc
408      but its not done, to sync with WinIDEA and CR16 4.1 tools */
409   HOWTO (R_CR16_DISP24,            /* type */
410          0,                        /* rightshift */
411          2,                        /* size (0 = byte, 1 = short, 2 = long) */
412          24,                       /* bitsize */
413          TRUE,                     /* pc_relative */
414          0,                        /* bitpos */
415          complain_overflow_unsigned, /* complain_on_overflow */
416          bfd_elf_generic_reloc,    /* special_function */
417          "R_CR16_DISP24",          /* name */
418          FALSE,                    /* partial_inplace */
419          0x1ffffff,                /* src_mask */
420          0x1ffffff,                /* dst_mask */
421          FALSE),                   /* pcrel_offset */
422
423   HOWTO (R_CR16_DISP24a,           /* type */
424          0,                        /* rightshift */
425          2,                        /* size (0 = byte, 1 = short, 2 = long) */
426          24,                       /* bitsize */
427          TRUE,                     /* pc_relative */
428          0,                        /* bitpos */
429          complain_overflow_unsigned, /* complain_on_overflow */
430          bfd_elf_generic_reloc,    /* special_function */
431          "R_CR16_DISP24a",         /* name */
432          FALSE,                    /* partial_inplace */
433          0xffffff,                 /* src_mask */
434          0xffffff,                 /* dst_mask */
435          FALSE),                   /* pcrel_offset */
436
437   /* An 8 bit switch table entry.  This is generated for an expression
438      such as ``.byte L1 - L2''.  The offset holds the difference
439      between the reloc address and L2.  */
440   HOWTO (R_CR16_SWITCH8,           /* type */
441          0,                        /* rightshift */
442          0,                        /* size (0 = byte, 1 = short, 2 = long) */
443          8,                        /* bitsize */
444          FALSE,                    /* pc_relative */
445          0,                        /* bitpos */
446          complain_overflow_unsigned, /* complain_on_overflow */
447          bfd_elf_generic_reloc,    /* special_function */
448          "R_CR16_SWITCH8",         /* name */
449          FALSE,                    /* partial_inplace */
450          0xff,                     /* src_mask */
451          0xff,                     /* dst_mask */
452          TRUE),                    /* pcrel_offset */
453
454   /* A 16 bit switch table entry.  This is generated for an expression
455      such as ``.word L1 - L2''.  The offset holds the difference
456      between the reloc address and L2.  */
457   HOWTO (R_CR16_SWITCH16,          /* type */
458          0,                        /* rightshift */
459          1,                        /* size (0 = byte, 1 = short, 2 = long) */
460          16,                       /* bitsize */
461          FALSE,                    /* pc_relative */
462          0,                        /* bitpos */
463          complain_overflow_unsigned, /* complain_on_overflow */
464          bfd_elf_generic_reloc,    /* special_function */
465          "R_CR16_SWITCH16",        /* name */
466          FALSE,                    /* partial_inplace */
467          0xffff,                   /* src_mask */
468          0xffff,                   /* dst_mask */
469          TRUE),                    /* pcrel_offset */
470
471   /* A 32 bit switch table entry.  This is generated for an expression
472      such as ``.long L1 - L2''.  The offset holds the difference
473      between the reloc address and L2.  */
474   HOWTO (R_CR16_SWITCH32,          /* type */
475          0,                        /* rightshift */
476          2,                        /* size (0 = byte, 1 = short, 2 = long) */
477          32,                       /* bitsize */
478          FALSE,                    /* pc_relative */
479          0,                        /* bitpos */
480          complain_overflow_unsigned, /* complain_on_overflow */
481          bfd_elf_generic_reloc,    /* special_function */
482          "R_CR16_SWITCH32",        /* name */
483          FALSE,                    /* partial_inplace */
484          0xffffffff,               /* src_mask */
485          0xffffffff,               /* dst_mask */
486          TRUE)                     /* pcrel_offset */
487 };
488
489 /* Retrieve a howto ptr using a BFD reloc_code.  */
490
491 static reloc_howto_type *
492 elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
493                             bfd_reloc_code_real_type code)
494 {
495   unsigned int i;
496
497   for (i = 0; i < R_CR16_MAX; i++)
498     if (code == cr16_reloc_map[i].bfd_reloc_enum)
499       return &cr16_elf_howto_table[cr16_reloc_map[i].cr16_reloc_type];
500
501   _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code);
502   return NULL;
503 }
504
505 static reloc_howto_type *
506 elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
507                             const char *r_name)
508 {
509   unsigned int i;
510
511   for (i = 0; ARRAY_SIZE (cr16_elf_howto_table); i++)
512     if (cr16_elf_howto_table[i].name != NULL
513         && strcasecmp (cr16_elf_howto_table[i].name, r_name) == 0)
514       return cr16_elf_howto_table + i;
515
516   return NULL;
517 }
518
519 /* Retrieve a howto ptr using an internal relocation entry.  */
520
521 static void
522 elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
523                         Elf_Internal_Rela *dst)
524 {
525   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
526
527   BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
528   cache_ptr->howto = &cr16_elf_howto_table[r_type];
529 }
530
531 /* Perform a relocation as part of a final link.  */
532
533 static bfd_reloc_status_type
534 cr16_elf_final_link_relocate (reloc_howto_type *howto,
535                               bfd *input_bfd,
536                               bfd *output_bfd ATTRIBUTE_UNUSED,
537                               asection *input_section,
538                               bfd_byte *contents,
539                               bfd_vma offset,
540                               bfd_vma Rvalue,
541                               bfd_vma addend,
542                               struct bfd_link_info *info ATTRIBUTE_UNUSED,
543                               asection *sec ATTRIBUTE_UNUSED,
544                               int is_local ATTRIBUTE_UNUSED)
545 {
546   unsigned short r_type = howto->type;
547   bfd_byte *hit_data = contents + offset;
548   bfd_vma reloc_bits, check, Rvalue1;
549
550   switch (r_type)
551     {
552      case R_CR16_IMM4:
553      case R_CR16_IMM20:
554      case R_CR16_ABS20:
555        break;
556
557      case R_CR16_IMM8:
558      case R_CR16_IMM16:
559      case R_CR16_IMM32:
560      case R_CR16_IMM32a:
561      case R_CR16_REGREL4:
562      case R_CR16_REGREL4a:
563      case R_CR16_REGREL14:
564      case R_CR16_REGREL14a:
565      case R_CR16_REGREL16:
566      case R_CR16_REGREL20:
567      case R_CR16_ABS24:
568      case R_CR16_DISP16:
569      case R_CR16_DISP24:
570        /* 'hit_data' is relative to the start of the instruction, not the
571            relocation offset. Advance it to account for the exact offset.  */
572        hit_data += 2;
573        break;
574
575      case R_CR16_NONE:
576        return bfd_reloc_ok;
577        break;
578
579      case R_CR16_DISP4:
580        if (is_local)
581          Rvalue += -1;
582        break;
583
584      case R_CR16_DISP8:
585      case R_CR16_DISP24a:
586        if (is_local)
587          Rvalue -= -1;
588        break;
589
590      case R_CR16_SWITCH8:
591      case R_CR16_SWITCH16:
592      case R_CR16_SWITCH32:
593        /* We only care about the addend, where the difference between
594           expressions is kept.  */
595        Rvalue = 0;
596
597      default:
598        break;
599     }
600
601   if (howto->pc_relative)
602     {
603       /* Subtract the address of the section containing the location.  */
604       Rvalue -= (input_section->output_section->vma
605                  + input_section->output_offset);
606       /* Subtract the position of the location within the section.  */
607       Rvalue -= offset;
608     }
609
610   /* Add in supplied addend.  */
611   Rvalue += addend;
612
613   /* Complain if the bitfield overflows, whether it is considered
614      as signed or unsigned.  */
615   check = Rvalue >> howto->rightshift;
616
617   /* Assumes two's complement.  This expression avoids
618      overflow if howto->bitsize is the number of bits in
619      bfd_vma.  */
620   reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
621
622   if (((bfd_vma) check & ~reloc_bits) != 0
623       && (((bfd_vma) check & ~reloc_bits)
624       != (-(bfd_vma) 1 & ~reloc_bits)))
625     {
626       /* The above right shift is incorrect for a signed
627          value.  See if turning on the upper bits fixes the
628          overflow.  */
629       if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
630         {
631           check |= ((bfd_vma) - 1
632                     & ~((bfd_vma) - 1
633                         >> howto->rightshift));
634
635           if (((bfd_vma) check & ~reloc_bits)
636               != (-(bfd_vma) 1 & ~reloc_bits))
637              return bfd_reloc_overflow;
638         }
639       else
640         return bfd_reloc_overflow;
641     }
642
643   /* Drop unwanted bits from the value we are relocating to.  */
644   Rvalue >>= (bfd_vma) howto->rightshift;
645
646   /* Apply dst_mask to select only relocatable part of the insn.  */
647   Rvalue &= howto->dst_mask;
648
649   switch (howto->size)
650     {
651       case 0:
652         if (r_type == R_CR16_DISP8)
653           {
654              Rvalue1 = bfd_get_16 (input_bfd, hit_data);
655              Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00)
656                        | (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
657              bfd_put_16 (input_bfd, Rvalue, hit_data);
658           }
659         else if (r_type == R_CR16_IMM4)
660           {
661              Rvalue1 = bfd_get_16 (input_bfd, hit_data);
662              Rvalue = (((Rvalue1 & 0xff) << 8) | ((Rvalue << 4) & 0xf0)
663                        | ((Rvalue1 & 0x0f00) >> 8));
664              bfd_put_16 (input_bfd, Rvalue, hit_data);
665           }
666         else if (r_type == R_CR16_DISP4)
667           {
668              Rvalue1 = bfd_get_16 (input_bfd, hit_data);
669              Rvalue = (Rvalue1 | ((Rvalue & 0xf) << 4));
670              bfd_put_16 (input_bfd, Rvalue, hit_data);
671           }
672         else 
673           {
674              bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
675           }
676         break;
677
678       case 1:
679         if (r_type == R_CR16_DISP16)
680           {
681             Rvalue |= (bfd_get_16 (input_bfd, hit_data));
682             Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
683           }
684
685           bfd_put_16 (input_bfd, Rvalue, hit_data);
686         break;
687
688       case 2:
689         if ((r_type == R_CR16_ABS20) || (r_type == R_CR16_IMM20))
690           {
691              bfd_put_16 (input_bfd, (bfd_get_16 (input_bfd, hit_data))
692                          | ((Rvalue >> 16) & 0xf), hit_data);
693              bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
694           }
695         else   
696           {
697             if (r_type == R_CR16_ABS24)
698               {
699                 Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf) << 8)
700                           | (bfd_get_16 (input_bfd, hit_data))) 
701                           | ((Rvalue & 0xffff) << 16));
702               }
703             if (r_type == R_CR16_DISP24)
704               {
705                 Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf) << 8)
706                           | (bfd_get_16 (input_bfd, hit_data))) 
707                           | (((Rvalue & 0xfffe)
708                               | ((Rvalue >> 24) & 0x1)) << 16));
709               }
710             else if ((r_type == R_CR16_IMM32) ||(r_type == R_CR16_IMM32a))
711               {
712                 Rvalue = (((Rvalue >> 16)& 0xffff)
713                           | (bfd_get_16 (input_bfd, hit_data))) 
714                           | ((Rvalue & 0xffff) << 16);
715               }
716             else if (r_type == R_CR16_DISP24a)
717               {
718                 Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
719                 Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
720                           | (bfd_get_32 (input_bfd, hit_data));
721               }
722
723             bfd_put_32 (input_bfd, Rvalue, hit_data);
724           }
725         break;
726
727       default:
728         return bfd_reloc_notsupported;
729     }
730
731   return bfd_reloc_ok;
732 }
733
734 /* Delete some bytes from a section while relaxing.  */
735
736 static bfd_boolean
737 elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
738                                asection *sec, bfd_vma addr, int count)
739 {
740   Elf_Internal_Shdr *symtab_hdr;
741   unsigned int sec_shndx;
742   bfd_byte *contents;
743   Elf_Internal_Rela *irel, *irelend;
744   Elf_Internal_Rela *irelalign;
745   bfd_vma toaddr;
746   Elf_Internal_Sym *isym;
747   Elf_Internal_Sym *isymend;
748   struct elf_link_hash_entry **sym_hashes;
749   struct elf_link_hash_entry **end_hashes;
750   struct elf_link_hash_entry **start_hashes;
751   unsigned int symcount;
752
753   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
754
755   contents = elf_section_data (sec)->this_hdr.contents;
756
757   /* The deletion must stop at the next ALIGN reloc for an aligment
758      power larger than the number of bytes we are deleting.  */
759   irelalign = NULL;
760   toaddr = sec->size;
761
762   irel = elf_section_data (sec)->relocs;
763   irelend = irel + sec->reloc_count;
764
765   /* Actually delete the bytes.  */
766   memmove (contents + addr, contents + addr + count,
767            (size_t) (toaddr - addr - count));
768   sec->size -= count;
769
770   /* Adjust all the relocs.  */
771   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
772     /* Get the new reloc address.  */
773     if ((irel->r_offset > addr && irel->r_offset < toaddr))
774         irel->r_offset -= count;
775
776   /* Adjust the local symbols defined in this section.  */
777   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
778   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
779   for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
780     {
781       if (isym->st_shndx == sec_shndx
782           && isym->st_value > addr
783           && isym->st_value < toaddr)
784         {
785           /* Adjust the addend of SWITCH relocations in this section,
786              which reference this local symbol.  */
787           for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
788             {
789               unsigned long r_symndx;
790               Elf_Internal_Sym *rsym;
791               bfd_vma addsym, subsym;
792
793               /* Skip if not a SWITCH relocation.  */
794               if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH8
795                   && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
796                   && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
797                 continue;
798
799               r_symndx = ELF32_R_SYM (irel->r_info);
800               rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
801
802               /* Skip if not the local adjusted symbol.  */
803               if (rsym != isym)
804                 continue;
805
806               addsym = isym->st_value;
807               subsym = addsym - irel->r_addend;
808
809               /* Fix the addend only when -->> (addsym > addr >= subsym).  */
810               if (subsym <= addr)
811                 irel->r_addend -= count;
812               else
813                 continue;
814             }
815
816           isym->st_value -= count;
817         }
818     }
819
820   /* Now adjust the global symbols defined in this section.  */
821   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
822                - symtab_hdr->sh_info);
823   sym_hashes = start_hashes = elf_sym_hashes (abfd);
824   end_hashes = sym_hashes + symcount;
825
826   for (; sym_hashes < end_hashes; sym_hashes++)
827     {
828       struct elf_link_hash_entry *sym_hash = *sym_hashes;
829
830       /* The '--wrap SYMBOL' option is causing a pain when the object file,
831          containing the definition of __wrap_SYMBOL, includes a direct
832          call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
833          the same symbol (which is __wrap_SYMBOL), but still exist as two
834          different symbols in 'sym_hashes', we don't want to adjust
835          the global symbol __wrap_SYMBOL twice.
836          This check is only relevant when symbols are being wrapped.  */
837       if (link_info->wrap_hash != NULL)
838         {
839           struct elf_link_hash_entry **cur_sym_hashes;
840
841           /* Loop only over the symbols whom been already checked.  */
842           for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
843                cur_sym_hashes++)
844             /* If the current symbol is identical to 'sym_hash', that means
845                the symbol was already adjusted (or at least checked).  */
846             if (*cur_sym_hashes == sym_hash)
847               break;
848
849           /* Don't adjust the symbol again.  */
850           if (cur_sym_hashes < sym_hashes)
851             continue;
852         }
853
854       if ((sym_hash->root.type == bfd_link_hash_defined
855           || sym_hash->root.type == bfd_link_hash_defweak)
856           && sym_hash->root.u.def.section == sec
857           && sym_hash->root.u.def.value > addr
858           && sym_hash->root.u.def.value < toaddr)
859         sym_hash->root.u.def.value -= count;
860     }
861
862   return TRUE;
863 }
864
865 /* Relocate a CR16 ELF section.  */
866
867 static bfd_boolean
868 elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
869                              bfd *input_bfd, asection *input_section,
870                              bfd_byte *contents, Elf_Internal_Rela *relocs,
871                              Elf_Internal_Sym *local_syms,
872                              asection **local_sections)
873 {
874   Elf_Internal_Shdr *symtab_hdr;
875   struct elf_link_hash_entry **sym_hashes;
876   Elf_Internal_Rela *rel, *relend;
877
878   if (info->relocatable)
879     return TRUE;
880
881   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
882   sym_hashes = elf_sym_hashes (input_bfd);
883
884   rel = relocs;
885   relend = relocs + input_section->reloc_count;
886   for (; rel < relend; rel++)
887     {
888       int r_type;
889       reloc_howto_type *howto;
890       unsigned long r_symndx;
891       Elf_Internal_Sym *sym;
892       asection *sec;
893       struct elf_link_hash_entry *h;
894       bfd_vma relocation;
895       bfd_reloc_status_type r;
896
897       r_symndx = ELF32_R_SYM (rel->r_info);
898       r_type = ELF32_R_TYPE (rel->r_info);
899       howto = cr16_elf_howto_table + (r_type);
900
901       h = NULL;
902       sym = NULL;
903       sec = NULL;
904       if (r_symndx < symtab_hdr->sh_info)
905         {
906           sym = local_syms + r_symndx;
907           sec = local_sections[r_symndx];
908           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
909         }
910       else
911         {
912           bfd_boolean unresolved_reloc, warned;
913
914           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
915                                    r_symndx, symtab_hdr, sym_hashes,
916                                    h, sec, relocation,
917                                    unresolved_reloc, warned);
918         }
919
920       r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
921                                         input_section,
922                                         contents, rel->r_offset,
923                                         relocation, rel->r_addend,
924                                         info, sec, h == NULL);
925
926       if (r != bfd_reloc_ok)
927         {
928           const char *name;
929           const char *msg = NULL;
930
931           if (h != NULL)
932             name = h->root.root.string;
933           else
934             {
935               name = (bfd_elf_string_from_elf_section
936                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
937               if (name == NULL || *name == '\0')
938                 name = bfd_section_name (input_bfd, sec);
939             }
940
941           switch (r)
942             {
943              case bfd_reloc_overflow:
944                if (!((*info->callbacks->reloc_overflow)
945                      (info, (h ? &h->root : NULL), name, howto->name,
946                       (bfd_vma) 0, input_bfd, input_section,
947                       rel->r_offset)))
948                  return FALSE;
949                break;
950
951              case bfd_reloc_undefined:
952                if (!((*info->callbacks->undefined_symbol)
953                      (info, name, input_bfd, input_section,
954                       rel->r_offset, TRUE)))
955                  return FALSE;
956                break;
957
958              case bfd_reloc_outofrange:
959                msg = _("internal error: out of range error");
960                goto common_error;
961
962              case bfd_reloc_notsupported:
963                msg = _("internal error: unsupported relocation error");
964                goto common_error;
965
966              case bfd_reloc_dangerous:
967                msg = _("internal error: dangerous error");
968                goto common_error;
969
970              default:
971                msg = _("internal error: unknown error");
972                /* Fall through.  */
973
974              common_error:
975                if (!((*info->callbacks->warning)
976                      (info, msg, name, input_bfd, input_section,
977                       rel->r_offset)))
978                  return FALSE;
979                break;
980             }
981         }
982     }
983
984   return TRUE;
985 }
986
987 /* This is a version of bfd_generic_get_relocated_section_contents
988    which uses elf32_cr16_relocate_section.  */
989
990 static bfd_byte *
991 elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
992                                            struct bfd_link_info *link_info,
993                                            struct bfd_link_order *link_order,
994                                            bfd_byte *data,
995                                            bfd_boolean relocatable,
996                                            asymbol **symbols)
997 {
998   Elf_Internal_Shdr *symtab_hdr;
999   asection *input_section = link_order->u.indirect.section;
1000   bfd *input_bfd = input_section->owner;
1001   asection **sections = NULL;
1002   Elf_Internal_Rela *internal_relocs = NULL;
1003   Elf_Internal_Sym *isymbuf = NULL;
1004
1005   /* We only need to handle the case of relaxing, or of having a
1006      particular set of section contents, specially.  */
1007   if (relocatable
1008       || elf_section_data (input_section)->this_hdr.contents == NULL)
1009     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1010                                                        link_order, data,
1011                                                        relocatable,
1012                                                        symbols);
1013
1014   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1015
1016   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
1017           (size_t) input_section->size);
1018
1019   if ((input_section->flags & SEC_RELOC) != 0
1020       && input_section->reloc_count > 0)
1021     {
1022       Elf_Internal_Sym *isym;
1023       Elf_Internal_Sym *isymend;
1024       asection **secpp;
1025       bfd_size_type amt;
1026
1027       internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
1028                                                    NULL, NULL, FALSE);
1029       if (internal_relocs == NULL)
1030         goto error_return;
1031
1032       if (symtab_hdr->sh_info != 0)
1033         {
1034           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1035           if (isymbuf == NULL)
1036             isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
1037                                             symtab_hdr->sh_info, 0,
1038                                             NULL, NULL, NULL);
1039           if (isymbuf == NULL)
1040             goto error_return;
1041         }
1042
1043       amt = symtab_hdr->sh_info;
1044       amt *= sizeof (asection *);
1045       sections = bfd_malloc (amt);
1046       if (sections == NULL && amt != 0)
1047         goto error_return;
1048
1049       isymend = isymbuf + symtab_hdr->sh_info;
1050       for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
1051         {
1052           asection *isec;
1053
1054           if (isym->st_shndx == SHN_UNDEF)
1055             isec = bfd_und_section_ptr;
1056           else if (isym->st_shndx == SHN_ABS)
1057             isec = bfd_abs_section_ptr;
1058           else if (isym->st_shndx == SHN_COMMON)
1059             isec = bfd_com_section_ptr;
1060           else
1061             isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
1062
1063           *secpp = isec;
1064         }
1065
1066       if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd,
1067                                      input_section, data, internal_relocs,
1068                                      isymbuf, sections))
1069         goto error_return;
1070
1071       if (sections != NULL)
1072         free (sections);
1073       if (isymbuf != NULL
1074           && symtab_hdr->contents != (unsigned char *) isymbuf)
1075         free (isymbuf);
1076       if (elf_section_data (input_section)->relocs != internal_relocs)
1077         free (internal_relocs);
1078     }
1079
1080   return data;
1081
1082  error_return:
1083   if (sections != NULL)
1084     free (sections);
1085   if (isymbuf != NULL
1086       && symtab_hdr->contents != (unsigned char *) isymbuf)
1087     free (isymbuf);
1088   if (internal_relocs != NULL
1089       && elf_section_data (input_section)->relocs != internal_relocs)
1090     free (internal_relocs);
1091   return NULL;
1092 }
1093
1094 /* This function handles relaxing for the CR16.
1095
1096    There's quite a few relaxing opportunites available on the CR16:
1097
1098         * bcond:24 -> bcond:16                                2 bytes
1099         * bcond:16 -> bcond:8                                 2 bytes
1100         * arithmetic imm32 -> arithmetic imm20/imm16          2 bytes
1101         * arithmetic imm20/imm16 -> arithmetic imm4           2 bytes
1102
1103    Symbol- and reloc-reading infrastructure copied from elf-m10200.c.  */
1104
1105 static bfd_boolean
1106 elf32_cr16_relax_section (bfd *abfd, asection *sec,
1107                          struct bfd_link_info *link_info, bfd_boolean *again)
1108 {
1109   Elf_Internal_Shdr *symtab_hdr;
1110   Elf_Internal_Rela *internal_relocs;
1111   Elf_Internal_Rela *irel, *irelend;
1112   bfd_byte *contents = NULL;
1113   Elf_Internal_Sym *isymbuf = NULL;
1114
1115   /* Assume nothing changes.  */
1116   *again = FALSE;
1117
1118   /* We don't have to do anything for a relocatable link, if
1119      this section does not have relocs, or if this is not a
1120      code section.  */
1121   if (link_info->relocatable
1122       || (sec->flags & SEC_RELOC) == 0
1123       || sec->reloc_count == 0
1124       || (sec->flags & SEC_CODE) == 0)
1125     return TRUE;
1126
1127   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1128
1129   /* Get a copy of the native relocations.  */
1130   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1131                                                link_info->keep_memory);
1132   if (internal_relocs == NULL)
1133     goto error_return;
1134
1135   /* Walk through them looking for relaxing opportunities.  */
1136   irelend = internal_relocs + sec->reloc_count;
1137   for (irel = internal_relocs; irel < irelend; irel++)
1138     {
1139       bfd_vma symval;
1140
1141       /* If this isn't something that can be relaxed, then ignore
1142          this reloc.  */
1143       if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
1144           && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24
1145           && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM32
1146           && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM20
1147           && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM16)
1148         continue;
1149
1150       /* Get the section contents if we haven't done so already.  */
1151       if (contents == NULL)
1152         {
1153           /* Get cached copy if it exists.  */
1154           if (elf_section_data (sec)->this_hdr.contents != NULL)
1155             contents = elf_section_data (sec)->this_hdr.contents;
1156           /* Go get them off disk.  */
1157           else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1158             goto error_return;
1159         }
1160
1161       /* Read this BFD's local symbols if we haven't done so already.  */
1162       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1163         {
1164           isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1165           if (isymbuf == NULL)
1166             isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1167                                             symtab_hdr->sh_info, 0,
1168                                             NULL, NULL, NULL);
1169           if (isymbuf == NULL)
1170             goto error_return;
1171         }
1172
1173       /* Get the value of the symbol referred to by the reloc.  */
1174       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1175         {
1176           /* A local symbol.  */
1177           Elf_Internal_Sym *isym;
1178           asection *sym_sec;
1179
1180           isym = isymbuf + ELF32_R_SYM (irel->r_info);
1181           if (isym->st_shndx == SHN_UNDEF)
1182             sym_sec = bfd_und_section_ptr;
1183           else if (isym->st_shndx == SHN_ABS)
1184             sym_sec = bfd_abs_section_ptr;
1185           else if (isym->st_shndx == SHN_COMMON)
1186             sym_sec = bfd_com_section_ptr;
1187           else
1188             sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1189           symval = (isym->st_value
1190                     + sym_sec->output_section->vma
1191                     + sym_sec->output_offset);
1192         }
1193       else
1194         {
1195           unsigned long indx;
1196           struct elf_link_hash_entry *h;
1197
1198           /* An external symbol.  */
1199           indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1200           h = elf_sym_hashes (abfd)[indx];
1201           BFD_ASSERT (h != NULL);
1202
1203           if (h->root.type != bfd_link_hash_defined
1204               && h->root.type != bfd_link_hash_defweak)
1205             /* This appears to be a reference to an undefined
1206                symbol.  Just ignore it--it will be caught by the
1207                regular reloc processing.  */
1208             continue;
1209
1210           symval = (h->root.u.def.value
1211                     + h->root.u.def.section->output_section->vma
1212                     + h->root.u.def.section->output_offset);
1213         }
1214
1215       /* For simplicity of coding, we are going to modify the section
1216          contents, the section relocs, and the BFD symbol table.  We
1217          must tell the rest of the code not to free up this
1218          information.  It would be possible to instead create a table
1219          of changes which have to be made, as is done in coff-mips.c;
1220          that would be more work, but would require less memory when
1221          the linker is run.  */
1222
1223       /* Try to turn a 24  branch/call into a 16bit relative
1224          branch/call.  */
1225       if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
1226         {
1227           bfd_vma value = symval;
1228
1229           /* Deal with pc-relative gunk.  */
1230           value -= (sec->output_section->vma + sec->output_offset);
1231           value -= irel->r_offset;
1232           value += irel->r_addend;
1233
1234           /* See if the value will fit in 16 bits, note the high value is
1235              0xfffe + 2 as the target will be two bytes closer if we are
1236              able to relax.  */
1237           if ((long) value < 0x10000 && (long) value > -0x10002)
1238             {
1239               unsigned int code;
1240
1241               /* Get the opcode.  */
1242               code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset);
1243
1244               /* Verify it's a 'bcond' and fix the opcode.  */
1245               if ((code  & 0xffff) == 0x0010)
1246                 {
1247                   bfd_put_16 (abfd, 0x1800 | ((0xf & (code >> 20)) << 4), contents + irel->r_offset);
1248                   bfd_put_16 (abfd, value, contents + irel->r_offset + 2);
1249                 }
1250               else
1251                 continue;
1252
1253               /* Note that we've changed the relocs, section contents, etc.  */
1254               elf_section_data (sec)->relocs = internal_relocs;
1255               elf_section_data (sec)->this_hdr.contents = contents;
1256               symtab_hdr->contents = (unsigned char *) isymbuf;
1257
1258               /* Fix the relocation's type.  */
1259               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1260                                            R_CR16_DISP16);
1261
1262               /* Delete two bytes of data.  */
1263               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1264                                                    irel->r_offset + 2, 2))
1265                 goto error_return;
1266
1267               /* That will change things, so, we should relax again.
1268                  Note that this is not required, and it may be slow.  */
1269               *again = TRUE;
1270             }
1271         }
1272
1273       /* Try to turn a 16-bit pc-relative branch into an
1274          8-bit pc-relative branch.  */
1275       if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
1276         {
1277           bfd_vma value = symval;
1278
1279           /* Deal with pc-relative gunk.  */
1280           value -= (sec->output_section->vma + sec->output_offset);
1281           value -= irel->r_offset;
1282           value += irel->r_addend;
1283
1284           /* See if the value will fit in 8 bits, note the high value is
1285              0xfc + 2 as the target will be two bytes closer if we are
1286              able to relax.  */
1287           if ((long) value < 0xfe && (long) value > -0x100)
1288             {
1289               unsigned short code;
1290
1291               /* Get the opcode.  */
1292               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1293
1294               /* Verify it's a 'bcond' opcode.  */
1295               if ((code & 0xff00) == 0x1800)
1296                 {
1297                  bfd_put_8 (abfd, 0x1 | ((0xf & (code >> 4)) << 4), contents + irel->r_offset);
1298                  bfd_put_8 (abfd, value, contents + irel->r_offset + 2);
1299                 }
1300               else
1301                 continue;
1302
1303               /* Note that we've changed the relocs, section contents, etc.  */
1304               elf_section_data (sec)->relocs = internal_relocs;
1305               elf_section_data (sec)->this_hdr.contents = contents;
1306               symtab_hdr->contents = (unsigned char *) isymbuf;
1307
1308               /* Fix the relocation's type.  */
1309               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1310                                            R_CR16_DISP8);
1311
1312               /* Delete two bytes of data.  */
1313               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1314                                                    irel->r_offset + 2, 2))
1315                 goto error_return;
1316
1317               /* That will change things, so, we should relax again.
1318                  Note that this is not required, and it may be slow.  */
1319               *again = TRUE;
1320             }
1321         }
1322
1323       /* Try to turn a 32bit immediate address into
1324          a 20/16bit immediate address.  */
1325       if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
1326         {
1327           bfd_vma value = symval;
1328           unsigned short is_add_mov = 0;
1329
1330           /* See if the value will fit in 20 bits.  */
1331           if ((long) value < 0xfffff && (long) value > 0)
1332             {
1333               unsigned short code;
1334
1335               /* Get the opcode.  */
1336               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1337
1338               /* Verify it's a arithmetic ADDD or MOVD instruction.
1339                  For ADDD and MOVD only, convert to IMM32 -> IMM20.  */
1340               if (((code & 0xfff0) != 0x0070) || ((code & 0xfff0) != 0x0020))
1341                 is_add_mov = 1;
1342
1343               if (is_add_mov)
1344                 {
1345                   /* Note that we've changed the relocs, section contents, 
1346                      etc.  */
1347                   elf_section_data (sec)->relocs = internal_relocs;
1348                   elf_section_data (sec)->this_hdr.contents = contents;
1349                   symtab_hdr->contents = (unsigned char *) isymbuf;
1350
1351                   /* Fix the opcode.  */
1352                   if ((code & 0xfff0) == 0x0070) /* For movd.  */
1353                     bfd_put_8 (abfd, 0x05, contents + irel->r_offset + 1);
1354                   else                          /* code == 0x0020 for addd.  */
1355                     bfd_put_8 (abfd, 0x04, contents + irel->r_offset + 1);
1356  
1357                   bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
1358
1359
1360                   /* Fix the relocation's type.  */
1361                   irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1362                                                R_CR16_IMM20);
1363                   /* Delete two bytes of data.  */
1364                   if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1365                                                       irel->r_offset + 2, 2))
1366                     goto error_return;
1367
1368                   /* That will change things, so, we should relax again.
1369                      Note that this is not required, and it may be slow.  */
1370                   *again = TRUE;
1371                 }
1372             }
1373          /* See if the value will fit in 16 bits.  */
1374           if ((!is_add_mov) && ((long) value < 0x7fff && (long) value > 0))
1375             {
1376               unsigned short code;
1377
1378               /* Get the opcode.  */
1379               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1380
1381               /* Note that we've changed the relocs, section contents, etc.  */
1382               elf_section_data (sec)->relocs = internal_relocs;
1383               elf_section_data (sec)->this_hdr.contents = contents;
1384               symtab_hdr->contents = (unsigned char *) isymbuf;
1385
1386               /* Fix the opcode.  */
1387               if ((code & 0xf0) == 0x70)          /* For movd.  */
1388                 bfd_put_8 (abfd, 0x54, contents + irel->r_offset + 1);
1389               else if ((code & 0xf0) == 0x20)     /* For addd.  */
1390                 bfd_put_8 (abfd, 0x60, contents + irel->r_offset + 1);
1391               else if ((code & 0xf0) == 0x90)     /* For cmpd.  */
1392                 bfd_put_8 (abfd, 0x56, contents + irel->r_offset + 1);
1393               else
1394                 continue;
1395
1396               bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
1397
1398               /* Fix the relocation's type.  */
1399               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1400                                            R_CR16_IMM16);
1401
1402               /* Delete two bytes of data.  */
1403               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1404                                                   irel->r_offset + 2, 2))
1405                  goto error_return;
1406
1407               /* That will change things, so, we should relax again.
1408                  Note that this is not required, and it may be slow.  */
1409                  *again = TRUE;
1410             }
1411         }
1412
1413       /* Try to turn a 20/16bit immediate address into
1414          a 4bit immediate address.  */
1415       if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
1416           || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
1417         {
1418           bfd_vma value = symval;
1419
1420           /* See if the value will fit in 4 bits.  */
1421           if ((long) value < 0xf && (long) value > 0)
1422             {
1423               unsigned short code;
1424
1425               /* Get the opcode.  */
1426               code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1427
1428               /* Note that we've changed the relocs, section contents, etc.  */
1429               elf_section_data (sec)->relocs = internal_relocs;
1430               elf_section_data (sec)->this_hdr.contents = contents;
1431               symtab_hdr->contents = (unsigned char *) isymbuf;
1432
1433               /* Fix the opcode.  */
1434               if (((code & 0x0f00) == 0x0400) || ((code & 0x0f00) == 0x0500))
1435                 {
1436                   if ((code & 0x0f00) == 0x0400)      /* For movd imm20.  */
1437                     bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
1438                   else                                /* For addd imm20.  */
1439                     bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
1440                   bfd_put_8 (abfd, (code & 0xf0) >> 4, contents + irel->r_offset + 1);
1441                 }
1442               else
1443                 {
1444                   if ((code & 0xfff0) == 0x56b0)       /*  For cmpd imm16.  */
1445                     bfd_put_8 (abfd, 0x56, contents + irel->r_offset);
1446                   else if ((code & 0xfff0) == 0x54b0)  /*  For movd imm16.  */
1447                     bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
1448                   else if ((code & 0xfff0) == 0x58b0)  /*  For movb imm16.  */
1449                     bfd_put_8 (abfd, 0x58, contents + irel->r_offset);
1450                   else if ((code & 0xfff0) == 0x5Ab0)  /*  For movw imm16.  */
1451                     bfd_put_8 (abfd, 0x5A, contents + irel->r_offset);
1452                   else if ((code & 0xfff0) == 0x60b0)  /*  For addd imm16.  */
1453                     bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
1454                   else if ((code & 0xfff0) == 0x30b0)  /*  For addb imm16.  */
1455                     bfd_put_8 (abfd, 0x30, contents + irel->r_offset);
1456                   else if ((code & 0xfff0) == 0x2Cb0)  /*  For addub imm16.  */
1457                     bfd_put_8 (abfd, 0x2C, contents + irel->r_offset);
1458                   else if ((code & 0xfff0) == 0x32b0)  /*  For adduw imm16.  */
1459                     bfd_put_8 (abfd, 0x32, contents + irel->r_offset);
1460                   else if ((code & 0xfff0) == 0x38b0)  /*  For subb imm16.  */
1461                     bfd_put_8 (abfd, 0x38, contents + irel->r_offset);
1462                   else if ((code & 0xfff0) == 0x3Ab0)  /*  For subw imm16.  */
1463                     bfd_put_8 (abfd, 0x3A, contents + irel->r_offset);
1464                   else if ((code & 0xfff0) == 0x50b0)  /*  For cmpb imm16.  */
1465                     bfd_put_8 (abfd, 0x50, contents + irel->r_offset);
1466                   else if ((code & 0xfff0) == 0x52b0)  /*  For cmpw imm16.  */
1467                     bfd_put_8 (abfd, 0x52, contents + irel->r_offset);
1468                   else
1469                     continue;
1470               
1471                   bfd_put_8 (abfd, (code & 0xf), contents + irel->r_offset + 1);
1472                 }
1473
1474               /* Fix the relocation's type.  */
1475               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1476                                            R_CR16_IMM4);
1477
1478               /* Delete two bytes of data.  */
1479               if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1480                                                   irel->r_offset + 2, 2))
1481                 goto error_return;
1482
1483               /* That will change things, so, we should relax again.
1484                  Note that this is not required, and it may be slow.  */
1485               *again = TRUE;
1486             }
1487         }
1488     }
1489
1490   if (isymbuf != NULL
1491       && symtab_hdr->contents != (unsigned char *) isymbuf)
1492     {
1493       if (! link_info->keep_memory)
1494         free (isymbuf);
1495       else
1496         /* Cache the symbols for elf_link_input_bfd.  */
1497         symtab_hdr->contents = (unsigned char *) isymbuf;
1498     }
1499
1500   if (contents != NULL
1501       && elf_section_data (sec)->this_hdr.contents != contents)
1502     {
1503       if (! link_info->keep_memory)
1504         free (contents);
1505       else
1506         /* Cache the section contents for elf_link_input_bfd.  */
1507         elf_section_data (sec)->this_hdr.contents = contents;
1508     }
1509
1510   if (internal_relocs != NULL
1511       && elf_section_data (sec)->relocs != internal_relocs)
1512     free (internal_relocs);
1513
1514   return TRUE;
1515
1516  error_return:
1517   if (isymbuf != NULL
1518       && symtab_hdr->contents != (unsigned char *) isymbuf)
1519     free (isymbuf);
1520   if (contents != NULL
1521       && elf_section_data (sec)->this_hdr.contents != contents)
1522     free (contents);
1523   if (internal_relocs != NULL
1524       && elf_section_data (sec)->relocs != internal_relocs)
1525     free (internal_relocs);
1526
1527   return FALSE;
1528 }
1529
1530 static asection *
1531 elf32_cr16_gc_mark_hook (asection *sec,
1532                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
1533                          Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1534                          struct elf_link_hash_entry *h,
1535                          Elf_Internal_Sym *sym)
1536 {
1537   if (h == NULL)
1538     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1539
1540   switch (h->root.type)
1541     {
1542       case bfd_link_hash_defined:
1543       case bfd_link_hash_defweak:
1544         return h->root.u.def.section;
1545
1546       case bfd_link_hash_common:
1547         return h->root.u.c.p->section;
1548
1549       default:
1550         return NULL;
1551     }
1552 }
1553
1554 /* Update the got entry reference counts for the section being removed.  */
1555
1556 static bfd_boolean
1557 elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
1558                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
1559                           asection *sec ATTRIBUTE_UNUSED,
1560                           const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
1561 {
1562   /* We don't support garbage collection of GOT and PLT relocs yet.  */
1563   return TRUE;
1564 }
1565
1566 /* Definitions for setting CR16 target vector.  */
1567 #define TARGET_LITTLE_SYM                 bfd_elf32_cr16_vec
1568 #define TARGET_LITTLE_NAME                "elf32-cr16"
1569 #define ELF_ARCH                          bfd_arch_cr16
1570 #define ELF_MACHINE_CODE                  EM_CR16
1571 #define ELF_MAXPAGESIZE                   0x1
1572 #define elf_symbol_leading_char           '_'
1573
1574 #define bfd_elf32_bfd_reloc_type_lookup   elf_cr16_reloc_type_lookup
1575 #define bfd_elf32_bfd_reloc_name_lookup   elf_cr16_reloc_name_lookup
1576 #define elf_info_to_howto                 elf_cr16_info_to_howto
1577 #define elf_info_to_howto_rel             0
1578 #define elf_backend_relocate_section      elf32_cr16_relocate_section
1579 #define bfd_elf32_bfd_relax_section       elf32_cr16_relax_section
1580 #define bfd_elf32_bfd_get_relocated_section_contents \
1581                                 elf32_cr16_get_relocated_section_contents
1582 #define elf_backend_gc_mark_hook          elf32_cr16_gc_mark_hook
1583 #define elf_backend_gc_sweep_hook         elf32_cr16_gc_sweep_hook
1584 #define elf_backend_can_gc_sections       1
1585 #define elf_backend_rela_normal           1
1586
1587 #include "elf32-target.h"