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