1 /* BFD back-end for National Semiconductor's CR16C ELF
2 Copyright 2004, 2005, 2006, 2007, 2009, 2010
3 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
26 #include "elf/cr16c.h"
30 #define USE_REL 1 /* CR16C uses REL relocations instead of RELA. */
32 /* The following definition is based on EMPTY_HOWTO macro,
33 but also initiates the "name" field in HOWTO struct. */
34 #define ONLY_NAME_HOWTO(C) \
35 HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \
36 STRINGX(C), FALSE, 0, 0, FALSE)
38 /* reloc_map_index array maps CRASM relocation type into a BFD
39 relocation enum. The array's indices are synchronized with
40 RINDEX_16C_* indices, created in include/elf/cr16c.h.
42 1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
43 2. asreloc.c : find_reloc_type(). */
45 RELOC_MAP reloc_map_index
[RINDEX_16C_MAX
] =
47 {R_16C_NUM08
, BFD_RELOC_16C_NUM08
},
48 {R_16C_NUM08_C
, BFD_RELOC_16C_NUM08_C
},
49 {R_16C_NUM16
, BFD_RELOC_16C_NUM16
},
50 {R_16C_NUM16_C
, BFD_RELOC_16C_NUM16_C
},
51 {R_16C_NUM32
, BFD_RELOC_16C_NUM32
},
52 {R_16C_NUM32_C
, BFD_RELOC_16C_NUM32_C
},
53 {R_16C_DISP04
, BFD_RELOC_16C_DISP04
},
54 {R_16C_DISP04_C
, BFD_RELOC_16C_DISP04_C
},
55 {R_16C_DISP08
, BFD_RELOC_16C_DISP08
},
56 {R_16C_DISP08_C
, BFD_RELOC_16C_DISP08_C
},
57 {R_16C_DISP16
, BFD_RELOC_16C_DISP16
},
58 {R_16C_DISP16_C
, BFD_RELOC_16C_DISP16_C
},
59 {R_16C_DISP24
, BFD_RELOC_16C_DISP24
},
60 {R_16C_DISP24_C
, BFD_RELOC_16C_DISP24_C
},
61 {R_16C_DISP24a
, BFD_RELOC_16C_DISP24a
},
62 {R_16C_DISP24a_C
, BFD_RELOC_16C_DISP24a_C
},
63 {R_16C_REG04
, BFD_RELOC_16C_REG04
},
64 {R_16C_REG04_C
, BFD_RELOC_16C_REG04_C
},
65 {R_16C_REG04a
, BFD_RELOC_16C_REG04a
},
66 {R_16C_REG04a_C
, BFD_RELOC_16C_REG04a_C
},
67 {R_16C_REG14
, BFD_RELOC_16C_REG14
},
68 {R_16C_REG14_C
, BFD_RELOC_16C_REG14_C
},
69 {R_16C_REG16
, BFD_RELOC_16C_REG16
},
70 {R_16C_REG16_C
, BFD_RELOC_16C_REG16_C
},
71 {R_16C_REG20
, BFD_RELOC_16C_REG20
},
72 {R_16C_REG20_C
, BFD_RELOC_16C_REG20_C
},
73 {R_16C_ABS20
, BFD_RELOC_16C_ABS20
},
74 {R_16C_ABS20_C
, BFD_RELOC_16C_ABS20_C
},
75 {R_16C_ABS24
, BFD_RELOC_16C_ABS24
},
76 {R_16C_ABS24_C
, BFD_RELOC_16C_ABS24_C
},
77 {R_16C_IMM04
, BFD_RELOC_16C_IMM04
},
78 {R_16C_IMM04_C
, BFD_RELOC_16C_IMM04_C
},
79 {R_16C_IMM16
, BFD_RELOC_16C_IMM16
},
80 {R_16C_IMM16_C
, BFD_RELOC_16C_IMM16_C
},
81 {R_16C_IMM20
, BFD_RELOC_16C_IMM20
},
82 {R_16C_IMM20_C
, BFD_RELOC_16C_IMM20_C
},
83 {R_16C_IMM24
, BFD_RELOC_16C_IMM24
},
84 {R_16C_IMM24_C
, BFD_RELOC_16C_IMM24_C
},
85 {R_16C_IMM32
, BFD_RELOC_16C_IMM32
},
86 {R_16C_IMM32_C
, BFD_RELOC_16C_IMM32_C
}
89 static reloc_howto_type elf_howto_table
[] =
91 /* 00 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08
),
92 /* 01 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM08_C
),
93 /* 02 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16
),
94 /* 03 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM16_C
),
95 /* 04 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32
),
96 /* 05 */ ONLY_NAME_HOWTO (RINDEX_16C_NUM32_C
),
97 /* 06 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04
),
98 /* 07 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP04_C
),
99 /* 08 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08
),
100 /* 09 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP08_C
),
101 /* 10 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16
),
102 /* 11 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP16_C
),
103 /* 12 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24
),
104 /* 13 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24_C
),
105 /* 14 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a
),
106 /* 15 */ ONLY_NAME_HOWTO (RINDEX_16C_DISP24a_C
),
107 /* 16 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04
),
108 /* 17 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04_C
),
109 /* 18 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a
),
110 /* 19 */ ONLY_NAME_HOWTO (RINDEX_16C_REG04a_C
),
111 /* 20 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14
),
112 /* 21 */ ONLY_NAME_HOWTO (RINDEX_16C_REG14_C
),
113 /* 22 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16
),
114 /* 23 */ ONLY_NAME_HOWTO (RINDEX_16C_REG16_C
),
115 /* 24 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20
),
116 /* 25 */ ONLY_NAME_HOWTO (RINDEX_16C_REG20_C
),
117 /* 26 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20
),
118 /* 27 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS20_C
),
119 /* 28 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24
),
120 /* 29 */ ONLY_NAME_HOWTO (RINDEX_16C_ABS24_C
),
121 /* 30 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04
),
122 /* 31 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM04_C
),
123 /* 32 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16
),
124 /* 33 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM16_C
),
125 /* 34 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20
),
126 /* 35 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM20_C
),
127 /* 36 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24
),
128 /* 37 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM24_C
),
129 /* 38 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32
),
130 /* 39 */ ONLY_NAME_HOWTO (RINDEX_16C_IMM32_C
)
134 /* Code to turn a code_type into a howto ptr, uses the above howto table. */
136 static reloc_howto_type
*
137 elf_cr16c_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
138 bfd_reloc_code_real_type code
)
142 for (i
= 0; i
< RINDEX_16C_MAX
; i
++)
144 if (code
== reloc_map_index
[i
].bfd_reloc_enum
)
146 /* printf ("CR16C Relocation Type is - %x\n", code); */
147 return & elf_howto_table
[i
];
151 /* printf ("This relocation Type is not supported - %x\n", code); */
155 static reloc_howto_type
*
156 elf_cr16c_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
161 for (i
= 0; i
< sizeof (elf_howto_table
) / sizeof (elf_howto_table
[0]); i
++)
162 if (elf_howto_table
[i
].name
!= NULL
163 && strcasecmp (elf_howto_table
[i
].name
, r_name
) == 0)
164 return &elf_howto_table
[i
];
170 elf_cr16c_info_to_howto (bfd
*abfd ATTRIBUTE_UNUSED
,
171 arelent
*cache_ptr ATTRIBUTE_UNUSED
,
172 Elf_Internal_Rela
*dst ATTRIBUTE_UNUSED
)
178 elf_cr16c_info_to_howto_rel (bfd
*abfd ATTRIBUTE_UNUSED
,
180 Elf_Internal_Rela
*dst
)
182 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
184 BFD_ASSERT (r_type
< (unsigned int) RINDEX_16C_MAX
);
185 cache_ptr
->howto
= &elf_howto_table
[r_type
];
188 /* Perform a relocation as part of a final link. */
190 static bfd_reloc_status_type
191 cr16c_elf_final_link_relocate (reloc_howto_type
*howto
,
193 bfd
*output_bfd ATTRIBUTE_UNUSED
,
194 asection
*input_section
,
198 bfd_vma addend ATTRIBUTE_UNUSED
,
199 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
200 asection
*sym_sec ATTRIBUTE_UNUSED
,
201 int is_local ATTRIBUTE_UNUSED
)
204 short sword
; /* Extracted from the hole and put back. */
205 unsigned long format
, addr_type
, code_factor
;
207 unsigned short r_type
;
209 unsigned long disp20_opcod
;
214 long plus_factor
= 0; /* To be added to the hole. */
216 #define MIN_BYTE ((int) 0xFFFFFF80)
217 #define MIN_WORD ((int) 0xFFFF8000)
218 #define MAX_UWORD ((unsigned) 0x0000FFFF)
219 #define MAX_UBYTE ((unsigned) 0x000000FF)
221 r_type
= reloc_map_index
[howto
->type
].cr_reloc_type
;
222 format
= r_type
& R_FORMAT
;
223 size
= r_type
& R_SIZESP
;
224 addr_type
= r_type
& R_ADDRTYPE
;
225 code_factor
= ((addr_type
== R_CODE_ADDR
) ? 1 : 0);
232 case R_S_16C_08
: /* One byte. */
233 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
235 case R_S_16C_16
: /* Two bytes. */
236 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
239 case R_S_16C_32
: /* Four bytes. */
240 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
243 return bfd_reloc_notsupported
;
250 case R_S_16C_04
: /* word1(4-7). */
251 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
252 left_val
= value
& 0xF;
253 value
= (value
& 0xF0) >> 4;
257 case R_S_16C_08
: /* word1(0-3,8-11). */
258 sword
= bfd_get_16 (abfd
, (char *) data
+ octets
);
259 value
= sword
& 0x000F;
260 value
|= ((sword
& 0x0F00) >> 4);
261 left_val
= sword
& 0xF0F0;
266 case R_S_16C_16
: /* word2. */
267 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
269 value
= ((value
& 0xFFFE) >> 1) | ((value
& 0x1) << 15);
274 case R_S_16C_24_a
: /* word1(0-7),word2. */
275 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
276 left_val
= value
& 0x0000FF00;
277 value
= ((value
& 0xFFFE0000) >> 17) |
278 ((value
& 0x00010000) << 7) | ((value
& 0x000000FF) << 15);
280 if (value
& 0x1000000)
283 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
284 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
285 left_val
= value
& 0x0000F0F0;
286 value
= ((value
>> 16) & 0x0000FFFF) |
287 ((value
& 0x00000F00) << 8) | ((value
& 0x0000000F) << 20);
289 value
= ((value
& 0x00FFFFFE) >> 1) | ((value
& 0x00000001) << 23);
292 if (value
& 0x1000000)
296 return bfd_reloc_notsupported
;
303 case R_S_16C_04
: /* word1(12-15) not scaled. */
304 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
305 left_val
= value
& 0xF0;
308 case R_S_16C_04_a
: /* word1(12-15) scaled by 2. */
309 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
310 left_val
= value
& 0xF0;
314 case R_S_16C_14
: /* word1(4-5),word2(0-3,8-15). */
315 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
316 left_val
= value
& 0x00F0FFCF;
317 value
= ((value
& 0xc0000000) >> 24) |
318 ((value
& 0x3F000000) >> 16) |
319 ((value
& 0x000F0000) >> 16) | (value
& 0x00000030);
321 case R_S_16C_16
: /* word2. */
322 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
325 case R_S_16C_20
: /* word2(8-11),word3. */
326 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
327 left_val
= value
& 0xF0;
328 value
= (value
& 0xF) << 16;
329 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
+ 1);
330 value
= value
| (unsigned short) sword
;
331 disp20_opcod
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
- 3);
332 disp20_opcod
|= 0x0FFF0000;
333 if ((disp20_opcod
== 0x4FFF0018) || /* loadb -disp20(reg) */
334 (disp20_opcod
== 0x5FFF0018) || /* loadb -disp20(rp) */
335 (disp20_opcod
== 0x8FFF0018) || /* loadd -disp20(reg) */
336 (disp20_opcod
== 0x9FFF0018) || /* loadd -disp20(rp) */
337 (disp20_opcod
== 0xCFFF0018) || /* loadw -disp20(reg) */
338 (disp20_opcod
== 0xDFFF0018) || /* loadw -disp20(rp) */
339 (disp20_opcod
== 0x4FFF0019) || /* storb -disp20(reg) */
340 (disp20_opcod
== 0x5FFF0019) || /* storb -disp20(rp) */
341 (disp20_opcod
== 0x8FFF0019) || /* stord -disp20(reg) */
342 (disp20_opcod
== 0x9FFF0019) || /* stord -disp20(rp) */
343 (disp20_opcod
== 0xCFFF0019) || /* storw -disp20(reg) */
344 (disp20_opcod
== 0xDFFF0019))
345 { /* storw -disp20(rp). */
352 return bfd_reloc_notsupported
;
359 case R_S_16C_20
: /* word1(0-3),word2. */
360 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
361 left_val
= value
& 0x0000FFF0;
362 value
= ((value
& 0xFFFF0000) >> 16) |
363 ((value
& 0x0000000F) << 16);
365 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
366 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
367 left_val
= value
& 0x0000F0F0;
368 value
= ((value
& 0xFFFF0000) >> 16) |
369 ((value
& 0x00000F00) << 8) | ((value
& 0x0000000F) << 20);
372 return bfd_reloc_notsupported
;
379 case R_S_16C_04
: /* word1/2(4-7). */
380 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
381 left_val
= value
& 0xF;
382 value
= (value
& 0xF0) >> 4;
384 case R_S_16C_16
: /* word2. */
385 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
388 case R_S_16C_20
: /* word1(0-3),word2. */
389 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
390 left_val
= value
& 0x0000FFF0;
391 value
= ((value
& 0xFFFF0000) >> 16) |
392 ((value
& 0x0000000F) << 16);
394 case R_S_16C_32
: /* word2, word3. */
395 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
396 value
= ((value
& 0x0000FFFF) << 16) |
397 ((value
& 0xFFFF0000) >> 16);
400 return bfd_reloc_notsupported
;
404 return bfd_reloc_notsupported
;
407 switch ((r_type
& R_RELTO
) >> 4)
411 plus_factor
= Rvalue
;
413 case 1: /* R_PCREL. */
414 plus_factor
= Rvalue
-
415 (input_section
->output_section
->vma
+ input_section
->output_offset
);
418 return bfd_reloc_notsupported
;
423 if (plus_factor
>= -value
)
425 /* We need to change load/stor with negative
426 displ opcode to positive disp opcode (CR16C). */
429 value
= value
+ (plus_factor
>> code_factor
);
436 case R_S_16C_08
: /* One byte. */
437 if (value
> (int) MAX_UBYTE
|| value
< MIN_BYTE
)
438 return bfd_reloc_overflow
;
440 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
443 case R_S_16C_16
: /* Two bytes. */
444 if (value
> (int) MAX_UWORD
|| value
< MIN_WORD
)
445 return bfd_reloc_overflow
;
448 bfd_put_16 (abfd
, (bfd_vma
) sword
,
449 (unsigned char *) data
+ octets
);
452 case R_S_16C_32
: /* Four bytes. */
454 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
458 return bfd_reloc_notsupported
;
465 case R_S_16C_04
: /* word1(4-7). */
466 if ((value
- 32) > 32 || value
< 2)
467 return bfd_reloc_overflow
;
473 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
476 case R_S_16C_08
: /* word1(0-3,8-11). */
477 if (value
> 255 || value
< -256 || value
== 0x80)
478 return bfd_reloc_overflow
;
481 sword
= value
& 0x000F;
482 sword
|= (value
& 0x00F0) << 4;
484 bfd_put_16 (abfd
, (bfd_vma
) sword
,
485 (unsigned char *) data
+ octets
);
488 case R_S_16C_16
: /* word2. */
489 if (value
> 65535 || value
< -65536)
490 return bfd_reloc_overflow
;
493 value
= ((value
& 0x8000) >> 15) | ((value
& 0x7FFF) << 1);
495 bfd_put_16 (abfd
, (bfd_vma
) sword
,
496 (unsigned char *) data
+ octets
);
499 case R_S_16C_24_a
: /* word1(0-7),word2. */
500 if (value
> 16777215 || value
< -16777216)
501 return bfd_reloc_overflow
;
504 value
= ((value
& 0x00007FFF) << 17) |
505 ((value
& 0x00800000) >> 7) | ((value
& 0x007F8000) >> 15);
507 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
510 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
511 if (value
> 16777215 || value
< -16777216)
512 return bfd_reloc_overflow
;
516 value
= ((value
& 0x007FFFFF) << 1) | ((value
& 0x00800000) >> 23);
518 value
= ((value
& 0x0000FFFF) << 16) |
519 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
521 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
525 return bfd_reloc_notsupported
;
532 case R_S_16C_04
: /* word1(12-15) not scaled. */
533 if (value
> 13 || value
< 0)
534 return bfd_reloc_overflow
;
537 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
540 case R_S_16C_04_a
: /* word1(12-15) not scaled. */
541 if (value
> 26 || value
< 0)
542 return bfd_reloc_overflow
;
546 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
549 case R_S_16C_14
: /* word1(4-5),word2(0-3,8-15). */
550 if (value
< 0 || value
> 16383)
551 return bfd_reloc_overflow
;
553 value
= ((value
& 0x000000c0) << 24) |
554 ((value
& 0x00003F00) << 16) |
555 ((value
& 0x0000000F) << 16) | (value
& 0x00000030);
557 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
560 case R_S_16C_16
: /* word2. */
561 if (value
> 65535 || value
< 0)
562 return bfd_reloc_overflow
;
565 bfd_put_16 (abfd
, (bfd_vma
) sword
,
566 (unsigned char *) data
+ octets
);
569 case R_S_16C_20
: /* word2(8-11),word3. */
570 /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
572 sword
= value
& 0x0000FFFF;
573 value
= (value
& 0x000F0000) >> 16;
575 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
576 bfd_put_16 (abfd
, (bfd_vma
) sword
,
577 (unsigned char *) data
+ octets
+ 1);
580 /* Change load/stor negative displ opcode
581 to load/stor positive displ opcode. */
582 value
= bfd_get_8 (abfd
, (char *) data
+ octets
- 3);
585 bfd_put_8 (abfd
, (bfd_vma
) value
,
586 (unsigned char *) data
+ octets
- 3);
591 return bfd_reloc_notsupported
;
598 case R_S_16C_20
: /* word1(0-3),word2. */
599 if (value
> 1048575 || value
< 0)
600 return bfd_reloc_overflow
;
602 value
= ((value
& 0x0000FFFF) << 16) |
603 ((value
& 0x000F0000) >> 16);
605 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
608 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
609 /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
611 value
= ((value
& 0x0000FFFF) << 16) |
612 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
614 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
618 return bfd_reloc_notsupported
;
625 case R_S_16C_04
: /* word1/2(4-7). */
626 if (value
> 15 || value
< -1)
627 return bfd_reloc_overflow
;
631 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
634 case R_S_16C_16
: /* word2. */
635 if (value
> 32767 || value
< -32768)
636 return bfd_reloc_overflow
;
639 bfd_put_16 (abfd
, (bfd_vma
) sword
,
640 (unsigned char *) data
+ octets
);
643 case R_S_16C_20
: /* word1(0-3),word2. */
644 if (value
> 1048575 || value
< 0)
645 return bfd_reloc_overflow
;
647 value
= ((value
& 0x0000FFFF) << 16) |
648 ((value
& 0x000F0000) >> 16);
650 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
653 case R_S_16C_32
: /* word2, word3. */
655 value
= ((value
& 0x0000FFFF) << 16) |
656 ((value
& 0xFFFF0000) >> 16);
657 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
661 return bfd_reloc_notsupported
;
665 return bfd_reloc_notsupported
;
671 /* Relocate a CR16C ELF section. */
674 elf32_cr16c_relocate_section (bfd
*output_bfd
,
675 struct bfd_link_info
*info
,
677 asection
*input_section
,
679 Elf_Internal_Rela
*relocs
,
680 Elf_Internal_Sym
*local_syms
,
681 asection
**local_sections
)
683 Elf_Internal_Shdr
*symtab_hdr
;
684 struct elf_link_hash_entry
**sym_hashes
;
685 Elf_Internal_Rela
*rel
, *relend
;
687 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
688 sym_hashes
= elf_sym_hashes (input_bfd
);
691 relend
= relocs
+ input_section
->reloc_count
;
692 for (; rel
< relend
; rel
++)
695 reloc_howto_type
*howto
;
696 unsigned long r_symndx
;
697 Elf_Internal_Sym
*sym
;
699 struct elf_link_hash_entry
*h
;
701 bfd_reloc_status_type r
;
703 r_symndx
= ELF32_R_SYM (rel
->r_info
);
704 r_type
= ELF32_R_TYPE (rel
->r_info
);
705 howto
= elf_howto_table
+ r_type
;
710 if (r_symndx
< symtab_hdr
->sh_info
)
712 sym
= local_syms
+ r_symndx
;
713 sec
= local_sections
[r_symndx
];
714 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
718 bfd_boolean unresolved_reloc
, warned
;
720 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
721 r_symndx
, symtab_hdr
, sym_hashes
,
723 unresolved_reloc
, warned
);
726 if (sec
!= NULL
&& elf_discarded_section (sec
))
727 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
728 rel
, relend
, howto
, contents
);
730 if (info
->relocatable
)
732 /* This is a relocatable link. We don't have to change
733 anything, unless the reloc is against a section symbol,
734 in which case we have to adjust according to where the
735 section symbol winds up in the output section. */
736 if (sym
!= NULL
&& ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
737 rel
->r_addend
+= sec
->output_offset
;
741 r
= cr16c_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
743 contents
, rel
->r_offset
,
744 relocation
, rel
->r_addend
,
745 info
, sec
, h
== NULL
);
747 if (r
!= bfd_reloc_ok
)
750 const char *msg
= (const char *) 0;
753 name
= h
->root
.root
.string
;
756 name
= (bfd_elf_string_from_elf_section
757 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
758 if (name
== NULL
|| *name
== '\0')
759 name
= bfd_section_name (input_bfd
, sec
);
764 case bfd_reloc_overflow
:
765 if (!((*info
->callbacks
->reloc_overflow
)
766 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
767 (bfd_vma
) 0, input_bfd
, input_section
,
772 case bfd_reloc_undefined
:
773 if (!((*info
->callbacks
->undefined_symbol
)
774 (info
, name
, input_bfd
, input_section
,
775 rel
->r_offset
, TRUE
)))
779 case bfd_reloc_outofrange
:
780 msg
= _("internal error: out of range error");
783 case bfd_reloc_notsupported
:
784 msg
= _("internal error: unsupported relocation error");
787 case bfd_reloc_dangerous
:
788 msg
= _("internal error: dangerous error");
792 msg
= _("internal error: unknown error");
796 if (!((*info
->callbacks
->warning
)
797 (info
, msg
, name
, input_bfd
, input_section
,
808 /* CR16C ELF uses three common sections:
809 One is for default common symbols (placed in usual common section).
810 Second is for near common symbols (placed in "ncommon" section).
811 Third is for far common symbols (placed in "fcommon" section).
812 The following implementation is based on elf32-mips architecture */
814 static asection cr16c_elf_fcom_section
;
815 static asymbol cr16c_elf_fcom_symbol
;
816 static asymbol
* cr16c_elf_fcom_symbol_ptr
;
817 static asection cr16c_elf_ncom_section
;
818 static asymbol cr16c_elf_ncom_symbol
;
819 static asymbol
* cr16c_elf_ncom_symbol_ptr
;
821 /* Given a BFD section, try to locate the
822 corresponding ELF section index. */
825 elf32_cr16c_section_from_bfd_section (bfd
*abfd ATTRIBUTE_UNUSED
,
829 if (strcmp (bfd_get_section_name (abfd
, sec
), ".fcommon") == 0)
830 *retval
= SHN_CR16C_FCOMMON
;
831 else if (strcmp (bfd_get_section_name (abfd
, sec
), ".ncommon") == 0)
832 *retval
= SHN_CR16C_NCOMMON
;
839 /* Handle the special CR16C section numbers that a symbol may use. */
842 elf32_cr16c_symbol_processing (bfd
*abfd ATTRIBUTE_UNUSED
,
845 elf_symbol_type
*elfsym
= (elf_symbol_type
*) asym
;
848 indx
= elfsym
->internal_elf_sym
.st_shndx
;
852 case SHN_CR16C_FCOMMON
:
853 if (cr16c_elf_fcom_section
.name
== NULL
)
855 /* Initialize the far common section. */
856 cr16c_elf_fcom_section
.name
= ".fcommon";
857 cr16c_elf_fcom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
858 cr16c_elf_fcom_section
.output_section
= &cr16c_elf_fcom_section
;
859 cr16c_elf_fcom_section
.symbol
= &cr16c_elf_fcom_symbol
;
860 cr16c_elf_fcom_section
.symbol_ptr_ptr
= &cr16c_elf_fcom_symbol_ptr
;
861 cr16c_elf_fcom_symbol
.name
= ".fcommon";
862 cr16c_elf_fcom_symbol
.flags
= BSF_SECTION_SYM
;
863 cr16c_elf_fcom_symbol
.section
= &cr16c_elf_fcom_section
;
864 cr16c_elf_fcom_symbol_ptr
= &cr16c_elf_fcom_symbol
;
866 asym
->section
= &cr16c_elf_fcom_section
;
867 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
869 case SHN_CR16C_NCOMMON
:
870 if (cr16c_elf_ncom_section
.name
== NULL
)
872 /* Initialize the far common section. */
873 cr16c_elf_ncom_section
.name
= ".ncommon";
874 cr16c_elf_ncom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
875 cr16c_elf_ncom_section
.output_section
= &cr16c_elf_ncom_section
;
876 cr16c_elf_ncom_section
.symbol
= &cr16c_elf_ncom_symbol
;
877 cr16c_elf_ncom_section
.symbol_ptr_ptr
= &cr16c_elf_ncom_symbol_ptr
;
878 cr16c_elf_ncom_symbol
.name
= ".ncommon";
879 cr16c_elf_ncom_symbol
.flags
= BSF_SECTION_SYM
;
880 cr16c_elf_ncom_symbol
.section
= &cr16c_elf_ncom_section
;
881 cr16c_elf_ncom_symbol_ptr
= &cr16c_elf_ncom_symbol
;
883 asym
->section
= &cr16c_elf_ncom_section
;
884 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
889 /* Hook called by the linker routine which adds symbols from an object
890 file. We must handle the special cr16c section numbers here. */
893 elf32_cr16c_add_symbol_hook (bfd
*abfd
,
894 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
895 Elf_Internal_Sym
*sym
,
896 const char **namep ATTRIBUTE_UNUSED
,
897 flagword
*flagsp ATTRIBUTE_UNUSED
,
901 unsigned int indx
= sym
->st_shndx
;
905 case SHN_CR16C_FCOMMON
:
906 *secp
= bfd_make_section_old_way (abfd
, ".fcommon");
907 (*secp
)->flags
|= SEC_IS_COMMON
;
908 *valp
= sym
->st_size
;
910 case SHN_CR16C_NCOMMON
:
911 *secp
= bfd_make_section_old_way (abfd
, ".ncommon");
912 (*secp
)->flags
|= SEC_IS_COMMON
;
913 *valp
= sym
->st_size
;
921 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
922 const char *name ATTRIBUTE_UNUSED
,
923 Elf_Internal_Sym
*sym
,
925 struct elf_link_hash_entry
*h ATTRIBUTE_UNUSED
)
927 /* If we see a common symbol, which implies a relocatable link, then
928 if a symbol was in a special common section in an input file, mark
929 it as a special common in the output file. */
931 if (sym
->st_shndx
== SHN_COMMON
)
933 if (strcmp (input_sec
->name
, ".fcommon") == 0)
934 sym
->st_shndx
= SHN_CR16C_FCOMMON
;
935 else if (strcmp (input_sec
->name
, ".ncommon") == 0)
936 sym
->st_shndx
= SHN_CR16C_NCOMMON
;
942 /* Definitions for setting CR16C target vector. */
943 #define TARGET_LITTLE_SYM bfd_elf32_cr16c_vec
944 #define TARGET_LITTLE_NAME "elf32-cr16c"
945 #define ELF_ARCH bfd_arch_cr16c
946 #define ELF_MACHINE_CODE EM_CR
947 #define ELF_MAXPAGESIZE 0x1
948 #define elf_symbol_leading_char '_'
950 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16c_reloc_type_lookup
951 #define bfd_elf32_bfd_reloc_name_lookup elf_cr16c_reloc_name_lookup
952 #define elf_info_to_howto elf_cr16c_info_to_howto
953 #define elf_info_to_howto_rel elf_cr16c_info_to_howto_rel
954 #define elf_backend_relocate_section elf32_cr16c_relocate_section
955 #define elf_backend_symbol_processing elf32_cr16c_symbol_processing
956 #define elf_backend_section_from_bfd_section elf32_cr16c_section_from_bfd_section
957 #define elf_backend_add_symbol_hook elf32_cr16c_add_symbol_hook
958 #define elf_backend_link_output_symbol_hook elf32_cr16c_link_output_symbol_hook
960 #define elf_backend_can_gc_sections 1
962 #include "elf32-target.h"