From 09952cd9552ace00ab7183be9b3cc5f120a9df5a Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Wed, 19 Aug 1992 14:42:21 +0000 Subject: [PATCH] mainly link-relax changes --- gas/ChangeLog | 29 ++++++++++++ gas/as.h | 17 +++---- gas/config/obj-bout.c | 3 +- gas/config/tc-i960.c | 124 ++++++++++++++++++++++++++++++++++++------------ gas/messages.c | 6 +-- gas/write.c | 129 +++++++++++++++++++++++++++----------------------- 6 files changed, 206 insertions(+), 102 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 0fabc9d..50c438c 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,32 @@ +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 diff --git a/gas/as.h b/gas/as.h index 9787f21..30c5b12 100644 --- a/gas/as.h +++ b/gas/as.h @@ -197,9 +197,9 @@ extern int section_alignment[]; /* 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. */ @@ -281,13 +281,14 @@ COMMON fragS bss_address_frag; /* For local common (N_BSS segment) fixups. */ /* 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 '.' */ diff --git a/gas/config/obj-bout.c b/gas/config/obj-bout.c index f07f6f9..4199efc 100644 --- a/gas/config/obj-bout.c +++ b/gas/config/obj-bout.c @@ -102,7 +102,8 @@ fixS *fixP; /* Fixup chain for this segment. */ 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 */ diff --git a/gas/config/tc-i960.c b/gas/config/tc-i960.c index 262ed8b..6e173fc1 100644 --- a/gas/config/tc-i960.c +++ b/gas/config/tc-i960.c @@ -126,8 +126,8 @@ static int targ_has_iclass();/* Target chip supports instruction set? */ /* 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. @@ -186,19 +186,17 @@ const relax_typeS #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 } +}; /* Macros to extract info from an 'expressionS' structure 'e' */ #define adds(e) e.X_add_symbol @@ -479,7 +477,7 @@ char *textP; /* Source text of instruction */ * replaced by decimal numbers */ int n_ops; /* Number of instruction operands */ - + int callx; struct i960_opcode *oP; /* Pointer to instruction description */ int branch_predict; @@ -509,6 +507,8 @@ char *textP; /* Source text of instruction */ return; } } + + /* Check for branch-prediction suffix on opcode mnemonic, strip it off */ n = strlen(args[0]) - 1; @@ -556,6 +556,15 @@ char *textP; /* Source text of instruction */ 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: @@ -564,7 +573,7 @@ char *textP; /* Source text of instruction */ if (branch_predict){ as_warn(bp_error_msg); } - mem_fmt(args, oP); + mem_fmt(args, oP, 0); break; case CALLJ: if (branch_predict){ @@ -833,8 +842,10 @@ char ***vecP; 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'){ @@ -1062,7 +1073,7 @@ void 0, 0, 0); - fixP->fx_im_disp = 2; /* 32-bit displacement fix */ + fixP->fx_im_disp = 2; /* 32-bit displacement fix */ } } @@ -1459,9 +1470,10 @@ char *args[]; /* Output arg: pointers to opcode and operands placed * 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 */ @@ -1546,8 +1558,9 @@ struct i960_opcode *oP; /* Pointer to description of instruction */ 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: @@ -2245,7 +2258,7 @@ fixS *fixP; /* Relocation that can be done at assembly time */ 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)) { @@ -2552,17 +2565,42 @@ relax_addressT segment_address_in_file; /* 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 { @@ -2749,6 +2787,32 @@ symbolS *symbolP; 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 diff --git a/gas/messages.c b/gas/messages.c index f8286b8..b48df098 100644 --- a/gas/messages.c +++ b/gas/messages.c @@ -92,7 +92,7 @@ */ -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); @@ -101,7 +101,7 @@ int had_warnings() { /* 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); @@ -177,7 +177,7 @@ char *Format; /* * 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. diff --git a/gas/write.c b/gas/write.c index f94300a..150ea09 100644 --- a/gas/write.c +++ b/gas/write.c @@ -34,12 +34,12 @@ #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 @@ -53,24 +53,10 @@ char *next_object_file_charP; /* Tracks object file bytes. */ 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() @@ -111,7 +97,7 @@ int r_type; /* Relocation type */ 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; @@ -160,10 +146,6 @@ void write_object_file() 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; @@ -178,10 +160,11 @@ void write_object_file() 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) { @@ -213,7 +196,8 @@ void write_object_file() /* * 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); @@ -304,6 +288,7 @@ void write_object_file() bss_address_frag.fr_address = (H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers)); + /* Slide all the frags */ if (bss_frag_root) { @@ -316,7 +301,10 @@ void write_object_file() } #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 ); /* * @@ -362,6 +350,9 @@ void write_object_file() 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); @@ -522,12 +513,16 @@ void write_object_file() * 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); @@ -660,16 +655,15 @@ 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) ; + 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) { @@ -687,7 +681,8 @@ segT segment; /* SEG_DATA or SEG_TEXT */ case rs_org: /* - * Assume .org is nugatory. It will grow with 1st relax. + * Assume .org is nugatory. It will grow with 1st + * relax. */ break; @@ -804,7 +799,7 @@ segT segment; /* SEG_DATA or SEG_TEXT */ 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 @@ -833,7 +828,7 @@ segT segment; /* SEG_DATA or SEG_TEXT */ 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 ); @@ -953,16 +948,21 @@ segT segment; /* SEG_DATA or SEG_TEXT */ */ /* 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() @@ -976,9 +976,10 @@ register long alignment; /* Alignment (binary). */ 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; @@ -993,7 +994,15 @@ segT this_segment_type; /* N_TYPE bits for segment. */ /* 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); -- 2.7.4