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