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