OSDN Git Service

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