2007-07-03 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / bfd / elf32-cr16c.c
CommitLineData
0949843d 1/* BFD back-end for National Semiconductor's CR16C ELF
ab96bf03 2 Copyright 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
0949843d
NC
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
3e110533 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
0949843d 19
0949843d 20#include "sysdep.h"
3db64b00 21#include "bfd.h"
0949843d
NC
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
157090f7
AM
153static reloc_howto_type *
154elf_cr16c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
155 const char *r_name)
156{
157 unsigned int i;
158
159 for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
160 if (elf_howto_table[i].name != NULL
161 && strcasecmp (elf_howto_table[i].name, r_name) == 0)
162 return &elf_howto_table[i];
163
164 return NULL;
165}
166
0949843d
NC
167static void
168elf_cr16c_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
169 arelent *cache_ptr ATTRIBUTE_UNUSED,
170 Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
171{
172 abort ();
173}
174
175static void
176elf_cr16c_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
177 arelent *cache_ptr,
178 Elf_Internal_Rela *dst)
179{
180 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
181
182 BFD_ASSERT (r_type < (unsigned int) RINDEX_16C_MAX);
183 cache_ptr->howto = &elf_howto_table[r_type];
184}
185
186/* Perform a relocation as part of a final link. */
187
188static bfd_reloc_status_type
189cr16c_elf_final_link_relocate (reloc_howto_type *howto,
190 bfd *abfd,
191 bfd *output_bfd ATTRIBUTE_UNUSED,
192 asection *input_section,
193 bfd_byte *data,
194 bfd_vma octets,
195 bfd_vma Rvalue,
196 bfd_vma addend ATTRIBUTE_UNUSED,
197 struct bfd_link_info *info ATTRIBUTE_UNUSED,
198 asection *sym_sec ATTRIBUTE_UNUSED,
199 int is_local ATTRIBUTE_UNUSED)
200{
201 long value;
202 short sword; /* Extracted from the hole and put back. */
203 unsigned long format, addr_type, code_factor;
204 unsigned short size;
205 unsigned short r_type;
206 asymbol *symbol = NULL;
207
208 unsigned long disp20_opcod;
209 char neg = 0;
210 char neg2pos = 0;
211
212 long left_val = 0;
213 long plus_factor = 0; /* To be added to the hole. */
214
215#define MIN_BYTE ((int) 0xFFFFFF80)
216#define MIN_WORD ((int) 0xFFFF8000)
217#define MAX_UWORD ((unsigned) 0x0000FFFF)
218#define MAX_UBYTE ((unsigned) 0x000000FF)
219
220 r_type = reloc_map_index[howto->type].cr_reloc_type;
221 format = r_type & R_FORMAT;
222 size = r_type & R_SIZESP;
223 addr_type = r_type & R_ADDRTYPE;
224 code_factor = ((addr_type == R_CODE_ADDR) ? 1 : 0);
225
226 if (sym_sec)
227 symbol = sym_sec->symbol;
228
229 switch (format)
230 {
231 case R_NUMBER:
232 switch (size)
233 {
234 case R_S_16C_08: /* One byte. */
235 value = bfd_get_8 (abfd, (char *) data + octets);
236 break;
237 case R_S_16C_16: /* Two bytes. */
238 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
239 value = sword;
240 break;
241 case R_S_16C_32: /* Four bytes. */
242 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
243 break;
244 default:
245 return bfd_reloc_notsupported;
246 }
247 break;
248
249 case R_16C_DISPL:
250 switch (size)
251 {
252 case R_S_16C_04: /* word1(4-7). */
253 value = bfd_get_8 (abfd, (char *) data + octets);
254 left_val = value & 0xF;
255 value = (value & 0xF0) >> 4;
256 value++;
257 value <<= 1;
258 break;
259 case R_S_16C_08: /* word1(0-3,8-11). */
260 sword = bfd_get_16 (abfd, (char *) data + octets);
261 value = sword & 0x000F;
262 value |= ((sword & 0x0F00) >> 4);
263 left_val = sword & 0xF0F0;
264 value <<= 1;
265 if (value & 0x100)
266 value |= 0xFFFFFF00;
267 break;
268 case R_S_16C_16: /* word2. */
269 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
270 value = sword;
271 value = ((value & 0xFFFE) >> 1) | ((value & 0x1) << 15);
272 value <<= 1;
273 if (value & 0x10000)
274 value |= 0xFFFF0000;
275 break;
276 case R_S_16C_24_a: /* word1(0-7),word2. */
277 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
278 left_val = value & 0x0000FF00;
279 value = ((value & 0xFFFE0000) >> 17) |
280 ((value & 0x00010000) << 7) | ((value & 0x000000FF) << 15);
281 value <<= 1;
282 if (value & 0x1000000)
283 value |= 0xFE000000;
284 break;
285 case R_S_16C_24: /* word2(0-3,8-11),word3. */
286 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
287 left_val = value & 0x0000F0F0;
288 value = ((value >> 16) & 0x0000FFFF) |
289 ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
290
291 value = ((value & 0x00FFFFFE) >> 1) | ((value & 0x00000001) << 23);
292
293 value <<= 1;
294 if (value & 0x1000000)
295 value |= 0xFE000000;
296 break;
297 default:
298 return bfd_reloc_notsupported;
299 }
300 break;
301
302 case R_16C_REGREL:
303 switch (size)
304 {
305 case R_S_16C_04: /* word1(12-15) not scaled. */
306 value = bfd_get_8 (abfd, (char *) data + octets);
307 left_val = value & 0xF0;
308 value = value & 0xF;
309 break;
310 case R_S_16C_04_a: /* word1(12-15) scaled by 2. */
311 value = bfd_get_8 (abfd, (char *) data + octets);
312 left_val = value & 0xF0;
313 value = value & 0xF;
314 value <<= 1;
315 break;
316 case R_S_16C_14: /* word1(4-5),word2(0-3,8-15). */
317 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
318 left_val = value & 0x00F0FFCF;
319 value = ((value & 0xc0000000) >> 24) |
320 ((value & 0x3F000000) >> 16) |
321 ((value & 0x000F0000) >> 16) | (value & 0x00000030);
322 break;
323 case R_S_16C_16: /* word2. */
324 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
325 value = sword;
326 break;
327 case R_S_16C_20: /* word2(8-11),word3. */
328 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
329 left_val = value & 0xF0;
330 value = (value & 0xF) << 16;
331 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets + 1);
332 value = value | (unsigned short) sword;
333 disp20_opcod = bfd_get_32 (abfd, (bfd_byte *) data + octets - 3);
334 disp20_opcod |= 0x0FFF0000;
335 if ((disp20_opcod == 0x4FFF0018) || /* loadb -disp20(reg) */
336 (disp20_opcod == 0x5FFF0018) || /* loadb -disp20(rp) */
337 (disp20_opcod == 0x8FFF0018) || /* loadd -disp20(reg) */
338 (disp20_opcod == 0x9FFF0018) || /* loadd -disp20(rp) */
339 (disp20_opcod == 0xCFFF0018) || /* loadw -disp20(reg) */
340 (disp20_opcod == 0xDFFF0018) || /* loadw -disp20(rp) */
341 (disp20_opcod == 0x4FFF0019) || /* storb -disp20(reg) */
342 (disp20_opcod == 0x5FFF0019) || /* storb -disp20(rp) */
343 (disp20_opcod == 0x8FFF0019) || /* stord -disp20(reg) */
344 (disp20_opcod == 0x9FFF0019) || /* stord -disp20(rp) */
345 (disp20_opcod == 0xCFFF0019) || /* storw -disp20(reg) */
346 (disp20_opcod == 0xDFFF0019))
347 { /* storw -disp20(rp). */
348 neg = 1;
349 value |= 0xFFF00000;
350 }
351
352 break;
353 default:
354 return bfd_reloc_notsupported;
355 }
356 break;
357
358 case R_16C_ABS:
359 switch (size)
360 {
361 case R_S_16C_20: /* word1(0-3),word2. */
362 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
363 left_val = value & 0x0000FFF0;
364 value = ((value & 0xFFFF0000) >> 16) |
365 ((value & 0x0000000F) << 16);
366 break;
367 case R_S_16C_24: /* word2(0-3,8-11),word3. */
368 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
369 left_val = value & 0x0000F0F0;
370 value = ((value & 0xFFFF0000) >> 16) |
371 ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
372 break;
373 default:
374 return bfd_reloc_notsupported;
375 }
376 break;
377
378 case R_16C_IMMED:
379 switch (size)
380 {
381 case R_S_16C_04: /* word1/2(4-7). */
382 value = bfd_get_8 (abfd, (char *) data + octets);
383 left_val = value & 0xF;
384 value = (value & 0xF0) >> 4;
385 break;
386 case R_S_16C_16: /* word2. */
387 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
388 value = sword;
389 break;
390 case R_S_16C_20: /* word1(0-3),word2. */
391 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
392 left_val = value & 0x0000FFF0;
393 value = ((value & 0xFFFF0000) >> 16) |
394 ((value & 0x0000000F) << 16);
395 break;
396 case R_S_16C_32: /* word2, word3. */
397 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
398 value = ((value & 0x0000FFFF) << 16) |
399 ((value & 0xFFFF0000) >> 16);
400 break;
401 default:
402 return bfd_reloc_notsupported;
403 }
404 break;
405 default:
406 return bfd_reloc_notsupported;
407 }
408
409 switch ((r_type & R_RELTO) >> 4)
410 {
411
412 case 0: /* R_ABS. */
413 plus_factor = Rvalue;
414 break;
415 case 1: /* R_PCREL. */
416 plus_factor = Rvalue -
417 (input_section->output_section->vma + input_section->output_offset);
418 break;
419 default:
420 return bfd_reloc_notsupported;
421 }
422
423 if (neg)
424 {
425 if (plus_factor >= -value)
426 neg2pos = 1;
427 /* We need to change load/stor with negative
428 displ opcode to positive disp opcode (CR16C). */
429 }
430
431 value = value + (plus_factor >> code_factor);
432
433 switch (format)
434 {
435 case R_NUMBER:
436 switch (size)
437 {
438 case R_S_16C_08: /* One byte. */
439 if (value > (int) MAX_UBYTE || value < MIN_BYTE)
440 return bfd_reloc_overflow;
441 value &= 0xFF;
442 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 443 break;
90e868ac 444
0949843d
NC
445 case R_S_16C_16: /* Two bytes. */
446 if (value > (int) MAX_UWORD || value < MIN_WORD)
447 return bfd_reloc_overflow;
448 value &= 0xFFFF;
449 sword = value;
450 bfd_put_16 (abfd, (bfd_vma) sword,
451 (unsigned char *) data + octets);
0949843d 452 break;
90e868ac 453
0949843d
NC
454 case R_S_16C_32: /* Four bytes. */
455 value &= 0xFFFFFFFF;
456 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 457 break;
90e868ac 458
0949843d
NC
459 default:
460 return bfd_reloc_notsupported;
461 }
462 break;
463
464 case R_16C_DISPL:
465 switch (size)
466 {
467 case R_S_16C_04: /* word1(4-7). */
468 if ((value - 32) > 32 || value < 2)
469 return bfd_reloc_overflow;
470 value >>= 1;
471 value--;
472 value &= 0xF;
473 value <<= 4;
474 value |= left_val;
475 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 476 break;
90e868ac 477
0949843d
NC
478 case R_S_16C_08: /* word1(0-3,8-11). */
479 if (value > 255 || value < -256 || value == 0x80)
480 return bfd_reloc_overflow;
481 value &= 0x1FF;
482 value >>= 1;
483 sword = value & 0x000F;
484 sword |= (value & 0x00F0) << 4;
485 sword |= left_val;
486 bfd_put_16 (abfd, (bfd_vma) sword,
487 (unsigned char *) data + octets);
0949843d 488 break;
90e868ac 489
0949843d
NC
490 case R_S_16C_16: /* word2. */
491 if (value > 65535 || value < -65536)
492 return bfd_reloc_overflow;
493 value >>= 1;
494 value &= 0xFFFF;
495 value = ((value & 0x8000) >> 15) | ((value & 0x7FFF) << 1);
496 sword = value;
497 bfd_put_16 (abfd, (bfd_vma) sword,
498 (unsigned char *) data + octets);
0949843d 499 break;
90e868ac 500
0949843d
NC
501 case R_S_16C_24_a: /* word1(0-7),word2. */
502 if (value > 16777215 || value < -16777216)
503 return bfd_reloc_overflow;
504 value &= 0x1FFFFFF;
505 value >>= 1;
506 value = ((value & 0x00007FFF) << 17) |
507 ((value & 0x00800000) >> 7) | ((value & 0x007F8000) >> 15);
508 value |= left_val;
509 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 510 break;
90e868ac 511
0949843d
NC
512 case R_S_16C_24: /* word2(0-3,8-11),word3. */
513 if (value > 16777215 || value < -16777216)
514 return bfd_reloc_overflow;
515 value &= 0x1FFFFFF;
516 value >>= 1;
517
518 value = ((value & 0x007FFFFF) << 1) | ((value & 0x00800000) >> 23);
519
520 value = ((value & 0x0000FFFF) << 16) |
521 ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
522 value |= left_val;
523 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 524 break;
90e868ac 525
0949843d
NC
526 default:
527 return bfd_reloc_notsupported;
528 }
529 break;
530
531 case R_16C_REGREL:
532 switch (size)
533 {
534 case R_S_16C_04: /* word1(12-15) not scaled. */
535 if (value > 13 || value < 0)
536 return bfd_reloc_overflow;
537 value &= 0xF;
538 value |= left_val;
539 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 540 break;
90e868ac 541
0949843d
NC
542 case R_S_16C_04_a: /* word1(12-15) not scaled. */
543 if (value > 26 || value < 0)
544 return bfd_reloc_overflow;
545 value &= 0x1F;
546 value >>= 1;
547 value |= left_val;
548 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 549 break;
90e868ac 550
0949843d
NC
551 case R_S_16C_14: /* word1(4-5),word2(0-3,8-15). */
552 if (value < 0 || value > 16383)
553 return bfd_reloc_overflow;
554 value &= 0x3FFF;
555 value = ((value & 0x000000c0) << 24) |
556 ((value & 0x00003F00) << 16) |
557 ((value & 0x0000000F) << 16) | (value & 0x00000030);
558 value |= left_val;
559 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 560 break;
90e868ac 561
0949843d
NC
562 case R_S_16C_16: /* word2. */
563 if (value > 65535 || value < 0)
564 return bfd_reloc_overflow;
565 value &= 0xFFFF;
566 sword = value;
567 bfd_put_16 (abfd, (bfd_vma) sword,
568 (unsigned char *) data + octets);
0949843d 569 break;
90e868ac 570
0949843d
NC
571 case R_S_16C_20: /* word2(8-11),word3. */
572 /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
573 value &= 0xFFFFF;
574 sword = value & 0x0000FFFF;
575 value = (value & 0x000F0000) >> 16;
576 value |= left_val;
577 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
578 bfd_put_16 (abfd, (bfd_vma) sword,
579 (unsigned char *) data + octets + 1);
580 if (neg2pos)
581 {
582 /* Change load/stor negative displ opcode
583 to load/stor positive displ opcode. */
584 value = bfd_get_8 (abfd, (char *) data + octets - 3);
585 value &= 0xF7;
586 value |= 0x2;
587 bfd_put_8 (abfd, (bfd_vma) value,
588 (unsigned char *) data + octets - 3);
589 }
0949843d 590 break;
90e868ac 591
0949843d
NC
592 default:
593 return bfd_reloc_notsupported;
594 }
595 break;
596
597 case R_16C_ABS:
598 switch (size)
599 {
600 case R_S_16C_20: /* word1(0-3),word2. */
601 if (value > 1048575 || value < 0)
602 return bfd_reloc_overflow;
603 value &= 0xFFFFF;
604 value = ((value & 0x0000FFFF) << 16) |
605 ((value & 0x000F0000) >> 16);
606 value |= left_val;
607 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 608 break;
90e868ac 609
0949843d
NC
610 case R_S_16C_24: /* word2(0-3,8-11),word3. */
611 /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
612 value &= 0xFFFFFF;
613 value = ((value & 0x0000FFFF) << 16) |
614 ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
615 value |= left_val;
616 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 617 break;
90e868ac 618
0949843d
NC
619 default:
620 return bfd_reloc_notsupported;
621 }
622 break;
623
624 case R_16C_IMMED:
625 switch (size)
626 {
627 case R_S_16C_04: /* word1/2(4-7). */
628 if (value > 15 || value < -1)
629 return bfd_reloc_overflow;
630 value &= 0xF;
631 value <<= 4;
632 value |= left_val;
633 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 634 break;
90e868ac 635
0949843d
NC
636 case R_S_16C_16: /* word2. */
637 if (value > 32767 || value < -32768)
638 return bfd_reloc_overflow;
639 value &= 0xFFFF;
640 sword = value;
641 bfd_put_16 (abfd, (bfd_vma) sword,
642 (unsigned char *) data + octets);
0949843d 643 break;
90e868ac 644
0949843d
NC
645 case R_S_16C_20: /* word1(0-3),word2. */
646 if (value > 1048575 || value < 0)
647 return bfd_reloc_overflow;
648 value &= 0xFFFFF;
649 value = ((value & 0x0000FFFF) << 16) |
650 ((value & 0x000F0000) >> 16);
651 value |= left_val;
652 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 653 break;
90e868ac 654
0949843d
NC
655 case R_S_16C_32: /* word2, word3. */
656 value &= 0xFFFFFFFF;
657 value = ((value & 0x0000FFFF) << 16) |
658 ((value & 0xFFFF0000) >> 16);
659 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 660 break;
90e868ac 661
0949843d
NC
662 default:
663 return bfd_reloc_notsupported;
664 }
665 break;
666 default:
667 return bfd_reloc_notsupported;
668 }
90e868ac
NC
669
670 return bfd_reloc_ok;
0949843d
NC
671}
672
673/* Relocate a CR16C ELF section. */
674
675static bfd_boolean
676elf32_cr16c_relocate_section (bfd *output_bfd,
677 struct bfd_link_info *info,
678 bfd *input_bfd,
679 asection *input_section,
680 bfd_byte *contents,
681 Elf_Internal_Rela *relocs,
682 Elf_Internal_Sym *local_syms,
683 asection **local_sections)
684{
685 Elf_Internal_Shdr *symtab_hdr;
686 struct elf_link_hash_entry **sym_hashes;
687 Elf_Internal_Rela *rel, *relend;
688
689 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
690 sym_hashes = elf_sym_hashes (input_bfd);
691
692 rel = relocs;
693 relend = relocs + input_section->reloc_count;
694 for (; rel < relend; rel++)
695 {
696 int r_type;
697 reloc_howto_type *howto;
698 unsigned long r_symndx;
699 Elf_Internal_Sym *sym;
700 asection *sec;
701 struct elf_link_hash_entry *h;
702 bfd_vma relocation;
703 bfd_reloc_status_type r;
704
705 r_symndx = ELF32_R_SYM (rel->r_info);
706 r_type = ELF32_R_TYPE (rel->r_info);
707 howto = elf_howto_table + r_type;
708
0949843d
NC
709 h = NULL;
710 sym = NULL;
711 sec = NULL;
712 if (r_symndx < symtab_hdr->sh_info)
713 {
714 sym = local_syms + r_symndx;
715 sec = local_sections[r_symndx];
716 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
717 }
718 else
719 {
a4d7b4b5
L
720 bfd_boolean unresolved_reloc, warned;
721
722 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
723 r_symndx, symtab_hdr, sym_hashes,
724 h, sec, relocation,
725 unresolved_reloc, warned);
0949843d
NC
726 }
727
ab96bf03
AM
728 if (sec != NULL && elf_discarded_section (sec))
729 {
730 /* For relocs against symbols from removed linkonce sections,
731 or sections discarded by a linker script, we just want the
732 section contents zeroed. Avoid any special processing. */
733 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
734 rel->r_info = 0;
735 rel->r_addend = 0;
736 continue;
737 }
738
739 if (info->relocatable)
740 {
741 /* This is a relocatable link. We don't have to change
742 anything, unless the reloc is against a section symbol,
743 in which case we have to adjust according to where the
744 section symbol winds up in the output section. */
745 if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
746 rel->r_addend += sec->output_offset;
747 continue;
748 }
749
0949843d
NC
750 r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
751 input_section,
752 contents, rel->r_offset,
753 relocation, rel->r_addend,
754 info, sec, h == NULL);
755
756 if (r != bfd_reloc_ok)
757 {
758 const char *name;
759 const char *msg = (const char *) 0;
760
761 if (h != NULL)
762 name = h->root.root.string;
763 else
764 {
765 name = (bfd_elf_string_from_elf_section
766 (input_bfd, symtab_hdr->sh_link, sym->st_name));
767 if (name == NULL || *name == '\0')
768 name = bfd_section_name (input_bfd, sec);
769 }
770
771 switch (r)
772 {
773 case bfd_reloc_overflow:
774 if (!((*info->callbacks->reloc_overflow)
dfeffb9f
L
775 (info, (h ? &h->root : NULL), name, howto->name,
776 (bfd_vma) 0, input_bfd, input_section,
777 rel->r_offset)))
0949843d
NC
778 return FALSE;
779 break;
780
781 case bfd_reloc_undefined:
782 if (!((*info->callbacks->undefined_symbol)
783 (info, name, input_bfd, input_section,
784 rel->r_offset, TRUE)))
785 return FALSE;
786 break;
787
788 case bfd_reloc_outofrange:
789 msg = _("internal error: out of range error");
790 goto common_error;
791
792 case bfd_reloc_notsupported:
793 msg = _("internal error: unsupported relocation error");
794 goto common_error;
795
796 case bfd_reloc_dangerous:
797 msg = _("internal error: dangerous error");
798 goto common_error;
799
800 default:
801 msg = _("internal error: unknown error");
802 /* fall through */
803
804 common_error:
805 if (!((*info->callbacks->warning)
806 (info, msg, name, input_bfd, input_section,
807 rel->r_offset)))
808 return FALSE;
809 break;
810 }
811 }
812 }
813
814 return TRUE;
815}
816
0949843d
NC
817/* CR16C ELF uses three common sections:
818 One is for default common symbols (placed in usual common section).
819 Second is for near common symbols (placed in "ncommon" section).
820 Third is for far common symbols (placed in "fcommon" section).
821 The following implementation is based on elf32-mips architecture */
822
823static asection cr16c_elf_fcom_section;
824static asymbol cr16c_elf_fcom_symbol;
825static asymbol * cr16c_elf_fcom_symbol_ptr;
826static asection cr16c_elf_ncom_section;
827static asymbol cr16c_elf_ncom_symbol;
828static asymbol * cr16c_elf_ncom_symbol_ptr;
829
830/* Given a BFD section, try to locate the
831 corresponding ELF section index. */
832
833static bfd_boolean
834elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
835 asection *sec,
836 int *retval)
837{
838 if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
839 *retval = SHN_CR16C_FCOMMON;
840 else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
841 *retval = SHN_CR16C_NCOMMON;
842 else
843 return FALSE;
844
845 return TRUE;
846}
847
848/* Handle the special CR16C section numbers that a symbol may use. */
849
850static void
851elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
852 asymbol *asym)
853{
854 elf_symbol_type *elfsym = (elf_symbol_type *) asym;
855 unsigned int indx;
856
857 indx = elfsym->internal_elf_sym.st_shndx;
858
859 switch (indx)
860 {
861 case SHN_CR16C_FCOMMON:
862 if (cr16c_elf_fcom_section.name == NULL)
863 {
864 /* Initialize the far common section. */
865 cr16c_elf_fcom_section.name = ".fcommon";
866 cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
867 cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
868 cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
869 cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
870 cr16c_elf_fcom_symbol.name = ".fcommon";
871 cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
872 cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
873 cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
874 }
875 asym->section = &cr16c_elf_fcom_section;
876 asym->value = elfsym->internal_elf_sym.st_size;
877 break;
878 case SHN_CR16C_NCOMMON:
879 if (cr16c_elf_ncom_section.name == NULL)
880 {
881 /* Initialize the far common section. */
882 cr16c_elf_ncom_section.name = ".ncommon";
883 cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
884 cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
885 cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
886 cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
887 cr16c_elf_ncom_symbol.name = ".ncommon";
888 cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
889 cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
890 cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
891 }
892 asym->section = &cr16c_elf_ncom_section;
893 asym->value = elfsym->internal_elf_sym.st_size;
894 break;
895 }
896}
897
898/* Hook called by the linker routine which adds symbols from an object
899 file. We must handle the special cr16c section numbers here. */
900
901static bfd_boolean
902elf32_cr16c_add_symbol_hook (bfd *abfd,
903 struct bfd_link_info *info ATTRIBUTE_UNUSED,
a4d7b4b5 904 Elf_Internal_Sym *sym,
0949843d
NC
905 const char **namep ATTRIBUTE_UNUSED,
906 flagword *flagsp ATTRIBUTE_UNUSED,
907 asection **secp,
908 bfd_vma *valp)
909{
910 unsigned int indx = sym->st_shndx;
911
912 switch (indx)
913 {
914 case SHN_CR16C_FCOMMON:
915 *secp = bfd_make_section_old_way (abfd, ".fcommon");
916 (*secp)->flags |= SEC_IS_COMMON;
917 *valp = sym->st_size;
918 break;
919 case SHN_CR16C_NCOMMON:
920 *secp = bfd_make_section_old_way (abfd, ".ncommon");
921 (*secp)->flags |= SEC_IS_COMMON;
922 *valp = sym->st_size;
923 break;
924 }
925
926 return TRUE;
927}
928
929static bfd_boolean
930elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
931 const char *name ATTRIBUTE_UNUSED,
932 Elf_Internal_Sym *sym,
933 asection *input_sec,
934 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
935{
936 /* If we see a common symbol, which implies a relocatable link, then
937 if a symbol was in a special common section in an input file, mark
938 it as a special common in the output file. */
939
940 if (sym->st_shndx == SHN_COMMON)
941 {
942 if (strcmp (input_sec->name, ".fcommon") == 0)
943 sym->st_shndx = SHN_CR16C_FCOMMON;
944 else if (strcmp (input_sec->name, ".ncommon") == 0)
945 sym->st_shndx = SHN_CR16C_NCOMMON;
946 }
947
948 return TRUE;
949}
950
951/* Definitions for setting CR16C target vector. */
952#define TARGET_LITTLE_SYM bfd_elf32_cr16c_vec
953#define TARGET_LITTLE_NAME "elf32-cr16c"
954#define ELF_ARCH bfd_arch_cr16c
955#define ELF_MACHINE_CODE EM_CR
956#define ELF_MAXPAGESIZE 0x1
957#define elf_symbol_leading_char '_'
958
959#define bfd_elf32_bfd_reloc_type_lookup elf_cr16c_reloc_type_lookup
157090f7 960#define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
0949843d
NC
961#define elf_info_to_howto elf_cr16c_info_to_howto
962#define elf_info_to_howto_rel elf_cr16c_info_to_howto_rel
963#define elf_backend_relocate_section elf32_cr16c_relocate_section
0949843d
NC
964#define elf_backend_symbol_processing elf32_cr16c_symbol_processing
965#define elf_backend_section_from_bfd_section elf32_cr16c_section_from_bfd_section
966#define elf_backend_add_symbol_hook elf32_cr16c_add_symbol_hook
967#define elf_backend_link_output_symbol_hook elf32_cr16c_link_output_symbol_hook
968
969#define elf_backend_can_gc_sections 1
970
971#include "elf32-target.h"
This page took 0.184287 seconds and 4 git commands to generate.