*c-cr16.texi (cr16-operand specifiers): Add got/GOT and cgot/cGOT.
[deliverable/binutils-gdb.git] / bfd / elf32-cr16.c
CommitLineData
3d3d428f
NC
1/* BFD back-end for National Semiconductor's CR16 ELF
2 Copyright 2007 Free Software Foundation, Inc.
3 Written by M R Swami Reddy.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
3d3d428f
NC
10 (at your option) any later version.
11
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.
16
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 Foundation,
19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21#include "sysdep.h"
22#include "bfd.h"
23#include "bfdlink.h"
24#include "libbfd.h"
25#include "libiberty.h"
26#include "elf-bfd.h"
27#include "elf/cr16.h"
28
29/* cr16_reloc_map array maps BFD relocation enum into a CRGAS relocation type. */
30
31struct cr16_reloc_map
32{
33 bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum. */
34 unsigned short cr16_reloc_type; /* CR16 relocation type. */
35};
36
37static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] =
38{
39 {BFD_RELOC_NONE, R_CR16_NONE},
40 {BFD_RELOC_CR16_NUM8, R_CR16_NUM8},
41 {BFD_RELOC_CR16_NUM16, R_CR16_NUM16},
42 {BFD_RELOC_CR16_NUM32, R_CR16_NUM32},
43 {BFD_RELOC_CR16_NUM32a, R_CR16_NUM32a},
44 {BFD_RELOC_CR16_REGREL4, R_CR16_REGREL4},
45 {BFD_RELOC_CR16_REGREL4a, R_CR16_REGREL4a},
46 {BFD_RELOC_CR16_REGREL14, R_CR16_REGREL14},
47 {BFD_RELOC_CR16_REGREL14a, R_CR16_REGREL14a},
48 {BFD_RELOC_CR16_REGREL16, R_CR16_REGREL16},
49 {BFD_RELOC_CR16_REGREL20, R_CR16_REGREL20},
50 {BFD_RELOC_CR16_REGREL20a, R_CR16_REGREL20a},
51 {BFD_RELOC_CR16_ABS20, R_CR16_ABS20},
52 {BFD_RELOC_CR16_ABS24, R_CR16_ABS24},
53 {BFD_RELOC_CR16_IMM4, R_CR16_IMM4},
54 {BFD_RELOC_CR16_IMM8, R_CR16_IMM8},
55 {BFD_RELOC_CR16_IMM16, R_CR16_IMM16},
56 {BFD_RELOC_CR16_IMM20, R_CR16_IMM20},
57 {BFD_RELOC_CR16_IMM24, R_CR16_IMM24},
58 {BFD_RELOC_CR16_IMM32, R_CR16_IMM32},
59 {BFD_RELOC_CR16_IMM32a, R_CR16_IMM32a},
60 {BFD_RELOC_CR16_DISP4, R_CR16_DISP4},
61 {BFD_RELOC_CR16_DISP8, R_CR16_DISP8},
62 {BFD_RELOC_CR16_DISP16, R_CR16_DISP16},
63 {BFD_RELOC_CR16_DISP24, R_CR16_DISP24},
7fac7ff4
NC
64 {BFD_RELOC_CR16_DISP24a, R_CR16_DISP24a},
65 {BFD_RELOC_CR16_SWITCH8, R_CR16_SWITCH8},
66 {BFD_RELOC_CR16_SWITCH16, R_CR16_SWITCH16},
67 {BFD_RELOC_CR16_SWITCH32, R_CR16_SWITCH32}
3d3d428f
NC
68};
69
70static reloc_howto_type cr16_elf_howto_table[] =
71{
72 HOWTO (R_CR16_NONE, /* type */
73 0, /* rightshift */
74 2, /* size */
75 32, /* bitsize */
76 FALSE, /* pc_relative */
77 0, /* bitpos */
78 complain_overflow_dont, /* complain_on_overflow */
79 bfd_elf_generic_reloc, /* special_function */
80 "R_CR16_NONE", /* name */
81 FALSE, /* partial_inplace */
82 0, /* src_mask */
83 0, /* dst_mask */
84 FALSE), /* pcrel_offset */
85
86 HOWTO (R_CR16_NUM8, /* type */
87 0, /* rightshift */
88 0, /* size */
89 8, /* bitsize */
90 FALSE, /* pc_relative */
91 0, /* bitpos */
92 complain_overflow_bitfield,/* complain_on_overflow */
93 bfd_elf_generic_reloc, /* special_function */
94 "R_CR16_NUM8", /* name */
95 FALSE, /* partial_inplace */
dc80fd5c 96 0x0, /* src_mask */
3d3d428f
NC
97 0xff, /* dst_mask */
98 FALSE), /* pcrel_offset */
99
100 HOWTO (R_CR16_NUM16, /* type */
101 0, /* rightshift */
102 1, /* size */
103 16, /* bitsize */
104 FALSE, /* pc_relative */
105 0, /* bitpos */
106 complain_overflow_bitfield,/* complain_on_overflow */
107 bfd_elf_generic_reloc, /* special_function */
108 "R_CR16_NUM16", /* name */
109 FALSE, /* partial_inplace */
dc80fd5c 110 0x0, /* src_mask */
3d3d428f
NC
111 0xffff, /* dst_mask */
112 FALSE), /* pcrel_offset */
113
114 HOWTO (R_CR16_NUM32, /* type */
115 0, /* rightshift */
116 2, /* size */
117 32, /* bitsize */
118 FALSE, /* pc_relative */
119 0, /* bitpos */
120 complain_overflow_bitfield,/* complain_on_overflow */
121 bfd_elf_generic_reloc, /* special_function */
122 "R_CR16_NUM32", /* name */
123 FALSE, /* partial_inplace */
dc80fd5c 124 0x0, /* src_mask */
3d3d428f
NC
125 0xffffffff, /* dst_mask */
126 FALSE), /* pcrel_offset */
127
128 HOWTO (R_CR16_NUM32a, /* type */
129 1, /* rightshift */
130 2, /* size */
131 32, /* bitsize */
132 FALSE, /* pc_relative */
133 0, /* bitpos */
134 complain_overflow_bitfield,/* complain_on_overflow */
135 bfd_elf_generic_reloc, /* special_function */
136 "R_CR16_NUM32a", /* name */
137 FALSE, /* partial_inplace */
dc80fd5c 138 0x0, /* src_mask */
3d3d428f
NC
139 0xffffffff, /* dst_mask */
140 FALSE), /* pcrel_offset */
141
142 HOWTO (R_CR16_REGREL4, /* type */
143 0, /* rightshift */
144 0, /* size */
145 4, /* bitsize */
146 FALSE, /* pc_relative */
147 0, /* bitpos */
148 complain_overflow_bitfield,/* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_CR16_REGREL4", /* name */
151 FALSE, /* partial_inplace */
dc80fd5c 152 0x0, /* src_mask */
3d3d428f
NC
153 0xf, /* dst_mask */
154 FALSE), /* pcrel_offset */
155
156 HOWTO (R_CR16_REGREL4a, /* type */
157 0, /* rightshift */
158 0, /* size */
159 4, /* bitsize */
160 FALSE, /* pc_relative */
161 0, /* bitpos */
162 complain_overflow_bitfield,/* complain_on_overflow */
163 bfd_elf_generic_reloc, /* special_function */
164 "R_CR16_REGREL4a", /* name */
165 FALSE, /* partial_inplace */
dc80fd5c 166 0x0, /* src_mask */
3d3d428f
NC
167 0xf, /* dst_mask */
168 FALSE), /* pcrel_offset */
169
170 HOWTO (R_CR16_REGREL14, /* type */
171 0, /* rightshift */
172 1, /* size */
173 14, /* bitsize */
174 FALSE, /* pc_relative */
175 0, /* bitpos */
176 complain_overflow_bitfield,/* complain_on_overflow */
177 bfd_elf_generic_reloc, /* special_function */
178 "R_CR16_REGREL14", /* name */
179 FALSE, /* partial_inplace */
dc80fd5c 180 0x0, /* src_mask */
3d3d428f
NC
181 0x3fff, /* dst_mask */
182 FALSE), /* pcrel_offset */
183
184 HOWTO (R_CR16_REGREL14a, /* type */
185 0, /* rightshift */
186 1, /* size */
187 14, /* bitsize */
188 FALSE, /* pc_relative */
189 0, /* bitpos */
190 complain_overflow_bitfield,/* complain_on_overflow */
191 bfd_elf_generic_reloc, /* special_function */
192 "R_CR16_REGREL14a", /* name */
193 FALSE, /* partial_inplace */
dc80fd5c 194 0x0, /* src_mask */
3d3d428f
NC
195 0x3fff, /* dst_mask */
196 FALSE), /* pcrel_offset */
197
198 HOWTO (R_CR16_REGREL16, /* type */
199 0, /* rightshift */
200 1, /* size */
201 16, /* bitsize */
202 FALSE, /* pc_relative */
203 0, /* bitpos */
204 complain_overflow_bitfield,/* complain_on_overflow */
205 bfd_elf_generic_reloc, /* special_function */
206 "R_CR16_REGREL16", /* name */
207 FALSE, /* partial_inplace */
dc80fd5c 208 0x0, /* src_mask */
3d3d428f
NC
209 0xffff, /* dst_mask */
210 FALSE), /* pcrel_offset */
211
212 HOWTO (R_CR16_REGREL20, /* type */
213 0, /* rightshift */
214 2, /* size */
215 20, /* bitsize */
216 FALSE, /* pc_relative */
217 0, /* bitpos */
218 complain_overflow_bitfield,/* complain_on_overflow */
219 bfd_elf_generic_reloc, /* special_function */
220 "R_CR16_REGREL20", /* name */
221 FALSE, /* partial_inplace */
dc80fd5c 222 0x0, /* src_mask */
3d3d428f
NC
223 0xfffff, /* dst_mask */
224 FALSE), /* pcrel_offset */
225
226 HOWTO (R_CR16_REGREL20a, /* type */
227 0, /* rightshift */
228 2, /* size */
229 20, /* bitsize */
230 FALSE, /* pc_relative */
231 0, /* bitpos */
232 complain_overflow_bitfield,/* complain_on_overflow */
233 bfd_elf_generic_reloc, /* special_function */
234 "R_CR16_REGREL20a", /* name */
235 FALSE, /* partial_inplace */
dc80fd5c 236 0x0, /* src_mask */
3d3d428f
NC
237 0xfffff, /* dst_mask */
238 FALSE), /* pcrel_offset */
239
240 HOWTO (R_CR16_ABS20, /* type */
241 0, /* rightshift */
242 2, /* size */
243 20, /* bitsize */
244 FALSE, /* pc_relative */
245 0, /* bitpos */
246 complain_overflow_bitfield,/* complain_on_overflow */
247 bfd_elf_generic_reloc, /* special_function */
248 "R_CR16_ABS20", /* name */
249 FALSE, /* partial_inplace */
dc80fd5c 250 0x0, /* src_mask */
3d3d428f
NC
251 0xfffff, /* dst_mask */
252 FALSE), /* pcrel_offset */
253
254 HOWTO (R_CR16_ABS24, /* type */
255 0, /* rightshift */
256 2, /* size */
257 24, /* bitsize */
258 FALSE, /* pc_relative */
259 0, /* bitpos */
260 complain_overflow_bitfield,/* complain_on_overflow */
261 bfd_elf_generic_reloc, /* special_function */
262 "R_CR16_ABS24", /* name */
263 FALSE, /* partial_inplace */
dc80fd5c 264 0x0, /* src_mask */
3d3d428f
NC
265 0xffffff, /* dst_mask */
266 FALSE), /* pcrel_offset */
267
268 HOWTO (R_CR16_IMM4, /* type */
269 0, /* rightshift */
270 0, /* size */
271 4, /* bitsize */
272 FALSE, /* pc_relative */
273 0, /* bitpos */
274 complain_overflow_bitfield,/* complain_on_overflow */
275 bfd_elf_generic_reloc, /* special_function */
276 "R_CR16_IMM4", /* name */
277 FALSE, /* partial_inplace */
dc80fd5c 278 0x0, /* src_mask */
3d3d428f
NC
279 0xf, /* dst_mask */
280 FALSE), /* pcrel_offset */
281
282 HOWTO (R_CR16_IMM8, /* type */
283 0, /* rightshift */
284 0, /* size */
285 8, /* bitsize */
286 FALSE, /* pc_relative */
287 0, /* bitpos */
288 complain_overflow_bitfield,/* complain_on_overflow */
289 bfd_elf_generic_reloc, /* special_function */
290 "R_CR16_IMM8", /* name */
291 FALSE, /* partial_inplace */
dc80fd5c 292 0x0, /* src_mask */
3d3d428f
NC
293 0xff, /* dst_mask */
294 FALSE), /* pcrel_offset */
295
296 HOWTO (R_CR16_IMM16, /* type */
297 0, /* rightshift */
298 1, /* size */
299 16, /* bitsize */
300 FALSE, /* pc_relative */
301 0, /* bitpos */
302 complain_overflow_bitfield,/* complain_on_overflow */
303 bfd_elf_generic_reloc, /* special_function */
304 "R_CR16_IMM16", /* name */
305 FALSE, /* partial_inplace */
dc80fd5c 306 0x0, /* src_mask */
3d3d428f
NC
307 0xffff, /* dst_mask */
308 FALSE), /* pcrel_offset */
309
310 HOWTO (R_CR16_IMM20, /* type */
311 0, /* rightshift */
312 2, /* size */
313 20, /* bitsize */
314 FALSE, /* pc_relative */
315 0, /* bitpos */
316 complain_overflow_bitfield,/* complain_on_overflow */
317 bfd_elf_generic_reloc, /* special_function */
318 "R_CR16_IMM20", /* name */
319 FALSE, /* partial_inplace */
dc80fd5c 320 0x0, /* src_mask */
3d3d428f
NC
321 0xfffff, /* dst_mask */
322 FALSE), /* pcrel_offset */
323
324 HOWTO (R_CR16_IMM24, /* type */
325 0, /* rightshift */
326 2, /* size */
327 24, /* bitsize */
328 FALSE, /* pc_relative */
329 0, /* bitpos */
330 complain_overflow_bitfield,/* complain_on_overflow */
331 bfd_elf_generic_reloc, /* special_function */
332 "R_CR16_IMM24", /* name */
333 FALSE, /* partial_inplace */
dc80fd5c 334 0x0, /* src_mask */
3d3d428f
NC
335 0xffffff, /* dst_mask */
336 FALSE), /* pcrel_offset */
337
338 HOWTO (R_CR16_IMM32, /* type */
339 0, /* rightshift */
340 2, /* size */
341 32, /* bitsize */
342 FALSE, /* pc_relative */
343 0, /* bitpos */
344 complain_overflow_bitfield,/* complain_on_overflow */
345 bfd_elf_generic_reloc, /* special_function */
346 "R_CR16_IMM32", /* name */
347 FALSE, /* partial_inplace */
dc80fd5c 348 0x0, /* src_mask */
3d3d428f
NC
349 0xffffffff, /* dst_mask */
350 FALSE), /* pcrel_offset */
351
352 HOWTO (R_CR16_IMM32a, /* type */
353 1, /* rightshift */
354 2, /* size */
355 32, /* bitsize */
356 FALSE, /* pc_relative */
357 0, /* bitpos */
358 complain_overflow_bitfield,/* complain_on_overflow */
359 bfd_elf_generic_reloc, /* special_function */
360 "R_CR16_IMM32a", /* name */
361 FALSE, /* partial_inplace */
dc80fd5c 362 0x0, /* src_mask */
3d3d428f
NC
363 0xffffffff, /* dst_mask */
364 FALSE), /* pcrel_offset */
365
366 HOWTO (R_CR16_DISP4, /* type */
367 1, /* rightshift */
368 0, /* size (0 = byte, 1 = short, 2 = long) */
369 4, /* bitsize */
370 TRUE, /* pc_relative */
371 0, /* bitpos */
372 complain_overflow_unsigned, /* complain_on_overflow */
373 bfd_elf_generic_reloc, /* special_function */
374 "R_CR16_DISP4", /* name */
375 FALSE, /* partial_inplace */
dc80fd5c 376 0x0, /* src_mask */
3d3d428f
NC
377 0xf, /* dst_mask */
378 FALSE), /* pcrel_offset */
379
380 HOWTO (R_CR16_DISP8, /* type */
381 1, /* rightshift */
382 0, /* size (0 = byte, 1 = short, 2 = long) */
383 8, /* bitsize */
384 TRUE, /* pc_relative */
385 0, /* bitpos */
386 complain_overflow_unsigned, /* complain_on_overflow */
387 bfd_elf_generic_reloc, /* special_function */
388 "R_CR16_DISP8", /* name */
389 FALSE, /* partial_inplace */
dc80fd5c 390 0x0, /* src_mask */
3d3d428f
NC
391 0x1ff, /* dst_mask */
392 FALSE), /* pcrel_offset */
393
394 HOWTO (R_CR16_DISP16, /* type */
395 0, /* rightshift REVIITS: To sync with WinIDEA*/
396 1, /* size (0 = byte, 1 = short, 2 = long) */
397 16, /* bitsize */
398 TRUE, /* pc_relative */
399 0, /* bitpos */
400 complain_overflow_unsigned, /* complain_on_overflow */
401 bfd_elf_generic_reloc, /* special_function */
402 "R_CR16_DISP16", /* name */
403 FALSE, /* partial_inplace */
dc80fd5c 404 0x0, /* src_mask */
3d3d428f
NC
405 0x1ffff, /* dst_mask */
406 FALSE), /* pcrel_offset */
407 /* REVISIT: DISP24 should be left-shift by 2 as per ISA doc
408 but its not done, to sync with WinIDEA and CR16 4.1 tools */
409 HOWTO (R_CR16_DISP24, /* type */
410 0, /* rightshift */
411 2, /* size (0 = byte, 1 = short, 2 = long) */
412 24, /* bitsize */
413 TRUE, /* pc_relative */
414 0, /* bitpos */
415 complain_overflow_unsigned, /* complain_on_overflow */
416 bfd_elf_generic_reloc, /* special_function */
417 "R_CR16_DISP24", /* name */
418 FALSE, /* partial_inplace */
dc80fd5c 419 0x0, /* src_mask */
3d3d428f
NC
420 0x1ffffff, /* dst_mask */
421 FALSE), /* pcrel_offset */
422
423 HOWTO (R_CR16_DISP24a, /* type */
424 0, /* rightshift */
425 2, /* size (0 = byte, 1 = short, 2 = long) */
426 24, /* bitsize */
427 TRUE, /* pc_relative */
428 0, /* bitpos */
429 complain_overflow_unsigned, /* complain_on_overflow */
430 bfd_elf_generic_reloc, /* special_function */
431 "R_CR16_DISP24a", /* name */
432 FALSE, /* partial_inplace */
dc80fd5c 433 0x0, /* src_mask */
3d3d428f 434 0xffffff, /* dst_mask */
7fac7ff4
NC
435 FALSE), /* pcrel_offset */
436
437 /* An 8 bit switch table entry. This is generated for an expression
438 such as ``.byte L1 - L2''. The offset holds the difference
439 between the reloc address and L2. */
440 HOWTO (R_CR16_SWITCH8, /* type */
441 0, /* rightshift */
442 0, /* size (0 = byte, 1 = short, 2 = long) */
443 8, /* bitsize */
444 FALSE, /* pc_relative */
445 0, /* bitpos */
446 complain_overflow_unsigned, /* complain_on_overflow */
447 bfd_elf_generic_reloc, /* special_function */
448 "R_CR16_SWITCH8", /* name */
449 FALSE, /* partial_inplace */
dc80fd5c 450 0x0, /* src_mask */
7fac7ff4
NC
451 0xff, /* dst_mask */
452 TRUE), /* pcrel_offset */
453
454 /* A 16 bit switch table entry. This is generated for an expression
455 such as ``.word L1 - L2''. The offset holds the difference
456 between the reloc address and L2. */
457 HOWTO (R_CR16_SWITCH16, /* type */
458 0, /* rightshift */
459 1, /* size (0 = byte, 1 = short, 2 = long) */
460 16, /* bitsize */
461 FALSE, /* pc_relative */
462 0, /* bitpos */
463 complain_overflow_unsigned, /* complain_on_overflow */
464 bfd_elf_generic_reloc, /* special_function */
465 "R_CR16_SWITCH16", /* name */
466 FALSE, /* partial_inplace */
dc80fd5c 467 0x0, /* src_mask */
7fac7ff4
NC
468 0xffff, /* dst_mask */
469 TRUE), /* pcrel_offset */
470
471 /* A 32 bit switch table entry. This is generated for an expression
472 such as ``.long L1 - L2''. The offset holds the difference
473 between the reloc address and L2. */
474 HOWTO (R_CR16_SWITCH32, /* type */
475 0, /* rightshift */
476 2, /* size (0 = byte, 1 = short, 2 = long) */
477 32, /* bitsize */
478 FALSE, /* pc_relative */
479 0, /* bitpos */
480 complain_overflow_unsigned, /* complain_on_overflow */
481 bfd_elf_generic_reloc, /* special_function */
482 "R_CR16_SWITCH32", /* name */
483 FALSE, /* partial_inplace */
dc80fd5c 484 0x0, /* src_mask */
7fac7ff4
NC
485 0xffffffff, /* dst_mask */
486 TRUE) /* pcrel_offset */
3d3d428f
NC
487};
488
489/* Retrieve a howto ptr using a BFD reloc_code. */
490
491static reloc_howto_type *
492elf_cr16_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
493 bfd_reloc_code_real_type code)
494{
495 unsigned int i;
496
497 for (i = 0; i < R_CR16_MAX; i++)
498 if (code == cr16_reloc_map[i].bfd_reloc_enum)
499 return &cr16_elf_howto_table[cr16_reloc_map[i].cr16_reloc_type];
500
501 _bfd_error_handler ("Unsupported CR16 relocation type: 0x%x\n", code);
502 return NULL;
503}
504
505static reloc_howto_type *
506elf_cr16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
507 const char *r_name)
508{
509 unsigned int i;
510
511 for (i = 0; ARRAY_SIZE (cr16_elf_howto_table); i++)
512 if (cr16_elf_howto_table[i].name != NULL
513 && strcasecmp (cr16_elf_howto_table[i].name, r_name) == 0)
514 return cr16_elf_howto_table + i;
515
516 return NULL;
517}
518
519/* Retrieve a howto ptr using an internal relocation entry. */
520
521static void
522elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
523 Elf_Internal_Rela *dst)
524{
525 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
526
527 BFD_ASSERT (r_type < (unsigned int) R_CR16_MAX);
528 cache_ptr->howto = &cr16_elf_howto_table[r_type];
529}
530
531/* Perform a relocation as part of a final link. */
532
533static bfd_reloc_status_type
534cr16_elf_final_link_relocate (reloc_howto_type *howto,
7fac7ff4 535 bfd *input_bfd,
3d3d428f
NC
536 bfd *output_bfd ATTRIBUTE_UNUSED,
537 asection *input_section,
7fac7ff4 538 bfd_byte *contents,
3d3d428f 539 bfd_vma offset,
7fac7ff4
NC
540 bfd_vma Rvalue,
541 bfd_vma addend,
3d3d428f
NC
542 struct bfd_link_info *info ATTRIBUTE_UNUSED,
543 asection *sec ATTRIBUTE_UNUSED,
544 int is_local ATTRIBUTE_UNUSED)
545{
546 unsigned short r_type = howto->type;
547 bfd_byte *hit_data = contents + offset;
548 bfd_vma reloc_bits, check, Rvalue1;
549
550 switch (r_type)
551 {
552 case R_CR16_IMM4:
7fac7ff4
NC
553 case R_CR16_IMM20:
554 case R_CR16_ABS20:
555 break;
556
3d3d428f
NC
557 case R_CR16_IMM8:
558 case R_CR16_IMM16:
3d3d428f
NC
559 case R_CR16_IMM32:
560 case R_CR16_IMM32a:
561 case R_CR16_REGREL4:
562 case R_CR16_REGREL4a:
563 case R_CR16_REGREL14:
564 case R_CR16_REGREL14a:
565 case R_CR16_REGREL16:
566 case R_CR16_REGREL20:
3d3d428f
NC
567 case R_CR16_ABS24:
568 case R_CR16_DISP16:
569 case R_CR16_DISP24:
570 /* 'hit_data' is relative to the start of the instruction, not the
571 relocation offset. Advance it to account for the exact offset. */
572 hit_data += 2;
573 break;
574
575 case R_CR16_NONE:
576 return bfd_reloc_ok;
577 break;
578
579 case R_CR16_DISP4:
7fac7ff4
NC
580 if (is_local)
581 Rvalue += -1;
582 break;
583
3d3d428f
NC
584 case R_CR16_DISP8:
585 case R_CR16_DISP24a:
7fac7ff4
NC
586 if (is_local)
587 Rvalue -= -1;
588 break;
589
590 case R_CR16_SWITCH8:
591 case R_CR16_SWITCH16:
592 case R_CR16_SWITCH32:
3d3d428f
NC
593 /* We only care about the addend, where the difference between
594 expressions is kept. */
7fac7ff4 595 Rvalue = 0;
3d3d428f
NC
596
597 default:
598 break;
599 }
600
601 if (howto->pc_relative)
602 {
603 /* Subtract the address of the section containing the location. */
604 Rvalue -= (input_section->output_section->vma
605 + input_section->output_offset);
606 /* Subtract the position of the location within the section. */
607 Rvalue -= offset;
608 }
609
610 /* Add in supplied addend. */
611 Rvalue += addend;
612
613 /* Complain if the bitfield overflows, whether it is considered
614 as signed or unsigned. */
615 check = Rvalue >> howto->rightshift;
616
617 /* Assumes two's complement. This expression avoids
618 overflow if howto->bitsize is the number of bits in
619 bfd_vma. */
620 reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
621
622 if (((bfd_vma) check & ~reloc_bits) != 0
623 && (((bfd_vma) check & ~reloc_bits)
624 != (-(bfd_vma) 1 & ~reloc_bits)))
625 {
626 /* The above right shift is incorrect for a signed
627 value. See if turning on the upper bits fixes the
628 overflow. */
629 if (howto->rightshift && (bfd_signed_vma) Rvalue < 0)
630 {
631 check |= ((bfd_vma) - 1
632 & ~((bfd_vma) - 1
7fac7ff4 633 >> howto->rightshift));
3d3d428f
NC
634
635 if (((bfd_vma) check & ~reloc_bits)
636 != (-(bfd_vma) 1 & ~reloc_bits))
637 return bfd_reloc_overflow;
638 }
639 else
640 return bfd_reloc_overflow;
641 }
642
643 /* Drop unwanted bits from the value we are relocating to. */
644 Rvalue >>= (bfd_vma) howto->rightshift;
645
646 /* Apply dst_mask to select only relocatable part of the insn. */
647 Rvalue &= howto->dst_mask;
648
649 switch (howto->size)
650 {
651 case 0:
7fac7ff4 652 if (r_type == R_CR16_DISP8)
3d3d428f
NC
653 {
654 Rvalue1 = bfd_get_16 (input_bfd, hit_data);
655 Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00)
7fac7ff4
NC
656 | (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
657 bfd_put_16 (input_bfd, Rvalue, hit_data);
658 }
659 else if (r_type == R_CR16_IMM4)
660 {
661 Rvalue1 = bfd_get_16 (input_bfd, hit_data);
662 Rvalue = (((Rvalue1 & 0xff) << 8) | ((Rvalue << 4) & 0xf0)
663 | ((Rvalue1 & 0x0f00) >> 8));
664 bfd_put_16 (input_bfd, Rvalue, hit_data);
665 }
666 else if (r_type == R_CR16_DISP4)
667 {
668 Rvalue1 = bfd_get_16 (input_bfd, hit_data);
669 Rvalue = (Rvalue1 | ((Rvalue & 0xf) << 4));
670 bfd_put_16 (input_bfd, Rvalue, hit_data);
671 }
672 else
673 {
674 bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
3d3d428f
NC
675 }
676 break;
677
678 case 1:
679 if (r_type == R_CR16_DISP16)
680 {
681 Rvalue |= (bfd_get_16 (input_bfd, hit_data));
682 Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
3d3d428f 683 }
7fac7ff4
NC
684
685 bfd_put_16 (input_bfd, Rvalue, hit_data);
3d3d428f
NC
686 break;
687
688 case 2:
7fac7ff4 689 if ((r_type == R_CR16_ABS20) || (r_type == R_CR16_IMM20))
3d3d428f 690 {
7fac7ff4
NC
691 bfd_put_16 (input_bfd, (bfd_get_16 (input_bfd, hit_data))
692 | ((Rvalue >> 16) & 0xf), hit_data);
693 bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
3d3d428f 694 }
7fac7ff4 695 else
3d3d428f 696 {
7fac7ff4
NC
697 if (r_type == R_CR16_ABS24)
698 {
699 Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf) << 8)
700 | (bfd_get_16 (input_bfd, hit_data)))
701 | ((Rvalue & 0xffff) << 16));
702 }
703 if (r_type == R_CR16_DISP24)
704 {
705 Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf) << 8)
706 | (bfd_get_16 (input_bfd, hit_data)))
707 | (((Rvalue & 0xfffe)
708 | ((Rvalue >> 24) & 0x1)) << 16));
709 }
710 else if ((r_type == R_CR16_IMM32) ||(r_type == R_CR16_IMM32a))
711 {
712 Rvalue = (((Rvalue >> 16)& 0xffff)
713 | (bfd_get_16 (input_bfd, hit_data)))
714 | ((Rvalue & 0xffff) << 16);
715 }
716 else if (r_type == R_CR16_DISP24a)
717 {
718 Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
719 Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
720 | (bfd_get_32 (input_bfd, hit_data));
721 }
3d3d428f
NC
722
723 bfd_put_32 (input_bfd, Rvalue, hit_data);
724 }
7fac7ff4 725 break;
3d3d428f
NC
726
727 default:
728 return bfd_reloc_notsupported;
729 }
730
731 return bfd_reloc_ok;
732}
733
734/* Delete some bytes from a section while relaxing. */
735
736static bfd_boolean
737elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
738 asection *sec, bfd_vma addr, int count)
739{
740 Elf_Internal_Shdr *symtab_hdr;
741 unsigned int sec_shndx;
742 bfd_byte *contents;
743 Elf_Internal_Rela *irel, *irelend;
744 Elf_Internal_Rela *irelalign;
745 bfd_vma toaddr;
746 Elf_Internal_Sym *isym;
747 Elf_Internal_Sym *isymend;
748 struct elf_link_hash_entry **sym_hashes;
749 struct elf_link_hash_entry **end_hashes;
750 struct elf_link_hash_entry **start_hashes;
751 unsigned int symcount;
752
753 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
754
755 contents = elf_section_data (sec)->this_hdr.contents;
756
757 /* The deletion must stop at the next ALIGN reloc for an aligment
758 power larger than the number of bytes we are deleting. */
759 irelalign = NULL;
760 toaddr = sec->size;
761
762 irel = elf_section_data (sec)->relocs;
763 irelend = irel + sec->reloc_count;
764
765 /* Actually delete the bytes. */
766 memmove (contents + addr, contents + addr + count,
767 (size_t) (toaddr - addr - count));
768 sec->size -= count;
769
770 /* Adjust all the relocs. */
771 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
772 /* Get the new reloc address. */
773 if ((irel->r_offset > addr && irel->r_offset < toaddr))
7fac7ff4 774 irel->r_offset -= count;
3d3d428f
NC
775
776 /* Adjust the local symbols defined in this section. */
777 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
778 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
779 for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
780 {
781 if (isym->st_shndx == sec_shndx
782 && isym->st_value > addr
783 && isym->st_value < toaddr)
784 {
785 /* Adjust the addend of SWITCH relocations in this section,
786 which reference this local symbol. */
787 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
788 {
789 unsigned long r_symndx;
790 Elf_Internal_Sym *rsym;
791 bfd_vma addsym, subsym;
792
7fac7ff4
NC
793 /* Skip if not a SWITCH relocation. */
794 if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH8
795 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
796 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
797 continue;
798
3d3d428f
NC
799 r_symndx = ELF32_R_SYM (irel->r_info);
800 rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
801
802 /* Skip if not the local adjusted symbol. */
803 if (rsym != isym)
804 continue;
805
806 addsym = isym->st_value;
807 subsym = addsym - irel->r_addend;
808
809 /* Fix the addend only when -->> (addsym > addr >= subsym). */
810 if (subsym <= addr)
811 irel->r_addend -= count;
812 else
813 continue;
814 }
815
816 isym->st_value -= count;
817 }
818 }
819
820 /* Now adjust the global symbols defined in this section. */
821 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
822 - symtab_hdr->sh_info);
823 sym_hashes = start_hashes = elf_sym_hashes (abfd);
824 end_hashes = sym_hashes + symcount;
825
826 for (; sym_hashes < end_hashes; sym_hashes++)
827 {
828 struct elf_link_hash_entry *sym_hash = *sym_hashes;
829
830 /* The '--wrap SYMBOL' option is causing a pain when the object file,
831 containing the definition of __wrap_SYMBOL, includes a direct
832 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
833 the same symbol (which is __wrap_SYMBOL), but still exist as two
834 different symbols in 'sym_hashes', we don't want to adjust
835 the global symbol __wrap_SYMBOL twice.
836 This check is only relevant when symbols are being wrapped. */
837 if (link_info->wrap_hash != NULL)
838 {
839 struct elf_link_hash_entry **cur_sym_hashes;
840
841 /* Loop only over the symbols whom been already checked. */
842 for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
843 cur_sym_hashes++)
7fac7ff4
NC
844 /* If the current symbol is identical to 'sym_hash', that means
845 the symbol was already adjusted (or at least checked). */
846 if (*cur_sym_hashes == sym_hash)
847 break;
3d3d428f
NC
848
849 /* Don't adjust the symbol again. */
850 if (cur_sym_hashes < sym_hashes)
851 continue;
852 }
853
854 if ((sym_hash->root.type == bfd_link_hash_defined
855 || sym_hash->root.type == bfd_link_hash_defweak)
856 && sym_hash->root.u.def.section == sec
857 && sym_hash->root.u.def.value > addr
858 && sym_hash->root.u.def.value < toaddr)
859 sym_hash->root.u.def.value -= count;
860 }
861
862 return TRUE;
863}
864
865/* Relocate a CR16 ELF section. */
866
867static bfd_boolean
868elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
7fac7ff4
NC
869 bfd *input_bfd, asection *input_section,
870 bfd_byte *contents, Elf_Internal_Rela *relocs,
871 Elf_Internal_Sym *local_syms,
872 asection **local_sections)
3d3d428f
NC
873{
874 Elf_Internal_Shdr *symtab_hdr;
875 struct elf_link_hash_entry **sym_hashes;
876 Elf_Internal_Rela *rel, *relend;
877
878 if (info->relocatable)
879 return TRUE;
880
881 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
882 sym_hashes = elf_sym_hashes (input_bfd);
883
884 rel = relocs;
885 relend = relocs + input_section->reloc_count;
886 for (; rel < relend; rel++)
887 {
888 int r_type;
889 reloc_howto_type *howto;
890 unsigned long r_symndx;
891 Elf_Internal_Sym *sym;
892 asection *sec;
893 struct elf_link_hash_entry *h;
894 bfd_vma relocation;
895 bfd_reloc_status_type r;
896
897 r_symndx = ELF32_R_SYM (rel->r_info);
898 r_type = ELF32_R_TYPE (rel->r_info);
899 howto = cr16_elf_howto_table + (r_type);
900
901 h = NULL;
902 sym = NULL;
903 sec = NULL;
904 if (r_symndx < symtab_hdr->sh_info)
905 {
906 sym = local_syms + r_symndx;
907 sec = local_sections[r_symndx];
908 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
909 }
910 else
911 {
912 bfd_boolean unresolved_reloc, warned;
913
914 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
915 r_symndx, symtab_hdr, sym_hashes,
916 h, sec, relocation,
917 unresolved_reloc, warned);
918 }
919
920 r = cr16_elf_final_link_relocate (howto, input_bfd, output_bfd,
921 input_section,
922 contents, rel->r_offset,
923 relocation, rel->r_addend,
924 info, sec, h == NULL);
925
926 if (r != bfd_reloc_ok)
927 {
928 const char *name;
929 const char *msg = NULL;
930
931 if (h != NULL)
932 name = h->root.root.string;
933 else
934 {
935 name = (bfd_elf_string_from_elf_section
936 (input_bfd, symtab_hdr->sh_link, sym->st_name));
937 if (name == NULL || *name == '\0')
938 name = bfd_section_name (input_bfd, sec);
939 }
940
941 switch (r)
942 {
943 case bfd_reloc_overflow:
944 if (!((*info->callbacks->reloc_overflow)
945 (info, (h ? &h->root : NULL), name, howto->name,
946 (bfd_vma) 0, input_bfd, input_section,
947 rel->r_offset)))
dc80fd5c 948 return FALSE;
3d3d428f
NC
949 break;
950
951 case bfd_reloc_undefined:
952 if (!((*info->callbacks->undefined_symbol)
953 (info, name, input_bfd, input_section,
954 rel->r_offset, TRUE)))
955 return FALSE;
956 break;
957
958 case bfd_reloc_outofrange:
959 msg = _("internal error: out of range error");
960 goto common_error;
961
962 case bfd_reloc_notsupported:
963 msg = _("internal error: unsupported relocation error");
964 goto common_error;
965
966 case bfd_reloc_dangerous:
967 msg = _("internal error: dangerous error");
968 goto common_error;
969
970 default:
971 msg = _("internal error: unknown error");
972 /* Fall through. */
973
974 common_error:
975 if (!((*info->callbacks->warning)
976 (info, msg, name, input_bfd, input_section,
977 rel->r_offset)))
978 return FALSE;
979 break;
980 }
981 }
982 }
983
984 return TRUE;
985}
986
987/* This is a version of bfd_generic_get_relocated_section_contents
988 which uses elf32_cr16_relocate_section. */
989
990static bfd_byte *
991elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
992 struct bfd_link_info *link_info,
993 struct bfd_link_order *link_order,
994 bfd_byte *data,
995 bfd_boolean relocatable,
996 asymbol **symbols)
997{
998 Elf_Internal_Shdr *symtab_hdr;
999 asection *input_section = link_order->u.indirect.section;
1000 bfd *input_bfd = input_section->owner;
1001 asection **sections = NULL;
1002 Elf_Internal_Rela *internal_relocs = NULL;
1003 Elf_Internal_Sym *isymbuf = NULL;
1004
1005 /* We only need to handle the case of relaxing, or of having a
1006 particular set of section contents, specially. */
1007 if (relocatable
1008 || elf_section_data (input_section)->this_hdr.contents == NULL)
1009 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
1010 link_order, data,
1011 relocatable,
1012 symbols);
1013
1014 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1015
1016 memcpy (data, elf_section_data (input_section)->this_hdr.contents,
1017 (size_t) input_section->size);
1018
1019 if ((input_section->flags & SEC_RELOC) != 0
1020 && input_section->reloc_count > 0)
1021 {
1022 Elf_Internal_Sym *isym;
1023 Elf_Internal_Sym *isymend;
1024 asection **secpp;
1025 bfd_size_type amt;
1026
1027 internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
7fac7ff4 1028 NULL, NULL, FALSE);
3d3d428f
NC
1029 if (internal_relocs == NULL)
1030 goto error_return;
1031
1032 if (symtab_hdr->sh_info != 0)
1033 {
1034 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1035 if (isymbuf == NULL)
1036 isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
1037 symtab_hdr->sh_info, 0,
1038 NULL, NULL, NULL);
1039 if (isymbuf == NULL)
1040 goto error_return;
1041 }
1042
1043 amt = symtab_hdr->sh_info;
1044 amt *= sizeof (asection *);
1045 sections = bfd_malloc (amt);
1046 if (sections == NULL && amt != 0)
1047 goto error_return;
1048
1049 isymend = isymbuf + symtab_hdr->sh_info;
1050 for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp)
1051 {
1052 asection *isec;
1053
1054 if (isym->st_shndx == SHN_UNDEF)
1055 isec = bfd_und_section_ptr;
1056 else if (isym->st_shndx == SHN_ABS)
1057 isec = bfd_abs_section_ptr;
1058 else if (isym->st_shndx == SHN_COMMON)
1059 isec = bfd_com_section_ptr;
1060 else
1061 isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
1062
1063 *secpp = isec;
1064 }
1065
1066 if (! elf32_cr16_relocate_section (output_bfd, link_info, input_bfd,
1067 input_section, data, internal_relocs,
1068 isymbuf, sections))
1069 goto error_return;
1070
1071 if (sections != NULL)
1072 free (sections);
1073 if (isymbuf != NULL
1074 && symtab_hdr->contents != (unsigned char *) isymbuf)
1075 free (isymbuf);
1076 if (elf_section_data (input_section)->relocs != internal_relocs)
1077 free (internal_relocs);
1078 }
1079
1080 return data;
1081
1082 error_return:
1083 if (sections != NULL)
1084 free (sections);
1085 if (isymbuf != NULL
1086 && symtab_hdr->contents != (unsigned char *) isymbuf)
1087 free (isymbuf);
1088 if (internal_relocs != NULL
1089 && elf_section_data (input_section)->relocs != internal_relocs)
1090 free (internal_relocs);
1091 return NULL;
1092}
1093
1094/* This function handles relaxing for the CR16.
1095
1096 There's quite a few relaxing opportunites available on the CR16:
1097
1098 * bcond:24 -> bcond:16 2 bytes
7fac7ff4
NC
1099 * bcond:16 -> bcond:8 2 bytes
1100 * arithmetic imm32 -> arithmetic imm20/imm16 2 bytes
1101 * arithmetic imm20/imm16 -> arithmetic imm4 2 bytes
3d3d428f
NC
1102
1103 Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
1104
1105static bfd_boolean
1106elf32_cr16_relax_section (bfd *abfd, asection *sec,
1107 struct bfd_link_info *link_info, bfd_boolean *again)
1108{
1109 Elf_Internal_Shdr *symtab_hdr;
1110 Elf_Internal_Rela *internal_relocs;
1111 Elf_Internal_Rela *irel, *irelend;
1112 bfd_byte *contents = NULL;
1113 Elf_Internal_Sym *isymbuf = NULL;
1114
1115 /* Assume nothing changes. */
1116 *again = FALSE;
1117
1118 /* We don't have to do anything for a relocatable link, if
1119 this section does not have relocs, or if this is not a
1120 code section. */
1121 if (link_info->relocatable
1122 || (sec->flags & SEC_RELOC) == 0
1123 || sec->reloc_count == 0
1124 || (sec->flags & SEC_CODE) == 0)
1125 return TRUE;
1126
1127 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1128
1129 /* Get a copy of the native relocations. */
1130 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
7fac7ff4 1131 link_info->keep_memory);
3d3d428f
NC
1132 if (internal_relocs == NULL)
1133 goto error_return;
1134
1135 /* Walk through them looking for relaxing opportunities. */
1136 irelend = internal_relocs + sec->reloc_count;
1137 for (irel = internal_relocs; irel < irelend; irel++)
1138 {
1139 bfd_vma symval;
1140
1141 /* If this isn't something that can be relaxed, then ignore
1142 this reloc. */
1143 if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
7fac7ff4
NC
1144 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24
1145 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM32
1146 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM20
1147 && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM16)
3d3d428f
NC
1148 continue;
1149
1150 /* Get the section contents if we haven't done so already. */
1151 if (contents == NULL)
1152 {
1153 /* Get cached copy if it exists. */
1154 if (elf_section_data (sec)->this_hdr.contents != NULL)
1155 contents = elf_section_data (sec)->this_hdr.contents;
1156 /* Go get them off disk. */
1157 else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
1158 goto error_return;
1159 }
1160
1161 /* Read this BFD's local symbols if we haven't done so already. */
1162 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1163 {
1164 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1165 if (isymbuf == NULL)
1166 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1167 symtab_hdr->sh_info, 0,
1168 NULL, NULL, NULL);
1169 if (isymbuf == NULL)
1170 goto error_return;
1171 }
1172
1173 /* Get the value of the symbol referred to by the reloc. */
1174 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1175 {
1176 /* A local symbol. */
1177 Elf_Internal_Sym *isym;
1178 asection *sym_sec;
1179
1180 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1181 if (isym->st_shndx == SHN_UNDEF)
1182 sym_sec = bfd_und_section_ptr;
1183 else if (isym->st_shndx == SHN_ABS)
1184 sym_sec = bfd_abs_section_ptr;
1185 else if (isym->st_shndx == SHN_COMMON)
1186 sym_sec = bfd_com_section_ptr;
1187 else
1188 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1189 symval = (isym->st_value
1190 + sym_sec->output_section->vma
1191 + sym_sec->output_offset);
1192 }
1193 else
1194 {
1195 unsigned long indx;
1196 struct elf_link_hash_entry *h;
1197
1198 /* An external symbol. */
1199 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1200 h = elf_sym_hashes (abfd)[indx];
1201 BFD_ASSERT (h != NULL);
1202
1203 if (h->root.type != bfd_link_hash_defined
1204 && h->root.type != bfd_link_hash_defweak)
1205 /* This appears to be a reference to an undefined
1206 symbol. Just ignore it--it will be caught by the
1207 regular reloc processing. */
1208 continue;
1209
1210 symval = (h->root.u.def.value
1211 + h->root.u.def.section->output_section->vma
1212 + h->root.u.def.section->output_offset);
1213 }
1214
1215 /* For simplicity of coding, we are going to modify the section
1216 contents, the section relocs, and the BFD symbol table. We
1217 must tell the rest of the code not to free up this
1218 information. It would be possible to instead create a table
1219 of changes which have to be made, as is done in coff-mips.c;
1220 that would be more work, but would require less memory when
1221 the linker is run. */
1222
1223 /* Try to turn a 24 branch/call into a 16bit relative
7fac7ff4 1224 branch/call. */
3d3d428f
NC
1225 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
1226 {
1227 bfd_vma value = symval;
1228
1229 /* Deal with pc-relative gunk. */
1230 value -= (sec->output_section->vma + sec->output_offset);
1231 value -= irel->r_offset;
1232 value += irel->r_addend;
1233
1234 /* See if the value will fit in 16 bits, note the high value is
1235 0xfffe + 2 as the target will be two bytes closer if we are
1236 able to relax. */
1237 if ((long) value < 0x10000 && (long) value > -0x10002)
1238 {
1239 unsigned int code;
1240
1241 /* Get the opcode. */
1242 code = (unsigned int) bfd_get_32 (abfd, contents + irel->r_offset);
1243
1244 /* Verify it's a 'bcond' and fix the opcode. */
1245 if ((code & 0xffff) == 0x0010)
1246 {
7fac7ff4
NC
1247 bfd_put_16 (abfd, 0x1800 | ((0xf & (code >> 20)) << 4), contents + irel->r_offset);
1248 bfd_put_16 (abfd, value, contents + irel->r_offset + 2);
3d3d428f
NC
1249 }
1250 else
1251 continue;
1252
1253 /* Note that we've changed the relocs, section contents, etc. */
1254 elf_section_data (sec)->relocs = internal_relocs;
1255 elf_section_data (sec)->this_hdr.contents = contents;
1256 symtab_hdr->contents = (unsigned char *) isymbuf;
1257
1258 /* Fix the relocation's type. */
1259 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1260 R_CR16_DISP16);
1261
1262 /* Delete two bytes of data. */
1263 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1264 irel->r_offset + 2, 2))
1265 goto error_return;
1266
1267 /* That will change things, so, we should relax again.
1268 Note that this is not required, and it may be slow. */
1269 *again = TRUE;
1270 }
1271 }
1272
7fac7ff4
NC
1273 /* Try to turn a 16-bit pc-relative branch into an
1274 8-bit pc-relative branch. */
3d3d428f
NC
1275 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
1276 {
1277 bfd_vma value = symval;
1278
1279 /* Deal with pc-relative gunk. */
1280 value -= (sec->output_section->vma + sec->output_offset);
1281 value -= irel->r_offset;
1282 value += irel->r_addend;
1283
1284 /* See if the value will fit in 8 bits, note the high value is
1285 0xfc + 2 as the target will be two bytes closer if we are
1286 able to relax. */
1287 if ((long) value < 0xfe && (long) value > -0x100)
1288 {
1289 unsigned short code;
1290
1291 /* Get the opcode. */
1292 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1293
1294 /* Verify it's a 'bcond' opcode. */
1295 if ((code & 0xff00) == 0x1800)
1296 {
7fac7ff4
NC
1297 bfd_put_8 (abfd, 0x1 | ((0xf & (code >> 4)) << 4), contents + irel->r_offset);
1298 bfd_put_8 (abfd, value, contents + irel->r_offset + 2);
3d3d428f
NC
1299 }
1300 else
1301 continue;
1302
1303 /* Note that we've changed the relocs, section contents, etc. */
1304 elf_section_data (sec)->relocs = internal_relocs;
1305 elf_section_data (sec)->this_hdr.contents = contents;
1306 symtab_hdr->contents = (unsigned char *) isymbuf;
1307
1308 /* Fix the relocation's type. */
1309 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1310 R_CR16_DISP8);
1311
1312 /* Delete two bytes of data. */
1313 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1314 irel->r_offset + 2, 2))
1315 goto error_return;
1316
1317 /* That will change things, so, we should relax again.
1318 Note that this is not required, and it may be slow. */
1319 *again = TRUE;
1320 }
1321 }
1322
3d3d428f 1323 /* Try to turn a 32bit immediate address into
7fac7ff4 1324 a 20/16bit immediate address. */
3d3d428f
NC
1325 if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
1326 {
1327 bfd_vma value = symval;
7fac7ff4 1328 unsigned short is_add_mov = 0;
3d3d428f
NC
1329
1330 /* See if the value will fit in 20 bits. */
7fac7ff4 1331 if ((long) value < 0xfffff && (long) value > 0)
3d3d428f
NC
1332 {
1333 unsigned short code;
1334
1335 /* Get the opcode. */
1336 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
1337
7fac7ff4
NC
1338 /* Verify it's a arithmetic ADDD or MOVD instruction.
1339 For ADDD and MOVD only, convert to IMM32 -> IMM20. */
e9deb29d 1340 if (((code & 0xfff0) == 0x0070) || ((code & 0xfff0) == 0x0020))
7fac7ff4
NC
1341 is_add_mov = 1;
1342
1343 if (is_add_mov)
1344 {
1345 /* Note that we've changed the relocs, section contents,
1346 etc. */
1347 elf_section_data (sec)->relocs = internal_relocs;
1348 elf_section_data (sec)->this_hdr.contents = contents;
1349 symtab_hdr->contents = (unsigned char *) isymbuf;
1350
1351 /* Fix the opcode. */
1352 if ((code & 0xfff0) == 0x0070) /* For movd. */
1353 bfd_put_8 (abfd, 0x05, contents + irel->r_offset + 1);
1354 else /* code == 0x0020 for addd. */
1355 bfd_put_8 (abfd, 0x04, contents + irel->r_offset + 1);
1356
1357 bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
1358
1359
1360 /* Fix the relocation's type. */
1361 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1362 R_CR16_IMM20);
1363 /* Delete two bytes of data. */
1364 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
1365 irel->r_offset + 2, 2))
1366 goto error_return;
1367
1368 /* That will change things, so, we should relax again.
1369 Note that this is not required, and it may be slow. */
1370 *again = TRUE;
1371 }
1372 }
1373 /* See if the value will fit in 16 bits. */
1374 if ((!is_add_mov) && ((long) value < 0x7fff && (long) value > 0))
1375 {
1376 unsigned short code;
1377
1378 /* Get the opcode. */
1379 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
3d3d428f
NC
1380
1381 /* Note that we've changed the relocs, section contents, etc. */
1382 elf_section_data (sec)->relocs = internal_relocs;
1383 elf_section_data (sec)->this_hdr.contents = contents;
1384 symtab_hdr->contents = (unsigned char *) isymbuf;
1385
1386 /* Fix the opcode. */
7fac7ff4
NC
1387 if ((code & 0xf0) == 0x70) /* For movd. */
1388 bfd_put_8 (abfd, 0x54, contents + irel->r_offset + 1);
1389 else if ((code & 0xf0) == 0x20) /* For addd. */
1390 bfd_put_8 (abfd, 0x60, contents + irel->r_offset + 1);
1391 else if ((code & 0xf0) == 0x90) /* For cmpd. */
1392 bfd_put_8 (abfd, 0x56, contents + irel->r_offset + 1);
1393 else
1394 continue;
1395
1396 bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
3d3d428f
NC
1397
1398 /* Fix the relocation's type. */
1399 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
7fac7ff4 1400 R_CR16_IMM16);
3d3d428f
NC
1401
1402 /* Delete two bytes of data. */
1403 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
7fac7ff4
NC
1404 irel->r_offset + 2, 2))
1405 goto error_return;
3d3d428f
NC
1406
1407 /* That will change things, so, we should relax again.
1408 Note that this is not required, and it may be slow. */
7fac7ff4 1409 *again = TRUE;
3d3d428f
NC
1410 }
1411 }
7fac7ff4
NC
1412
1413 /* Try to turn a 20/16bit immediate address into
3d3d428f
NC
1414 a 4bit immediate address. */
1415 if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
7fac7ff4 1416 || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
3d3d428f
NC
1417 {
1418 bfd_vma value = symval;
1419
1420 /* See if the value will fit in 4 bits. */
7fac7ff4 1421 if ((long) value < 0xf && (long) value > 0)
3d3d428f
NC
1422 {
1423 unsigned short code;
1424
1425 /* Get the opcode. */
7fac7ff4 1426 code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
3d3d428f
NC
1427
1428 /* Note that we've changed the relocs, section contents, etc. */
1429 elf_section_data (sec)->relocs = internal_relocs;
1430 elf_section_data (sec)->this_hdr.contents = contents;
1431 symtab_hdr->contents = (unsigned char *) isymbuf;
1432
1433 /* Fix the opcode. */
7fac7ff4
NC
1434 if (((code & 0x0f00) == 0x0400) || ((code & 0x0f00) == 0x0500))
1435 {
1436 if ((code & 0x0f00) == 0x0400) /* For movd imm20. */
1437 bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
1438 else /* For addd imm20. */
1439 bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
1440 bfd_put_8 (abfd, (code & 0xf0) >> 4, contents + irel->r_offset + 1);
1441 }
1442 else
1443 {
1444 if ((code & 0xfff0) == 0x56b0) /* For cmpd imm16. */
1445 bfd_put_8 (abfd, 0x56, contents + irel->r_offset);
1446 else if ((code & 0xfff0) == 0x54b0) /* For movd imm16. */
1447 bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
1448 else if ((code & 0xfff0) == 0x58b0) /* For movb imm16. */
1449 bfd_put_8 (abfd, 0x58, contents + irel->r_offset);
1450 else if ((code & 0xfff0) == 0x5Ab0) /* For movw imm16. */
1451 bfd_put_8 (abfd, 0x5A, contents + irel->r_offset);
1452 else if ((code & 0xfff0) == 0x60b0) /* For addd imm16. */
1453 bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
1454 else if ((code & 0xfff0) == 0x30b0) /* For addb imm16. */
1455 bfd_put_8 (abfd, 0x30, contents + irel->r_offset);
1456 else if ((code & 0xfff0) == 0x2Cb0) /* For addub imm16. */
1457 bfd_put_8 (abfd, 0x2C, contents + irel->r_offset);
1458 else if ((code & 0xfff0) == 0x32b0) /* For adduw imm16. */
1459 bfd_put_8 (abfd, 0x32, contents + irel->r_offset);
1460 else if ((code & 0xfff0) == 0x38b0) /* For subb imm16. */
1461 bfd_put_8 (abfd, 0x38, contents + irel->r_offset);
1462 else if ((code & 0xfff0) == 0x3Ab0) /* For subw imm16. */
1463 bfd_put_8 (abfd, 0x3A, contents + irel->r_offset);
1464 else if ((code & 0xfff0) == 0x50b0) /* For cmpb imm16. */
1465 bfd_put_8 (abfd, 0x50, contents + irel->r_offset);
1466 else if ((code & 0xfff0) == 0x52b0) /* For cmpw imm16. */
1467 bfd_put_8 (abfd, 0x52, contents + irel->r_offset);
1468 else
1469 continue;
1470
1471 bfd_put_8 (abfd, (code & 0xf), contents + irel->r_offset + 1);
1472 }
3d3d428f
NC
1473
1474 /* Fix the relocation's type. */
1475 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1476 R_CR16_IMM4);
1477
1478 /* Delete two bytes of data. */
1479 if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
7fac7ff4 1480 irel->r_offset + 2, 2))
3d3d428f
NC
1481 goto error_return;
1482
1483 /* That will change things, so, we should relax again.
1484 Note that this is not required, and it may be slow. */
1485 *again = TRUE;
1486 }
1487 }
3d3d428f
NC
1488 }
1489
1490 if (isymbuf != NULL
1491 && symtab_hdr->contents != (unsigned char *) isymbuf)
1492 {
1493 if (! link_info->keep_memory)
1494 free (isymbuf);
1495 else
7fac7ff4
NC
1496 /* Cache the symbols for elf_link_input_bfd. */
1497 symtab_hdr->contents = (unsigned char *) isymbuf;
3d3d428f
NC
1498 }
1499
1500 if (contents != NULL
1501 && elf_section_data (sec)->this_hdr.contents != contents)
1502 {
1503 if (! link_info->keep_memory)
1504 free (contents);
1505 else
7fac7ff4
NC
1506 /* Cache the section contents for elf_link_input_bfd. */
1507 elf_section_data (sec)->this_hdr.contents = contents;
3d3d428f
NC
1508 }
1509
1510 if (internal_relocs != NULL
1511 && elf_section_data (sec)->relocs != internal_relocs)
1512 free (internal_relocs);
1513
1514 return TRUE;
1515
1516 error_return:
1517 if (isymbuf != NULL
1518 && symtab_hdr->contents != (unsigned char *) isymbuf)
1519 free (isymbuf);
1520 if (contents != NULL
1521 && elf_section_data (sec)->this_hdr.contents != contents)
1522 free (contents);
1523 if (internal_relocs != NULL
1524 && elf_section_data (sec)->relocs != internal_relocs)
1525 free (internal_relocs);
1526
1527 return FALSE;
1528}
1529
1530static asection *
1531elf32_cr16_gc_mark_hook (asection *sec,
7fac7ff4
NC
1532 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1533 Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
1534 struct elf_link_hash_entry *h,
1535 Elf_Internal_Sym *sym)
3d3d428f
NC
1536{
1537 if (h == NULL)
1538 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1539
1540 switch (h->root.type)
1541 {
1542 case bfd_link_hash_defined:
1543 case bfd_link_hash_defweak:
1544 return h->root.u.def.section;
1545
1546 case bfd_link_hash_common:
1547 return h->root.u.c.p->section;
1548
1549 default:
1550 return NULL;
1551 }
1552}
1553
1554/* Update the got entry reference counts for the section being removed. */
1555
1556static bfd_boolean
1557elf32_cr16_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
7fac7ff4
NC
1558 struct bfd_link_info *info ATTRIBUTE_UNUSED,
1559 asection *sec ATTRIBUTE_UNUSED,
1560 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
3d3d428f
NC
1561{
1562 /* We don't support garbage collection of GOT and PLT relocs yet. */
1563 return TRUE;
1564}
1565
1566/* Definitions for setting CR16 target vector. */
1567#define TARGET_LITTLE_SYM bfd_elf32_cr16_vec
1568#define TARGET_LITTLE_NAME "elf32-cr16"
1569#define ELF_ARCH bfd_arch_cr16
1570#define ELF_MACHINE_CODE EM_CR16
1e1d9f39 1571#define ELF_MACHINE_ALT1 EM_CR16_OLD
3d3d428f
NC
1572#define ELF_MAXPAGESIZE 0x1
1573#define elf_symbol_leading_char '_'
1574
1575#define bfd_elf32_bfd_reloc_type_lookup elf_cr16_reloc_type_lookup
1576#define bfd_elf32_bfd_reloc_name_lookup elf_cr16_reloc_name_lookup
1577#define elf_info_to_howto elf_cr16_info_to_howto
1578#define elf_info_to_howto_rel 0
1579#define elf_backend_relocate_section elf32_cr16_relocate_section
1580#define bfd_elf32_bfd_relax_section elf32_cr16_relax_section
1581#define bfd_elf32_bfd_get_relocated_section_contents \
1582 elf32_cr16_get_relocated_section_contents
1583#define elf_backend_gc_mark_hook elf32_cr16_gc_mark_hook
1584#define elf_backend_gc_sweep_hook elf32_cr16_gc_sweep_hook
1585#define elf_backend_can_gc_sections 1
1586#define elf_backend_rela_normal 1
1587
1588#include "elf32-target.h"
This page took 0.159041 seconds and 4 git commands to generate.