OSDN Git Service

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