1 /* BFD back-end for National Semiconductor's CR16C ELF
2 Copyright (C) 2004-2014 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
25 #include "elf/cr16c.h"
29 #define USE_REL 1 /* CR16C uses REL relocations instead of RELA. */
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)
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.
41 1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
42 2. asreloc.c : find_reloc_type(). */
44 RELOC_MAP reloc_map_index
[RINDEX_16C_MAX
] =
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
}
88 static reloc_howto_type elf_howto_table
[] =
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
)
133 /* Code to turn a code_type into a howto ptr, uses the above howto table. */
135 static reloc_howto_type
*
136 elf_cr16c_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
137 bfd_reloc_code_real_type code
)
141 for (i
= 0; i
< RINDEX_16C_MAX
; i
++)
143 if (code
== reloc_map_index
[i
].bfd_reloc_enum
)
145 /* printf ("CR16C Relocation Type is - %x\n", code); */
146 return & elf_howto_table
[i
];
150 /* printf ("This relocation Type is not supported - %x\n", code); */
154 static reloc_howto_type
*
155 elf_cr16c_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
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
];
169 elf_cr16c_info_to_howto (bfd
*abfd ATTRIBUTE_UNUSED
,
170 arelent
*cache_ptr ATTRIBUTE_UNUSED
,
171 Elf_Internal_Rela
*dst ATTRIBUTE_UNUSED
)
177 elf_cr16c_info_to_howto_rel (bfd
*abfd ATTRIBUTE_UNUSED
,
179 Elf_Internal_Rela
*dst
)
181 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
183 BFD_ASSERT (r_type
< (unsigned int) RINDEX_16C_MAX
);
184 cache_ptr
->howto
= &elf_howto_table
[r_type
];
187 /* Perform a relocation as part of a final link. */
189 static bfd_reloc_status_type
190 cr16c_elf_final_link_relocate (reloc_howto_type
*howto
,
192 bfd
*output_bfd ATTRIBUTE_UNUSED
,
193 asection
*input_section
,
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
)
203 short sword
; /* Extracted from the hole and put back. */
204 unsigned long format
, addr_type
, code_factor
;
206 unsigned short r_type
;
208 unsigned long disp20_opcod
;
213 long plus_factor
= 0; /* To be added to the hole. */
215 #define MIN_BYTE ((int) 0xFFFFFF80)
216 #define MIN_WORD ((int) 0xFFFF8000)
217 #define MAX_UWORD ((unsigned) 0x0000FFFF)
218 #define MAX_UBYTE ((unsigned) 0x000000FF)
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);
231 case R_S_16C_08
: /* One byte. */
232 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
234 case R_S_16C_16
: /* Two bytes. */
235 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
238 case R_S_16C_32
: /* Four bytes. */
239 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
242 return bfd_reloc_notsupported
;
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;
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;
265 case R_S_16C_16
: /* word2. */
266 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
268 value
= ((value
& 0xFFFE) >> 1) | ((value
& 0x1) << 15);
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);
279 if (value
& 0x1000000)
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);
288 value
= ((value
& 0x00FFFFFE) >> 1) | ((value
& 0x00000001) << 23);
291 if (value
& 0x1000000)
295 return bfd_reloc_notsupported
;
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;
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;
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);
320 case R_S_16C_16
: /* word2. */
321 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
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). */
351 return bfd_reloc_notsupported
;
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);
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);
371 return bfd_reloc_notsupported
;
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;
383 case R_S_16C_16
: /* word2. */
384 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
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);
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);
399 return bfd_reloc_notsupported
;
403 return bfd_reloc_notsupported
;
406 switch ((r_type
& R_RELTO
) >> 4)
410 plus_factor
= Rvalue
;
412 case 1: /* R_PCREL. */
413 plus_factor
= Rvalue
-
414 (input_section
->output_section
->vma
+ input_section
->output_offset
);
417 return bfd_reloc_notsupported
;
422 if (plus_factor
>= -value
)
424 /* We need to change load/stor with negative
425 displ opcode to positive disp opcode (CR16C). */
428 value
= value
+ (plus_factor
>> code_factor
);
435 case R_S_16C_08
: /* One byte. */
436 if (value
> (int) MAX_UBYTE
|| value
< MIN_BYTE
)
437 return bfd_reloc_overflow
;
439 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
442 case R_S_16C_16
: /* Two bytes. */
443 if (value
> (int) MAX_UWORD
|| value
< MIN_WORD
)
444 return bfd_reloc_overflow
;
447 bfd_put_16 (abfd
, (bfd_vma
) sword
,
448 (unsigned char *) data
+ octets
);
451 case R_S_16C_32
: /* Four bytes. */
453 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
457 return bfd_reloc_notsupported
;
464 case R_S_16C_04
: /* word1(4-7). */
465 if ((value
- 32) > 32 || value
< 2)
466 return bfd_reloc_overflow
;
472 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
475 case R_S_16C_08
: /* word1(0-3,8-11). */
476 if (value
> 255 || value
< -256 || value
== 0x80)
477 return bfd_reloc_overflow
;
480 sword
= value
& 0x000F;
481 sword
|= (value
& 0x00F0) << 4;
483 bfd_put_16 (abfd
, (bfd_vma
) sword
,
484 (unsigned char *) data
+ octets
);
487 case R_S_16C_16
: /* word2. */
488 if (value
> 65535 || value
< -65536)
489 return bfd_reloc_overflow
;
492 value
= ((value
& 0x8000) >> 15) | ((value
& 0x7FFF) << 1);
494 bfd_put_16 (abfd
, (bfd_vma
) sword
,
495 (unsigned char *) data
+ octets
);
498 case R_S_16C_24_a
: /* word1(0-7),word2. */
499 if (value
> 16777215 || value
< -16777216)
500 return bfd_reloc_overflow
;
503 value
= ((value
& 0x00007FFF) << 17) |
504 ((value
& 0x00800000) >> 7) | ((value
& 0x007F8000) >> 15);
506 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
509 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
510 if (value
> 16777215 || value
< -16777216)
511 return bfd_reloc_overflow
;
515 value
= ((value
& 0x007FFFFF) << 1) | ((value
& 0x00800000) >> 23);
517 value
= ((value
& 0x0000FFFF) << 16) |
518 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
520 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
524 return bfd_reloc_notsupported
;
531 case R_S_16C_04
: /* word1(12-15) not scaled. */
532 if (value
> 13 || value
< 0)
533 return bfd_reloc_overflow
;
536 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
539 case R_S_16C_04_a
: /* word1(12-15) not scaled. */
540 if (value
> 26 || value
< 0)
541 return bfd_reloc_overflow
;
545 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
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
;
552 value
= ((value
& 0x000000c0) << 24) |
553 ((value
& 0x00003F00) << 16) |
554 ((value
& 0x0000000F) << 16) | (value
& 0x00000030);
556 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
559 case R_S_16C_16
: /* word2. */
560 if (value
> 65535 || value
< 0)
561 return bfd_reloc_overflow
;
564 bfd_put_16 (abfd
, (bfd_vma
) sword
,
565 (unsigned char *) data
+ octets
);
568 case R_S_16C_20
: /* word2(8-11),word3. */
569 /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
571 sword
= value
& 0x0000FFFF;
572 value
= (value
& 0x000F0000) >> 16;
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);
579 /* Change load/stor negative displ opcode
580 to load/stor positive displ opcode. */
581 value
= bfd_get_8 (abfd
, (char *) data
+ octets
- 3);
584 bfd_put_8 (abfd
, (bfd_vma
) value
,
585 (unsigned char *) data
+ octets
- 3);
590 return bfd_reloc_notsupported
;
597 case R_S_16C_20
: /* word1(0-3),word2. */
598 if (value
> 1048575 || value
< 0)
599 return bfd_reloc_overflow
;
601 value
= ((value
& 0x0000FFFF) << 16) |
602 ((value
& 0x000F0000) >> 16);
604 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
607 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
608 /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
610 value
= ((value
& 0x0000FFFF) << 16) |
611 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
613 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
617 return bfd_reloc_notsupported
;
624 case R_S_16C_04
: /* word1/2(4-7). */
625 if (value
> 15 || value
< -1)
626 return bfd_reloc_overflow
;
630 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
633 case R_S_16C_16
: /* word2. */
634 if (value
> 32767 || value
< -32768)
635 return bfd_reloc_overflow
;
638 bfd_put_16 (abfd
, (bfd_vma
) sword
,
639 (unsigned char *) data
+ octets
);
642 case R_S_16C_20
: /* word1(0-3),word2. */
643 if (value
> 1048575 || value
< 0)
644 return bfd_reloc_overflow
;
646 value
= ((value
& 0x0000FFFF) << 16) |
647 ((value
& 0x000F0000) >> 16);
649 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
652 case R_S_16C_32
: /* word2, word3. */
654 value
= ((value
& 0x0000FFFF) << 16) |
655 ((value
& 0xFFFF0000) >> 16);
656 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
660 return bfd_reloc_notsupported
;
664 return bfd_reloc_notsupported
;
670 /* Relocate a CR16C ELF section. */
673 elf32_cr16c_relocate_section (bfd
*output_bfd
,
674 struct bfd_link_info
*info
,
676 asection
*input_section
,
678 Elf_Internal_Rela
*relocs
,
679 Elf_Internal_Sym
*local_syms
,
680 asection
**local_sections
)
682 Elf_Internal_Shdr
*symtab_hdr
;
683 struct elf_link_hash_entry
**sym_hashes
;
684 Elf_Internal_Rela
*rel
, *relend
;
686 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
687 sym_hashes
= elf_sym_hashes (input_bfd
);
690 relend
= relocs
+ input_section
->reloc_count
;
691 for (; rel
< relend
; rel
++)
694 reloc_howto_type
*howto
;
695 unsigned long r_symndx
;
696 Elf_Internal_Sym
*sym
;
698 struct elf_link_hash_entry
*h
;
700 bfd_reloc_status_type r
;
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
;
709 if (r_symndx
< symtab_hdr
->sh_info
)
711 sym
= local_syms
+ r_symndx
;
712 sec
= local_sections
[r_symndx
];
713 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
717 bfd_boolean unresolved_reloc
, warned
, ignored
;
719 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
720 r_symndx
, symtab_hdr
, sym_hashes
,
722 unresolved_reloc
, warned
, ignored
);
725 if (sec
!= NULL
&& discarded_section (sec
))
726 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
727 rel
, 1, relend
, howto
, 0, contents
);
729 if (info
->relocatable
)
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
;
740 r
= cr16c_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
742 contents
, rel
->r_offset
,
743 relocation
, rel
->r_addend
,
744 info
, sec
, h
== NULL
);
746 if (r
!= bfd_reloc_ok
)
749 const char *msg
= (const char *) 0;
752 name
= h
->root
.root
.string
;
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
);
763 case bfd_reloc_overflow
:
764 if (!((*info
->callbacks
->reloc_overflow
)
765 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
766 (bfd_vma
) 0, input_bfd
, input_section
,
771 case bfd_reloc_undefined
:
772 if (!((*info
->callbacks
->undefined_symbol
)
773 (info
, name
, input_bfd
, input_section
,
774 rel
->r_offset
, TRUE
)))
778 case bfd_reloc_outofrange
:
779 msg
= _("internal error: out of range error");
782 case bfd_reloc_notsupported
:
783 msg
= _("internal error: unsupported relocation error");
786 case bfd_reloc_dangerous
:
787 msg
= _("internal error: dangerous error");
791 msg
= _("internal error: unknown error");
795 if (!((*info
->callbacks
->warning
)
796 (info
, msg
, name
, input_bfd
, input_section
,
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 */
813 static asection cr16c_elf_fcom_section
;
814 static asymbol cr16c_elf_fcom_symbol
;
815 static asymbol
* cr16c_elf_fcom_symbol_ptr
;
816 static asection cr16c_elf_ncom_section
;
817 static asymbol cr16c_elf_ncom_symbol
;
818 static asymbol
* cr16c_elf_ncom_symbol_ptr
;
820 /* Given a BFD section, try to locate the
821 corresponding ELF section index. */
824 elf32_cr16c_section_from_bfd_section (bfd
*abfd ATTRIBUTE_UNUSED
,
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
;
838 /* Handle the special CR16C section numbers that a symbol may use. */
841 elf32_cr16c_symbol_processing (bfd
*abfd ATTRIBUTE_UNUSED
,
844 elf_symbol_type
*elfsym
= (elf_symbol_type
*) asym
;
847 indx
= elfsym
->internal_elf_sym
.st_shndx
;
851 case SHN_CR16C_FCOMMON
:
852 if (cr16c_elf_fcom_section
.name
== NULL
)
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
;
865 asym
->section
= &cr16c_elf_fcom_section
;
866 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
868 case SHN_CR16C_NCOMMON
:
869 if (cr16c_elf_ncom_section
.name
== NULL
)
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
;
882 asym
->section
= &cr16c_elf_ncom_section
;
883 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
888 /* Hook called by the linker routine which adds symbols from an object
889 file. We must handle the special cr16c section numbers here. */
892 elf32_cr16c_add_symbol_hook (bfd
*abfd
,
893 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
894 Elf_Internal_Sym
*sym
,
895 const char **namep ATTRIBUTE_UNUSED
,
896 flagword
*flagsp ATTRIBUTE_UNUSED
,
900 unsigned int indx
= sym
->st_shndx
;
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
;
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
;
920 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
921 const char *name ATTRIBUTE_UNUSED
,
922 Elf_Internal_Sym
*sym
,
924 struct elf_link_hash_entry
*h ATTRIBUTE_UNUSED
)
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. */
930 if (sym
->st_shndx
== SHN_COMMON
)
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
;
941 /* Definitions for setting CR16C target vector. */
942 #define TARGET_LITTLE_SYM bfd_elf32_cr16c_vec
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 '_'
949 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16c_reloc_type_lookup
950 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
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
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
959 #define elf_backend_can_gc_sections 1
961 #include "elf32-target.h"