mainly link-relax changes
authorKen Raeburn <raeburn@cygnus>
Wed, 19 Aug 1992 14:42:21 +0000 (14:42 +0000)
committerKen Raeburn <raeburn@cygnus>
Wed, 19 Aug 1992 14:42:21 +0000 (14:42 +0000)
gas/ChangeLog
gas/as.h
gas/config/obj-bout.c
gas/config/tc-i960.c
gas/messages.c
gas/write.c

index 0fabc9d489130dcb75965f33abad8126cb582351..50c438c58441adbff6c675eee123a095c7c07caa 100644 (file)
@@ -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
index 9787f211d12afd776e3cf40a7b49551979d24093..30c5b126f5b4f683d7792318ffd1d44e37274605 100644 (file)
--- 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 '.' */
index f07f6f9e4281c4a56ffb2cdc3b556a25ebbfc54b..4199efc6588bc9857018f40a2dfb748156c1567c 100644 (file)
@@ -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 */
index 262ed8bdabfe946f90a7444de0d46b86e16ca013..6e173fc1ad474f76efb08fee5aa672eac998c6f1 100644 (file)
@@ -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 }
+};
 \f
 /* 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
index f8286b8f9507cde4561b5928d5952185db0bb362..b48df0982748ed67fbb7f30bf94f0e153d0acb6a 100644 (file)
@@ -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.
index f94300a2526a98017ec61aa6b3a55bf93c027810..150ea099f91666e04eef00e869f09b581169f99f 100644 (file)
 #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);