1/* BFD back-end for National Semiconductor's CR16C ELF
2   Copyright 2004, 2005, 2006 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
43RELOC_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
87static 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
134static reloc_howto_type *
135elf_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
153static void
154elf_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
161static void
162elf_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
174static bfd_reloc_status_type
175cr16c_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
661static bfd_boolean
662elf32_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/* CR16C ELF uses three common sections:
802   One is for default common symbols (placed in usual common section).
803   Second is for near common symbols (placed in "ncommon" section).
804   Third is for far common symbols (placed in "fcommon" section).
805   The following implementation is based on elf32-mips architecture */
806
807static asection  cr16c_elf_fcom_section;
808static asymbol   cr16c_elf_fcom_symbol;
809static asymbol * cr16c_elf_fcom_symbol_ptr;
810static asection  cr16c_elf_ncom_section;
811static asymbol   cr16c_elf_ncom_symbol;
812static asymbol * cr16c_elf_ncom_symbol_ptr;
813
814/* Given a BFD section, try to locate the
815   corresponding ELF section index.  */
816
817static bfd_boolean
818elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
819				      asection *sec,
820				      int *retval)
821{
822  if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
823    *retval = SHN_CR16C_FCOMMON;
824  else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
825    *retval = SHN_CR16C_NCOMMON;
826  else
827    return FALSE;
828
829  return TRUE;
830}
831
832/* Handle the special CR16C section numbers that a symbol may use.  */
833
834static void
835elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
836			       asymbol *asym)
837{
838  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
839  unsigned int indx;
840
841  indx = elfsym->internal_elf_sym.st_shndx;
842
843  switch (indx)
844    {
845    case SHN_CR16C_FCOMMON:
846      if (cr16c_elf_fcom_section.name == NULL)
847	{
848	  /* Initialize the far common section.  */
849	  cr16c_elf_fcom_section.name = ".fcommon";
850	  cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
851	  cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
852	  cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
853	  cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
854	  cr16c_elf_fcom_symbol.name = ".fcommon";
855	  cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
856	  cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
857	  cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
858	}
859      asym->section = &cr16c_elf_fcom_section;
860      asym->value = elfsym->internal_elf_sym.st_size;
861      break;
862    case SHN_CR16C_NCOMMON:
863      if (cr16c_elf_ncom_section.name == NULL)
864	{
865	  /* Initialize the far common section.  */
866	  cr16c_elf_ncom_section.name = ".ncommon";
867	  cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
868	  cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
869	  cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
870	  cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
871	  cr16c_elf_ncom_symbol.name = ".ncommon";
872	  cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
873	  cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
874	  cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
875	}
876      asym->section = &cr16c_elf_ncom_section;
877      asym->value = elfsym->internal_elf_sym.st_size;
878      break;
879    }
880}
881
882/* Hook called by the linker routine which adds symbols from an object
883   file.  We must handle the special cr16c section numbers here.  */
884
885static bfd_boolean
886elf32_cr16c_add_symbol_hook (bfd *abfd,
887			     struct bfd_link_info *info ATTRIBUTE_UNUSED,
888			     Elf_Internal_Sym *sym,
889			     const char **namep ATTRIBUTE_UNUSED,
890			     flagword *flagsp ATTRIBUTE_UNUSED,
891			     asection **secp,
892			     bfd_vma *valp)
893{
894  unsigned int indx = sym->st_shndx;
895
896  switch (indx)
897    {
898    case SHN_CR16C_FCOMMON:
899      *secp = bfd_make_section_old_way (abfd, ".fcommon");
900      (*secp)->flags |= SEC_IS_COMMON;
901      *valp = sym->st_size;
902      break;
903    case SHN_CR16C_NCOMMON:
904      *secp = bfd_make_section_old_way (abfd, ".ncommon");
905      (*secp)->flags |= SEC_IS_COMMON;
906      *valp = sym->st_size;
907      break;
908    }
909
910  return TRUE;
911}
912
913static bfd_boolean
914elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
915				     const char *name ATTRIBUTE_UNUSED,
916				     Elf_Internal_Sym *sym,
917				     asection *input_sec,
918				     struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
919{
920  /* If we see a common symbol, which implies a relocatable link, then
921     if a symbol was in a special common section in an input file, mark
922     it as a special common in the output file.  */
923
924  if (sym->st_shndx == SHN_COMMON)
925    {
926      if (strcmp (input_sec->name, ".fcommon") == 0)
927	sym->st_shndx = SHN_CR16C_FCOMMON;
928      else if (strcmp (input_sec->name, ".ncommon") == 0)
929	sym->st_shndx = SHN_CR16C_NCOMMON;
930    }
931
932  return TRUE;
933}
934
935/* Definitions for setting CR16C target vector.  */
936#define TARGET_LITTLE_SYM		bfd_elf32_cr16c_vec
937#define TARGET_LITTLE_NAME		"elf32-cr16c"
938#define ELF_ARCH			bfd_arch_cr16c
939#define ELF_MACHINE_CODE		EM_CR
940#define ELF_MAXPAGESIZE			0x1
941#define elf_symbol_leading_char		'_'
942
943#define bfd_elf32_bfd_reloc_type_lookup		elf_cr16c_reloc_type_lookup
944#define elf_info_to_howto			elf_cr16c_info_to_howto
945#define elf_info_to_howto_rel			elf_cr16c_info_to_howto_rel
946#define elf_backend_relocate_section		elf32_cr16c_relocate_section
947#define elf_backend_symbol_processing		elf32_cr16c_symbol_processing
948#define elf_backend_section_from_bfd_section 	elf32_cr16c_section_from_bfd_section
949#define elf_backend_add_symbol_hook		elf32_cr16c_add_symbol_hook
950#define elf_backend_link_output_symbol_hook 	elf32_cr16c_link_output_symbol_hook
951
952#define elf_backend_can_gc_sections     1
953
954#include "elf32-target.h"
955