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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
19 
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23 #include "bfdlink.h"
24 #include "elf/cr16c.h"
25 #include "elf-bfd.h"
26 
27 
28 #define USE_REL	1	/* CR16C uses REL relocations instead of RELA.  */
29 
30 /* The following definition is based on EMPTY_HOWTO macro,
31    but also initiates the "name" field in HOWTO struct.  */
32 #define ONLY_NAME_HOWTO(C) \
33   HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
34 	  STRINGX(C), FALSE, 0, 0, FALSE)
35 
36 /* reloc_map_index array maps CRASM relocation type into a BFD
37    relocation enum. The array's indices are synchronized with
38    RINDEX_16C_* indices, created in include/elf/cr16c.h.
39    The array is used in:
40    1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
41    2. asreloc.c : find_reloc_type(). */
42 
43 RELOC_MAP reloc_map_index[RINDEX_16C_MAX] =
44 {
45   {R_16C_NUM08,     BFD_RELOC_16C_NUM08},
46   {R_16C_NUM08_C,   BFD_RELOC_16C_NUM08_C},
47   {R_16C_NUM16,     BFD_RELOC_16C_NUM16},
48   {R_16C_NUM16_C,   BFD_RELOC_16C_NUM16_C},
49   {R_16C_NUM32,     BFD_RELOC_16C_NUM32},
50   {R_16C_NUM32_C,   BFD_RELOC_16C_NUM32_C},
51   {R_16C_DISP04,    BFD_RELOC_16C_DISP04},
52   {R_16C_DISP04_C,  BFD_RELOC_16C_DISP04_C},
53   {R_16C_DISP08,    BFD_RELOC_16C_DISP08},
54   {R_16C_DISP08_C,  BFD_RELOC_16C_DISP08_C},
55   {R_16C_DISP16,    BFD_RELOC_16C_DISP16},
56   {R_16C_DISP16_C,  BFD_RELOC_16C_DISP16_C},
57   {R_16C_DISP24,    BFD_RELOC_16C_DISP24},
58   {R_16C_DISP24_C,  BFD_RELOC_16C_DISP24_C},
59   {R_16C_DISP24a,   BFD_RELOC_16C_DISP24a},
60   {R_16C_DISP24a_C, BFD_RELOC_16C_DISP24a_C},
61   {R_16C_REG04,     BFD_RELOC_16C_REG04},
62   {R_16C_REG04_C,   BFD_RELOC_16C_REG04_C},
63   {R_16C_REG04a,    BFD_RELOC_16C_REG04a},
64   {R_16C_REG04a_C,  BFD_RELOC_16C_REG04a_C},
65   {R_16C_REG14,     BFD_RELOC_16C_REG14},
66   {R_16C_REG14_C,   BFD_RELOC_16C_REG14_C},
67   {R_16C_REG16,     BFD_RELOC_16C_REG16},
68   {R_16C_REG16_C,   BFD_RELOC_16C_REG16_C},
69   {R_16C_REG20,     BFD_RELOC_16C_REG20},
70   {R_16C_REG20_C,   BFD_RELOC_16C_REG20_C},
71   {R_16C_ABS20,     BFD_RELOC_16C_ABS20},
72   {R_16C_ABS20_C,   BFD_RELOC_16C_ABS20_C},
73   {R_16C_ABS24,     BFD_RELOC_16C_ABS24},
74   {R_16C_ABS24_C,   BFD_RELOC_16C_ABS24_C},
75   {R_16C_IMM04,     BFD_RELOC_16C_IMM04},
76   {R_16C_IMM04_C,   BFD_RELOC_16C_IMM04_C},
77   {R_16C_IMM16,     BFD_RELOC_16C_IMM16},
78   {R_16C_IMM16_C,   BFD_RELOC_16C_IMM16_C},
79   {R_16C_IMM20,     BFD_RELOC_16C_IMM20},
80   {R_16C_IMM20_C,   BFD_RELOC_16C_IMM20_C},
81   {R_16C_IMM24,     BFD_RELOC_16C_IMM24},
82   {R_16C_IMM24_C,   BFD_RELOC_16C_IMM24_C},
83   {R_16C_IMM32,     BFD_RELOC_16C_IMM32},
84   {R_16C_IMM32_C,   BFD_RELOC_16C_IMM32_C}
85 };
86 
87 static reloc_howto_type elf_howto_table[] =
88 {
89   /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08),
90   /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C),
91   /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16),
92   /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C),
93   /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32),
94   /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C),
95   /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04),
96   /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C),
97   /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08),
98   /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C),
99   /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16),
100   /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C),
101   /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24),
102   /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C),
103   /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a),
104   /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C),
105   /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04),
106   /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C),
107   /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a),
108   /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C),
109   /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14),
110   /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C),
111   /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16),
112   /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C),
113   /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20),
114   /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C),
115   /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20),
116   /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C),
117   /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24),
118   /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C),
119   /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04),
120   /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C),
121   /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16),
122   /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C),
123   /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20),
124   /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C),
125   /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24),
126   /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C),
127   /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32),
128   /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C)
129 };
130 
131 
132 /* Code to turn a code_type into a howto ptr, uses the above howto table.  */
133 
134 static reloc_howto_type *
elf_cr16c_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)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
elf_cr16c_info_to_howto(bfd * abfd ATTRIBUTE_UNUSED,arelent * cache_ptr ATTRIBUTE_UNUSED,Elf_Internal_Rela * dst ATTRIBUTE_UNUSED)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
elf_cr16c_info_to_howto_rel(bfd * abfd ATTRIBUTE_UNUSED,arelent * cache_ptr,Elf_Internal_Rela * dst)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
cr16c_elf_final_link_relocate(reloc_howto_type * howto,bfd * abfd,bfd * output_bfd ATTRIBUTE_UNUSED,asection * input_section,bfd_byte * data,bfd_vma octets,bfd_vma Rvalue,bfd_vma addend ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sym_sec ATTRIBUTE_UNUSED,int is_local ATTRIBUTE_UNUSED)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
elf32_cr16c_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,Elf_Internal_Rela * relocs,Elf_Internal_Sym * local_syms,asection ** local_sections)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 *
elf32_cr16c_gc_mark_hook(asection * sec,struct bfd_link_info * info ATTRIBUTE_UNUSED,Elf_Internal_Rela * rel,struct elf_link_hash_entry * h,Elf_Internal_Sym * sym)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
elf32_cr16c_gc_sweep_hook(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)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
elf32_cr16c_section_from_bfd_section(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,int * retval)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
elf32_cr16c_symbol_processing(bfd * abfd ATTRIBUTE_UNUSED,asymbol * asym)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
elf32_cr16c_add_symbol_hook(bfd * abfd,struct bfd_link_info * info ATTRIBUTE_UNUSED,Elf_Internal_Sym * sym,const char ** namep ATTRIBUTE_UNUSED,flagword * flagsp ATTRIBUTE_UNUSED,asection ** secp,bfd_vma * valp)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
elf32_cr16c_link_output_symbol_hook(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * name ATTRIBUTE_UNUSED,Elf_Internal_Sym * sym,asection * input_sec,struct elf_link_hash_entry * h ATTRIBUTE_UNUSED)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"
1004