bfd target vector rationalisation
[deliverable/binutils-gdb.git] / bfd / elf32-cr16c.c
CommitLineData
0949843d 1/* BFD back-end for National Semiconductor's CR16C ELF
4b95cf5c 2 Copyright (C) 2004-2014 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
cd123cb7 8 the Free Software Foundation; either version 3 of the License, or
0949843d
NC
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
cd123cb7
NC
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
0949843d 20
0949843d 21#include "sysdep.h"
3db64b00 22#include "bfd.h"
0949843d
NC
23#include "libbfd.h"
24#include "bfdlink.h"
25#include "elf/cr16c.h"
26#include "elf-bfd.h"
27
28
29#define USE_REL 1 /* CR16C uses REL relocations instead of RELA. */
30
68ffbac6 31/* The following definition is based on EMPTY_HOWTO macro,
0949843d
NC
32 but also initiates the "name" field in HOWTO struct. */
33#define ONLY_NAME_HOWTO(C) \
34 HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
35 STRINGX(C), FALSE, 0, 0, FALSE)
36
37/* reloc_map_index array maps CRASM relocation type into a BFD
68ffbac6 38 relocation enum. The array's indices are synchronized with
0949843d
NC
39 RINDEX_16C_* indices, created in include/elf/cr16c.h.
40 The array is used in:
41 1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
42 2. asreloc.c : find_reloc_type(). */
43
44RELOC_MAP reloc_map_index[RINDEX_16C_MAX] =
45{
46 {R_16C_NUM08, BFD_RELOC_16C_NUM08},
47 {R_16C_NUM08_C, BFD_RELOC_16C_NUM08_C},
48 {R_16C_NUM16, BFD_RELOC_16C_NUM16},
49 {R_16C_NUM16_C, BFD_RELOC_16C_NUM16_C},
50 {R_16C_NUM32, BFD_RELOC_16C_NUM32},
51 {R_16C_NUM32_C, BFD_RELOC_16C_NUM32_C},
52 {R_16C_DISP04, BFD_RELOC_16C_DISP04},
53 {R_16C_DISP04_C, BFD_RELOC_16C_DISP04_C},
54 {R_16C_DISP08, BFD_RELOC_16C_DISP08},
55 {R_16C_DISP08_C, BFD_RELOC_16C_DISP08_C},
56 {R_16C_DISP16, BFD_RELOC_16C_DISP16},
57 {R_16C_DISP16_C, BFD_RELOC_16C_DISP16_C},
58 {R_16C_DISP24, BFD_RELOC_16C_DISP24},
59 {R_16C_DISP24_C, BFD_RELOC_16C_DISP24_C},
60 {R_16C_DISP24a, BFD_RELOC_16C_DISP24a},
61 {R_16C_DISP24a_C, BFD_RELOC_16C_DISP24a_C},
62 {R_16C_REG04, BFD_RELOC_16C_REG04},
63 {R_16C_REG04_C, BFD_RELOC_16C_REG04_C},
64 {R_16C_REG04a, BFD_RELOC_16C_REG04a},
65 {R_16C_REG04a_C, BFD_RELOC_16C_REG04a_C},
66 {R_16C_REG14, BFD_RELOC_16C_REG14},
67 {R_16C_REG14_C, BFD_RELOC_16C_REG14_C},
68 {R_16C_REG16, BFD_RELOC_16C_REG16},
69 {R_16C_REG16_C, BFD_RELOC_16C_REG16_C},
70 {R_16C_REG20, BFD_RELOC_16C_REG20},
71 {R_16C_REG20_C, BFD_RELOC_16C_REG20_C},
72 {R_16C_ABS20, BFD_RELOC_16C_ABS20},
73 {R_16C_ABS20_C, BFD_RELOC_16C_ABS20_C},
74 {R_16C_ABS24, BFD_RELOC_16C_ABS24},
75 {R_16C_ABS24_C, BFD_RELOC_16C_ABS24_C},
76 {R_16C_IMM04, BFD_RELOC_16C_IMM04},
77 {R_16C_IMM04_C, BFD_RELOC_16C_IMM04_C},
78 {R_16C_IMM16, BFD_RELOC_16C_IMM16},
79 {R_16C_IMM16_C, BFD_RELOC_16C_IMM16_C},
80 {R_16C_IMM20, BFD_RELOC_16C_IMM20},
81 {R_16C_IMM20_C, BFD_RELOC_16C_IMM20_C},
82 {R_16C_IMM24, BFD_RELOC_16C_IMM24},
83 {R_16C_IMM24_C, BFD_RELOC_16C_IMM24_C},
84 {R_16C_IMM32, BFD_RELOC_16C_IMM32},
85 {R_16C_IMM32_C, BFD_RELOC_16C_IMM32_C}
86};
87
88static reloc_howto_type elf_howto_table[] =
89{
90 /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08),
91 /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C),
92 /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16),
93 /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C),
94 /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32),
95 /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C),
96 /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04),
97 /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C),
98 /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08),
99 /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C),
100 /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16),
101 /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C),
102 /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24),
103 /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C),
104 /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a),
105 /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C),
106 /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04),
107 /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C),
108 /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a),
109 /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C),
110 /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14),
111 /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C),
112 /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16),
113 /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C),
114 /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20),
115 /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C),
116 /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20),
117 /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C),
118 /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24),
119 /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C),
120 /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04),
121 /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C),
122 /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16),
123 /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C),
124 /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20),
125 /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C),
126 /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24),
127 /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C),
128 /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32),
129 /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C)
130};
131
132
133/* Code to turn a code_type into a howto ptr, uses the above howto table. */
134
135static reloc_howto_type *
136elf_cr16c_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
137 bfd_reloc_code_real_type code)
138{
139 unsigned int i;
140
141 for (i = 0; i < RINDEX_16C_MAX; i++)
142 {
143 if (code == reloc_map_index[i].bfd_reloc_enum)
144 {
145 /* printf ("CR16C Relocation Type is - %x\n", code); */
146 return & elf_howto_table[i];
147 }
148 }
149
150 /* printf ("This relocation Type is not supported - %x\n", code); */
151 return 0;
152}
153
157090f7
AM
154static reloc_howto_type *
155elf_cr16c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
156 const char *r_name)
157{
158 unsigned int i;
159
160 for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
161 if (elf_howto_table[i].name != NULL
162 && strcasecmp (elf_howto_table[i].name, r_name) == 0)
163 return &elf_howto_table[i];
164
165 return NULL;
166}
167
0949843d
NC
168static void
169elf_cr16c_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
170 arelent *cache_ptr ATTRIBUTE_UNUSED,
171 Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
172{
173 abort ();
174}
175
176static void
177elf_cr16c_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
178 arelent *cache_ptr,
179 Elf_Internal_Rela *dst)
180{
181 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
182
183 BFD_ASSERT (r_type < (unsigned int) RINDEX_16C_MAX);
184 cache_ptr->howto = &elf_howto_table[r_type];
185}
186
187/* Perform a relocation as part of a final link. */
188
189static bfd_reloc_status_type
190cr16c_elf_final_link_relocate (reloc_howto_type *howto,
191 bfd *abfd,
192 bfd *output_bfd ATTRIBUTE_UNUSED,
193 asection *input_section,
194 bfd_byte *data,
195 bfd_vma octets,
196 bfd_vma Rvalue,
197 bfd_vma addend ATTRIBUTE_UNUSED,
198 struct bfd_link_info *info ATTRIBUTE_UNUSED,
199 asection *sym_sec ATTRIBUTE_UNUSED,
200 int is_local ATTRIBUTE_UNUSED)
201{
202 long value;
203 short sword; /* Extracted from the hole and put back. */
204 unsigned long format, addr_type, code_factor;
205 unsigned short size;
206 unsigned short r_type;
0949843d
NC
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
0949843d
NC
226 switch (format)
227 {
228 case R_NUMBER:
229 switch (size)
230 {
231 case R_S_16C_08: /* One byte. */
232 value = bfd_get_8 (abfd, (char *) data + octets);
233 break;
234 case R_S_16C_16: /* Two bytes. */
235 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
236 value = sword;
237 break;
238 case R_S_16C_32: /* Four bytes. */
239 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
240 break;
241 default:
242 return bfd_reloc_notsupported;
243 }
244 break;
245
246 case R_16C_DISPL:
247 switch (size)
248 {
249 case R_S_16C_04: /* word1(4-7). */
250 value = bfd_get_8 (abfd, (char *) data + octets);
251 left_val = value & 0xF;
252 value = (value & 0xF0) >> 4;
253 value++;
254 value <<= 1;
255 break;
256 case R_S_16C_08: /* word1(0-3,8-11). */
257 sword = bfd_get_16 (abfd, (char *) data + octets);
258 value = sword & 0x000F;
259 value |= ((sword & 0x0F00) >> 4);
260 left_val = sword & 0xF0F0;
261 value <<= 1;
262 if (value & 0x100)
263 value |= 0xFFFFFF00;
264 break;
265 case R_S_16C_16: /* word2. */
266 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
267 value = sword;
268 value = ((value & 0xFFFE) >> 1) | ((value & 0x1) << 15);
269 value <<= 1;
270 if (value & 0x10000)
271 value |= 0xFFFF0000;
272 break;
273 case R_S_16C_24_a: /* word1(0-7),word2. */
274 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
275 left_val = value & 0x0000FF00;
276 value = ((value & 0xFFFE0000) >> 17) |
277 ((value & 0x00010000) << 7) | ((value & 0x000000FF) << 15);
278 value <<= 1;
279 if (value & 0x1000000)
280 value |= 0xFE000000;
281 break;
282 case R_S_16C_24: /* word2(0-3,8-11),word3. */
283 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
284 left_val = value & 0x0000F0F0;
285 value = ((value >> 16) & 0x0000FFFF) |
286 ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
287
288 value = ((value & 0x00FFFFFE) >> 1) | ((value & 0x00000001) << 23);
289
290 value <<= 1;
291 if (value & 0x1000000)
292 value |= 0xFE000000;
293 break;
294 default:
295 return bfd_reloc_notsupported;
296 }
297 break;
298
299 case R_16C_REGREL:
300 switch (size)
301 {
302 case R_S_16C_04: /* word1(12-15) not scaled. */
303 value = bfd_get_8 (abfd, (char *) data + octets);
304 left_val = value & 0xF0;
305 value = value & 0xF;
306 break;
307 case R_S_16C_04_a: /* word1(12-15) scaled by 2. */
308 value = bfd_get_8 (abfd, (char *) data + octets);
309 left_val = value & 0xF0;
310 value = value & 0xF;
311 value <<= 1;
312 break;
313 case R_S_16C_14: /* word1(4-5),word2(0-3,8-15). */
314 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
315 left_val = value & 0x00F0FFCF;
316 value = ((value & 0xc0000000) >> 24) |
317 ((value & 0x3F000000) >> 16) |
318 ((value & 0x000F0000) >> 16) | (value & 0x00000030);
319 break;
320 case R_S_16C_16: /* word2. */
321 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
322 value = sword;
323 break;
324 case R_S_16C_20: /* word2(8-11),word3. */
325 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
326 left_val = value & 0xF0;
327 value = (value & 0xF) << 16;
328 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets + 1);
329 value = value | (unsigned short) sword;
330 disp20_opcod = bfd_get_32 (abfd, (bfd_byte *) data + octets - 3);
331 disp20_opcod |= 0x0FFF0000;
332 if ((disp20_opcod == 0x4FFF0018) || /* loadb -disp20(reg) */
333 (disp20_opcod == 0x5FFF0018) || /* loadb -disp20(rp) */
334 (disp20_opcod == 0x8FFF0018) || /* loadd -disp20(reg) */
335 (disp20_opcod == 0x9FFF0018) || /* loadd -disp20(rp) */
336 (disp20_opcod == 0xCFFF0018) || /* loadw -disp20(reg) */
337 (disp20_opcod == 0xDFFF0018) || /* loadw -disp20(rp) */
338 (disp20_opcod == 0x4FFF0019) || /* storb -disp20(reg) */
339 (disp20_opcod == 0x5FFF0019) || /* storb -disp20(rp) */
340 (disp20_opcod == 0x8FFF0019) || /* stord -disp20(reg) */
341 (disp20_opcod == 0x9FFF0019) || /* stord -disp20(rp) */
342 (disp20_opcod == 0xCFFF0019) || /* storw -disp20(reg) */
343 (disp20_opcod == 0xDFFF0019))
344 { /* storw -disp20(rp). */
345 neg = 1;
346 value |= 0xFFF00000;
347 }
348
349 break;
350 default:
351 return bfd_reloc_notsupported;
352 }
353 break;
354
355 case R_16C_ABS:
356 switch (size)
357 {
358 case R_S_16C_20: /* word1(0-3),word2. */
359 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
360 left_val = value & 0x0000FFF0;
361 value = ((value & 0xFFFF0000) >> 16) |
362 ((value & 0x0000000F) << 16);
363 break;
364 case R_S_16C_24: /* word2(0-3,8-11),word3. */
365 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
366 left_val = value & 0x0000F0F0;
367 value = ((value & 0xFFFF0000) >> 16) |
368 ((value & 0x00000F00) << 8) | ((value & 0x0000000F) << 20);
369 break;
370 default:
371 return bfd_reloc_notsupported;
372 }
373 break;
374
375 case R_16C_IMMED:
376 switch (size)
377 {
378 case R_S_16C_04: /* word1/2(4-7). */
379 value = bfd_get_8 (abfd, (char *) data + octets);
380 left_val = value & 0xF;
381 value = (value & 0xF0) >> 4;
382 break;
383 case R_S_16C_16: /* word2. */
384 sword = bfd_get_16 (abfd, (bfd_byte *) data + octets);
385 value = sword;
386 break;
387 case R_S_16C_20: /* word1(0-3),word2. */
388 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
389 left_val = value & 0x0000FFF0;
390 value = ((value & 0xFFFF0000) >> 16) |
391 ((value & 0x0000000F) << 16);
392 break;
393 case R_S_16C_32: /* word2, word3. */
394 value = bfd_get_32 (abfd, (bfd_byte *) data + octets);
395 value = ((value & 0x0000FFFF) << 16) |
396 ((value & 0xFFFF0000) >> 16);
397 break;
398 default:
399 return bfd_reloc_notsupported;
400 }
401 break;
402 default:
403 return bfd_reloc_notsupported;
404 }
405
406 switch ((r_type & R_RELTO) >> 4)
407 {
408
409 case 0: /* R_ABS. */
410 plus_factor = Rvalue;
411 break;
412 case 1: /* R_PCREL. */
413 plus_factor = Rvalue -
414 (input_section->output_section->vma + input_section->output_offset);
415 break;
416 default:
417 return bfd_reloc_notsupported;
418 }
419
420 if (neg)
421 {
422 if (plus_factor >= -value)
423 neg2pos = 1;
424 /* We need to change load/stor with negative
425 displ opcode to positive disp opcode (CR16C). */
426 }
427
428 value = value + (plus_factor >> code_factor);
429
430 switch (format)
431 {
432 case R_NUMBER:
433 switch (size)
434 {
435 case R_S_16C_08: /* One byte. */
436 if (value > (int) MAX_UBYTE || value < MIN_BYTE)
437 return bfd_reloc_overflow;
438 value &= 0xFF;
439 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 440 break;
90e868ac 441
0949843d
NC
442 case R_S_16C_16: /* Two bytes. */
443 if (value > (int) MAX_UWORD || value < MIN_WORD)
444 return bfd_reloc_overflow;
445 value &= 0xFFFF;
446 sword = value;
447 bfd_put_16 (abfd, (bfd_vma) sword,
448 (unsigned char *) data + octets);
0949843d 449 break;
90e868ac 450
0949843d
NC
451 case R_S_16C_32: /* Four bytes. */
452 value &= 0xFFFFFFFF;
453 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 454 break;
90e868ac 455
0949843d
NC
456 default:
457 return bfd_reloc_notsupported;
458 }
459 break;
460
461 case R_16C_DISPL:
462 switch (size)
463 {
464 case R_S_16C_04: /* word1(4-7). */
465 if ((value - 32) > 32 || value < 2)
466 return bfd_reloc_overflow;
467 value >>= 1;
468 value--;
469 value &= 0xF;
470 value <<= 4;
471 value |= left_val;
472 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 473 break;
90e868ac 474
0949843d
NC
475 case R_S_16C_08: /* word1(0-3,8-11). */
476 if (value > 255 || value < -256 || value == 0x80)
477 return bfd_reloc_overflow;
478 value &= 0x1FF;
479 value >>= 1;
480 sword = value & 0x000F;
481 sword |= (value & 0x00F0) << 4;
482 sword |= left_val;
483 bfd_put_16 (abfd, (bfd_vma) sword,
484 (unsigned char *) data + octets);
0949843d 485 break;
90e868ac 486
0949843d
NC
487 case R_S_16C_16: /* word2. */
488 if (value > 65535 || value < -65536)
489 return bfd_reloc_overflow;
490 value >>= 1;
491 value &= 0xFFFF;
492 value = ((value & 0x8000) >> 15) | ((value & 0x7FFF) << 1);
493 sword = value;
494 bfd_put_16 (abfd, (bfd_vma) sword,
495 (unsigned char *) data + octets);
0949843d 496 break;
90e868ac 497
0949843d
NC
498 case R_S_16C_24_a: /* word1(0-7),word2. */
499 if (value > 16777215 || value < -16777216)
500 return bfd_reloc_overflow;
501 value &= 0x1FFFFFF;
502 value >>= 1;
503 value = ((value & 0x00007FFF) << 17) |
504 ((value & 0x00800000) >> 7) | ((value & 0x007F8000) >> 15);
505 value |= left_val;
506 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 507 break;
90e868ac 508
0949843d
NC
509 case R_S_16C_24: /* word2(0-3,8-11),word3. */
510 if (value > 16777215 || value < -16777216)
511 return bfd_reloc_overflow;
512 value &= 0x1FFFFFF;
513 value >>= 1;
514
515 value = ((value & 0x007FFFFF) << 1) | ((value & 0x00800000) >> 23);
516
517 value = ((value & 0x0000FFFF) << 16) |
518 ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
519 value |= left_val;
520 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 521 break;
90e868ac 522
0949843d
NC
523 default:
524 return bfd_reloc_notsupported;
525 }
526 break;
527
528 case R_16C_REGREL:
529 switch (size)
530 {
531 case R_S_16C_04: /* word1(12-15) not scaled. */
532 if (value > 13 || value < 0)
533 return bfd_reloc_overflow;
534 value &= 0xF;
535 value |= left_val;
536 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 537 break;
90e868ac 538
0949843d
NC
539 case R_S_16C_04_a: /* word1(12-15) not scaled. */
540 if (value > 26 || value < 0)
541 return bfd_reloc_overflow;
542 value &= 0x1F;
543 value >>= 1;
544 value |= left_val;
545 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 546 break;
90e868ac 547
0949843d
NC
548 case R_S_16C_14: /* word1(4-5),word2(0-3,8-15). */
549 if (value < 0 || value > 16383)
550 return bfd_reloc_overflow;
551 value &= 0x3FFF;
552 value = ((value & 0x000000c0) << 24) |
553 ((value & 0x00003F00) << 16) |
554 ((value & 0x0000000F) << 16) | (value & 0x00000030);
555 value |= left_val;
556 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 557 break;
90e868ac 558
0949843d
NC
559 case R_S_16C_16: /* word2. */
560 if (value > 65535 || value < 0)
561 return bfd_reloc_overflow;
562 value &= 0xFFFF;
563 sword = value;
564 bfd_put_16 (abfd, (bfd_vma) sword,
565 (unsigned char *) data + octets);
0949843d 566 break;
90e868ac 567
0949843d
NC
568 case R_S_16C_20: /* word2(8-11),word3. */
569 /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
570 value &= 0xFFFFF;
571 sword = value & 0x0000FFFF;
572 value = (value & 0x000F0000) >> 16;
573 value |= left_val;
574 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
575 bfd_put_16 (abfd, (bfd_vma) sword,
576 (unsigned char *) data + octets + 1);
577 if (neg2pos)
578 {
579 /* Change load/stor negative displ opcode
580 to load/stor positive displ opcode. */
581 value = bfd_get_8 (abfd, (char *) data + octets - 3);
582 value &= 0xF7;
583 value |= 0x2;
584 bfd_put_8 (abfd, (bfd_vma) value,
585 (unsigned char *) data + octets - 3);
586 }
0949843d 587 break;
90e868ac 588
0949843d
NC
589 default:
590 return bfd_reloc_notsupported;
591 }
592 break;
593
594 case R_16C_ABS:
595 switch (size)
596 {
597 case R_S_16C_20: /* word1(0-3),word2. */
598 if (value > 1048575 || value < 0)
599 return bfd_reloc_overflow;
600 value &= 0xFFFFF;
601 value = ((value & 0x0000FFFF) << 16) |
602 ((value & 0x000F0000) >> 16);
603 value |= left_val;
604 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 605 break;
90e868ac 606
0949843d
NC
607 case R_S_16C_24: /* word2(0-3,8-11),word3. */
608 /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
609 value &= 0xFFFFFF;
610 value = ((value & 0x0000FFFF) << 16) |
611 ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
612 value |= left_val;
613 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 614 break;
90e868ac 615
0949843d
NC
616 default:
617 return bfd_reloc_notsupported;
618 }
619 break;
620
621 case R_16C_IMMED:
622 switch (size)
623 {
624 case R_S_16C_04: /* word1/2(4-7). */
625 if (value > 15 || value < -1)
626 return bfd_reloc_overflow;
627 value &= 0xF;
628 value <<= 4;
629 value |= left_val;
630 bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
0949843d 631 break;
90e868ac 632
0949843d
NC
633 case R_S_16C_16: /* word2. */
634 if (value > 32767 || value < -32768)
635 return bfd_reloc_overflow;
636 value &= 0xFFFF;
637 sword = value;
638 bfd_put_16 (abfd, (bfd_vma) sword,
639 (unsigned char *) data + octets);
0949843d 640 break;
90e868ac 641
0949843d
NC
642 case R_S_16C_20: /* word1(0-3),word2. */
643 if (value > 1048575 || value < 0)
644 return bfd_reloc_overflow;
645 value &= 0xFFFFF;
646 value = ((value & 0x0000FFFF) << 16) |
647 ((value & 0x000F0000) >> 16);
648 value |= left_val;
649 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 650 break;
90e868ac 651
0949843d
NC
652 case R_S_16C_32: /* word2, word3. */
653 value &= 0xFFFFFFFF;
654 value = ((value & 0x0000FFFF) << 16) |
655 ((value & 0xFFFF0000) >> 16);
656 bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
0949843d 657 break;
90e868ac 658
0949843d
NC
659 default:
660 return bfd_reloc_notsupported;
661 }
662 break;
663 default:
664 return bfd_reloc_notsupported;
665 }
90e868ac
NC
666
667 return bfd_reloc_ok;
0949843d
NC
668}
669
670/* Relocate a CR16C ELF section. */
671
672static bfd_boolean
673elf32_cr16c_relocate_section (bfd *output_bfd,
674 struct bfd_link_info *info,
675 bfd *input_bfd,
676 asection *input_section,
677 bfd_byte *contents,
678 Elf_Internal_Rela *relocs,
679 Elf_Internal_Sym *local_syms,
680 asection **local_sections)
681{
682 Elf_Internal_Shdr *symtab_hdr;
683 struct elf_link_hash_entry **sym_hashes;
684 Elf_Internal_Rela *rel, *relend;
685
686 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
687 sym_hashes = elf_sym_hashes (input_bfd);
688
689 rel = relocs;
690 relend = relocs + input_section->reloc_count;
691 for (; rel < relend; rel++)
692 {
693 int r_type;
694 reloc_howto_type *howto;
695 unsigned long r_symndx;
696 Elf_Internal_Sym *sym;
697 asection *sec;
698 struct elf_link_hash_entry *h;
699 bfd_vma relocation;
700 bfd_reloc_status_type r;
701
702 r_symndx = ELF32_R_SYM (rel->r_info);
703 r_type = ELF32_R_TYPE (rel->r_info);
704 howto = elf_howto_table + r_type;
705
0949843d
NC
706 h = NULL;
707 sym = NULL;
708 sec = NULL;
709 if (r_symndx < symtab_hdr->sh_info)
710 {
711 sym = local_syms + r_symndx;
712 sec = local_sections[r_symndx];
713 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
714 }
715 else
716 {
62d887d4 717 bfd_boolean unresolved_reloc, warned, ignored;
a4d7b4b5
L
718
719 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
720 r_symndx, symtab_hdr, sym_hashes,
721 h, sec, relocation,
62d887d4 722 unresolved_reloc, warned, ignored);
0949843d
NC
723 }
724
dbaa2011 725 if (sec != NULL && discarded_section (sec))
e4067dbb 726 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
545fd46b 727 rel, 1, relend, howto, 0, contents);
ab96bf03
AM
728
729 if (info->relocatable)
730 {
731 /* This is a relocatable link. We don't have to change
732 anything, unless the reloc is against a section symbol,
733 in which case we have to adjust according to where the
734 section symbol winds up in the output section. */
735 if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
736 rel->r_addend += sec->output_offset;
737 continue;
738 }
739
0949843d
NC
740 r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
741 input_section,
742 contents, rel->r_offset,
743 relocation, rel->r_addend,
744 info, sec, h == NULL);
745
746 if (r != bfd_reloc_ok)
747 {
748 const char *name;
749 const char *msg = (const char *) 0;
750
751 if (h != NULL)
752 name = h->root.root.string;
753 else
754 {
755 name = (bfd_elf_string_from_elf_section
756 (input_bfd, symtab_hdr->sh_link, sym->st_name));
757 if (name == NULL || *name == '\0')
758 name = bfd_section_name (input_bfd, sec);
759 }
760
761 switch (r)
762 {
763 case bfd_reloc_overflow:
764 if (!((*info->callbacks->reloc_overflow)
dfeffb9f
L
765 (info, (h ? &h->root : NULL), name, howto->name,
766 (bfd_vma) 0, input_bfd, input_section,
767 rel->r_offset)))
0949843d
NC
768 return FALSE;
769 break;
770
771 case bfd_reloc_undefined:
772 if (!((*info->callbacks->undefined_symbol)
773 (info, name, input_bfd, input_section,
774 rel->r_offset, TRUE)))
775 return FALSE;
776 break;
777
778 case bfd_reloc_outofrange:
779 msg = _("internal error: out of range error");
780 goto common_error;
781
782 case bfd_reloc_notsupported:
783 msg = _("internal error: unsupported relocation error");
784 goto common_error;
785
786 case bfd_reloc_dangerous:
787 msg = _("internal error: dangerous error");
788 goto common_error;
789
790 default:
791 msg = _("internal error: unknown error");
792 /* fall through */
793
794 common_error:
795 if (!((*info->callbacks->warning)
796 (info, msg, name, input_bfd, input_section,
797 rel->r_offset)))
798 return FALSE;
799 break;
800 }
801 }
802 }
803
804 return TRUE;
805}
806
0949843d
NC
807/* CR16C ELF uses three common sections:
808 One is for default common symbols (placed in usual common section).
809 Second is for near common symbols (placed in "ncommon" section).
810 Third is for far common symbols (placed in "fcommon" section).
811 The following implementation is based on elf32-mips architecture */
812
813static asection cr16c_elf_fcom_section;
814static asymbol cr16c_elf_fcom_symbol;
815static asymbol * cr16c_elf_fcom_symbol_ptr;
816static asection cr16c_elf_ncom_section;
817static asymbol cr16c_elf_ncom_symbol;
818static asymbol * cr16c_elf_ncom_symbol_ptr;
819
820/* Given a BFD section, try to locate the
821 corresponding ELF section index. */
822
823static bfd_boolean
824elf32_cr16c_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
825 asection *sec,
826 int *retval)
827{
828 if (strcmp (bfd_get_section_name (abfd, sec), ".fcommon") == 0)
829 *retval = SHN_CR16C_FCOMMON;
830 else if (strcmp (bfd_get_section_name (abfd, sec), ".ncommon") == 0)
831 *retval = SHN_CR16C_NCOMMON;
832 else
833 return FALSE;
834
835 return TRUE;
836}
837
838/* Handle the special CR16C section numbers that a symbol may use. */
839
840static void
841elf32_cr16c_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
842 asymbol *asym)
843{
844 elf_symbol_type *elfsym = (elf_symbol_type *) asym;
845 unsigned int indx;
846
847 indx = elfsym->internal_elf_sym.st_shndx;
848
849 switch (indx)
850 {
851 case SHN_CR16C_FCOMMON:
852 if (cr16c_elf_fcom_section.name == NULL)
853 {
854 /* Initialize the far common section. */
855 cr16c_elf_fcom_section.name = ".fcommon";
856 cr16c_elf_fcom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
857 cr16c_elf_fcom_section.output_section = &cr16c_elf_fcom_section;
858 cr16c_elf_fcom_section.symbol = &cr16c_elf_fcom_symbol;
859 cr16c_elf_fcom_section.symbol_ptr_ptr = &cr16c_elf_fcom_symbol_ptr;
860 cr16c_elf_fcom_symbol.name = ".fcommon";
861 cr16c_elf_fcom_symbol.flags = BSF_SECTION_SYM;
862 cr16c_elf_fcom_symbol.section = &cr16c_elf_fcom_section;
863 cr16c_elf_fcom_symbol_ptr = &cr16c_elf_fcom_symbol;
864 }
865 asym->section = &cr16c_elf_fcom_section;
866 asym->value = elfsym->internal_elf_sym.st_size;
867 break;
868 case SHN_CR16C_NCOMMON:
869 if (cr16c_elf_ncom_section.name == NULL)
870 {
871 /* Initialize the far common section. */
872 cr16c_elf_ncom_section.name = ".ncommon";
873 cr16c_elf_ncom_section.flags = SEC_IS_COMMON | SEC_ALLOC;
874 cr16c_elf_ncom_section.output_section = &cr16c_elf_ncom_section;
875 cr16c_elf_ncom_section.symbol = &cr16c_elf_ncom_symbol;
876 cr16c_elf_ncom_section.symbol_ptr_ptr = &cr16c_elf_ncom_symbol_ptr;
877 cr16c_elf_ncom_symbol.name = ".ncommon";
878 cr16c_elf_ncom_symbol.flags = BSF_SECTION_SYM;
879 cr16c_elf_ncom_symbol.section = &cr16c_elf_ncom_section;
880 cr16c_elf_ncom_symbol_ptr = &cr16c_elf_ncom_symbol;
881 }
882 asym->section = &cr16c_elf_ncom_section;
883 asym->value = elfsym->internal_elf_sym.st_size;
884 break;
885 }
886}
887
888/* Hook called by the linker routine which adds symbols from an object
889 file. We must handle the special cr16c section numbers here. */
890
891static bfd_boolean
892elf32_cr16c_add_symbol_hook (bfd *abfd,
893 struct bfd_link_info *info ATTRIBUTE_UNUSED,
a4d7b4b5 894 Elf_Internal_Sym *sym,
0949843d
NC
895 const char **namep ATTRIBUTE_UNUSED,
896 flagword *flagsp ATTRIBUTE_UNUSED,
897 asection **secp,
898 bfd_vma *valp)
899{
900 unsigned int indx = sym->st_shndx;
901
902 switch (indx)
903 {
904 case SHN_CR16C_FCOMMON:
905 *secp = bfd_make_section_old_way (abfd, ".fcommon");
906 (*secp)->flags |= SEC_IS_COMMON;
907 *valp = sym->st_size;
908 break;
909 case SHN_CR16C_NCOMMON:
910 *secp = bfd_make_section_old_way (abfd, ".ncommon");
911 (*secp)->flags |= SEC_IS_COMMON;
912 *valp = sym->st_size;
913 break;
914 }
915
916 return TRUE;
917}
918
6e0b88f1 919static int
0949843d
NC
920elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
921 const char *name ATTRIBUTE_UNUSED,
922 Elf_Internal_Sym *sym,
923 asection *input_sec,
924 struct elf_link_hash_entry *h ATTRIBUTE_UNUSED)
925{
926 /* If we see a common symbol, which implies a relocatable link, then
927 if a symbol was in a special common section in an input file, mark
928 it as a special common in the output file. */
929
930 if (sym->st_shndx == SHN_COMMON)
931 {
932 if (strcmp (input_sec->name, ".fcommon") == 0)
933 sym->st_shndx = SHN_CR16C_FCOMMON;
934 else if (strcmp (input_sec->name, ".ncommon") == 0)
935 sym->st_shndx = SHN_CR16C_NCOMMON;
936 }
937
6e0b88f1 938 return 1;
0949843d
NC
939}
940
941/* Definitions for setting CR16C target vector. */
6d00b590 942#define TARGET_LITTLE_SYM cr16c_elf32_vec
0949843d
NC
943#define TARGET_LITTLE_NAME "elf32-cr16c"
944#define ELF_ARCH bfd_arch_cr16c
945#define ELF_MACHINE_CODE EM_CR
946#define ELF_MAXPAGESIZE 0x1
947#define elf_symbol_leading_char '_'
948
949#define bfd_elf32_bfd_reloc_type_lookup elf_cr16c_reloc_type_lookup
157090f7 950#define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
0949843d
NC
951#define elf_info_to_howto elf_cr16c_info_to_howto
952#define elf_info_to_howto_rel elf_cr16c_info_to_howto_rel
953#define elf_backend_relocate_section elf32_cr16c_relocate_section
0949843d
NC
954#define elf_backend_symbol_processing elf32_cr16c_symbol_processing
955#define elf_backend_section_from_bfd_section elf32_cr16c_section_from_bfd_section
956#define elf_backend_add_symbol_hook elf32_cr16c_add_symbol_hook
957#define elf_backend_link_output_symbol_hook elf32_cr16c_link_output_symbol_hook
958
959#define elf_backend_can_gc_sections 1
960
961#include "elf32-target.h"
This page took 0.49241 seconds and 4 git commands to generate.