along with GAS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-/*
-
- This thing should be set up to do byteordering correctly. But...
-
- In order to cross-assemble the target machine must have an a.out header
- similar to the one in a.out.h on THIS machine. Byteorder doesn't matter,
- we take special care of it, but the numbers must be the same SIZE (# of
- bytes) and in the same PLACE. If this is not true, you will have some
- trouble.
- */
+/* This thing should be set up to do byteordering correctly. But... */
#include "as.h"
#include "subsegs.h"
#endif
#ifndef MANY_SEGMENTS
-static struct frag *text_frag_root;
-static struct frag *data_frag_root;
-static struct frag *bss_frag_root;
+struct frag *text_frag_root;
+struct frag *data_frag_root;
+struct frag *bss_frag_root;
-static struct frag *text_last_frag; /* Last frag in segment. */
-static struct frag *data_last_frag; /* Last frag in segment. */
+struct frag *text_last_frag; /* Last frag in segment. */
+struct frag *data_last_frag; /* Last frag in segment. */
static struct frag *bss_last_frag; /* Last frag in segment. */
#endif
int magic_number_for_object_file = DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE;
-/* static long length; JF unused */ /* String length, including trailing '\0'. */
-
-
-#if __STDC__ == 1
-
-static int is_dnrange(struct frag *f1, struct frag *f2);
-static long fixup_segment(fixS *fixP, segT this_segment_type);
-static relax_addressT relax_align(relax_addressT address, long alignment);
-void relax_segment(struct frag *segment_frag_root, segT segment_type);
-
-#else
-
-static int is_dnrange();
-static long fixup_segment();
-static relax_addressT relax_align();
-void relax_segment();
-
-#endif /* not __STDC__ */
+static int is_dnrange PARAMS ((struct frag *f1, struct frag *f2));
+static long fixup_segment PARAMS ((fixS *fixP, segT this_segment_type));
+static relax_addressT relax_align PARAMS ((relax_addressT addr, long align));
+void relax_segment PARAMS ((struct frag *seg_frag_root, segT seg_type));
/*
* fix_new()
symbolS *sub_symbol; /* X_subtract_symbol. */
long offset; /* X_add_number. */
int pcrel; /* TRUE if PC-relative relocation. */
-enum reloc_type r_type; /* Relocation type */
+int r_type; /* Relocation type */
{
fixS *fixP;
fixP->fx_subsy = sub_symbol;
fixP->fx_offset = offset;
fixP->fx_pcrel = pcrel;
+#if defined(TC_SPARC) || defined(TC_A29K) || defined( NEED_FX_R_TYPE)
fixP->fx_r_type = r_type;
-
+#endif
/* JF these 'cuz of the NS32K stuff */
fixP->fx_im_disp = 0;
fixP->fx_pcrel_adjust = 0;
comparing to older versions of gas that have relocs
reverse sorted, it is convenient to have this compile
time option. xoxorich. */
-
+
#ifdef REVERSE_SORT_RELOCS
fixP->fx_next = *seg_fix_rootP;
} /* fix_new() */
#ifndef BFD
+
+void remove_subsegs(head, seg, root, last)
+frchainS *head;
+int seg;
+fragS **root;
+fragS ** last;
+{
+ fragS dummy;
+ fragS * prev_frag = &dummy;
+ *root = head->frch_root;
+ while (head && head->frch_seg == seg)
+ {
+ prev_frag->fr_next = head->frch_root;
+
+ prev_frag = head->frch_last;
+ head = head->frch_next;
+ }
+ *last = prev_frag;
+ prev_frag->fr_next = 0;
+}
void write_object_file()
{
register struct frchain * frchainP; /* Track along all frchains. */
register fragS * fragP; /* Track along all frags. */
register struct frchain * next_frchainP;
register fragS * * prev_fragPP;
- /* register char * name; */
- /* symbolS *symbolP; */
- /* register symbolS ** symbolPP; */
- /* register fixS * fixP; JF unused */
unsigned int data_siz;
long object_file_size;
VMS_Check_For_Main();
#endif /* VMS */
/*
- * After every sub-segment, we fake an ".align ...". This conforms to BSD4.2
- * brane-damage. We then fake ".fill 0" because that is the kind of frag
- * that requires least thought. ".align" frags like to have a following
- * frag since that makes calculating their intended length trivial.
+ * After every sub-segment, we fake an ".align ...". This conforms to
+ * BSD4.2 brane-damage. We then fake ".fill 0" because that is the
+ * kind of frag that requires least thought. ".align" frags like to
+ * have a following frag since that makes calculating their intended
+ * length trivial.
*/
#define SUB_SEGMENT_ALIGN (2)
for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next) {
/*
* From now on, we don't care about sub-segments.
* Build one frag chain for each segment. Linked thru fr_next.
- * We know that there is at least 1 text frchain & at least 1 data frchain.
+ * We know that there is at least 1 text frchain & at least 1 data
+ * frchain.
*/
- prev_fragPP = &text_frag_root;
- for (frchainP = frchain_root; frchainP; frchainP = next_frchainP) {
- know( frchainP->frch_root );
- * prev_fragPP = frchainP->frch_root;
- prev_fragPP = & frchainP->frch_last->fr_next;
- next_frchainP = frchainP->frch_next;
- if (next_frchainP == NULL)
- {
- bss_last_frag = frchainP->frch_last;
- }
- else if (next_frchainP == data0_frchainP)
- {
- text_last_frag = frchainP->frch_last;
- prev_fragPP = & data_frag_root;
- }
- else if (next_frchainP == bss0_frchainP)
- {
- data_last_frag = frchainP->frch_last;
- prev_fragPP = & bss_frag_root;
- }
- } /* walk the frag chain */
+ remove_subsegs(frchain_root, SEG_TEXT, &text_frag_root, &text_last_frag);
+ remove_subsegs(data0_frchainP, SEG_DATA, &data_frag_root, &data_last_frag);
+ remove_subsegs(bss0_frchainP, SEG_BSS, &bss_frag_root, &bss_last_frag);
/*
* We have two segments. If user gave -R flag, then we must put the
* data frags into the text segment. Do this before relaxing so
* we know to take advantage of -R and make shorter addresses.
*/
+#ifndef OBJ_AOUT
if (flagseen[ 'R' ]) {
fixS *tmp;
if (text_fix_root) {
for (tmp = text_fix_root; tmp->fx_next; tmp = tmp->fx_next) ;;
tmp->fx_next=data_fix_root;
+ text_fix_tail = data_fix_tail;
} else
text_fix_root=data_fix_root;
data_fix_root=NULL;
}
-
+#endif
relax_segment(text_frag_root, SEG_TEXT);
relax_segment(data_frag_root, SEG_DATA);
- relax_segment(bss_frag_root, SEG_BSS);
+ relax_segment(bss_frag_root, SEG_BSS);
/*
* Now the addresses of frags are correct within the segment.
*/
H_SET_DATA_SIZE(&headers, data_last_frag->fr_address);
data_last_frag->fr_address = H_GET_DATA_SIZE(&headers);
slide = H_GET_TEXT_SIZE(&headers); /* & in file of the data segment. */
-
+#ifdef OBJ_BOUT
+#define RoundUp(N,S) (((N)+(S)-1)&-(S))
+ /* For b.out: If the data section has a strict alignment
+ requirement, its load address in the .o file will be
+ rounded up from the size of the text section. These
+ two values are *not* the same! Similarly for the bss
+ section.... */
+ slide = RoundUp (slide, 1 << section_alignment[SEG_DATA]);
+#endif
+
for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
fragP->fr_address += slide;
} /* for each data frag */
H_SET_DATA_SIZE(&headers,0);
data_siz = 0;
}
-
+
+#ifdef OBJ_BOUT
+ /* See above comments on b.out data section address. */
+ {
+ long bss_vma;
+ if (data_last_frag == 0)
+ bss_vma = H_GET_TEXT_SIZE (&headers);
+ else
+ bss_vma = data_last_frag->fr_address;
+ bss_vma = RoundUp (bss_vma, 1 << section_alignment[SEG_BSS]);
+ bss_address_frag.fr_address = bss_vma;
+ }
+#else
bss_address_frag.fr_address = (H_GET_TEXT_SIZE(&headers) +
H_GET_DATA_SIZE(&headers));
-
- H_SET_BSS_SIZE(&headers, bss_last_frag->fr_address);
- /*
- * now fixup all bss frags addresses
- */
- if (bss_frag_root)
+
+ /* Slide all the frags */
+ if (bss_frag_root)
+ {
+ relax_addressT slide = bss_address_frag.fr_address + local_bss_counter;
+
+ for (fragP = bss_frag_root; fragP; fragP = fragP->fr_next)
{
- relax_addressT slide;
- slide = bss_address_frag.fr_address;
- for (fragP = bss_frag_root; fragP; fragP = fragP->fr_next)
- fragP->fr_address += slide;
- }
+ fragP->fr_address += slide;
+ } /* for each bss frag */
+ }
+
+#endif
+if(bss_last_frag) {
+local_bss_counter += bss_last_frag->fr_address - bss_frag_root->fr_address;
+}
+ H_SET_BSS_SIZE(&headers,local_bss_counter );
/*
*
switch (fragP->fr_type) {
case rs_align:
case rs_org:
+#ifdef HANDLE_ALIGN
+ HANDLE_ALIGN (fragP);
+#endif
fragP->fr_type = rs_fill;
know(fragP->fr_var == 1);
know(fragP->fr_next != NULL);
BAD_CASE( fragP->fr_type );
break;
} /* switch (fr_type) */
-
- know((fragP->fr_next == NULL) || ((fragP->fr_next->fr_address - fragP->fr_address) == (fragP->fr_fix + (fragP->fr_offset * fragP->fr_var))));
+
+ if (!((fragP->fr_next == NULL)
+#ifdef OBJ_BOUT
+ || (fragP->fr_next == data_frag_root)
+#endif
+ || ((fragP->fr_next->fr_address - fragP->fr_address)
+ == (fragP->fr_fix + (fragP->fr_offset * fragP->fr_var)))))
+ {
+ fprintf (stderr, "assertion failed: file `%s', line %d\n",
+ __FILE__, __LINE__ - 4);
+ exit (1);
+ }
} /* for each frag. */
#ifndef WORKING_DOT_WORD
lie->sub,
lie->addnum,
0, 0, 2, 0, 0);
-#else /* TC_NS32K */
+#else
+# if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE)
fix_new( lie->frag, lie->word_goes_here - lie->frag->fr_literal,
2, lie->add,
lie->sub, lie->addnum,
0, NO_RELOC);
+# else
+ fix_new( lie->frag, lie->word_goes_here - lie->frag->fr_literal,
+ 2, lie->add,
+ lie->sub, lie->addnum,
+ 0, 0);
+
+# endif /* tc_sparc|tc_a29k|need_fx_r_type */
#endif /* TC_NS32K */
/* md_number_to_chars(lie->word_goes_here,
S_GET_VALUE(lie->add)
* Scan every FixS performing fixups. We had to wait until now to do
* this because md_convert_frag() may have made some fixSs.
*/
-
- H_SET_RELOCATION_SIZE(&headers,
- md_reloc_size * fixup_segment(text_fix_root, SEG_TEXT),
- md_reloc_size * fixup_segment(data_fix_root, SEG_DATA));
-
-
+ int trsize, drsize;
+
+ subseg_change (SEG_TEXT, 0);
+ trsize = md_reloc_size * fixup_segment (text_fix_root,
+ SEG_TEXT);
+ subseg_change (SEG_DATA, 0);
+ drsize = md_reloc_size * fixup_segment (data_fix_root,
+ SEG_DATA);
+ H_SET_RELOCATION_SIZE (&headers, trsize, drsize);
+
/* FIXME move this stuff into the pre-write-hook */
H_SET_MAGIC_NUMBER(&headers, magic_number_for_object_file);
H_SET_ENTRY_POINT(&headers, 0);
void relax_segment(segment_frag_root, segment)
struct frag * segment_frag_root;
-segT segment; /* SEG_DATA or SEG_TEXT or SEG_BSS */
+segT segment; /* SEG_DATA or SEG_TEXT */
{
register struct frag * fragP;
register relax_addressT address;
- /* register relax_addressT old_address; JF unused */
- /* register relax_addressT new_address; JF unused */
#ifndef MANY_SEGMENTS
know(segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS);
#endif
subseg_change(segment, 0);
/*
- * For each frag in segment: count and store (a 1st guess of) fr_address.
+ * For each frag in segment: count and store (a 1st guess of)
+ * fr_address.
*/
address = 0;
for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
case rs_org:
/*
- * Assume .org is nugatory. It will grow with 1st relax.
+ * Assume .org is nugatory. It will grow with 1st
+ * relax.
*/
break;
offset= lie->add->sy_frag->fr_address+ S_GET_VALUE(lie->add) + lie->addnum -
(lie->sub->sy_frag->fr_address+ S_GET_VALUE(lie->sub));
if (offset<=-32768 || offset>=32767) {
- if (flagseen['k'])
+ if (flagseen['K'])
as_warn(".word %s-%s+%ld didn't fit",
S_GET_NAME(lie->add),
S_GET_NAME(lie->sub),
if (symbolP) {
#ifdef MANY_SEGMENTS
#else
- know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE)
- || (S_GET_SEGMENT(symbolP) == SEG_DATA)
- || (S_GET_SEGMENT(symbolP) == SEG_TEXT)
- || (S_GET_SEGMENT(symbolP) == SEG_BSS));
+ know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT(symbolP) == SEG_DATA) || (S_GET_SEGMENT(symbolP) == SEG_TEXT) || S_GET_SEGMENT(symbolP) == SEG_BSS);
know(symbolP->sy_frag);
know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || (symbolP->sy_frag == &zero_address_frag));
#endif
if (symbolP) {
#ifndef MANY_SEGMENTS
- know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT(symbolP) == SEG_DATA) || (S_GET_SEGMENT(symbolP) == SEG_TEXT));
+ know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT(symbolP) == SEG_DATA)|| (S_GET_SEGMENT(symbolP) == SEG_BSS) || (S_GET_SEGMENT(symbolP) == SEG_TEXT));
#endif
know(symbolP->sy_frag);
know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || symbolP->sy_frag==&zero_address_frag );
*/
/* 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). */
+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_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~ ( (~0) << alignment );
+ new_address = (address + mask) & (~ mask);
+ if (linkrelax)
+ /* We must provide lots of padding, so the linker can discard it
+ when needed. The linker will not add extra space, ever. */
+ new_address += (1 << alignment);
+ return (new_address - address);
} /* relax_align() */
/* fixup_segment()
handle the remaining fixS's that we couldn't completely handle here.
These will be output later by emit_relocations(). */
-static long fixup_segment(fixP, this_segment_type)
-register fixS * fixP;
-segT this_segment_type; /* N_TYPE bits for segment. */
+static long
+fixup_segment(fixP, this_segment_type)
+ register fixS *fixP;
+ segT this_segment_type; /* N_TYPE bits for segment. */
{
register long seg_reloc_count;
register symbolS *add_symbolP;
/* FIXME: remove this line */ /* fixS *orig = fixP; */
seg_reloc_count = 0;
-
+#ifdef TC_I960
+ /* If the linker is doing the relaxing, we must not do any fixups */
+ if (linkrelax) {
+ for ( ; fixP ; fixP = fixP->fx_next) {
+ seg_reloc_count++;
+ }
+ }
+ else
+#endif
for ( ; fixP; fixP = fixP->fx_next) {
fragP = fixP->fx_frag;
know(fragP);
#endif /* TC_I960 */
#ifdef OBJ_COFF
- /* This really needed to be
- like this for COFF output.
- - mtranle@paris
-
- But I'm not sure it's right
- for i960 or a29k coff.
- xoxorich. */
-
+#ifdef TE_I386AIX
if (S_IS_COMMON(add_symbolP))
add_number += S_GET_VALUE(add_symbolP);
+#endif /* TE_I386AIX */
#endif /* OBJ_COFF */
++seg_reloc_count;
if (!fixP->fx_bit_fixP) {
if ((size==1 &&
- (add_number& ~0xFF) && (add_number&~0xFF!=(-1&~0xFF))) ||
+ (add_number& ~0xFF) && ((add_number&~0xFF)!=(-1&~0xFF))) ||
(size==2 &&
- (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF)))) {
+ (add_number& ~0xFFFF) && ((add_number&~0xFFFF)!=(-1&~0xFFFF)))) {
as_bad("Value of %d too large for field of %d bytes at 0x%x",
add_number, size, fragP->fr_address + where);
} /* generic error checking */