+Wed Aug 19 09:25:09 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * as.h (enum _relax_state): Start off at one, not zero, to better
+ catch uninitialized-variable errors.
+ (linkrelax): Declare new variable.
+
+ * messages.c (warning_count, error_count): Default initializer is
+ sufficient.
+
+ * write.c: Merged some declarations, using PARMS macro.
+ (text_frag_root, data_frag_root, bss_frag_root, text_last_frag,
+ data_last_frag): No longer static.
+ (write_object_file, case rs_align or rs_org): If HANDLE_ALIGN is
+ defined, call it. Change segments before calling fixup_segment.
+ (relax_align): If linkrelax, provide extra padding.
+
+ * obj-bout.c (obj_emit_relocations): Emit alignment relocs despite
+ their not having symbols associated.
+
+ * tc-i960.c (norelax, instrument_branches): Default initializer is
+ sufficient.
+ (linkrelax): Delete variable definition.
+ (mem_fmt): Call fix_new with NO_RELOC.
+ (tc_bout_fix_to_chars): Handle alignment relocs.
+ (i960_handle_align): New function.
+ * tc-i960.h (linkrelax): Delete declaration.
+ (HANDLE_ALIGN): New macro; calls i960_handle_align.
+ (NEED_FX_R_TYPE, NO_RELOC): New macros.
+
Tue Aug 18 14:59:21 1992 Ken Raeburn (raeburn@cygnus.com)
* config/sparc.mt: New file. Grab sparc opcode table from bfd
/* relax() */
typedef enum _relax_state {
- rs_fill, /* Variable chars to be repeated fr_offset times. Fr_symbol
- unused. Used with fr_offset == 0 for a constant length
- frag. */
+ rs_fill = 1, /* Variable chars to be repeated fr_offset times.
+ Fr_symbol unused. Used with fr_offset == 0 for a
+ constant length frag. */
rs_align, /* Align: Fr_offset: power of 2. 1 variable char: fill
character. */
/* main program "as.c" (command arguments etc) */
-COMMON char
- flagseen[128]; /* ['x'] TRUE if "-x" seen. */
+COMMON char flagseen[128]; /* ['x'] TRUE if "-x" seen. */
-COMMON char *
- out_file_name; /* name of emitted object file */
+COMMON char * out_file_name; /* name of emitted object file */
-COMMON int need_pass_2; /* TRUE if we need a second pass. */
+COMMON int need_pass_2; /* TRUE if we need a second pass. */
+
+COMMON int linkrelax; /* TRUE if we should do no relaxing, and
+ leave lots of padding. */
typedef struct {
char * poc_name; /* assembler mnemonic, lower case, no '.' */
relax_addressT segment_address_in_file;
{
for (; fixP; fixP = fixP->fx_next) {
- if (fixP->fx_addsy != NULL) {
+ if (fixP->fx_addsy != NULL
+ || fixP->fx_r_type != NO_RELOC) {
tc_bout_fix_to_chars(*where, fixP, segment_address_in_file);
*where += sizeof(struct relocation_info);
} /* if there's a symbol */
/* static void unlink_sym(); */ /* Remove a symbol from the symbol list */
/* See md_parse_option() for meanings of these options */
-static char norelax = 0; /* True if -norelax switch seen */
-static char instrument_branches = 0; /* True if -b switch seen */
+static char norelax; /* True if -norelax switch seen */
+static char instrument_branches; /* True if -b switch seen */
/* Characters that always start a comment.
* If the pre-processor is disabled, these aren't very useful.
#define S_LEAFPROC 1
#define S_SYSPROC 2
-const pseudo_typeS
- md_pseudo_table[] = {
-
- { "bss", s_lcomm, 1 },
- { "extended", float_cons, 't' },
- { "leafproc", parse_po, S_LEAFPROC },
- { "sysproc", parse_po, S_SYSPROC },
-
- { "word", cons, 4 },
- { "quad", big_cons, 16 },
-
- { 0, 0, 0 }
- };
+const pseudo_typeS md_pseudo_table[] = {
+ { "bss", s_lcomm, 1 },
+ { "extended", float_cons, 't' },
+ { "leafproc", parse_po, S_LEAFPROC },
+ { "sysproc", parse_po, S_SYSPROC },
+
+ { "word", cons, 4 },
+ { "quad", big_cons, 16 },
+
+ { 0, 0, 0 }
+};
\f
/* Macros to extract info from an 'expressionS' structure 'e' */
#define adds(e) e.X_add_symbol
* replaced by decimal numbers
*/
int n_ops; /* Number of instruction operands */
-
+ int callx;
struct i960_opcode *oP;
/* Pointer to instruction description */
int branch_predict;
return;
}
}
+
+
/* Check for branch-prediction suffix on opcode mnemonic, strip it off */
n = strlen(args[0]) - 1;
reg_fmt(args, oP);
break;
case MEM1:
+ if (args[0][0] == 'c' && args[0][1] == 'a')
+ {
+ if (branch_predict)
+ {
+ as_warn(bp_error_msg);
+ }
+ mem_fmt(args, oP, 1);
+ break;
+ }
case MEM2:
case MEM4:
case MEM8:
if (branch_predict){
as_warn(bp_error_msg);
}
- mem_fmt(args, oP);
+ mem_fmt(args, oP, 0);
break;
case CALLJ:
if (branch_predict){
NULL, 0
};
struct tabentry *tp;
-
- if (!strcmp(*argP,"norelax")){
+ if (!strcmp(*argP,"linkrelax")){
+ linkrelax = 1;
+ flagseen ['L'] = 1;
+ } else if (!strcmp(*argP,"norelax")){
norelax = 1;
} else if (**argP == 'b'){
0,
0,
0);
- fixP->fx_im_disp = 2; /* 32-bit displacement fix */
+ fixP->fx_im_disp = 2; /* 32-bit displacement fix */
}
}
* mem_fmt: generate a MEMA- or MEMB-format instruction
*
**************************************************************************** */
-static void mem_fmt(args, oP)
+static void mem_fmt(args, oP, callx)
char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */
struct i960_opcode *oP; /* Pointer to description of instruction */
+int callx; /* Is this a callx opcode */
{
int i; /* Loop counter */
struct regop regop; /* Description of register operand */
subs(expr),
offs(expr),
0,
- 0);
- fixP->fx_im_disp = 2; /* 32-bit displacement fix */
+ NO_RELOC);
+ fixP->fx_im_disp = 2; /* 32-bit displacement fix */
+ fixP->fx_bsr = callx; /*SAC LD RELAX HACK */ /* Mark reloc as being in i stream */
break;
default:
if (!fixP->fx_callj) {
return;
} /* This wasn't a callj instruction in the first place */
-
+
where = fixP->fx_frag->fr_literal + fixP->fx_where;
if (TC_S_IS_SYSPROC(fixP->fx_addsy)) {
/* JF this is for paranoia */
memset((char *)&ri, '\0', sizeof(ri));
-
- know((symbolP = fixP->fx_addsy) != 0);
-
+ symbolP = fixP->fx_addsy;
+ know(symbolP != 0 || fixP->fx_r_type != NO_RELOC);
+ ri.r_bsr = fixP->fx_bsr; /*SAC LD RELAX HACK */
/* These two 'cuz of NS32K */
ri.r_callj = fixP->fx_callj;
-
- ri.r_length = nbytes_r_length[fixP->fx_size];
+ if(fixP->fx_bit_fixP) {
+ ri.r_length = 1;
+ }
+ else {
+ ri.r_length = nbytes_r_length[fixP->fx_size];
+ }
ri.r_pcrel = fixP->fx_pcrel;
ri.r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file;
- if (!S_IS_DEFINED(symbolP)) {
+ if (fixP->fx_r_type != NO_RELOC)
+ {
+ switch (fixP->fx_r_type)
+ {
+ case rs_align:
+ ri.r_index = -2;
+ ri.r_pcrel = 1;
+ ri.r_length = fixP->fx_size - 1;
+ break;
+ case rs_org:
+ ri.r_index = -2;
+ ri.r_pcrel = 0;
+ break;
+ case rs_fill:
+ ri.r_index = -1;
+ break;
+ default:
+ abort ();
+ }
+ ri.r_extern = 0;
+ }
+ else if (linkrelax || !S_IS_DEFINED(symbolP)) {
ri.r_extern = 1;
ri.r_index = symbolP->sy_number;
} else {
return;
} /* tc_coff_symbol_emit_hook() */
+void
+i960_handle_align (fragp)
+ fragS *fragp;
+{
+ fixS *fixp;
+ segT old_seg = now_seg, this_seg;
+ int old_subseg = now_subseg;
+ int pad_size;
+ extern struct frag *text_last_frag, *data_last_frag;
+
+ if (!linkrelax)
+ return;
+
+ /* The text section "ends" with another alignment reloc, to which we
+ aren't adding padding. */
+ if (fragp->fr_next == text_last_frag
+ || fragp->fr_next == data_last_frag)
+ {
+ return;
+ }
+
+ /* alignment directive */
+ fixp = fix_new (fragp, fragp->fr_fix, fragp->fr_offset, 0, 0, 0, 0,
+ (int) fragp->fr_type);
+}
+
/*
* Local Variables:
* comment-column: 0
*/
-static int warning_count = 0; /* Count of number of warnings issued */
+static int warning_count; /* Count of number of warnings issued */
int had_warnings() {
return(warning_count);
/* Nonzero if we've hit a 'bad error', and should not write an obj file,
and exit with a nonzero error code */
-static int error_count = 0;
+static int error_count;
int had_errors() {
return(error_count);
/*
* a s _ w a r n ()
*
- * Send to stderr a string (with bell) (JF: Bell is obnoxious!) as a warning, and locate warning
+ * Send to stderr a string as a warning, and locate warning
* in input file(s).
* Please only use this for when we have some recovery action.
* Please explain in string (which may have '\n's) what recovery was done.
#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()
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;
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.
*/
remove_subsegs(frchain_root, SEG_TEXT, &text_frag_root, &text_last_frag);
bss_address_frag.fr_address = (H_GET_TEXT_SIZE(&headers) +
H_GET_DATA_SIZE(&headers));
+
/* Slide all the frags */
if (bss_frag_root)
{
}
#endif
- H_SET_BSS_SIZE(&headers,local_bss_counter + bss_last_frag ? bss_last_frag->fr_address: 0);
+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);
* 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);
{
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) ;
+ know(segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS);
#endif
/* In case md_estimate_size_before_relax() wants to make fixSs. */
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;
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));
+ 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);