Upload Tizen:Base source
[external/binutils.git] / bfd / elf32-cr16c.c
1 /* BFD back-end for National Semiconductor's CR16C ELF
2    Copyright 2004, 2005, 2006, 2007, 2009, 2010
3    Free Software Foundation, Inc.
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
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "bfdlink.h"
26 #include "elf/cr16c.h"
27 #include "elf-bfd.h"
28
29
30 #define USE_REL 1       /* CR16C uses REL relocations instead of RELA.  */
31
32 /* The following definition is based on EMPTY_HOWTO macro, 
33    but also initiates the "name" field in HOWTO struct.  */
34 #define ONLY_NAME_HOWTO(C) \
35   HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
36           STRINGX(C), FALSE, 0, 0, FALSE)
37
38 /* reloc_map_index array maps CRASM relocation type into a BFD
39    relocation enum. The array's indices are synchronized with 
40    RINDEX_16C_* indices, created in include/elf/cr16c.h.
41    The array is used in:
42    1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
43    2. asreloc.c : find_reloc_type(). */
44
45 RELOC_MAP reloc_map_index[RINDEX_16C_MAX] =
46 {
47   {R_16C_NUM08,     BFD_RELOC_16C_NUM08},
48   {R_16C_NUM08_C,   BFD_RELOC_16C_NUM08_C},
49   {R_16C_NUM16,     BFD_RELOC_16C_NUM16},
50   {R_16C_NUM16_C,   BFD_RELOC_16C_NUM16_C},
51   {R_16C_NUM32,     BFD_RELOC_16C_NUM32},
52   {R_16C_NUM32_C,   BFD_RELOC_16C_NUM32_C},
53   {R_16C_DISP04,    BFD_RELOC_16C_DISP04},
54   {R_16C_DISP04_C,  BFD_RELOC_16C_DISP04_C},
55   {R_16C_DISP08,    BFD_RELOC_16C_DISP08},
56   {R_16C_DISP08_C,  BFD_RELOC_16C_DISP08_C},
57   {R_16C_DISP16,    BFD_RELOC_16C_DISP16},
58   {R_16C_DISP16_C,  BFD_RELOC_16C_DISP16_C},
59   {R_16C_DISP24,    BFD_RELOC_16C_DISP24},
60   {R_16C_DISP24_C,  BFD_RELOC_16C_DISP24_C},
61   {R_16C_DISP24a,   BFD_RELOC_16C_DISP24a},
62   {R_16C_DISP24a_C, BFD_RELOC_16C_DISP24a_C},
63   {R_16C_REG04,     BFD_RELOC_16C_REG04},
64   {R_16C_REG04_C,   BFD_RELOC_16C_REG04_C},
65   {R_16C_REG04a,    BFD_RELOC_16C_REG04a},
66   {R_16C_REG04a_C,  BFD_RELOC_16C_REG04a_C},
67   {R_16C_REG14,     BFD_RELOC_16C_REG14},
68   {R_16C_REG14_C,   BFD_RELOC_16C_REG14_C},
69   {R_16C_REG16,     BFD_RELOC_16C_REG16},
70   {R_16C_REG16_C,   BFD_RELOC_16C_REG16_C},
71   {R_16C_REG20,     BFD_RELOC_16C_REG20},
72   {R_16C_REG20_C,   BFD_RELOC_16C_REG20_C},
73   {R_16C_ABS20,     BFD_RELOC_16C_ABS20},
74   {R_16C_ABS20_C,   BFD_RELOC_16C_ABS20_C},
75   {R_16C_ABS24,     BFD_RELOC_16C_ABS24},
76   {R_16C_ABS24_C,   BFD_RELOC_16C_ABS24_C},
77   {R_16C_IMM04,     BFD_RELOC_16C_IMM04},
78   {R_16C_IMM04_C,   BFD_RELOC_16C_IMM04_C},
79   {R_16C_IMM16,     BFD_RELOC_16C_IMM16},
80   {R_16C_IMM16_C,   BFD_RELOC_16C_IMM16_C},
81   {R_16C_IMM20,     BFD_RELOC_16C_IMM20},
82   {R_16C_IMM20_C,   BFD_RELOC_16C_IMM20_C},
83   {R_16C_IMM24,     BFD_RELOC_16C_IMM24},
84   {R_16C_IMM24_C,   BFD_RELOC_16C_IMM24_C},
85   {R_16C_IMM32,     BFD_RELOC_16C_IMM32},
86   {R_16C_IMM32_C,   BFD_RELOC_16C_IMM32_C}
87 };
88
89 static reloc_howto_type elf_howto_table[] =
90 {
91   /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08),
92   /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C),
93   /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16),
94   /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C),
95   /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32),
96   /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C),
97   /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04),
98   /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C),
99   /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08),
100   /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C),
101   /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16),
102   /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C),
103   /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24),
104   /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C),
105   /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a),
106   /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C),
107   /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04),
108   /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C),
109   /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a),
110   /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C),
111   /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14),
112   /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C),
113   /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16),
114   /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C),
115   /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20),
116   /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C),
117   /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20),
118   /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C),
119   /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24),
120   /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C),
121   /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04),
122   /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C),
123   /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16),
124   /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C),
125   /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20),
126   /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C),
127   /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24),
128   /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C),
129   /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32),
130   /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C)
131 };
132
133
134 /* Code to turn a code_type into a howto ptr, uses the above howto table.  */
135
136 static reloc_howto_type *
137 elf_cr16c_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
138                              bfd_reloc_code_real_type code)
139 {
140   unsigned int i;
141
142   for (i = 0; i < RINDEX_16C_MAX; i++)
143     {
144       if (code == reloc_map_index[i].bfd_reloc_enum)
145         {
146           /* printf ("CR16C Relocation Type is - %x\n", code); */
147           return & elf_howto_table[i];
148         }
149     }
150
151   /* printf ("This relocation Type is not supported - %x\n", code); */
152   return 0;
153 }
154
155 static reloc_howto_type *
156 elf_cr16c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
157                              const char *r_name)
158 {
159   unsigned int i;
160
161   for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
162     if (elf_howto_table[i].name != NULL
163         && strcasecmp (elf_howto_table[i].name, r_name) == 0)
164       return &elf_howto_table[i];
165
166   return NULL;
167 }
168
169 static void
170 elf_cr16c_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
171                          arelent *cache_ptr ATTRIBUTE_UNUSED,
172                          Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
173 {
174   abort ();
175 }
176
177 static void
178 elf_cr16c_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
179                              arelent *cache_ptr,
180                              Elf_Internal_Rela *dst)
181 {
182   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
183
184   BFD_ASSERT (r_type < (unsigned int) RINDEX_16C_MAX);
185   cache_ptr->howto = &elf_howto_table[r_type];
186 }
187
188 /* Perform a relocation as part of a final link.  */
189
190 static bfd_reloc_status_type
191 cr16c_elf_final_link_relocate (reloc_howto_type *howto,
192                                bfd *abfd,
193                                bfd *output_bfd ATTRIBUTE_UNUSED,
194                                asection *input_section,
195                                bfd_byte *data,
196                                bfd_vma octets,
197                                bfd_vma Rvalue,
198                                bfd_vma addend ATTRIBUTE_UNUSED,
199                                struct bfd_link_info *info ATTRIBUTE_UNUSED,
200                                asection *sym_sec ATTRIBUTE_UNUSED,
201                                int is_local ATTRIBUTE_UNUSED)
202 {
203   long value;
204   short sword;                  /* Extracted from the hole and put back.  */
205   unsigned long format, addr_type, code_factor;
206   unsigned short size;
207   unsigned short r_type;
208
209   unsigned long disp20_opcod;
210   char neg = 0;
211   char neg2pos = 0;
212
213   long left_val = 0;
214   long plus_factor = 0;         /* To be added to the hole.  */
215
216 #define MIN_BYTE        ((int) 0xFFFFFF80)
217 #define MIN_WORD        ((int) 0xFFFF8000)
218 #define MAX_UWORD       ((unsigned) 0x0000FFFF)
219 #define MAX_UBYTE       ((unsigned) 0x000000FF)
220
221   r_type = reloc_map_index[howto->type].cr_reloc_type;
222   format = r_type & R_FORMAT;
223   size = r_type & R_SIZESP;
224   addr_type = r_type & R_ADDRTYPE;
225   code_factor = ((addr_type == R_CODE_ADDR) ? 1 : 0);
226
227   switch (format)
228     {
229     case R_NUMBER:
230       switch (size)
231         {
232         case R_S_16C_08:        /* One byte.  */
233           value = bfd_get_8 (abfd, (char *) data + octets);
234           break;
235         case R_S_16C_16:        /* Two bytes. */
236           sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
237           value = sword;
238           break;
239         case R_S_16C_32:        /* Four bytes.  */
240           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
241           break;
242         default:
243           return bfd_reloc_notsupported;
244         }
245       break;
246
247     case R_16C_DISPL:
248       switch (size)
249         {
250         case R_S_16C_04:    /* word1(4-7).  */
251           value = bfd_get_8 (abfd, (char *) data + octets);
252           left_val = value & 0xF;
253           value = (value & 0xF0) >> 4;
254           value++;
255           value <<= 1;
256           break;
257         case R_S_16C_08:    /* word1(0-3,8-11).  */
258           sword = bfd_get_16 (abfd, (char *) data + octets);
259           value = sword & 0x000F;
260           value |= ((sword & 0x0F00) >> 4);
261           left_val = sword & 0xF0F0;
262           value <<= 1;
263           if (value & 0x100)
264             value |= 0xFFFFFF00;
265           break;
266         case R_S_16C_16:    /* word2.  */
267           sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
268           value = sword;
269           value = ((value & 0xFFFE) >> 1) | ((value & 0x1) << 15);
270           value <<= 1;
271           if (value & 0x10000)
272             value |= 0xFFFF0000;
273           break;
274         case R_S_16C_24_a:      /* word1(0-7),word2.  */
275           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
276           left_val = value & 0x0000FF00;
277           value = ((value & 0xFFFE0000) >> 17) |
278             ((value & 0x00010000) << 7) | ((value & 0x000000FF) << 15);
279           value <<= 1;
280           if (value & 0x1000000)
281             value |= 0xFE000000;
282           break;
283         case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
284           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
285           left_val = value & 0x0000F0F0;
286           value = ((value >> 16) & 0x0000FFFF) |
287             ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
288
289           value = ((value & 0x00FFFFFE) >> 1) | ((value & 0x00000001) << 23);
290
291           value <<= 1;
292           if (value & 0x1000000)
293             value |= 0xFE000000;
294           break;
295         default:
296           return bfd_reloc_notsupported;
297         }
298       break;
299
300     case R_16C_REGREL:
301       switch (size)
302         {
303         case R_S_16C_04:    /* word1(12-15) not scaled.  */
304           value = bfd_get_8 (abfd, (char *) data + octets);
305           left_val = value & 0xF0;
306           value = value & 0xF;
307           break;
308         case R_S_16C_04_a:      /* word1(12-15) scaled by 2.  */
309           value = bfd_get_8 (abfd, (char *) data + octets);
310           left_val = value & 0xF0;
311           value = value & 0xF;
312           value <<= 1;
313           break;
314         case R_S_16C_14:    /* word1(4-5),word2(0-3,8-15).  */
315           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
316           left_val = value & 0x00F0FFCF;
317           value = ((value & 0xc0000000) >> 24) |
318             ((value & 0x3F000000) >> 16) |
319             ((value & 0x000F0000) >> 16) | (value & 0x00000030);
320           break;
321         case R_S_16C_16:    /* word2.  */
322           sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
323           value = sword;
324           break;
325         case R_S_16C_20:    /* word2(8-11),word3.  */
326           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
327           left_val = value & 0xF0;
328           value = (value & 0xF) << 16;
329           sword = bfd_get_16 (abfd, (bfd_byte *) data + octets + 1);
330           value = value | (unsigned short) sword;
331           disp20_opcod = bfd_get_32 (abfd, (bfd_byte *) data + octets - 3);
332           disp20_opcod |= 0x0FFF0000;
333           if ((disp20_opcod == 0x4FFF0018) ||   /* loadb -disp20(reg) */
334               (disp20_opcod == 0x5FFF0018) ||   /* loadb -disp20(rp)  */
335               (disp20_opcod == 0x8FFF0018) ||   /* loadd -disp20(reg) */
336               (disp20_opcod == 0x9FFF0018) ||   /* loadd -disp20(rp)  */
337               (disp20_opcod == 0xCFFF0018) ||   /* loadw -disp20(reg) */
338               (disp20_opcod == 0xDFFF0018) ||   /* loadw -disp20(rp)  */
339               (disp20_opcod == 0x4FFF0019) ||   /* storb -disp20(reg) */
340               (disp20_opcod == 0x5FFF0019) ||   /* storb -disp20(rp)  */
341               (disp20_opcod == 0x8FFF0019) ||   /* stord -disp20(reg) */
342               (disp20_opcod == 0x9FFF0019) ||   /* stord -disp20(rp)  */
343               (disp20_opcod == 0xCFFF0019) ||   /* storw -disp20(reg) */
344               (disp20_opcod == 0xDFFF0019))
345             {   /* storw -disp20(rp).  */
346               neg = 1;
347               value |= 0xFFF00000;
348             }
349
350           break;
351         default:
352           return bfd_reloc_notsupported;
353         }
354       break;
355
356     case R_16C_ABS:
357       switch (size)
358         {
359         case R_S_16C_20:    /* word1(0-3),word2.  */
360           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
361           left_val = value & 0x0000FFF0;
362           value = ((value & 0xFFFF0000) >> 16) |
363             ((value & 0x0000000F) << 16);
364           break;
365         case R_S_16C_24:   /* word2(0-3,8-11),word3.  */
366           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
367           left_val = value & 0x0000F0F0;
368           value = ((value & 0xFFFF0000) >> 16) |
369             ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
370           break;
371         default:
372           return bfd_reloc_notsupported;
373         }
374       break;
375
376     case R_16C_IMMED:
377       switch (size)
378         {
379         case R_S_16C_04:    /* word1/2(4-7).  */
380           value = bfd_get_8 (abfd, (char *) data + octets);
381           left_val = value & 0xF;
382           value = (value & 0xF0) >> 4;
383           break;
384         case R_S_16C_16:    /* word2.  */
385           sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
386           value = sword;
387           break;
388         case R_S_16C_20:    /* word1(0-3),word2.  */
389           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
390           left_val = value & 0x0000FFF0;
391           value = ((value & 0xFFFF0000) >> 16) |
392             ((value & 0x0000000F) << 16);
393           break;
394         case R_S_16C_32:    /* word2, word3.  */
395           value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
396           value = ((value & 0x0000FFFF) << 16) |
397             ((value & 0xFFFF0000) >> 16);
398           break;
399         default:
400           return bfd_reloc_notsupported;
401         }
402       break;
403     default:
404       return bfd_reloc_notsupported;
405     }
406
407   switch ((r_type & R_RELTO) >> 4)
408     {
409
410     case 0:     /* R_ABS.  */
411       plus_factor = Rvalue;
412       break;
413     case 1:     /* R_PCREL.  */
414       plus_factor = Rvalue -
415         (input_section->output_section->vma + input_section->output_offset);
416       break;
417     default:
418       return bfd_reloc_notsupported;
419     }
420
421   if (neg)
422     {
423       if (plus_factor >= -value)
424         neg2pos = 1;
425       /* We need to change load/stor with negative
426          displ opcode to positive disp opcode (CR16C).  */
427     }
428
429   value = value + (plus_factor >> code_factor);
430
431   switch (format)
432     {
433     case R_NUMBER:
434       switch (size)
435         {
436         case R_S_16C_08:        /* One byte.  */
437           if (value > (int) MAX_UBYTE || value < MIN_BYTE)
438             return bfd_reloc_overflow;
439           value &= 0xFF;
440           bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
441           break;
442
443         case R_S_16C_16:        /* Two bytes.  */
444           if (value > (int) MAX_UWORD || value < MIN_WORD)
445             return bfd_reloc_overflow;
446           value &= 0xFFFF;
447           sword = value;
448           bfd_put_16 (abfd, (bfd_vma) sword,
449                       (unsigned char *) data + octets);
450           break;
451
452         case R_S_16C_32:        /* Four bytes.  */
453           value &= 0xFFFFFFFF;
454           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
455           break;
456
457         default:
458           return bfd_reloc_notsupported;
459         }
460       break;
461
462     case R_16C_DISPL:
463       switch (size)
464         {
465         case R_S_16C_04:        /* word1(4-7).  */
466           if ((value - 32) > 32 || value < 2)
467             return bfd_reloc_overflow;
468           value >>= 1;
469           value--;
470           value &= 0xF;
471           value <<= 4;
472           value |= left_val;
473           bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
474           break;
475
476         case R_S_16C_08:    /* word1(0-3,8-11).  */
477           if (value > 255 || value < -256 || value == 0x80)
478             return bfd_reloc_overflow;
479           value &= 0x1FF;
480           value >>= 1;
481           sword = value & 0x000F;
482           sword |= (value & 0x00F0) << 4;
483           sword |= left_val;
484           bfd_put_16 (abfd, (bfd_vma) sword,
485                       (unsigned char *) data + octets);
486           break;
487
488         case R_S_16C_16:    /* word2.  */
489           if (value > 65535 || value < -65536)
490             return bfd_reloc_overflow;
491           value >>= 1;
492           value &= 0xFFFF;
493           value = ((value & 0x8000) >> 15) | ((value & 0x7FFF) << 1);
494           sword = value;
495           bfd_put_16 (abfd, (bfd_vma) sword,
496                       (unsigned char *) data + octets);
497           break;
498
499         case R_S_16C_24_a:      /* word1(0-7),word2.  */
500           if (value > 16777215 || value < -16777216)
501             return bfd_reloc_overflow;
502           value &= 0x1FFFFFF;
503           value >>= 1;
504           value = ((value & 0x00007FFF) << 17) |
505             ((value & 0x00800000) >> 7) | ((value & 0x007F8000) >> 15);
506           value |= left_val;
507           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
508           break;
509
510         case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
511           if (value > 16777215 || value < -16777216)
512             return bfd_reloc_overflow;
513           value &= 0x1FFFFFF;
514           value >>= 1;
515
516           value = ((value & 0x007FFFFF) << 1) | ((value & 0x00800000) >> 23);
517
518           value = ((value & 0x0000FFFF) << 16) |
519             ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
520           value |= left_val;
521           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
522           break;
523
524         default:
525           return bfd_reloc_notsupported;
526         }
527       break;
528
529     case R_16C_REGREL:
530       switch (size)
531         {
532         case R_S_16C_04:        /* word1(12-15) not scaled.  */
533           if (value > 13 || value < 0)
534             return bfd_reloc_overflow;
535           value &= 0xF;
536           value |= left_val;
537           bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
538           break;
539
540         case R_S_16C_04_a:      /* word1(12-15) not scaled.  */
541           if (value > 26 || value < 0)
542             return bfd_reloc_overflow;
543           value &= 0x1F;
544           value >>= 1;
545           value |= left_val;
546           bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
547           break;
548
549         case R_S_16C_14:        /* word1(4-5),word2(0-3,8-15).  */
550           if (value < 0 || value > 16383)
551             return bfd_reloc_overflow;
552           value &= 0x3FFF;
553           value = ((value & 0x000000c0) << 24) |
554             ((value & 0x00003F00) << 16) |
555             ((value & 0x0000000F) << 16) | (value & 0x00000030);
556           value |= left_val;
557           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
558           break;
559
560         case R_S_16C_16:        /* word2.  */
561           if (value > 65535 || value < 0)
562             return bfd_reloc_overflow;
563           value &= 0xFFFF;
564           sword = value;
565           bfd_put_16 (abfd, (bfd_vma) sword,
566                       (unsigned char *) data + octets);
567           break;
568
569         case R_S_16C_20:        /* word2(8-11),word3.  */
570           /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
571           value &= 0xFFFFF;
572           sword = value & 0x0000FFFF;
573           value = (value & 0x000F0000) >> 16;
574           value |= left_val;
575           bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
576           bfd_put_16 (abfd, (bfd_vma) sword,
577                       (unsigned char *) data + octets + 1);
578           if (neg2pos)
579             {
580               /* Change load/stor negative displ opcode
581                  to load/stor positive displ opcode.  */
582               value = bfd_get_8 (abfd, (char *) data + octets - 3);
583               value &= 0xF7;
584               value |= 0x2;
585               bfd_put_8 (abfd, (bfd_vma) value,
586                          (unsigned char *) data + octets - 3);
587             }
588           break;
589
590         default:
591           return bfd_reloc_notsupported;
592         }
593       break;
594
595     case R_16C_ABS:
596       switch (size)
597         {
598         case R_S_16C_20:        /* word1(0-3),word2.  */
599           if (value > 1048575 || value < 0)
600             return bfd_reloc_overflow;
601           value &= 0xFFFFF;
602           value = ((value & 0x0000FFFF) << 16) |
603             ((value & 0x000F0000) >> 16);
604           value |= left_val;
605           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
606           break;
607
608         case R_S_16C_24:        /* word2(0-3,8-11),word3.  */
609           /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
610           value &= 0xFFFFFF;
611           value = ((value & 0x0000FFFF) << 16) |
612             ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
613           value |= left_val;
614           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
615           break;
616
617         default:
618           return bfd_reloc_notsupported;
619         }
620       break;
621
622     case R_16C_IMMED:
623       switch (size)
624         {
625         case R_S_16C_04:        /* word1/2(4-7).  */
626           if (value > 15 || value < -1)
627             return bfd_reloc_overflow;
628           value &= 0xF;
629           value <<= 4;
630           value |= left_val;
631           bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
632           break;
633
634         case R_S_16C_16:        /* word2.  */
635           if (value > 32767 || value < -32768)
636             return bfd_reloc_overflow;
637           value &= 0xFFFF;
638           sword = value;
639           bfd_put_16 (abfd, (bfd_vma) sword,
640                       (unsigned char *) data + octets);
641           break;
642
643         case R_S_16C_20:        /* word1(0-3),word2.  */
644           if (value > 1048575 || value < 0)
645             return bfd_reloc_overflow;
646           value &= 0xFFFFF;
647           value = ((value & 0x0000FFFF) << 16) |
648             ((value & 0x000F0000) >> 16);
649           value |= left_val;
650           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
651           break;
652
653         case R_S_16C_32:        /* word2, word3.  */
654           value &= 0xFFFFFFFF;
655           value = ((value & 0x0000FFFF) << 16) |
656             ((value & 0xFFFF0000) >> 16);
657           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
658           break;
659
660         default:
661           return bfd_reloc_notsupported;
662         }
663       break;
664     default:
665       return bfd_reloc_notsupported;
666     }
667
668   return bfd_reloc_ok;
669 }
670
671 /* Relocate a CR16C ELF section.  */
672
673 static bfd_boolean
674 elf32_cr16c_relocate_section (bfd *output_bfd,
675                               struct bfd_link_info *info,
676                               bfd *input_bfd,
677                               asection *input_section,
678                               bfd_byte *contents,
679                               Elf_Internal_Rela *relocs,
680                               Elf_Internal_Sym *local_syms,
681                               asection **local_sections)
682 {
683   Elf_Internal_Shdr *symtab_hdr;
684   struct elf_link_hash_entry **sym_hashes;
685   Elf_Internal_Rela *rel, *relend;
686
687   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
688   sym_hashes = elf_sym_hashes (input_bfd);
689
690   rel = relocs;
691   relend = relocs + input_section->reloc_count;
692   for (; rel < relend; rel++)
693     {
694       int r_type;
695       reloc_howto_type *howto;
696       unsigned long r_symndx;
697       Elf_Internal_Sym *sym;
698       asection *sec;
699       struct elf_link_hash_entry *h;
700       bfd_vma relocation;
701       bfd_reloc_status_type r;
702
703       r_symndx = ELF32_R_SYM (rel->r_info);
704       r_type = ELF32_R_TYPE (rel->r_info);
705       howto = elf_howto_table + r_type;
706
707       h = NULL;
708       sym = NULL;
709       sec = NULL;
710       if (r_symndx < symtab_hdr->sh_info)
711         {
712           sym = local_syms + r_symndx;
713           sec = local_sections[r_symndx];
714           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
715         }
716       else
717         {
718           bfd_boolean unresolved_reloc, warned;
719
720           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
721                                    r_symndx, symtab_hdr, sym_hashes,
722                                    h, sec, relocation,
723                                    unresolved_reloc, warned);
724         }
725
726       if (sec != NULL && elf_discarded_section (sec))
727         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
728                                          rel, relend, howto, contents);
729
730       if (info->relocatable)
731         {
732           /* This is a relocatable link.  We don't have to change
733              anything, unless the reloc is against a section symbol,
734              in which case we have to adjust according to where the
735              section symbol winds up in the output section.  */
736           if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
737             rel->r_addend += sec->output_offset;
738           continue;
739         }
740
741       r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
742                                          input_section,
743                                          contents, rel->r_offset,
744                                          relocation, rel->r_addend,
745                                          info, sec, h == NULL);
746
747       if (r != bfd_reloc_ok)
748         {
749           const char *name;
750           const char *msg = (const char *) 0;
751
752           if (h != NULL)
753             name = h->root.root.string;
754           else
755             {
756               name = (bfd_elf_string_from_elf_section
757                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
758               if (name == NULL || *name == '\0')
759                 name = bfd_section_name (input_bfd, sec);
760             }
761
762           switch (r)
763             {
764             case bfd_reloc_overflow:
765               if (!((*info->callbacks->reloc_overflow)
766                     (info, (h ? &h->root : NULL), name, howto->name,
767                      (bfd_vma) 0, input_bfd, input_section,
768                      rel->r_offset)))
769                 return FALSE;
770               break;
771
772             case bfd_reloc_undefined:
773               if (!((*info->callbacks->undefined_symbol)
774                     (info, name, input_bfd, input_section,
775                      rel->r_offset, TRUE)))
776                 return FALSE;
777               break;
778
779             case bfd_reloc_outofrange:
780               msg = _("internal error: out of range error");
781               goto common_error;
782
783             case bfd_reloc_notsupported:
784               msg = _("internal error: unsupported relocation error");
785               goto common_error;
786
787             case bfd_reloc_dangerous:
788               msg = _("internal error: dangerous error");
789               goto common_error;
790
791             default:
792               msg = _("internal error: unknown error");
793               /* fall through */
794
795             common_error:
796               if (!((*info->callbacks->warning)
797                     (info, msg, name, input_bfd, input_section,
798                      rel->r_offset)))
799                 return FALSE;
800               break;
801             }
802         }
803     }
804
805   return TRUE;
806 }
807
808 /* CR16C ELF uses three common sections:
809    One is for default common symbols (placed in usual common section).
810    Second is for near common symbols (placed in "ncommon" section).
811    Third is for far common symbols (placed in "fcommon" section).
812    The following implementation is based on elf32-mips architecture */
813
814 static asection  cr16c_elf_fcom_section;
815 static asymbol   cr16c_elf_fcom_symbol;
816 static asymbol * cr16c_elf_fcom_symbol_ptr;
817 static asection  cr16c_elf_ncom_section;
818 static asymbol   cr16c_elf_ncom_symbol;
819 static asymbol * cr16c_elf_ncom_symbol_ptr;
820
821 /* Given a BFD section, try to locate the
822    corresponding ELF section index.  */
823
824 static bfd_boolean
825 elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
826                                       asection *sec,
827                                       int *retval)
828 {
829   if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
830     *retval = SHN_CR16C_FCOMMON;
831   else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
832     *retval = SHN_CR16C_NCOMMON;
833   else
834     return FALSE;
835
836   return TRUE;
837 }
838
839 /* Handle the special CR16C section numbers that a symbol may use.  */
840
841 static void
842 elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
843                                asymbol *asym)
844 {
845   elf_symbol_type *elfsym = (elf_symbol_type *) asym;
846   unsigned int indx;
847
848   indx = elfsym->internal_elf_sym.st_shndx;
849
850   switch (indx)
851     {
852     case SHN_CR16C_FCOMMON:
853       if (cr16c_elf_fcom_section.name == NULL)
854         {
855           /* Initialize the far common section.  */
856           cr16c_elf_fcom_section.name = ".fcommon";
857           cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
858           cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
859           cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
860           cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
861           cr16c_elf_fcom_symbol.name = ".fcommon";
862           cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
863           cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
864           cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
865         }
866       asym->section = &cr16c_elf_fcom_section;
867       asym->value = elfsym->internal_elf_sym.st_size;
868       break;
869     case SHN_CR16C_NCOMMON:
870       if (cr16c_elf_ncom_section.name == NULL)
871         {
872           /* Initialize the far common section.  */
873           cr16c_elf_ncom_section.name = ".ncommon";
874           cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
875           cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
876           cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
877           cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
878           cr16c_elf_ncom_symbol.name = ".ncommon";
879           cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
880           cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
881           cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
882         }
883       asym->section = &cr16c_elf_ncom_section;
884       asym->value = elfsym->internal_elf_sym.st_size;
885       break;
886     }
887 }
888
889 /* Hook called by the linker routine which adds symbols from an object
890    file.  We must handle the special cr16c section numbers here.  */
891
892 static bfd_boolean
893 elf32_cr16c_add_symbol_hook (bfd *abfd,
894                              struct bfd_link_info *info ATTRIBUTE_UNUSED,
895                              Elf_Internal_Sym *sym,
896                              const char **namep ATTRIBUTE_UNUSED,
897                              flagword *flagsp ATTRIBUTE_UNUSED,
898                              asection **secp,
899                              bfd_vma *valp)
900 {
901   unsigned int indx = sym->st_shndx;
902
903   switch (indx)
904     {
905     case SHN_CR16C_FCOMMON:
906       *secp = bfd_make_section_old_way (abfd, ".fcommon");
907       (*secp)->flags |= SEC_IS_COMMON;
908       *valp = sym->st_size;
909       break;
910     case SHN_CR16C_NCOMMON:
911       *secp = bfd_make_section_old_way (abfd, ".ncommon");
912       (*secp)->flags |= SEC_IS_COMMON;
913       *valp = sym->st_size;
914       break;
915     }
916
917   return TRUE;
918 }
919
920 static int
921 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
922                                      const char *name ATTRIBUTE_UNUSED,
923                                      Elf_Internal_Sym *sym,
924                                      asection *input_sec,
925                                      struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
926 {
927   /* If we see a common symbol, which implies a relocatable link, then
928      if a symbol was in a special common section in an input file, mark
929      it as a special common in the output file.  */
930
931   if (sym->st_shndx == SHN_COMMON)
932     {
933       if (strcmp (input_sec->name, ".fcommon") == 0)
934         sym->st_shndx = SHN_CR16C_FCOMMON;
935       else if (strcmp (input_sec->name, ".ncommon") == 0)
936         sym->st_shndx = SHN_CR16C_NCOMMON;
937     }
938
939   return 1;
940 }
941
942 /* Definitions for setting CR16C target vector.  */
943 #define TARGET_LITTLE_SYM               bfd_elf32_cr16c_vec
944 #define TARGET_LITTLE_NAME              "elf32-cr16c"
945 #define ELF_ARCH                        bfd_arch_cr16c
946 #define ELF_MACHINE_CODE                EM_CR
947 #define ELF_MAXPAGESIZE                 0x1
948 #define elf_symbol_leading_char         '_'
949
950 #define bfd_elf32_bfd_reloc_type_lookup         elf_cr16c_reloc_type_lookup
951 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
952 #define elf_info_to_howto                       elf_cr16c_info_to_howto
953 #define elf_info_to_howto_rel                   elf_cr16c_info_to_howto_rel
954 #define elf_backend_relocate_section            elf32_cr16c_relocate_section
955 #define elf_backend_symbol_processing           elf32_cr16c_symbol_processing
956 #define elf_backend_section_from_bfd_section    elf32_cr16c_section_from_bfd_section
957 #define elf_backend_add_symbol_hook             elf32_cr16c_add_symbol_hook
958 #define elf_backend_link_output_symbol_hook     elf32_cr16c_link_output_symbol_hook
959
960 #define elf_backend_can_gc_sections     1
961
962 #include "elf32-target.h"