1 /* BFD back-end for National Semiconductor's CR16C ELF
2 Copyright 2004 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #include "elf/cr16c.h"
28 #define USE_REL 1 /* CR16C uses REL relocations instead of RELA. */
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)
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.
40 1. elf32-cr16c.c : elf_cr16c_reloc_type_lookup().
41 2. asreloc.c : find_reloc_type(). */
43 RELOC_MAP reloc_map_index
[RINDEX_16C_MAX
] =
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
}
87 static reloc_howto_type elf_howto_table
[] =
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
)
132 /* Code to turn a code_type into a howto ptr, uses the above howto table. */
134 static reloc_howto_type
*
135 elf_cr16c_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
136 bfd_reloc_code_real_type code
)
140 for (i
= 0; i
< RINDEX_16C_MAX
; i
++)
142 if (code
== reloc_map_index
[i
].bfd_reloc_enum
)
144 /* printf ("CR16C Relocation Type is - %x\n", code); */
145 return & elf_howto_table
[i
];
149 /* printf ("This relocation Type is not supported - %x\n", code); */
154 elf_cr16c_info_to_howto (bfd
*abfd ATTRIBUTE_UNUSED
,
155 arelent
*cache_ptr ATTRIBUTE_UNUSED
,
156 Elf_Internal_Rela
*dst ATTRIBUTE_UNUSED
)
162 elf_cr16c_info_to_howto_rel (bfd
*abfd ATTRIBUTE_UNUSED
,
164 Elf_Internal_Rela
*dst
)
166 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
168 BFD_ASSERT (r_type
< (unsigned int) RINDEX_16C_MAX
);
169 cache_ptr
->howto
= &elf_howto_table
[r_type
];
172 /* Perform a relocation as part of a final link. */
174 static bfd_reloc_status_type
175 cr16c_elf_final_link_relocate (reloc_howto_type
*howto
,
177 bfd
*output_bfd ATTRIBUTE_UNUSED
,
178 asection
*input_section
,
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
)
188 short sword
; /* Extracted from the hole and put back. */
189 unsigned long format
, addr_type
, code_factor
;
191 unsigned short r_type
;
192 asymbol
*symbol
= NULL
;
194 unsigned long disp20_opcod
;
199 long plus_factor
= 0; /* To be added to the hole. */
201 #define MIN_BYTE ((int) 0xFFFFFF80)
202 #define MIN_WORD ((int) 0xFFFF8000)
203 #define MAX_UWORD ((unsigned) 0x0000FFFF)
204 #define MAX_UBYTE ((unsigned) 0x000000FF)
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);
213 symbol
= sym_sec
->symbol
;
220 case R_S_16C_08
: /* One byte. */
221 value
= bfd_get_8 (abfd
, (char *) data
+ octets
);
223 case R_S_16C_16
: /* Two bytes. */
224 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
227 case R_S_16C_32
: /* Four bytes. */
228 value
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ octets
);
231 return bfd_reloc_notsupported
;
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;
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;
254 case R_S_16C_16
: /* word2. */
255 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
257 value
= ((value
& 0xFFFE) >> 1) | ((value
& 0x1) << 15);
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);
268 if (value
& 0x1000000)
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);
277 value
= ((value
& 0x00FFFFFE) >> 1) | ((value
& 0x00000001) << 23);
280 if (value
& 0x1000000)
284 return bfd_reloc_notsupported
;
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;
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;
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);
309 case R_S_16C_16
: /* word2. */
310 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
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). */
340 return bfd_reloc_notsupported
;
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);
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);
360 return bfd_reloc_notsupported
;
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;
372 case R_S_16C_16
: /* word2. */
373 sword
= bfd_get_16 (abfd
, (bfd_byte
*) data
+ octets
);
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);
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);
388 return bfd_reloc_notsupported
;
392 return bfd_reloc_notsupported
;
395 switch ((r_type
& R_RELTO
) >> 4)
399 plus_factor
= Rvalue
;
401 case 1: /* R_PCREL. */
402 plus_factor
= Rvalue
-
403 (input_section
->output_section
->vma
+ input_section
->output_offset
);
406 return bfd_reloc_notsupported
;
411 if (plus_factor
>= -value
)
413 /* We need to change load/stor with negative
414 displ opcode to positive disp opcode (CR16C). */
417 value
= value
+ (plus_factor
>> code_factor
);
424 case R_S_16C_08
: /* One byte. */
425 if (value
> (int) MAX_UBYTE
|| value
< MIN_BYTE
)
426 return bfd_reloc_overflow
;
428 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
431 case R_S_16C_16
: /* Two bytes. */
432 if (value
> (int) MAX_UWORD
|| value
< MIN_WORD
)
433 return bfd_reloc_overflow
;
436 bfd_put_16 (abfd
, (bfd_vma
) sword
,
437 (unsigned char *) data
+ octets
);
440 case R_S_16C_32
: /* Four bytes. */
442 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
446 return bfd_reloc_notsupported
;
453 case R_S_16C_04
: /* word1(4-7). */
454 if ((value
- 32) > 32 || value
< 2)
455 return bfd_reloc_overflow
;
461 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
464 case R_S_16C_08
: /* word1(0-3,8-11). */
465 if (value
> 255 || value
< -256 || value
== 0x80)
466 return bfd_reloc_overflow
;
469 sword
= value
& 0x000F;
470 sword
|= (value
& 0x00F0) << 4;
472 bfd_put_16 (abfd
, (bfd_vma
) sword
,
473 (unsigned char *) data
+ octets
);
476 case R_S_16C_16
: /* word2. */
477 if (value
> 65535 || value
< -65536)
478 return bfd_reloc_overflow
;
481 value
= ((value
& 0x8000) >> 15) | ((value
& 0x7FFF) << 1);
483 bfd_put_16 (abfd
, (bfd_vma
) sword
,
484 (unsigned char *) data
+ octets
);
487 case R_S_16C_24_a
: /* word1(0-7),word2. */
488 if (value
> 16777215 || value
< -16777216)
489 return bfd_reloc_overflow
;
492 value
= ((value
& 0x00007FFF) << 17) |
493 ((value
& 0x00800000) >> 7) | ((value
& 0x007F8000) >> 15);
495 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
498 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
499 if (value
> 16777215 || value
< -16777216)
500 return bfd_reloc_overflow
;
504 value
= ((value
& 0x007FFFFF) << 1) | ((value
& 0x00800000) >> 23);
506 value
= ((value
& 0x0000FFFF) << 16) |
507 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
509 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
513 return bfd_reloc_notsupported
;
520 case R_S_16C_04
: /* word1(12-15) not scaled. */
521 if (value
> 13 || value
< 0)
522 return bfd_reloc_overflow
;
525 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
528 case R_S_16C_04_a
: /* word1(12-15) not scaled. */
529 if (value
> 26 || value
< 0)
530 return bfd_reloc_overflow
;
534 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
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
;
541 value
= ((value
& 0x000000c0) << 24) |
542 ((value
& 0x00003F00) << 16) |
543 ((value
& 0x0000000F) << 16) | (value
& 0x00000030);
545 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
548 case R_S_16C_16
: /* word2. */
549 if (value
> 65535 || value
< 0)
550 return bfd_reloc_overflow
;
553 bfd_put_16 (abfd
, (bfd_vma
) sword
,
554 (unsigned char *) data
+ octets
);
557 case R_S_16C_20
: /* word2(8-11),word3. */
558 /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
560 sword
= value
& 0x0000FFFF;
561 value
= (value
& 0x000F0000) >> 16;
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);
568 /* Change load/stor negative displ opcode
569 to load/stor positive displ opcode. */
570 value
= bfd_get_8 (abfd
, (char *) data
+ octets
- 3);
573 bfd_put_8 (abfd
, (bfd_vma
) value
,
574 (unsigned char *) data
+ octets
- 3);
579 return bfd_reloc_notsupported
;
586 case R_S_16C_20
: /* word1(0-3),word2. */
587 if (value
> 1048575 || value
< 0)
588 return bfd_reloc_overflow
;
590 value
= ((value
& 0x0000FFFF) << 16) |
591 ((value
& 0x000F0000) >> 16);
593 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
596 case R_S_16C_24
: /* word2(0-3,8-11),word3. */
597 /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
599 value
= ((value
& 0x0000FFFF) << 16) |
600 ((value
& 0x000F0000) >> 8) | ((value
& 0x00F00000) >> 20);
602 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
606 return bfd_reloc_notsupported
;
613 case R_S_16C_04
: /* word1/2(4-7). */
614 if (value
> 15 || value
< -1)
615 return bfd_reloc_overflow
;
619 bfd_put_8 (abfd
, (bfd_vma
) value
, (unsigned char *) data
+ octets
);
622 case R_S_16C_16
: /* word2. */
623 if (value
> 32767 || value
< -32768)
624 return bfd_reloc_overflow
;
627 bfd_put_16 (abfd
, (bfd_vma
) sword
,
628 (unsigned char *) data
+ octets
);
631 case R_S_16C_20
: /* word1(0-3),word2. */
632 if (value
> 1048575 || value
< 0)
633 return bfd_reloc_overflow
;
635 value
= ((value
& 0x0000FFFF) << 16) |
636 ((value
& 0x000F0000) >> 16);
638 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
641 case R_S_16C_32
: /* word2, word3. */
643 value
= ((value
& 0x0000FFFF) << 16) |
644 ((value
& 0xFFFF0000) >> 16);
645 bfd_put_32 (abfd
, (bfd_vma
) value
, (bfd_byte
*) data
+ octets
);
649 return bfd_reloc_notsupported
;
653 return bfd_reloc_notsupported
;
657 /* Relocate a CR16C ELF section. */
660 elf32_cr16c_relocate_section (bfd
*output_bfd
,
661 struct bfd_link_info
*info
,
663 asection
*input_section
,
665 Elf_Internal_Rela
*relocs
,
666 Elf_Internal_Sym
*local_syms
,
667 asection
**local_sections
)
669 Elf_Internal_Shdr
*symtab_hdr
;
670 struct elf_link_hash_entry
**sym_hashes
;
671 Elf_Internal_Rela
*rel
, *relend
;
673 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
674 sym_hashes
= elf_sym_hashes (input_bfd
);
677 relend
= relocs
+ input_section
->reloc_count
;
678 for (; rel
< relend
; rel
++)
681 reloc_howto_type
*howto
;
682 unsigned long r_symndx
;
683 Elf_Internal_Sym
*sym
;
685 struct elf_link_hash_entry
*h
;
687 bfd_reloc_status_type r
;
689 r_symndx
= ELF32_R_SYM (rel
->r_info
);
690 r_type
= ELF32_R_TYPE (rel
->r_info
);
691 howto
= elf_howto_table
+ r_type
;
693 if (info
->relocatable
)
695 /* This is a relocatable link. We don't have to change
696 anything, unless the reloc is against a section symbol,
697 in which case we have to adjust according to where the
698 section symbol winds up in the output section. */
699 if (r_symndx
< symtab_hdr
->sh_info
)
701 sym
= local_syms
+ r_symndx
;
702 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
704 sec
= local_sections
[r_symndx
];
705 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
712 /* This is a final link. */
716 if (r_symndx
< symtab_hdr
->sh_info
)
718 sym
= local_syms
+ r_symndx
;
719 sec
= local_sections
[r_symndx
];
720 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
724 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
725 while (h
->root
.type
== bfd_link_hash_indirect
726 || h
->root
.type
== bfd_link_hash_warning
)
727 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
728 if (h
->root
.type
== bfd_link_hash_defined
729 || h
->root
.type
== bfd_link_hash_defweak
)
731 sec
= h
->root
.u
.def
.section
;
732 relocation
= (h
->root
.u
.def
.value
733 + sec
->output_section
->vma
+ sec
->output_offset
);
735 else if (h
->root
.type
== bfd_link_hash_undefweak
)
739 if (!((*info
->callbacks
->undefined_symbol
)
740 (info
, h
->root
.root
.string
, input_bfd
,
741 input_section
, rel
->r_offset
, TRUE
)))
747 r
= cr16c_elf_final_link_relocate (howto
, input_bfd
, output_bfd
,
749 contents
, rel
->r_offset
,
750 relocation
, rel
->r_addend
,
751 info
, sec
, h
== NULL
);
753 if (r
!= bfd_reloc_ok
)
756 const char *msg
= (const char *) 0;
759 name
= h
->root
.root
.string
;
762 name
= (bfd_elf_string_from_elf_section
763 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
));
764 if (name
== NULL
|| *name
== '\0')
765 name
= bfd_section_name (input_bfd
, sec
);
770 case bfd_reloc_overflow
:
771 if (!((*info
->callbacks
->reloc_overflow
)
772 (info
, name
, howto
->name
, (bfd_vma
) 0,
773 input_bfd
, input_section
, rel
->r_offset
)))
777 case bfd_reloc_undefined
:
778 if (!((*info
->callbacks
->undefined_symbol
)
779 (info
, name
, input_bfd
, input_section
,
780 rel
->r_offset
, TRUE
)))
784 case bfd_reloc_outofrange
:
785 msg
= _("internal error: out of range error");
788 case bfd_reloc_notsupported
:
789 msg
= _("internal error: unsupported relocation error");
792 case bfd_reloc_dangerous
:
793 msg
= _("internal error: dangerous error");
797 msg
= _("internal error: unknown error");
801 if (!((*info
->callbacks
->warning
)
802 (info
, msg
, name
, input_bfd
, input_section
,
814 elf32_cr16c_gc_mark_hook (asection
*sec
,
815 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
816 Elf_Internal_Rela
*rel
,
817 struct elf_link_hash_entry
*h
,
818 Elf_Internal_Sym
*sym
)
822 switch (ELF32_R_TYPE (rel
->r_info
))
826 switch (h
->root
.type
)
828 case bfd_link_hash_defined
:
829 case bfd_link_hash_defweak
:
830 return h
->root
.u
.def
.section
;
832 case bfd_link_hash_common
:
833 return h
->root
.u
.c
.p
->section
;
842 return bfd_section_from_elf_index (sec
->owner
, sym
->st_shndx
);
848 /* Update the got entry reference counts for the section being removed. */
851 elf32_cr16c_gc_sweep_hook (bfd
*abfd ATTRIBUTE_UNUSED
,
852 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
853 asection
*sec ATTRIBUTE_UNUSED
,
854 const Elf_Internal_Rela
*relocs ATTRIBUTE_UNUSED
)
856 /* We don't support garbage collection of GOT and PLT relocs yet. */
860 /* CR16C ELF uses three common sections:
861 One is for default common symbols (placed in usual common section).
862 Second is for near common symbols (placed in "ncommon" section).
863 Third is for far common symbols (placed in "fcommon" section).
864 The following implementation is based on elf32-mips architecture */
866 static asection cr16c_elf_fcom_section
;
867 static asymbol cr16c_elf_fcom_symbol
;
868 static asymbol
* cr16c_elf_fcom_symbol_ptr
;
869 static asection cr16c_elf_ncom_section
;
870 static asymbol cr16c_elf_ncom_symbol
;
871 static asymbol
* cr16c_elf_ncom_symbol_ptr
;
873 /* Given a BFD section, try to locate the
874 corresponding ELF section index. */
877 elf32_cr16c_section_from_bfd_section (bfd
*abfd ATTRIBUTE_UNUSED
,
881 if (strcmp (bfd_get_section_name (abfd
, sec
), ".fcommon") == 0)
882 *retval
= SHN_CR16C_FCOMMON
;
883 else if (strcmp (bfd_get_section_name (abfd
, sec
), ".ncommon") == 0)
884 *retval
= SHN_CR16C_NCOMMON
;
891 /* Handle the special CR16C section numbers that a symbol may use. */
894 elf32_cr16c_symbol_processing (bfd
*abfd ATTRIBUTE_UNUSED
,
897 elf_symbol_type
*elfsym
= (elf_symbol_type
*) asym
;
900 indx
= elfsym
->internal_elf_sym
.st_shndx
;
904 case SHN_CR16C_FCOMMON
:
905 if (cr16c_elf_fcom_section
.name
== NULL
)
907 /* Initialize the far common section. */
908 cr16c_elf_fcom_section
.name
= ".fcommon";
909 cr16c_elf_fcom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
910 cr16c_elf_fcom_section
.output_section
= &cr16c_elf_fcom_section
;
911 cr16c_elf_fcom_section
.symbol
= &cr16c_elf_fcom_symbol
;
912 cr16c_elf_fcom_section
.symbol_ptr_ptr
= &cr16c_elf_fcom_symbol_ptr
;
913 cr16c_elf_fcom_symbol
.name
= ".fcommon";
914 cr16c_elf_fcom_symbol
.flags
= BSF_SECTION_SYM
;
915 cr16c_elf_fcom_symbol
.section
= &cr16c_elf_fcom_section
;
916 cr16c_elf_fcom_symbol_ptr
= &cr16c_elf_fcom_symbol
;
918 asym
->section
= &cr16c_elf_fcom_section
;
919 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
921 case SHN_CR16C_NCOMMON
:
922 if (cr16c_elf_ncom_section
.name
== NULL
)
924 /* Initialize the far common section. */
925 cr16c_elf_ncom_section
.name
= ".ncommon";
926 cr16c_elf_ncom_section
.flags
= SEC_IS_COMMON
| SEC_ALLOC
;
927 cr16c_elf_ncom_section
.output_section
= &cr16c_elf_ncom_section
;
928 cr16c_elf_ncom_section
.symbol
= &cr16c_elf_ncom_symbol
;
929 cr16c_elf_ncom_section
.symbol_ptr_ptr
= &cr16c_elf_ncom_symbol_ptr
;
930 cr16c_elf_ncom_symbol
.name
= ".ncommon";
931 cr16c_elf_ncom_symbol
.flags
= BSF_SECTION_SYM
;
932 cr16c_elf_ncom_symbol
.section
= &cr16c_elf_ncom_section
;
933 cr16c_elf_ncom_symbol_ptr
= &cr16c_elf_ncom_symbol
;
935 asym
->section
= &cr16c_elf_ncom_section
;
936 asym
->value
= elfsym
->internal_elf_sym
.st_size
;
941 /* Hook called by the linker routine which adds symbols from an object
942 file. We must handle the special cr16c section numbers here. */
945 elf32_cr16c_add_symbol_hook (bfd
*abfd
,
946 struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
947 const Elf_Internal_Sym
*sym
,
948 const char **namep ATTRIBUTE_UNUSED
,
949 flagword
*flagsp ATTRIBUTE_UNUSED
,
953 unsigned int indx
= sym
->st_shndx
;
957 case SHN_CR16C_FCOMMON
:
958 *secp
= bfd_make_section_old_way (abfd
, ".fcommon");
959 (*secp
)->flags
|= SEC_IS_COMMON
;
960 *valp
= sym
->st_size
;
962 case SHN_CR16C_NCOMMON
:
963 *secp
= bfd_make_section_old_way (abfd
, ".ncommon");
964 (*secp
)->flags
|= SEC_IS_COMMON
;
965 *valp
= sym
->st_size
;
973 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info
*info ATTRIBUTE_UNUSED
,
974 const char *name ATTRIBUTE_UNUSED
,
975 Elf_Internal_Sym
*sym
,
977 struct elf_link_hash_entry
*h ATTRIBUTE_UNUSED
)
979 /* If we see a common symbol, which implies a relocatable link, then
980 if a symbol was in a special common section in an input file, mark
981 it as a special common in the output file. */
983 if (sym
->st_shndx
== SHN_COMMON
)
985 if (strcmp (input_sec
->name
, ".fcommon") == 0)
986 sym
->st_shndx
= SHN_CR16C_FCOMMON
;
987 else if (strcmp (input_sec
->name
, ".ncommon") == 0)
988 sym
->st_shndx
= SHN_CR16C_NCOMMON
;
994 /* Definitions for setting CR16C target vector. */
995 #define TARGET_LITTLE_SYM bfd_elf32_cr16c_vec
996 #define TARGET_LITTLE_NAME "elf32-cr16c"
997 #define ELF_ARCH bfd_arch_cr16c
998 #define ELF_MACHINE_CODE EM_CR
999 #define ELF_MAXPAGESIZE 0x1
1000 #define elf_symbol_leading_char '_'
1002 #define bfd_elf32_bfd_reloc_type_lookup elf_cr16c_reloc_type_lookup
1003 #define elf_info_to_howto elf_cr16c_info_to_howto
1004 #define elf_info_to_howto_rel elf_cr16c_info_to_howto_rel
1005 #define elf_backend_relocate_section elf32_cr16c_relocate_section
1006 #define elf_backend_gc_mark_hook elf32_cr16c_gc_mark_hook
1007 #define elf_backend_gc_sweep_hook elf32_cr16c_gc_sweep_hook
1008 #define elf_backend_symbol_processing elf32_cr16c_symbol_processing
1009 #define elf_backend_section_from_bfd_section elf32_cr16c_section_from_bfd_section
1010 #define elf_backend_add_symbol_hook elf32_cr16c_add_symbol_hook
1011 #define elf_backend_link_output_symbol_hook elf32_cr16c_link_output_symbol_hook
1013 #define elf_backend_can_gc_sections 1
1015 #include "elf32-target.h"