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