OSDN Git Service

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