]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/binutils/gas/config/obj-ieee.c
This commit was generated by cvs2svn to compensate for changes in r52746,
[FreeBSD/FreeBSD.git] / contrib / binutils / gas / config / obj-ieee.c
1 /* obj-format for ieee-695 records.
2    Copyright (C) 1991, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
3
4    This file is part of GAS, the GNU Assembler.
5
6    GAS is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GAS is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GAS; see the file COPYING.  If not, write to the Free
18    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA. */
20
21
22 /*
23   created by
24
25   steve chamberlain steve@cygnus.com
26   */
27
28 /*
29   this will hopefully become the port through which bfd and gas talk,
30   for the moment, only ieee is known to work well.
31   */
32
33 #include "bfd.h"
34 #include "as.h"
35 #include "subsegs.h"
36 #include "output-file.h"
37 #include "frags.h"
38
39 bfd *abfd;
40
41 /* How many addresses does the .align take? */
42 static relax_addressT
43 relax_align (address, alignment)
44      register relax_addressT address;   /* Address now. */
45      register long alignment;   /* Alignment (binary). */
46 {
47   relax_addressT mask;
48   relax_addressT new_address;
49
50   mask = ~((~0) << alignment);
51   new_address = (address + mask) & (~mask);
52   return (new_address - address);
53 }                               /* relax_align() */
54
55 /* calculate the size of the frag chain and create a bfd section
56    to contain all of it */
57 static void
58 DEFUN (size_section, (abfd, idx),
59        bfd * abfd AND
60        unsigned int idx)
61 {
62   asection *sec;
63   unsigned int size = 0;
64   fragS *frag = segment_info[idx].frag_root;
65   while (frag)
66     {
67       if (frag->fr_address != size)
68         {
69           printf ("Out of step\n");
70           size = frag->fr_address;
71         }
72       size += frag->fr_fix;
73       switch (frag->fr_type)
74         {
75         case rs_fill:
76         case rs_org:
77           size += frag->fr_offset * frag->fr_var;
78           break;
79         case rs_align:
80         case rs_align_code:
81           {
82             addressT off;
83
84             off = relax_align (size, frag->fr_offset);
85             if (frag->fr_subtype != 0 && off > frag->fr_subtype)
86               off = 0;
87             size += off;
88           }
89         }
90       frag = frag->fr_next;
91     }
92   if (size)
93     {
94       char *name = segment_info[idx].name;
95       if (name == (char *) NULL)
96         {
97           name = ".data";
98         }
99       segment_info[idx].user_stuff = (char *) (sec = bfd_make_section (abfd, name));
100       /* Make it output through itself */
101       sec->output_section = sec;
102       sec->flags |= SEC_HAS_CONTENTS;
103       bfd_set_section_size (abfd, sec, size);
104     }
105 }
106
107 /* run through a frag chain and write out the data to go with it */
108 static void
109 DEFUN (fill_section, (abfd, idx),
110        bfd * abfd AND
111        unsigned int idx)
112 {
113   asection *sec = segment_info[idx].user_stuff;
114   if (sec)
115     {
116       fragS *frag = segment_info[idx].frag_root;
117       unsigned int offset = 0;
118       while (frag)
119         {
120           unsigned int fill_size;
121           unsigned int count;
122           switch (frag->fr_type)
123             {
124             case rs_fill:
125             case rs_align:
126             case rs_org:
127               if (frag->fr_fix)
128                 {
129                   bfd_set_section_contents (abfd,
130                                             sec,
131                                             frag->fr_literal,
132                                             frag->fr_address,
133                                             frag->fr_fix);
134                 }
135               offset += frag->fr_fix;
136               fill_size = frag->fr_var;
137               if (fill_size)
138                 {
139                   unsigned int off = frag->fr_fix;
140                   for (count = frag->fr_offset; count; count--)
141                     {
142                       bfd_set_section_contents (abfd, sec,
143                                                 frag->fr_literal +
144                                                 frag->fr_fix,
145                                                 frag->fr_address + off,
146                                                 fill_size);
147                       off += fill_size;
148                     }
149                 }
150               break;
151             default:
152               abort ();
153             }
154           frag = frag->fr_next;
155         }
156     }
157 }
158
159 /* Count the relocations in a chain */
160
161 static unsigned int
162 DEFUN (count_entries_in_chain, (idx),
163        unsigned int idx)
164 {
165   unsigned int nrelocs;
166   fixS *fixup_ptr;
167
168   /* Count the relocations */
169   fixup_ptr = segment_info[idx].fix_root;
170   nrelocs = 0;
171   while (fixup_ptr != (fixS *) NULL)
172     {
173       fixup_ptr = fixup_ptr->fx_next;
174       nrelocs++;
175     }
176   return nrelocs;
177 }
178
179 /* output all the relocations for a section */
180 void
181 DEFUN (do_relocs_for, (idx),
182        unsigned int idx)
183 {
184   unsigned int nrelocs;
185   arelent **reloc_ptr_vector;
186   arelent *reloc_vector;
187   asymbol **ptrs;
188   asection *section = (asection *) (segment_info[idx].user_stuff);
189   unsigned int i;
190   fixS *from;
191   if (section)
192     {
193       nrelocs = count_entries_in_chain (idx);
194
195       reloc_ptr_vector = (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *));
196       reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent));
197       ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *));
198       from = segment_info[idx].fix_root;
199       for (i = 0; i < nrelocs; i++)
200         {
201           arelent *to = reloc_vector + i;
202           asymbol *s;
203           reloc_ptr_vector[i] = to;
204           to->howto = (reloc_howto_type *) (from->fx_r_type);
205
206 #if 0     /* We can't represent complicated things in a reloc yet */
207           if (from->fx_addsy == 0 || from->fx_subsy != 0) abort();
208 #endif
209
210           s = &(from->fx_addsy->sy_symbol.sy);
211           to->address = ((char *) (from->fx_frag->fr_address +
212                                    from->fx_where))
213             - ((char *) (&(from->fx_frag->fr_literal)));
214           to->addend = from->fx_offset;
215           /* If we know the symbol which we want to relocate to, turn
216              this reloaction into a section relative.
217
218              If this relocation is pcrelative, and we know the
219              destination, we still want to keep the relocation - since
220              the linker might relax some of the bytes, but it stops
221              being pc relative and turns into an absolute relocation. */
222           if (s)
223             {
224               if ((s->flags & BSF_UNDEFINED) == 0)
225                 {
226                   to->section = s->section;
227
228                   /* We can refer directly to the value field here,
229                      rather than using S_GET_VALUE, because this is
230                      only called after do_symbols, which sets up the
231                      value field.  */
232                   to->addend += s->value;
233
234                   to->sym_ptr_ptr = 0;
235                   if (to->howto->pcrel_offset)
236                     {
237                       /* This is a pcrel relocation, the addend should be adjusted */
238                       to->addend -= to->address + 1;
239                     }
240                 }
241               else
242                 {
243                   to->section = 0;
244                   *ptrs = &(from->fx_addsy->sy_symbol.sy);
245                   to->sym_ptr_ptr = ptrs;
246
247                   if (to->howto->pcrel_offset)
248                     {
249                       /* This is a pcrel relocation, the addend should be adjusted */
250                       to->addend -= to->address - 1;
251                     }
252                 }
253
254             }
255           else
256             {
257               to->section = 0;
258             }
259
260           ptrs++;
261           from = from->fx_next;
262         }
263
264       /* attatch to the section */
265       section->orelocation = reloc_ptr_vector;
266       section->reloc_count = nrelocs;
267       section->flags |= SEC_LOAD;
268     }
269 }
270
271 /* do the symbols.. */
272 static void
273 DEFUN (do_symbols, (abfd),
274        bfd * abfd)
275 {
276   extern symbolS *symbol_rootP;
277   symbolS *ptr;
278   asymbol **symbol_ptr_vec;
279   asymbol *symbol_vec;
280   unsigned int count = 0;
281   unsigned int index;
282
283
284   for (ptr = symbol_rootP;
285        ptr != (symbolS *) NULL;
286        ptr = ptr->sy_next)
287     {
288       if (SEG_NORMAL (ptr->sy_symbol.seg))
289         {
290           ptr->sy_symbol.sy.section =
291             (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff);
292           S_SET_VALUE (ptr, S_GET_VALUE (ptr) + ptr->sy_frag->fr_address);
293           if (ptr->sy_symbol.sy.flags == 0)
294             {
295               ptr->sy_symbol.sy.flags = BSF_LOCAL;
296             }
297         }
298       else
299         {
300           switch (ptr->sy_symbol.seg)
301             {
302             case SEG_ABSOLUTE:
303               ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE;
304               ptr->sy_symbol.sy.section = 0;
305               break;
306             case SEG_UNKNOWN:
307               ptr->sy_symbol.sy.flags = BSF_UNDEFINED;
308               ptr->sy_symbol.sy.section = 0;
309               break;
310             default:
311               abort ();
312             }
313         }
314       ptr->sy_symbol.sy.value = S_GET_VALUE (ptr);
315       count++;
316     }
317   symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *));
318
319   index = 0;
320   for (ptr = symbol_rootP;
321        ptr != (symbolS *) NULL;
322        ptr = ptr->sy_next)
323     {
324       symbol_ptr_vec[index] = &(ptr->sy_symbol.sy);
325       index++;
326     }
327   symbol_ptr_vec[index] = 0;
328   abfd->outsymbols = symbol_ptr_vec;
329   abfd->symcount = count;
330 }
331
332 /* The generic as->bfd converter. Other backends may have special case
333    code */
334
335 void
336 DEFUN_VOID (bfd_as_write_hook)
337 {
338   int i;
339
340   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
341     {
342       size_section (abfd, i);
343     }
344
345
346   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
347     fill_section (abfd, i);
348
349   do_symbols (abfd);
350
351   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
352     do_relocs_for (i);
353
354 }
355
356 S_SET_SEGMENT (x, y)
357      symbolS *x;
358      int y;
359 {
360   x->sy_symbol.seg = y;
361 }
362
363 S_IS_DEFINED (x)
364      symbolS *x;
365 {
366   if (SEG_NORMAL (x->sy_symbol.seg))
367     {
368       return 1;
369     }
370   switch (x->sy_symbol.seg)
371     {
372     case SEG_UNKNOWN:
373       return 0;
374     default:
375       abort ();
376     }
377 }
378
379 S_IS_EXTERNAL (x)
380 {
381   abort ();
382 }
383
384 S_GET_DESC (x)
385 {
386   abort ();
387 }
388
389 S_GET_SEGMENT (x)
390      symbolS *x;
391 {
392   return x->sy_symbol.seg;
393 }
394
395 S_SET_EXTERNAL (x)
396      symbolS *x;
397 {
398   x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
399 }
400
401 S_SET_NAME (x, y)
402      symbolS *x;
403      char *y;
404 {
405   x->sy_symbol.sy.name = y;
406 }
407
408 S_GET_OTHER (x)
409 {
410   abort ();
411 }
412
413 S_IS_DEBUG (x)
414 {
415   abort ();
416 }
417
418 #ifndef segment_name
419 char *
420 segment_name ()
421 {
422   abort ();
423 }
424 #endif
425
426 void
427 obj_read_begin_hook ()
428 {
429 }
430
431 static void
432 obj_ieee_section (ignore)
433      int ignore;
434 {
435   extern char *input_line_pointer;
436   extern char is_end_of_line[];
437   char *p = input_line_pointer;
438   char *s = p;
439   int i;
440   /* Look up the name, if it doesn't exist, make it */
441   while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p])
442     {
443       p++;
444     }
445   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
446     {
447       if (segment_info[i].hadone)
448         {
449           if (strncmp (segment_info[i].name, s, p - s) == 0)
450             {
451               goto ok;
452
453             }
454         }
455       else
456         break;
457     }
458   if (i == SEG_UNKNOWN)
459     {
460       as_bad ("too many sections");
461       return;
462     }
463
464   segment_info[i].hadone = 1;
465   segment_info[i].name = malloc (p - s + 1);
466   memcpy (segment_info[i].name, s, p - s);
467   segment_info[i].name[p - s] = 0;
468 ok:
469   subseg_set (i, 0);
470   while (!is_end_of_line[*p])
471     p++;
472   input_line_pointer = p;
473
474 }
475
476
477 void cons ();
478 void s_ignore ();
479
480
481 void s_globl ();
482 const pseudo_typeS obj_pseudo_table[] =
483 {
484   {"section", obj_ieee_section, 0},
485   {"data.b", cons, 1},
486   {"data.w", cons, 2},
487   {"data.l", cons, 4},
488   {"export", s_globl, 0},
489   {"option", s_ignore, 0},
490   {"end", s_ignore, 0},
491   {"import", s_ignore, 0},
492   {"sdata", stringer, 0},
493   0,
494
495 };
496
497
498
499 void
500 obj_symbol_new_hook (symbolP)
501      symbolS *symbolP;
502 {
503   symbolP->sy_symbol.sy.the_bfd = abfd;
504 }
505
506
507
508
509
510 #if 1
511 extern void
512 DEFUN_VOID (write_object_file)
513 {
514   int i;
515   struct frchain *frchain_ptr;
516   struct frag *frag_ptr;
517
518   abfd = bfd_openw (out_file_name, "ieee");
519
520   if (abfd == 0)
521     {
522       as_perror ("FATAL: Can't create %s", out_file_name);
523       exit (EXIT_FAILURE);
524     }
525   bfd_set_format (abfd, bfd_object);
526   bfd_set_arch_mach (abfd, bfd_arch_h8300, 0);
527   subseg_set (1, 0);
528   subseg_set (2, 0);
529   subseg_set (3, 0);
530   for (frchain_ptr = frchain_root;
531        frchain_ptr != (struct frchain *) NULL;
532        frchain_ptr = frchain_ptr->frch_next)
533     {
534       /* Run through all the sub-segments and align them up. Also close any
535          open frags. We tack a .fill onto the end of the frag chain so
536          that any .align's size can be worked by looking at the next
537          frag.  */
538
539       subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
540 #ifndef SUB_SEGMENT_ALIGN
541 #define SUB_SEGMENT_ALIGN(SEG) 2
542 #endif
543       frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0);
544       frag_wane (frag_now);
545       frag_now->fr_fix = 0;
546       know (frag_now->fr_next == NULL);
547     }
548
549   /* Now build one big frag chain for each segment, linked through
550            fr_next. */
551   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
552     {
553
554       fragS **prev_frag_ptr_ptr;
555       struct frchain *next_frchain_ptr;
556
557       /*        struct frag **head_ptr = segment_info[i].frag_root;*/
558
559       segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
560 #if 0
561       /* Im not sure what this is for */
562       for (frchain_ptr = segment_info[i].frchainP->frch_root;
563            frchain_ptr != (struct frchain *) NULL;
564            frchain_ptr = frchain_ptr->frch_next)
565         {
566           *head_ptr = frchain_ptr;
567           head_ptr = &frchain_ptr->next;
568         }
569
570
571 #endif
572     }
573
574   for (i = SEG_E0; i < SEG_UNKNOWN; i++)
575     {
576       relax_segment (segment_info[i].frag_root, i);
577     }
578
579   /* Now the addresses of the frags are correct within the segment */
580
581   bfd_as_write_hook ();
582   bfd_close (abfd);
583 }
584
585 #endif
586
587 H_SET_TEXT_SIZE (a, b)
588 {
589   abort ();
590 }
591
592 H_GET_TEXT_SIZE ()
593 {
594   abort ();
595 }
596
597 H_SET_BSS_SIZE ()
598 {
599   abort ();
600 }
601
602 H_SET_STRING_SIZE ()
603 {
604   abort ();
605 }
606
607 H_SET_RELOCATION_SIZE ()
608 {
609   abort ();
610 }
611
612 H_SET_MAGIC_NUMBER ()
613 {
614   abort ();
615 }
616
617 H_GET_FILE_SIZE ()
618 {
619   abort ();
620 }
621
622 H_GET_TEXT_RELOCATION_SIZE ()
623 {
624   abort ();
625 }
626
627 /* end of obj-ieee.c */