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