Restore 2002 ChangeLog history.
[platform/upstream/binutils.git] / bfd / elf32-cr16c.c
1 /* BFD back-end for National Semiconductor's CR16C ELF
2    Copyright 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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           return bfd_reloc_ok;
430           break;
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           return bfd_reloc_ok;
439           break;
440         case R_S_16C_32:        /* Four bytes.  */
441           value &= 0xFFFFFFFF;
442           bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
443           return bfd_reloc_ok;
444           break;
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           return bfd_reloc_ok;
463           break;
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           return bfd_reloc_ok;
475           break;
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           return bfd_reloc_ok;
486           break;
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           return bfd_reloc_ok;
497           break;
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           return bfd_reloc_ok;
511           break;
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           return bfd_reloc_ok;
527           break;
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           return bfd_reloc_ok;
536           break;
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           return bfd_reloc_ok;
547           break;
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           return bfd_reloc_ok;
556           break;
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           return bfd_reloc_ok;
577           break;
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           return bfd_reloc_ok;
595           break;
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           return bfd_reloc_ok;
604           break;
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           return bfd_reloc_ok;
621           break;
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           return bfd_reloc_ok;
630           break;
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           return bfd_reloc_ok;
640           break;
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           return bfd_reloc_ok;
647           break;
648         default:
649           return bfd_reloc_notsupported;
650         }
651       break;
652     default:
653       return bfd_reloc_notsupported;
654     }
655 }
656
657 /* Relocate a CR16C ELF section.  */
658
659 static bfd_boolean
660 elf32_cr16c_relocate_section (bfd *output_bfd,
661                               struct bfd_link_info *info,
662                               bfd *input_bfd,
663                               asection *input_section,
664                               bfd_byte *contents,
665                               Elf_Internal_Rela *relocs,
666                               Elf_Internal_Sym *local_syms,
667                               asection **local_sections)
668 {
669   Elf_Internal_Shdr *symtab_hdr;
670   struct elf_link_hash_entry **sym_hashes;
671   Elf_Internal_Rela *rel, *relend;
672
673   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
674   sym_hashes = elf_sym_hashes (input_bfd);
675
676   rel = relocs;
677   relend = relocs + input_section->reloc_count;
678   for (; rel < relend; rel++)
679     {
680       int r_type;
681       reloc_howto_type *howto;
682       unsigned long r_symndx;
683       Elf_Internal_Sym *sym;
684       asection *sec;
685       struct elf_link_hash_entry *h;
686       bfd_vma relocation;
687       bfd_reloc_status_type r;
688
689       r_symndx = ELF32_R_SYM (rel->r_info);
690       r_type = ELF32_R_TYPE (rel->r_info);
691       howto = elf_howto_table + r_type;
692
693       if (info->relocatable)
694         {
695           /* This is a relocatable link.  We don't have to change
696              anything, unless the reloc is against a section symbol,
697              in which case we have to adjust according to where the
698              section symbol winds up in the output section.  */
699           if (r_symndx < symtab_hdr->sh_info)
700             {
701               sym = local_syms + r_symndx;
702               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
703                 {
704                   sec = local_sections[r_symndx];
705                   rel->r_addend += sec->output_offset + sym->st_value;
706                 }
707             }
708
709           continue;
710         }
711
712       /* This is a final link.  */
713       h = NULL;
714       sym = NULL;
715       sec = NULL;
716       if (r_symndx < symtab_hdr->sh_info)
717         {
718           sym = local_syms + r_symndx;
719           sec = local_sections[r_symndx];
720           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
721         }
722       else
723         {
724           bfd_boolean unresolved_reloc, warned;
725
726           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
727                                    r_symndx, symtab_hdr, sym_hashes,
728                                    h, sec, relocation,
729                                    unresolved_reloc, warned);
730         }
731
732       r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
733                                          input_section,
734                                          contents, rel->r_offset,
735                                          relocation, rel->r_addend,
736                                          info, sec, h == NULL);
737
738       if (r != bfd_reloc_ok)
739         {
740           const char *name;
741           const char *msg = (const char *) 0;
742
743           if (h != NULL)
744             name = h->root.root.string;
745           else
746             {
747               name = (bfd_elf_string_from_elf_section
748                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
749               if (name == NULL || *name == '\0')
750                 name = bfd_section_name (input_bfd, sec);
751             }
752
753           switch (r)
754             {
755             case bfd_reloc_overflow:
756               if (!((*info->callbacks->reloc_overflow)
757                     (info, name, howto->name, (bfd_vma) 0,
758                      input_bfd, input_section, rel->r_offset)))
759                 return FALSE;
760               break;
761
762             case bfd_reloc_undefined:
763               if (!((*info->callbacks->undefined_symbol)
764                     (info, name, input_bfd, input_section,
765                      rel->r_offset, TRUE)))
766                 return FALSE;
767               break;
768
769             case bfd_reloc_outofrange:
770               msg = _("internal error: out of range error");
771               goto common_error;
772
773             case bfd_reloc_notsupported:
774               msg = _("internal error: unsupported relocation error");
775               goto common_error;
776
777             case bfd_reloc_dangerous:
778               msg = _("internal error: dangerous error");
779               goto common_error;
780
781             default:
782               msg = _("internal error: unknown error");
783               /* fall through */
784
785             common_error:
786               if (!((*info->callbacks->warning)
787                     (info, msg, name, input_bfd, input_section,
788                      rel->r_offset)))
789                 return FALSE;
790               break;
791             }
792         }
793     }
794
795   return TRUE;
796 }
797
798 static asection *
799 elf32_cr16c_gc_mark_hook (asection *sec,
800                           struct bfd_link_info *info ATTRIBUTE_UNUSED,
801                           Elf_Internal_Rela *rel,
802                           struct elf_link_hash_entry *h,
803                           Elf_Internal_Sym *sym)
804 {
805   if (h != NULL)
806     {
807       switch (ELF32_R_TYPE (rel->r_info))
808         {
809
810         default:
811           switch (h->root.type)
812             {
813             case bfd_link_hash_defined:
814             case bfd_link_hash_defweak:
815               return h->root.u.def.section;
816
817             case bfd_link_hash_common:
818               return h->root.u.c.p->section;
819
820             default:
821               break;
822             }
823         }
824     }
825   else
826     {
827       return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
828     }
829
830   return NULL;
831 }
832
833 /* Update the got entry reference counts for the section being removed.  */
834
835 static bfd_boolean
836 elf32_cr16c_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
837                            struct bfd_link_info *info ATTRIBUTE_UNUSED,
838                            asection *sec ATTRIBUTE_UNUSED,
839                            const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
840 {
841   /* We don't support garbage collection of GOT and PLT relocs yet.  */
842   return TRUE;
843 }
844
845 /* CR16C ELF uses three common sections:
846    One is for default common symbols (placed in usual common section).
847    Second is for near common symbols (placed in "ncommon" section).
848    Third is for far common symbols (placed in "fcommon" section).
849    The following implementation is based on elf32-mips architecture */
850
851 static asection  cr16c_elf_fcom_section;
852 static asymbol   cr16c_elf_fcom_symbol;
853 static asymbol * cr16c_elf_fcom_symbol_ptr;
854 static asection  cr16c_elf_ncom_section;
855 static asymbol   cr16c_elf_ncom_symbol;
856 static asymbol * cr16c_elf_ncom_symbol_ptr;
857
858 /* Given a BFD section, try to locate the
859    corresponding ELF section index.  */
860
861 static bfd_boolean
862 elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
863                                       asection *sec,
864                                       int *retval)
865 {
866   if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
867     *retval = SHN_CR16C_FCOMMON;
868   else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
869     *retval = SHN_CR16C_NCOMMON;
870   else
871     return FALSE;
872
873   return TRUE;
874 }
875
876 /* Handle the special CR16C section numbers that a symbol may use.  */
877
878 static void
879 elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
880                                asymbol *asym)
881 {
882   elf_symbol_type *elfsym = (elf_symbol_type *) asym;
883   unsigned int indx;
884
885   indx = elfsym->internal_elf_sym.st_shndx;
886
887   switch (indx)
888     {
889     case SHN_CR16C_FCOMMON:
890       if (cr16c_elf_fcom_section.name == NULL)
891         {
892           /* Initialize the far common section.  */
893           cr16c_elf_fcom_section.name = ".fcommon";
894           cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
895           cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
896           cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
897           cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
898           cr16c_elf_fcom_symbol.name = ".fcommon";
899           cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
900           cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
901           cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
902         }
903       asym->section = &cr16c_elf_fcom_section;
904       asym->value = elfsym->internal_elf_sym.st_size;
905       break;
906     case SHN_CR16C_NCOMMON:
907       if (cr16c_elf_ncom_section.name == NULL)
908         {
909           /* Initialize the far common section.  */
910           cr16c_elf_ncom_section.name = ".ncommon";
911           cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
912           cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
913           cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
914           cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
915           cr16c_elf_ncom_symbol.name = ".ncommon";
916           cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
917           cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
918           cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
919         }
920       asym->section = &cr16c_elf_ncom_section;
921       asym->value = elfsym->internal_elf_sym.st_size;
922       break;
923     }
924 }
925
926 /* Hook called by the linker routine which adds symbols from an object
927    file.  We must handle the special cr16c section numbers here.  */
928
929 static bfd_boolean
930 elf32_cr16c_add_symbol_hook (bfd *abfd,
931                              struct bfd_link_info *info ATTRIBUTE_UNUSED,
932                              Elf_Internal_Sym *sym,
933                              const char **namep ATTRIBUTE_UNUSED,
934                              flagword *flagsp ATTRIBUTE_UNUSED,
935                              asection **secp,
936                              bfd_vma *valp)
937 {
938   unsigned int indx = sym->st_shndx;
939
940   switch (indx)
941     {
942     case SHN_CR16C_FCOMMON:
943       *secp = bfd_make_section_old_way (abfd, ".fcommon");
944       (*secp)->flags |= SEC_IS_COMMON;
945       *valp = sym->st_size;
946       break;
947     case SHN_CR16C_NCOMMON:
948       *secp = bfd_make_section_old_way (abfd, ".ncommon");
949       (*secp)->flags |= SEC_IS_COMMON;
950       *valp = sym->st_size;
951       break;
952     }
953
954   return TRUE;
955 }
956
957 static bfd_boolean
958 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
959                                      const char *name ATTRIBUTE_UNUSED,
960                                      Elf_Internal_Sym *sym,
961                                      asection *input_sec,
962                                      struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
963 {
964   /* If we see a common symbol, which implies a relocatable link, then
965      if a symbol was in a special common section in an input file, mark
966      it as a special common in the output file.  */
967
968   if (sym->st_shndx == SHN_COMMON)
969     {
970       if (strcmp (input_sec->name, ".fcommon") == 0)
971         sym->st_shndx = SHN_CR16C_FCOMMON;
972       else if (strcmp (input_sec->name, ".ncommon") == 0)
973         sym->st_shndx = SHN_CR16C_NCOMMON;
974     }
975
976   return TRUE;
977 }
978
979 /* Definitions for setting CR16C target vector.  */
980 #define TARGET_LITTLE_SYM               bfd_elf32_cr16c_vec
981 #define TARGET_LITTLE_NAME              "elf32-cr16c"
982 #define ELF_ARCH                        bfd_arch_cr16c
983 #define ELF_MACHINE_CODE                EM_CR
984 #define ELF_MAXPAGESIZE                 0x1
985 #define elf_symbol_leading_char         '_'
986
987 #define bfd_elf32_bfd_reloc_type_lookup         elf_cr16c_reloc_type_lookup
988 #define elf_info_to_howto                       elf_cr16c_info_to_howto
989 #define elf_info_to_howto_rel                   elf_cr16c_info_to_howto_rel
990 #define elf_backend_relocate_section            elf32_cr16c_relocate_section
991 #define elf_backend_gc_mark_hook                elf32_cr16c_gc_mark_hook
992 #define elf_backend_gc_sweep_hook               elf32_cr16c_gc_sweep_hook
993 #define elf_backend_symbol_processing           elf32_cr16c_symbol_processing
994 #define elf_backend_section_from_bfd_section    elf32_cr16c_section_from_bfd_section
995 #define elf_backend_add_symbol_hook             elf32_cr16c_add_symbol_hook
996 #define elf_backend_link_output_symbol_hook     elf32_cr16c_link_output_symbol_hook
997
998 #define elf_backend_can_gc_sections     1
999
1000 #include "elf32-target.h"