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