Sun Jan 15 13:57:45 1995 Steve Chamberlain <sac@splat>
[binutils-gdb.git] / bfd / coff-h8300.c
1 /* BFD back-end for Hitachi H8/300 COFF binaries.
2 Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3 Written by Steve Chamberlain, <sac@cygnus.com>.
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
9 the Free Software Foundation; either version 2 of the License, or
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
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "obstack.h"
24 #include "libbfd.h"
25 #include "bfdlink.h"
26 #include "coff/h8300.h"
27 #include "coff/internal.h"
28 #include "libcoff.h"
29
30 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
31
32
33 /* special handling for H8/300 relocs.
34 We only come here for pcrel stuff and return normally if not an -r link.
35 When doing -r, we can't do any arithmetic for the pcrel stuff, because
36 the code in reloc.c assumes that we can manipulate the targets of
37 the pcrel branches. This isn't so, since the H8/300 can do relaxing,
38 which means that the gap after the instruction may not be enough to
39 contain the offset required for the branch, so we have to use the only
40 the addend until the final link */
41
42 static bfd_reloc_status_type
43 special (abfd, reloc_entry, symbol, data, input_section, output_bfd,
44 error_message)
45 bfd *abfd;
46 arelent *reloc_entry;
47 asymbol *symbol;
48 PTR data;
49 asection *input_section;
50 bfd *output_bfd;
51 char **error_message;
52 {
53 symvalue diff;
54
55 if (output_bfd == (bfd *) NULL)
56 return bfd_reloc_continue;
57
58 return bfd_reloc_ok;
59 }
60
61 static reloc_howto_type howto_table[] =
62 {
63 HOWTO (R_RELBYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "8", false, 0x000000ff, 0x000000ff, false),
64 HOWTO (R_RELWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16", false, 0x0000ffff, 0x0000ffff, false),
65 HOWTO (R_RELLONG, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "32", false, 0xffffffff, 0xffffffff, false),
66 HOWTO (R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, special, "DISP8", false, 0x000000ff, 0x000000ff, true),
67 HOWTO (R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, special, "DISP16", false, 0x0000ffff, 0x0000ffff, true),
68 HOWTO (R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, special, "DISP32", false, 0xffffffff, 0xffffffff, true),
69 HOWTO (R_MOVB1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/8", false, 0x0000ffff, 0x0000ffff, false),
70 HOWTO (R_MOVB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/16", false, 0x0000ffff, 0x0000ffff, false),
71 HOWTO (R_JMP1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/pcrel", false, 0x0000ffff, 0x0000ffff, false),
72 HOWTO (R_JMP2, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pcrecl/16", false, 0x000000ff, 0x000000ff, false),
73
74
75 HOWTO (R_JMPL1, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "24/pcrell", false, 0x00ffffff, 0x00ffffff, false),
76 HOWTO (R_JMPL_B8, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pc8/24", false, 0x000000ff, 0x000000ff, false),
77
78 HOWTO (R_MOVLB1, 0, 1, 16, false, 0, complain_overflow_bitfield,special, "24/8", false, 0x0000ffff, 0x0000ffff, false),
79 HOWTO (R_MOVLB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/24", false, 0x0000ffff, 0x0000ffff, false),
80
81 };
82
83
84 /* Turn a howto into a reloc number */
85
86 #define SELECT_RELOC(x,howto) \
87 { x.r_type = select_reloc(howto); }
88
89 #define BADMAG(x) (H8300BADMAG(x)&& H8300HBADMAG(x))
90 #define H8300 1 /* Customize coffcode.h */
91 #define __A_MAGIC_SET__
92
93
94
95 /* Code to swap in the reloc */
96 #define SWAP_IN_RELOC_OFFSET bfd_h_get_32
97 #define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
98 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
99 dst->r_stuff[0] = 'S'; \
100 dst->r_stuff[1] = 'C';
101
102
103 static int
104 select_reloc (howto)
105 reloc_howto_type *howto;
106 {
107 return howto->type;
108 }
109
110 /* Code to turn a r_type into a howto ptr, uses the above howto table
111 */
112
113 static void
114 rtype2howto (internal, dst)
115 arelent *internal;
116 struct internal_reloc *dst;
117 {
118 switch (dst->r_type)
119 {
120 case R_RELBYTE:
121 internal->howto = howto_table + 0;
122 break;
123 case R_RELWORD:
124 internal->howto = howto_table + 1;
125 break;
126 case R_RELLONG:
127 internal->howto = howto_table + 2;
128 break;
129 case R_PCRBYTE:
130 internal->howto = howto_table + 3;
131 break;
132 case R_PCRWORD:
133 internal->howto = howto_table + 4;
134 break;
135 case R_PCRLONG:
136 internal->howto = howto_table + 5;
137 break;
138 case R_MOVB1:
139 internal->howto = howto_table + 6;
140 break;
141 case R_MOVB2:
142 internal->howto = howto_table + 7;
143 break;
144 case R_JMP1:
145 internal->howto = howto_table + 8;
146 break;
147 case R_JMP2:
148 internal->howto = howto_table + 9;
149 break;
150 case R_JMPL1:
151 internal->howto = howto_table + 10;
152 break;
153 case R_JMPL_B8:
154 internal->howto = howto_table + 11;
155 break;
156 case R_MOVLB1:
157 internal->howto = howto_table + 12;
158 break;
159 case R_MOVLB2:
160 internal->howto = howto_table + 13;
161 break;
162 default:
163 fprintf (stderr, "Bad reloc\n");
164 break;
165 }
166 }
167
168 #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
169
170
171 /* Perform any necessaru magic to the addend in a reloc entry */
172
173
174 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
175 cache_ptr->addend = ext_reloc.r_offset;
176
177
178 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
179 reloc_processing(relent, reloc, symbols, abfd, section)
180
181 static void
182 reloc_processing (relent, reloc, symbols, abfd, section)
183 arelent * relent;
184 struct internal_reloc *reloc;
185 asymbol ** symbols;
186 bfd * abfd;
187 asection * section;
188 {
189 relent->address = reloc->r_vaddr;
190 rtype2howto (relent, reloc);
191
192 if (((int) reloc->r_symndx) > 0)
193 {
194 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
195 }
196 else
197 {
198 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
199 }
200
201
202
203 relent->addend = reloc->r_offset;
204
205 relent->address -= section->vma;
206 /* relent->section = 0;*/
207 }
208
209
210 static int
211 h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
212 bfd *abfd;
213 asection *input_section;
214 arelent *reloc;
215 unsigned int shrink;
216 struct bfd_link_info *link_info;
217 {
218 bfd_vma value;
219 bfd_vma dot;
220 bfd_vma gap;
221
222 /* The address of the thing to be relocated will have moved back by
223 the size of the shrink - but we don't change reloc->address here,
224 since we need it to know where the relocation lives in the source
225 uncooked section */
226
227 /* reloc->address -= shrink; conceptual */
228
229 bfd_vma address = reloc->address - shrink;
230
231
232 switch (reloc->howto->type)
233 {
234 case R_MOVB2:
235 case R_JMP2:
236 shrink+=2;
237 break;
238
239 /* Thing is a move one byte */
240 case R_MOVB1:
241 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
242
243 if (value >= 0xff00)
244 {
245
246 /* Change the reloc type from 16bit, possible 8 to 8bit
247 possible 16 */
248 reloc->howto = reloc->howto + 1;
249 /* The place to relc moves back by one */
250 /* This will be two bytes smaller in the long run */
251 shrink +=2 ;
252 bfd_perform_slip(abfd, 2, input_section, address);
253 }
254
255 break;
256 /* This is the 24 bit branch which could become an 8 bitter,
257 the relocation points to the first byte of the insn, not the
258 actual data */
259
260 case R_JMPL1:
261 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
262
263 dot = input_section->output_section->vma +
264 input_section->output_offset + address;
265
266 /* See if the address we're looking at within 127 bytes of where
267 we are, if so then we can use a small branch rather than the
268 jump we were going to */
269
270 gap = value - dot ;
271
272 if (-120 < (long)gap && (long)gap < 120 )
273 {
274
275 /* Change the reloc type from 24bit, possible 8 to 8bit
276 possible 32 */
277 reloc->howto = reloc->howto + 1;
278 /* This will be two bytes smaller in the long run */
279 shrink +=2 ;
280 bfd_perform_slip(abfd, 2, input_section, address);
281 }
282 break;
283
284 case R_JMP1:
285
286 value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
287
288 dot = input_section->output_section->vma +
289 input_section->output_offset + address;
290
291 /* See if the address we're looking at within 127 bytes of where
292 we are, if so then we can use a small branch rather than the
293 jump we were going to */
294
295 gap = value - (dot - shrink);
296
297
298 if (-120 < (long)gap && (long)gap < 120 )
299 {
300
301 /* Change the reloc type from 16bit, possible 8 to 8bit
302 possible 16 */
303 reloc->howto = reloc->howto + 1;
304 /* The place to relc moves back by one */
305
306 /* This will be two bytes smaller in the long run */
307 shrink +=2 ;
308 bfd_perform_slip(abfd, 2, input_section, address);
309 }
310 break;
311 }
312
313
314 return shrink;
315 }
316
317
318 /* First phase of a relaxing link */
319
320 /* Reloc types
321 large small
322 R_MOVB1 R_MOVB2 mov.b with 16bit or 8 bit address
323 R_JMP1 R_JMP2 jmp or pcrel branch
324 R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
325 R_MOVLB1 R_MOVLB2 24 or 8 bit reloc for mov.b
326
327 */
328
329 static void
330 h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
331 dst_ptr)
332 bfd *abfd;
333 struct bfd_link_info *link_info;
334 struct bfd_link_order *link_order;
335 arelent *reloc;
336 bfd_byte *data;
337 unsigned int *src_ptr;
338 unsigned int *dst_ptr;
339 {
340 unsigned int src_address = *src_ptr;
341 unsigned int dst_address = *dst_ptr;
342 asection *input_section = link_order->u.indirect.section;
343
344 switch (reloc->howto->type)
345 {
346 /* A 24 bit branch which could be a 8 bit pcrel, really pointing to
347 the byte before the 24bit hole, so we can treat it as a 32bit pointer */
348 case R_PCRBYTE:
349 {
350 bfd_vma dot = link_order->offset
351 + dst_address
352 + link_order->u.indirect.section->output_section->vma;
353 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
354 - dot);
355 if (gap > 127 || gap < -128)
356 {
357 if (! ((*link_info->callbacks->reloc_overflow)
358 (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
359 reloc->howto->name, reloc->addend, input_section->owner,
360 input_section, reloc->address)))
361 abort ();
362 }
363 gap &= ~1;
364 bfd_put_8 (abfd, gap, data + dst_address);
365 dst_address++;
366 src_address++;
367
368 break;
369 }
370 case R_PCRWORD:
371 {
372 bfd_vma dot = link_order->offset
373 + dst_address
374 + link_order->u.indirect.section->output_section->vma;
375 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
376 - dot) - 1;
377 if (gap > 32767 || gap < -32768)
378 {
379 if (! ((*link_info->callbacks->reloc_overflow)
380 (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
381 reloc->howto->name, reloc->addend, input_section->owner,
382 input_section, reloc->address)))
383 abort ();
384 }
385
386 bfd_put_16 (abfd, gap, data + dst_address);
387 dst_address+=2;
388 src_address+=2;
389
390 break;
391 }
392
393 case R_RELBYTE:
394 {
395 unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
396 input_section);
397 if (gap < 0xff
398 || (gap >= 0x0000ff00
399 && gap <= 0x0000ffff)
400 || ( gap >= 0x00ffff00
401 && gap <= 0x00ffffff)
402 || ( gap >= 0xffffff00
403 && gap <= 0xffffffff))
404 {
405 bfd_put_8 (abfd, gap, data + dst_address);
406 dst_address += 1;
407 src_address += 1;
408 }
409 else
410 {
411 if (! ((*link_info->callbacks->reloc_overflow)
412 (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
413 reloc->howto->name, reloc->addend, input_section->owner,
414 input_section, reloc->address)))
415 abort ();
416 }
417 }
418 break;
419 case R_JMP1:
420 /* A relword which would have like to have been a pcrel */
421 case R_MOVB1:
422 /* A relword which would like to have been modified but
423 didn't make it */
424 case R_RELWORD:
425 bfd_put_16 (abfd,
426 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
427 data + dst_address);
428 dst_address += 2;
429 src_address += 2;
430 break;
431 case R_RELLONG:
432 bfd_put_32 (abfd,
433 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
434 data + dst_address);
435 dst_address += 4;
436 src_address += 4;
437 break;
438
439 case R_MOVB2:
440 /* Special relaxed type, there will be a gap between where we
441 get stuff from and where we put stuff to now
442
443 for a mov.b @aa:16 -> mov.b @aa:8
444 opcode 0x6a 0x0y offset
445 -> 0x2y off
446 */
447 if (data[dst_address - 1] != 0x6a)
448 abort ();
449 switch (data[src_address] & 0xf0)
450 {
451 case 0x00:
452 /* Src is memory */
453 data[dst_address - 1] = (data[src_address] & 0xf) | 0x20;
454 break;
455 case 0x80:
456 /* Src is reg */
457 data[dst_address - 1] = (data[src_address] & 0xf) | 0x30;
458 break;
459 default:
460 abort ();
461 }
462
463 /* the offset must fit ! after all, what was all the relaxing
464 about ? */
465
466 bfd_put_8 (abfd,
467 bfd_coff_reloc16_get_value (reloc, link_info, input_section),
468 data + dst_address);
469
470 /* Note the magic - src goes up by two bytes, but dst by only
471 one */
472 dst_address += 1;
473 src_address += 3;
474
475 break;
476
477 case R_JMP2:
478
479 /* Speciial relaxed type */
480 {
481 bfd_vma dot = link_order->offset
482 + dst_address
483 + link_order->u.indirect.section->output_section->vma;
484
485 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
486 - dot - 1);
487
488 if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
489 abort ();
490
491 bfd_put_8 (abfd, gap, data + dst_address);
492
493 switch (data[dst_address - 1])
494 {
495 case 0x5e:
496 /* jsr -> bsr */
497 bfd_put_8 (abfd, 0x55, data + dst_address - 1);
498 break;
499 case 0x5a:
500 /* jmp ->bra */
501 bfd_put_8 (abfd, 0x40, data + dst_address - 1);
502 break;
503
504 default:
505 abort ();
506 }
507 dst_address++;
508 src_address += 3;
509
510 break;
511 }
512 break;
513
514 case R_JMPL_B8: /* 24 bit branch which is now 8 bits */
515
516 /* Speciial relaxed type */
517 {
518 bfd_vma dot = link_order->offset
519 + dst_address
520 + link_order->u.indirect.section->output_section->vma;
521
522 int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
523 - dot - 2);
524
525 if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
526 abort ();
527
528 switch (data[src_address])
529 {
530 case 0x5e:
531 /* jsr -> bsr */
532 bfd_put_8 (abfd, 0x55, data + dst_address);
533 break;
534 case 0x5a:
535 /* jmp ->bra */
536 bfd_put_8 (abfd, 0x40, data + dst_address);
537 break;
538
539 default:
540 bfd_put_8 (abfd, 0xde, data + dst_address);
541 break;
542 }
543
544 bfd_put_8 (abfd, gap, data + dst_address + 1);
545 dst_address += 2;
546 src_address += 4;
547
548 break;
549 }
550
551 case R_JMPL1:
552 {
553 int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
554 int o = bfd_get_32 (abfd, data + src_address);
555 v = (v & 0x00ffffff) | (o & 0xff000000);
556 bfd_put_32 (abfd, v, data + dst_address);
557 dst_address += 4;
558 src_address += 4;
559 }
560
561 break;
562
563
564 /* A 24 bit mov which could be an 8 bit move, really pointing to
565 the byte before the 24bit hole, so we can treat it as a 32bit pointer */
566 case R_MOVLB1:
567 {
568 int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
569 int o = bfd_get_32 (abfd, data + dst_address);
570 v = (v & 0x00ffffff) | (o & 0xff000000);
571 bfd_put_32 (abfd, v, data + dst_address);
572 dst_address += 4;
573 src_address += 4;
574 }
575
576 break;
577 default:
578
579 abort ();
580 break;
581
582 }
583 *src_ptr = src_address;
584 *dst_ptr = dst_address;
585
586 }
587
588 #define coff_reloc16_extra_cases h8300_reloc16_extra_cases
589 #define coff_reloc16_estimate h8300_reloc16_estimate
590
591 #include "coffcode.h"
592
593
594 #undef coff_bfd_get_relocated_section_contents
595 #undef coff_bfd_relax_section
596 #define coff_bfd_get_relocated_section_contents \
597 bfd_coff_reloc16_get_relocated_section_contents
598 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
599
600
601
602 const bfd_target h8300coff_vec =
603 {
604 "coff-h8300", /* name */
605 bfd_target_coff_flavour,
606 true, /* data byte order is big */
607 true, /* header byte order is big */
608
609 (HAS_RELOC | EXEC_P | /* object flags */
610 HAS_LINENO | HAS_DEBUG |
611 HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
612 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
613 '_', /* leading char */
614 '/', /* ar_pad_char */
615 15, /* ar_max_namelen */
616 1, /* minimum section alignment */
617 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
618 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
619 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
620 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
621 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
622 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
623
624 {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
625 bfd_generic_archive_p, _bfd_dummy_target},
626 {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
627 bfd_false},
628 {bfd_false, coff_write_object_contents, /* bfd_write_contents */
629 _bfd_write_archive_contents, bfd_false},
630
631 BFD_JUMP_TABLE_GENERIC (coff),
632 BFD_JUMP_TABLE_COPY (coff),
633 BFD_JUMP_TABLE_CORE (_bfd_nocore),
634 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
635 BFD_JUMP_TABLE_SYMBOLS (coff),
636 BFD_JUMP_TABLE_RELOCS (coff),
637 BFD_JUMP_TABLE_WRITE (coff),
638 BFD_JUMP_TABLE_LINK (coff),
639 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
640
641 COFF_SWAP_TABLE,
642 };