1 /* BFD back-end for National Semiconductor's CR16C ELF
2 Copyright (C) 2004-2015 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 if (r_type
>= RINDEX_16C_MAX
)
185 _bfd_error_handler (_("%B: invalid CR16C reloc number: %d"), abfd
, r_type
);
188 cache_ptr
->howto
= &elf_howto_table
[r_type
];
191 /* Perform a relocation as part of a final link. */
193 static bfd_reloc_status_type
194 cr16c_elf_final_link_relocate (reloc_howto_type
*howto
,
196 bfd
*output_bfd ATTRIBUTE_UNUSED
,
197 asection
*input_section
,
201 bfd_vma addend ATTRIBUTE_UNUSED
,
202 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
203 asection
*sym_sec ATTRIBUTE_UNUSED
,
204 int is_local ATTRIBUTE_UNUSED
)
207 short sword
; /* Extracted from the hole and put back. */
208 unsigned long format
, addr_type
, code_factor
;
210 unsigned short r_type
;
212 unsigned long disp20_opcod
;
217 long plus_factor
= 0; /* To be added to the hole. */
219 #define MIN_BYTE ((int) 0xFFFFFF80)
220 #define MIN_WORD ((int) 0xFFFF8000)
221 #define MAX_UWORD ((unsigned) 0x0000FFFF)
222 #define MAX_UBYTE ((unsigned) 0x000000FF)
224 r_type
= reloc_map_index
[howto
->type
].cr_reloc_type
;
225 format
= r_type
& R_FORMAT
;
226 size
= r_type
& R_SIZESP
;
227 addr_type
= r_type
& R_ADDRTYPE
;
228 code_factor
= ((addr_type
== R_CODE_ADDR
) ? 1 : 0);
235 case R_S_16C_08
: /* One byte. */
236 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
238 case R_S_16C_16
: /* Two bytes. */
239 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
242 case R_S_16C_32
: /* Four bytes. */
243 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
246 return bfd_reloc_notsupported
;
253 case R_S_16C_04
: /* word1(4-7). */
254 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
255 left_val
= value
& 0xF;
256 value
= (value
& 0xF0) >> 4;
260 case R_S_16C_08
: /* word1(0-3,8-11). */
261 sword
= bfd_get_16 (abfd
, (char *) data
+ octets
);
262 value
= sword
& 0x000F;
263 value
|= ((sword
& 0x0F00) >> 4);
264 left_val
= sword
& 0xF0F0;
269 case R_S_16C_16
: /* word2. */
270 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
272 value
= ((value
& 0xFFFE) >> 1) | ((value
& 0x1) << 15);
277 case R_S_16C_24_a
: /* word1(0-7),word2. */
278 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
279 left_val
= value
& 0x0000FF00;
280 value
= ((value
& 0xFFFE0000) >> 17) |
281 ((value
& 0x00010000) << 7) | ((value
& 0x000000FF) << 15);
283 if (value
& 0x1000000)
286 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
287 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
288 left_val
= value
& 0x0000F0F0;
289 value
= ((value
>> 16) & 0x0000FFFF) |
290 ((value
& 0x00000F00) << 8) | ((value
& 0x0000000F) << 20);
292 value
= ((value
& 0x00FFFFFE) >> 1) | ((value
& 0x00000001) << 23);
295 if (value
& 0x1000000)
299 return bfd_reloc_notsupported
;
306 case R_S_16C_04
: /* word1(12-15) not scaled. */
307 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
308 left_val
= value
& 0xF0;
311 case R_S_16C_04_a
: /* word1(12-15) scaled by 2. */
312 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
313 left_val
= value
& 0xF0;
317 case R_S_16C_14
: /* word1(4-5),word2(0-3,8-15). */
318 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
319 left_val
= value
& 0x00F0FFCF;
320 value
= ((value
& 0xc0000000) >> 24) |
321 ((value
& 0x3F000000) >> 16) |
322 ((value
& 0x000F0000) >> 16) | (value
& 0x00000030);
324 case R_S_16C_16
: /* word2. */
325 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
328 case R_S_16C_20
: /* word2(8-11),word3. */
329 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
330 left_val
= value
& 0xF0;
331 value
= (value
& 0xF) << 16;
332 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
+ 1);
333 value
= value
| (unsigned short) sword
;
334 disp20_opcod
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
- 3);
335 disp20_opcod
|= 0x0FFF0000;
336 if ((disp20_opcod
== 0x4FFF0018) || /* loadb -disp20(reg) */
337 (disp20_opcod
== 0x5FFF0018) || /* loadb -disp20(rp) */
338 (disp20_opcod
== 0x8FFF0018) || /* loadd -disp20(reg) */
339 (disp20_opcod
== 0x9FFF0018) || /* loadd -disp20(rp) */
340 (disp20_opcod
== 0xCFFF0018) || /* loadw -disp20(reg) */
341 (disp20_opcod
== 0xDFFF0018) || /* loadw -disp20(rp) */
342 (disp20_opcod
== 0x4FFF0019) || /* storb -disp20(reg) */
343 (disp20_opcod
== 0x5FFF0019) || /* storb -disp20(rp) */
344 (disp20_opcod
== 0x8FFF0019) || /* stord -disp20(reg) */
345 (disp20_opcod
== 0x9FFF0019) || /* stord -disp20(rp) */
346 (disp20_opcod
== 0xCFFF0019) || /* storw -disp20(reg) */
347 (disp20_opcod
== 0xDFFF0019))
348 { /* storw -disp20(rp). */
355 return bfd_reloc_notsupported
;
362 case R_S_16C_20
: /* word1(0-3),word2. */
363 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
364 left_val
= value
& 0x0000FFF0;
365 value
= ((value
& 0xFFFF0000) >> 16) |
366 ((value
& 0x0000000F) << 16);
368 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
369 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
370 left_val
= value
& 0x0000F0F0;
371 value
= ((value
& 0xFFFF0000) >> 16) |
372 ((value
& 0x00000F00) << 8) | ((value
& 0x0000000F) << 20);
375 return bfd_reloc_notsupported
;
382 case R_S_16C_04
: /* word1/2(4-7). */
383 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
384 left_val
= value
& 0xF;
385 value
= (value
& 0xF0) >> 4;
387 case R_S_16C_16
: /* word2. */
388 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
391 case R_S_16C_20
: /* word1(0-3),word2. */
392 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
393 left_val
= value
& 0x0000FFF0;
394 value
= ((value
& 0xFFFF0000) >> 16) |
395 ((value
& 0x0000000F) << 16);
397 case R_S_16C_32
: /* word2, word3. */
398 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
399 value
= ((value
& 0x0000FFFF) << 16) |
400 ((value
& 0xFFFF0000) >> 16);
403 return bfd_reloc_notsupported
;
407 return bfd_reloc_notsupported
;
410 switch ((r_type
& R_RELTO
) >> 4)
414 plus_factor
= Rvalue
;
416 case 1: /* R_PCREL. */
417 plus_factor
= Rvalue
-
418 (input_section
->output_section
->vma
+ input_section
->output_offset
);
421 return bfd_reloc_notsupported
;
426 if (plus_factor
>= -value
)
428 /* We need to change load/stor with negative
429 displ opcode to positive disp opcode (CR16C). */
432 value
= value
+ (plus_factor
>> code_factor
);
439 case R_S_16C_08
: /* One byte. */
440 if (value
> (int) MAX_UBYTE
|| value
< MIN_BYTE
)
441 return bfd_reloc_overflow
;
443 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
446 case R_S_16C_16
: /* Two bytes. */
447 if (value
> (int) MAX_UWORD
|| value
< MIN_WORD
)
448 return bfd_reloc_overflow
;
451 bfd_put_16 (abfd
, (bfd_vma
) sword
,
452 (unsigned char *) data
+ octets
);
455 case R_S_16C_32
: /* Four bytes. */
457 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
461 return bfd_reloc_notsupported
;
468 case R_S_16C_04
: /* word1(4-7). */
469 if ((value
- 32) > 32 || value
< 2)
470 return bfd_reloc_overflow
;
476 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
479 case R_S_16C_08
: /* word1(0-3,8-11). */
480 if (value
> 255 || value
< -256 || value
== 0x80)
481 return bfd_reloc_overflow
;
484 sword
= value
& 0x000F;
485 sword
|= (value
& 0x00F0) << 4;
487 bfd_put_16 (abfd
, (bfd_vma
) sword
,
488 (unsigned char *) data
+ octets
);
491 case R_S_16C_16
: /* word2. */
492 if (value
> 65535 || value
< -65536)
493 return bfd_reloc_overflow
;
496 value
= ((value
& 0x8000) >> 15) | ((value
& 0x7FFF) << 1);
498 bfd_put_16 (abfd
, (bfd_vma
) sword
,
499 (unsigned char *) data
+ octets
);
502 case R_S_16C_24_a
: /* word1(0-7),word2. */
503 if (value
> 16777215 || value
< -16777216)
504 return bfd_reloc_overflow
;
507 value
= ((value
& 0x00007FFF) << 17) |
508 ((value
& 0x00800000) >> 7) | ((value
& 0x007F8000) >> 15);
510 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
513 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
514 if (value
> 16777215 || value
< -16777216)
515 return bfd_reloc_overflow
;
519 value
= ((value
& 0x007FFFFF) << 1) | ((value
& 0x00800000) >> 23);
521 value
= ((value
& 0x0000FFFF) << 16) |
522 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
524 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
528 return bfd_reloc_notsupported
;
535 case R_S_16C_04
: /* word1(12-15) not scaled. */
536 if (value
> 13 || value
< 0)
537 return bfd_reloc_overflow
;
540 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
543 case R_S_16C_04_a
: /* word1(12-15) not scaled. */
544 if (value
> 26 || value
< 0)
545 return bfd_reloc_overflow
;
549 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
552 case R_S_16C_14
: /* word1(4-5),word2(0-3,8-15). */
553 if (value
< 0 || value
> 16383)
554 return bfd_reloc_overflow
;
556 value
= ((value
& 0x000000c0) << 24) |
557 ((value
& 0x00003F00) << 16) |
558 ((value
& 0x0000000F) << 16) | (value
& 0x00000030);
560 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
563 case R_S_16C_16
: /* word2. */
564 if (value
> 65535 || value
< 0)
565 return bfd_reloc_overflow
;
568 bfd_put_16 (abfd
, (bfd_vma
) sword
,
569 (unsigned char *) data
+ octets
);
572 case R_S_16C_20
: /* word2(8-11),word3. */
573 /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
575 sword
= value
& 0x0000FFFF;
576 value
= (value
& 0x000F0000) >> 16;
578 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
579 bfd_put_16 (abfd
, (bfd_vma
) sword
,
580 (unsigned char *) data
+ octets
+ 1);
583 /* Change load/stor negative displ opcode
584 to load/stor positive displ opcode. */
585 value
= bfd_get_8 (abfd
, (char *) data
+ octets
- 3);
588 bfd_put_8 (abfd
, (bfd_vma
) value
,
589 (unsigned char *) data
+ octets
- 3);
594 return bfd_reloc_notsupported
;
601 case R_S_16C_20
: /* word1(0-3),word2. */
602 if (value
> 1048575 || value
< 0)
603 return bfd_reloc_overflow
;
605 value
= ((value
& 0x0000FFFF) << 16) |
606 ((value
& 0x000F0000) >> 16);
608 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
611 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
612 /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
614 value
= ((value
& 0x0000FFFF) << 16) |
615 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
617 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
621 return bfd_reloc_notsupported
;
628 case R_S_16C_04
: /* word1/2(4-7). */
629 if (value
> 15 || value
< -1)
630 return bfd_reloc_overflow
;
634 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
637 case R_S_16C_16
: /* word2. */
638 if (value
> 32767 || value
< -32768)
639 return bfd_reloc_overflow
;
642 bfd_put_16 (abfd
, (bfd_vma
) sword
,
643 (unsigned char *) data
+ octets
);
646 case R_S_16C_20
: /* word1(0-3),word2. */
647 if (value
> 1048575 || value
< 0)
648 return bfd_reloc_overflow
;
650 value
= ((value
& 0x0000FFFF) << 16) |
651 ((value
& 0x000F0000) >> 16);
653 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
656 case R_S_16C_32
: /* word2, word3. */
658 value
= ((value
& 0x0000FFFF) << 16) |
659 ((value
& 0xFFFF0000) >> 16);
660 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
664 return bfd_reloc_notsupported
;
668 return bfd_reloc_notsupported
;
674 /* Relocate a CR16C ELF section. */
677 elf32_cr16c_relocate_section (bfd
*output_bfd
,
678 struct bfd_link_info
*info
,
680 asection
*input_section
,
682 Elf_Internal_Rela
*relocs
,
683 Elf_Internal_Sym
*local_syms
,
684 asection
**local_sections
)
686 Elf_Internal_Shdr
*symtab_hdr
;
687 struct elf_link_hash_entry
**sym_hashes
;
688 Elf_Internal_Rela
*rel
, *relend
;
690 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
691 sym_hashes
= elf_sym_hashes (input_bfd
);
694 relend
= relocs
+ input_section
->reloc_count
;
695 for (; rel
< relend
; rel
++)
698 reloc_howto_type
*howto
;
699 unsigned long r_symndx
;
700 Elf_Internal_Sym
*sym
;
702 struct elf_link_hash_entry
*h
;
704 bfd_reloc_status_type r
;
706 r_symndx
= ELF32_R_SYM (rel
->r_info
);
707 r_type
= ELF32_R_TYPE (rel
->r_info
);
708 howto
= elf_howto_table
+ r_type
;
713 if (r_symndx
< symtab_hdr
->sh_info
)
715 sym
= local_syms
+ r_symndx
;
716 sec
= local_sections
[r_symndx
];
717 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
721 bfd_boolean unresolved_reloc
, warned
, ignored
;
723 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
724 r_symndx
, symtab_hdr
, sym_hashes
,
726 unresolved_reloc
, warned
, ignored
);
729 if (sec
!= NULL
&& discarded_section (sec
))
730 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
731 rel
, 1, relend
, howto
, 0, contents
);
733 if (info
->relocatable
)
735 /* This is a relocatable link. We don't have to change
736 anything, unless the reloc is against a section symbol,
737 in which case we have to adjust according to where the
738 section symbol winds up in the output section. */
739 if (sym
!= NULL
&& ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
740 rel
->r_addend
+= sec
->output_offset
;
744 r
= cr16c_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
746 contents
, rel
->r_offset
,
747 relocation
, rel
->r_addend
,
748 info
, sec
, h
== NULL
);
750 if (r
!= bfd_reloc_ok
)
753 const char *msg
= (const char *) 0;
756 name
= h
->root
.root
.string
;
759 name
= (bfd_elf_string_from_elf_section
760 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
761 if (name
== NULL
|| *name
== '\0')
762 name
= bfd_section_name (input_bfd
, sec
);
767 case bfd_reloc_overflow
:
768 if (!((*info
->callbacks
->reloc_overflow
)
769 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
770 (bfd_vma
) 0, input_bfd
, input_section
,
775 case bfd_reloc_undefined
:
776 if (!((*info
->callbacks
->undefined_symbol
)
777 (info
, name
, input_bfd
, input_section
,
778 rel
->r_offset
, TRUE
)))
782 case bfd_reloc_outofrange
:
783 msg
= _("internal error: out of range error");
786 case bfd_reloc_notsupported
:
787 msg
= _("internal error: unsupported relocation error");
790 case bfd_reloc_dangerous
:
791 msg
= _("internal error: dangerous error");
795 msg
= _("internal error: unknown error");
799 if (!((*info
->callbacks
->warning
)
800 (info
, msg
, name
, input_bfd
, input_section
,
811 /* CR16C ELF uses three common sections:
812 One is for default common symbols (placed in usual common section).
813 Second is for near common symbols (placed in "ncommon" section).
814 Third is for far common symbols (placed in "fcommon" section).
815 The following implementation is based on elf32-mips architecture */
817 static asection cr16c_elf_fcom_section
;
818 static asymbol cr16c_elf_fcom_symbol
;
819 static asymbol
* cr16c_elf_fcom_symbol_ptr
;
820 static asection cr16c_elf_ncom_section
;
821 static asymbol cr16c_elf_ncom_symbol
;
822 static asymbol
* cr16c_elf_ncom_symbol_ptr
;
824 /* Given a BFD section, try to locate the
825 corresponding ELF section index. */
828 elf32_cr16c_section_from_bfd_section (bfd
*abfd ATTRIBUTE_UNUSED
,
832 if (strcmp (bfd_get_section_name (abfd
, sec
), ".fcommon") == 0)
833 *retval
= SHN_CR16C_FCOMMON
;
834 else if (strcmp (bfd_get_section_name (abfd
, sec
), ".ncommon") == 0)
835 *retval
= SHN_CR16C_NCOMMON
;
842 /* Handle the special CR16C section numbers that a symbol may use. */
845 elf32_cr16c_symbol_processing (bfd
*abfd ATTRIBUTE_UNUSED
,
848 elf_symbol_type
*elfsym
= (elf_symbol_type
*) asym
;
851 indx
= elfsym
->internal_elf_sym
.st_shndx
;
855 case SHN_CR16C_FCOMMON
:
856 if (cr16c_elf_fcom_section
.name
== NULL
)
858 /* Initialize the far common section. */
859 cr16c_elf_fcom_section
.name
= ".fcommon";
860 cr16c_elf_fcom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
861 cr16c_elf_fcom_section
.output_section
= &cr16c_elf_fcom_section
;
862 cr16c_elf_fcom_section
.symbol
= &cr16c_elf_fcom_symbol
;
863 cr16c_elf_fcom_section
.symbol_ptr_ptr
= &cr16c_elf_fcom_symbol_ptr
;
864 cr16c_elf_fcom_symbol
.name
= ".fcommon";
865 cr16c_elf_fcom_symbol
.flags
= BSF_SECTION_SYM
;
866 cr16c_elf_fcom_symbol
.section
= &cr16c_elf_fcom_section
;
867 cr16c_elf_fcom_symbol_ptr
= &cr16c_elf_fcom_symbol
;
869 asym
->section
= &cr16c_elf_fcom_section
;
870 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
872 case SHN_CR16C_NCOMMON
:
873 if (cr16c_elf_ncom_section
.name
== NULL
)
875 /* Initialize the far common section. */
876 cr16c_elf_ncom_section
.name
= ".ncommon";
877 cr16c_elf_ncom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
878 cr16c_elf_ncom_section
.output_section
= &cr16c_elf_ncom_section
;
879 cr16c_elf_ncom_section
.symbol
= &cr16c_elf_ncom_symbol
;
880 cr16c_elf_ncom_section
.symbol_ptr_ptr
= &cr16c_elf_ncom_symbol_ptr
;
881 cr16c_elf_ncom_symbol
.name
= ".ncommon";
882 cr16c_elf_ncom_symbol
.flags
= BSF_SECTION_SYM
;
883 cr16c_elf_ncom_symbol
.section
= &cr16c_elf_ncom_section
;
884 cr16c_elf_ncom_symbol_ptr
= &cr16c_elf_ncom_symbol
;
886 asym
->section
= &cr16c_elf_ncom_section
;
887 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
892 /* Hook called by the linker routine which adds symbols from an object
893 file. We must handle the special cr16c section numbers here. */
896 elf32_cr16c_add_symbol_hook (bfd
*abfd
,
897 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
898 Elf_Internal_Sym
*sym
,
899 const char **namep ATTRIBUTE_UNUSED
,
900 flagword
*flagsp ATTRIBUTE_UNUSED
,
904 unsigned int indx
= sym
->st_shndx
;
908 case SHN_CR16C_FCOMMON
:
909 *secp
= bfd_make_section_old_way (abfd
, ".fcommon");
910 (*secp
)->flags
|= SEC_IS_COMMON
;
911 *valp
= sym
->st_size
;
913 case SHN_CR16C_NCOMMON
:
914 *secp
= bfd_make_section_old_way (abfd
, ".ncommon");
915 (*secp
)->flags
|= SEC_IS_COMMON
;
916 *valp
= sym
->st_size
;
924 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
925 const char *name ATTRIBUTE_UNUSED
,
926 Elf_Internal_Sym
*sym
,
928 struct elf_link_hash_entry
*h ATTRIBUTE_UNUSED
)
930 /* If we see a common symbol, which implies a relocatable link, then
931 if a symbol was in a special common section in an input file, mark
932 it as a special common in the output file. */
934 if (sym
->st_shndx
== SHN_COMMON
)
936 if (strcmp (input_sec
->name
, ".fcommon") == 0)
937 sym
->st_shndx
= SHN_CR16C_FCOMMON
;
938 else if (strcmp (input_sec
->name
, ".ncommon") == 0)
939 sym
->st_shndx
= SHN_CR16C_NCOMMON
;
945 /* Definitions for setting CR16C target vector. */
946 #define TARGET_LITTLE_SYM cr16c_elf32_vec
947 #define TARGET_LITTLE_NAME "elf32-cr16c"
948 #define ELF_ARCH bfd_arch_cr16c
949 #define ELF_MACHINE_CODE EM_CR
950 #define ELF_MAXPAGESIZE 0x1
951 #define elf_symbol_leading_char '_'
953 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16c_reloc_type_lookup
954 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
955 #define elf_info_to_howto elf_cr16c_info_to_howto
956 #define elf_info_to_howto_rel elf_cr16c_info_to_howto_rel
957 #define elf_backend_relocate_section elf32_cr16c_relocate_section
958 #define elf_backend_symbol_processing elf32_cr16c_symbol_processing
959 #define elf_backend_section_from_bfd_section elf32_cr16c_section_from_bfd_section
960 #define elf_backend_add_symbol_hook elf32_cr16c_add_symbol_hook
961 #define elf_backend_link_output_symbol_hook elf32_cr16c_link_output_symbol_hook
963 #define elf_backend_can_gc_sections 1
965 #include "elf32-target.h"