* read.c (do_align): Add max parameter. Change all callers.
[deliverable/binutils-gdb.git] / 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 char *
419 segment_name ()
420 {
421 abort ();
422 }
423
424 void
425 obj_read_begin_hook ()
426 {
427 }
428
429 static void
430 obj_ieee_section (ignore)
431 int ignore;
432 {
433 extern char *input_line_pointer;
434 extern char is_end_of_line[];
435 char *p = input_line_pointer;
436 char *s = p;
437 int i;
438 /* Look up the name, if it doesn't exist, make it */
439 while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p])
440 {
441 p++;
442 }
443 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
444 {
445 if (segment_info[i].hadone)
446 {
447 if (strncmp (segment_info[i].name, s, p - s) == 0)
448 {
449 goto ok;
450
451 }
452 }
453 else
454 break;
455 }
456 if (i == SEG_UNKNOWN)
457 {
458 as_bad ("too many sections");
459 return;
460 }
461
462 segment_info[i].hadone = 1;
463 segment_info[i].name = malloc (p - s + 1);
464 memcpy (segment_info[i].name, s, p - s);
465 segment_info[i].name[p - s] = 0;
466 ok:
467 subseg_set (i, 0);
468 while (!is_end_of_line[*p])
469 p++;
470 input_line_pointer = p;
471
472 }
473
474
475 void cons ();
476 void s_ignore ();
477
478
479 void s_globl ();
480 const pseudo_typeS obj_pseudo_table[] =
481 {
482 {"section", obj_ieee_section, 0},
483 {"data.b", cons, 1},
484 {"data.w", cons, 2},
485 {"data.l", cons, 4},
486 {"export", s_globl, 0},
487 {"option", s_ignore, 0},
488 {"end", s_ignore, 0},
489 {"import", s_ignore, 0},
490 {"sdata", stringer, 0},
491 0,
492
493 };
494
495
496
497 void
498 obj_symbol_new_hook (symbolP)
499 symbolS *symbolP;
500 {
501 symbolP->sy_symbol.sy.the_bfd = abfd;
502 }
503
504
505
506
507
508 #if 1
509 extern void
510 DEFUN_VOID (write_object_file)
511 {
512 int i;
513 struct frchain *frchain_ptr;
514 struct frag *frag_ptr;
515
516 abfd = bfd_openw (out_file_name, "ieee");
517
518 if (abfd == 0)
519 {
520 as_perror ("FATAL: Can't create %s", out_file_name);
521 exit (EXIT_FAILURE);
522 }
523 bfd_set_format (abfd, bfd_object);
524 bfd_set_arch_mach (abfd, bfd_arch_h8300, 0);
525 subseg_set (1, 0);
526 subseg_set (2, 0);
527 subseg_set (3, 0);
528 for (frchain_ptr = frchain_root;
529 frchain_ptr != (struct frchain *) NULL;
530 frchain_ptr = frchain_ptr->frch_next)
531 {
532 /* Run through all the sub-segments and align them up. Also close any
533 open frags. We tack a .fill onto the end of the frag chain so
534 that any .align's size can be worked by looking at the next
535 frag. */
536
537 subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
538 #ifndef SUB_SEGMENT_ALIGN
539 #define SUB_SEGMENT_ALIGN(SEG) 2
540 #endif
541 frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0);
542 frag_wane (frag_now);
543 frag_now->fr_fix = 0;
544 know (frag_now->fr_next == NULL);
545 }
546
547 /* Now build one big frag chain for each segment, linked through
548 fr_next. */
549 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
550 {
551
552 fragS **prev_frag_ptr_ptr;
553 struct frchain *next_frchain_ptr;
554
555 /* struct frag **head_ptr = segment_info[i].frag_root;*/
556
557 segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
558 #if 0
559 /* Im not sure what this is for */
560 for (frchain_ptr = segment_info[i].frchainP->frch_root;
561 frchain_ptr != (struct frchain *) NULL;
562 frchain_ptr = frchain_ptr->frch_next)
563 {
564 *head_ptr = frchain_ptr;
565 head_ptr = &frchain_ptr->next;
566 }
567
568
569 #endif
570 }
571
572 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
573 {
574 relax_segment (segment_info[i].frag_root, i);
575 }
576
577 /* Now the addresses of the frags are correct within the segment */
578
579 bfd_as_write_hook ();
580 bfd_close (abfd);
581 }
582
583 #endif
584
585 H_SET_TEXT_SIZE (a, b)
586 {
587 abort ();
588 }
589
590 H_GET_TEXT_SIZE ()
591 {
592 abort ();
593 }
594
595 H_SET_BSS_SIZE ()
596 {
597 abort ();
598 }
599
600 H_SET_STRING_SIZE ()
601 {
602 abort ();
603 }
604
605 H_SET_RELOCATION_SIZE ()
606 {
607 abort ();
608 }
609
610 H_SET_MAGIC_NUMBER ()
611 {
612 abort ();
613 }
614
615 H_GET_FILE_SIZE ()
616 {
617 abort ();
618 }
619
620 H_GET_TEXT_RELOCATION_SIZE ()
621 {
622 abort ();
623 }
624
625 /* end of obj-ieee.c */
This page took 0.073033 seconds and 5 git commands to generate.