summaryrefslogtreecommitdiff
path: root/gas/config/obj-ieee.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/obj-ieee.c')
-rw-r--r--gas/config/obj-ieee.c627
1 files changed, 627 insertions, 0 deletions
diff --git a/gas/config/obj-ieee.c b/gas/config/obj-ieee.c
new file mode 100644
index 00000000000..30a0798e295
--- /dev/null
+++ b/gas/config/obj-ieee.c
@@ -0,0 +1,627 @@
+/* obj-format for ieee-695 records.
+ Copyright (C) 1991, 92, 93, 94, 95, 1997, 1998 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+/*
+ created by
+
+ steve chamberlain steve@cygnus.com
+ */
+
+/*
+ this will hopefully become the port through which bfd and gas talk,
+ for the moment, only ieee is known to work well.
+ */
+
+#include "bfd.h"
+#include "as.h"
+#include "subsegs.h"
+#include "output-file.h"
+#include "frags.h"
+
+bfd *abfd;
+
+/* How many addresses does the .align take? */
+static relax_addressT
+relax_align (address, alignment)
+ register relax_addressT address; /* Address now. */
+ register long alignment; /* Alignment (binary). */
+{
+ relax_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~((~0) << alignment);
+ new_address = (address + mask) & (~mask);
+ return (new_address - address);
+} /* relax_align() */
+
+/* calculate the size of the frag chain and create a bfd section
+ to contain all of it */
+static void
+DEFUN (size_section, (abfd, idx),
+ bfd * abfd AND
+ unsigned int idx)
+{
+ asection *sec;
+ unsigned int size = 0;
+ fragS *frag = segment_info[idx].frag_root;
+ while (frag)
+ {
+ if (frag->fr_address != size)
+ {
+ printf (_("Out of step\n"));
+ size = frag->fr_address;
+ }
+ size += frag->fr_fix;
+ switch (frag->fr_type)
+ {
+ case rs_fill:
+ case rs_org:
+ size += frag->fr_offset * frag->fr_var;
+ break;
+ case rs_align:
+ case rs_align_code:
+ {
+ addressT off;
+
+ off = relax_align (size, frag->fr_offset);
+ if (frag->fr_subtype != 0 && off > frag->fr_subtype)
+ off = 0;
+ size += off;
+ }
+ }
+ frag = frag->fr_next;
+ }
+ if (size)
+ {
+ char *name = segment_info[idx].name;
+ if (name == (char *) NULL)
+ {
+ name = ".data";
+ }
+ segment_info[idx].user_stuff = (char *) (sec = bfd_make_section (abfd, name));
+ /* Make it output through itself */
+ sec->output_section = sec;
+ sec->flags |= SEC_HAS_CONTENTS;
+ bfd_set_section_size (abfd, sec, size);
+ }
+}
+
+/* run through a frag chain and write out the data to go with it */
+static void
+DEFUN (fill_section, (abfd, idx),
+ bfd * abfd AND
+ unsigned int idx)
+{
+ asection *sec = segment_info[idx].user_stuff;
+ if (sec)
+ {
+ fragS *frag = segment_info[idx].frag_root;
+ unsigned int offset = 0;
+ while (frag)
+ {
+ unsigned int fill_size;
+ unsigned int count;
+ switch (frag->fr_type)
+ {
+ case rs_fill:
+ case rs_align:
+ case rs_org:
+ if (frag->fr_fix)
+ {
+ bfd_set_section_contents (abfd,
+ sec,
+ frag->fr_literal,
+ frag->fr_address,
+ frag->fr_fix);
+ }
+ offset += frag->fr_fix;
+ fill_size = frag->fr_var;
+ if (fill_size)
+ {
+ unsigned int off = frag->fr_fix;
+ for (count = frag->fr_offset; count; count--)
+ {
+ bfd_set_section_contents (abfd, sec,
+ frag->fr_literal +
+ frag->fr_fix,
+ frag->fr_address + off,
+ fill_size);
+ off += fill_size;
+ }
+ }
+ break;
+ default:
+ abort ();
+ }
+ frag = frag->fr_next;
+ }
+ }
+}
+
+/* Count the relocations in a chain */
+
+static unsigned int
+DEFUN (count_entries_in_chain, (idx),
+ unsigned int idx)
+{
+ unsigned int nrelocs;
+ fixS *fixup_ptr;
+
+ /* Count the relocations */
+ fixup_ptr = segment_info[idx].fix_root;
+ nrelocs = 0;
+ while (fixup_ptr != (fixS *) NULL)
+ {
+ fixup_ptr = fixup_ptr->fx_next;
+ nrelocs++;
+ }
+ return nrelocs;
+}
+
+/* output all the relocations for a section */
+void
+DEFUN (do_relocs_for, (idx),
+ unsigned int idx)
+{
+ unsigned int nrelocs;
+ arelent **reloc_ptr_vector;
+ arelent *reloc_vector;
+ asymbol **ptrs;
+ asection *section = (asection *) (segment_info[idx].user_stuff);
+ unsigned int i;
+ fixS *from;
+ if (section)
+ {
+ nrelocs = count_entries_in_chain (idx);
+
+ reloc_ptr_vector = (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *));
+ reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent));
+ ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *));
+ from = segment_info[idx].fix_root;
+ for (i = 0; i < nrelocs; i++)
+ {
+ arelent *to = reloc_vector + i;
+ asymbol *s;
+ reloc_ptr_vector[i] = to;
+ to->howto = (reloc_howto_type *) (from->fx_r_type);
+
+#if 0 /* We can't represent complicated things in a reloc yet */
+ if (from->fx_addsy == 0 || from->fx_subsy != 0) abort();
+#endif
+
+ s = &(from->fx_addsy->sy_symbol.sy);
+ to->address = ((char *) (from->fx_frag->fr_address +
+ from->fx_where))
+ - ((char *) (&(from->fx_frag->fr_literal)));
+ to->addend = from->fx_offset;
+ /* If we know the symbol which we want to relocate to, turn
+ this reloaction into a section relative.
+
+ If this relocation is pcrelative, and we know the
+ destination, we still want to keep the relocation - since
+ the linker might relax some of the bytes, but it stops
+ being pc relative and turns into an absolute relocation. */
+ if (s)
+ {
+ if ((s->flags & BSF_UNDEFINED) == 0)
+ {
+ to->section = s->section;
+
+ /* We can refer directly to the value field here,
+ rather than using S_GET_VALUE, because this is
+ only called after do_symbols, which sets up the
+ value field. */
+ to->addend += s->value;
+
+ to->sym_ptr_ptr = 0;
+ if (to->howto->pcrel_offset)
+ {
+ /* This is a pcrel relocation, the addend should be adjusted */
+ to->addend -= to->address + 1;
+ }
+ }
+ else
+ {
+ to->section = 0;
+ *ptrs = &(from->fx_addsy->sy_symbol.sy);
+ to->sym_ptr_ptr = ptrs;
+
+ if (to->howto->pcrel_offset)
+ {
+ /* This is a pcrel relocation, the addend should be adjusted */
+ to->addend -= to->address - 1;
+ }
+ }
+
+ }
+ else
+ {
+ to->section = 0;
+ }
+
+ ptrs++;
+ from = from->fx_next;
+ }
+
+ /* attatch to the section */
+ section->orelocation = reloc_ptr_vector;
+ section->reloc_count = nrelocs;
+ section->flags |= SEC_LOAD;
+ }
+}
+
+/* do the symbols.. */
+static void
+DEFUN (do_symbols, (abfd),
+ bfd * abfd)
+{
+ extern symbolS *symbol_rootP;
+ symbolS *ptr;
+ asymbol **symbol_ptr_vec;
+ asymbol *symbol_vec;
+ unsigned int count = 0;
+ unsigned int index;
+
+
+ for (ptr = symbol_rootP;
+ ptr != (symbolS *) NULL;
+ ptr = ptr->sy_next)
+ {
+ if (SEG_NORMAL (ptr->sy_symbol.seg))
+ {
+ ptr->sy_symbol.sy.section =
+ (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff);
+ S_SET_VALUE (ptr, S_GET_VALUE (ptr) + ptr->sy_frag->fr_address);
+ if (ptr->sy_symbol.sy.flags == 0)
+ {
+ ptr->sy_symbol.sy.flags = BSF_LOCAL;
+ }
+ }
+ else
+ {
+ switch (ptr->sy_symbol.seg)
+ {
+ case SEG_ABSOLUTE:
+ ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE;
+ ptr->sy_symbol.sy.section = 0;
+ break;
+ case SEG_UNKNOWN:
+ ptr->sy_symbol.sy.flags = BSF_UNDEFINED;
+ ptr->sy_symbol.sy.section = 0;
+ break;
+ default:
+ abort ();
+ }
+ }
+ ptr->sy_symbol.sy.value = S_GET_VALUE (ptr);
+ count++;
+ }
+ symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *));
+
+ index = 0;
+ for (ptr = symbol_rootP;
+ ptr != (symbolS *) NULL;
+ ptr = ptr->sy_next)
+ {
+ symbol_ptr_vec[index] = &(ptr->sy_symbol.sy);
+ index++;
+ }
+ symbol_ptr_vec[index] = 0;
+ abfd->outsymbols = symbol_ptr_vec;
+ abfd->symcount = count;
+}
+
+/* The generic as->bfd converter. Other backends may have special case
+ code */
+
+void
+DEFUN_VOID (bfd_as_write_hook)
+{
+ int i;
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ size_section (abfd, i);
+ }
+
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ fill_section (abfd, i);
+
+ do_symbols (abfd);
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ do_relocs_for (i);
+
+}
+
+S_SET_SEGMENT (x, y)
+ symbolS *x;
+ int y;
+{
+ x->sy_symbol.seg = y;
+}
+
+S_IS_DEFINED (x)
+ symbolS *x;
+{
+ if (SEG_NORMAL (x->sy_symbol.seg))
+ {
+ return 1;
+ }
+ switch (x->sy_symbol.seg)
+ {
+ case SEG_UNKNOWN:
+ return 0;
+ default:
+ abort ();
+ }
+}
+
+S_IS_EXTERNAL (x)
+{
+ abort ();
+}
+
+S_GET_DESC (x)
+{
+ abort ();
+}
+
+S_GET_SEGMENT (x)
+ symbolS *x;
+{
+ return x->sy_symbol.seg;
+}
+
+S_SET_EXTERNAL (x)
+ symbolS *x;
+{
+ x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
+}
+
+S_SET_NAME (x, y)
+ symbolS *x;
+ char *y;
+{
+ x->sy_symbol.sy.name = y;
+}
+
+S_GET_OTHER (x)
+{
+ abort ();
+}
+
+S_IS_DEBUG (x)
+{
+ abort ();
+}
+
+#ifndef segment_name
+char *
+segment_name ()
+{
+ abort ();
+}
+#endif
+
+void
+obj_read_begin_hook ()
+{
+}
+
+static void
+obj_ieee_section (ignore)
+ int ignore;
+{
+ extern char *input_line_pointer;
+ extern char is_end_of_line[];
+ char *p = input_line_pointer;
+ char *s = p;
+ int i;
+ /* Look up the name, if it doesn't exist, make it */
+ while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p])
+ {
+ p++;
+ }
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ if (segment_info[i].hadone)
+ {
+ if (strncmp (segment_info[i].name, s, p - s) == 0)
+ {
+ goto ok;
+
+ }
+ }
+ else
+ break;
+ }
+ if (i == SEG_UNKNOWN)
+ {
+ as_bad (_("too many sections"));
+ return;
+ }
+
+ segment_info[i].hadone = 1;
+ segment_info[i].name = malloc (p - s + 1);
+ memcpy (segment_info[i].name, s, p - s);
+ segment_info[i].name[p - s] = 0;
+ok:
+ subseg_set (i, 0);
+ while (!is_end_of_line[*p])
+ p++;
+ input_line_pointer = p;
+
+}
+
+
+void cons ();
+void s_ignore ();
+
+
+void s_globl ();
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"section", obj_ieee_section, 0},
+ {"data.b", cons, 1},
+ {"data.w", cons, 2},
+ {"data.l", cons, 4},
+ {"export", s_globl, 0},
+ {"option", s_ignore, 0},
+ {"end", s_ignore, 0},
+ {"import", s_ignore, 0},
+ {"sdata", stringer, 0},
+ 0,
+
+};
+
+
+
+void
+obj_symbol_new_hook (symbolP)
+ symbolS *symbolP;
+{
+ symbolP->sy_symbol.sy.the_bfd = abfd;
+}
+
+
+
+
+
+#if 1
+extern void
+DEFUN_VOID (write_object_file)
+{
+ int i;
+ struct frchain *frchain_ptr;
+ struct frag *frag_ptr;
+
+ abfd = bfd_openw (out_file_name, "ieee");
+
+ if (abfd == 0)
+ {
+ as_perror (_("FATAL: Can't create %s"), out_file_name);
+ exit (EXIT_FAILURE);
+ }
+ bfd_set_format (abfd, bfd_object);
+ bfd_set_arch_mach (abfd, bfd_arch_h8300, 0);
+ subseg_set (1, 0);
+ subseg_set (2, 0);
+ subseg_set (3, 0);
+ for (frchain_ptr = frchain_root;
+ frchain_ptr != (struct frchain *) NULL;
+ frchain_ptr = frchain_ptr->frch_next)
+ {
+ /* Run through all the sub-segments and align them up. Also close any
+ open frags. We tack a .fill onto the end of the frag chain so
+ that any .align's size can be worked by looking at the next
+ frag. */
+
+ subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#ifndef SUB_SEGMENT_ALIGN
+#define SUB_SEGMENT_ALIGN(SEG) 2
+#endif
+ frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0);
+ frag_wane (frag_now);
+ frag_now->fr_fix = 0;
+ know (frag_now->fr_next == NULL);
+ }
+
+ /* Now build one big frag chain for each segment, linked through
+ fr_next. */
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+
+ fragS **prev_frag_ptr_ptr;
+ struct frchain *next_frchain_ptr;
+
+ /* struct frag **head_ptr = segment_info[i].frag_root;*/
+
+ segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
+#if 0
+ /* Im not sure what this is for */
+ for (frchain_ptr = segment_info[i].frchainP->frch_root;
+ frchain_ptr != (struct frchain *) NULL;
+ frchain_ptr = frchain_ptr->frch_next)
+ {
+ *head_ptr = frchain_ptr;
+ head_ptr = &frchain_ptr->next;
+ }
+
+
+#endif
+ }
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ relax_segment (segment_info[i].frag_root, i);
+ }
+
+ /* Now the addresses of the frags are correct within the segment */
+
+ bfd_as_write_hook ();
+ bfd_close (abfd);
+}
+
+#endif
+
+H_SET_TEXT_SIZE (a, b)
+{
+ abort ();
+}
+
+H_GET_TEXT_SIZE ()
+{
+ abort ();
+}
+
+H_SET_BSS_SIZE ()
+{
+ abort ();
+}
+
+H_SET_STRING_SIZE ()
+{
+ abort ();
+}
+
+H_SET_RELOCATION_SIZE ()
+{
+ abort ();
+}
+
+H_SET_MAGIC_NUMBER ()
+{
+ abort ();
+}
+
+H_GET_FILE_SIZE ()
+{
+ abort ();
+}
+
+H_GET_TEXT_RELOCATION_SIZE ()
+{
+ abort ();
+}
+
+/* end of obj-ieee.c */