From: Ian Lance Taylor Date: Wed, 6 Oct 1993 17:31:31 +0000 (+0000) Subject: Changes to let cons handle bignums like general expressions. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=80aab57939a0;p=binutils-gdb.git Changes to let cons handle bignums like general expressions. * expr.h (expressionS): New field X_unsigned. * expr.c (operand): Initialize X_unsigned to 1. Set it to 0 for unary minus case. (expr) Fix typo resultP to right if missing operand. Set X_unsigned to 1 when building new expression. * read.c (potable): Make "octa" and "quad" call cons, not big_cons. (cons): Handle bignums. If given an O_constant (small integer) to fill a big space, turn it into a bignum. (parse_bitfield_cons): Set X_unsigned field. (bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons): Removed. * read.h (big_cons): Remove prototype. * symbols.c (resolve_symbol_value): Don't give a warning if a symbol in expr_section can not be resolved. (S_SET_VALUE): Clear X_unsigned. * write.c (write_object_file): If resolve_symbol_value failed on a symbol we are writing out, give a warning. * config/tc-h8500.c (parse_reglist): Set X_unsigned. * config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to call pa_cons, not pa_big_cons. (pa_big_cons): Remove. * config/tc-hppa.h (pa_big_cons): Remove declaration. * config/tc-i960.c (md_pseudo_table): Change "quad" to call cons, not big_cons. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 7d94f43025f..4a5e80bea94 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,37 @@ +Wed Oct 6 13:01:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + Changes to let cons handle bignums like general expressions. + * expr.h (expressionS): New field X_unsigned. + * expr.c (operand): Initialize X_unsigned to 1. Set it to 0 for + unary minus case. + (expr) Fix typo resultP to right if missing operand. Set + X_unsigned to 1 when building new expression. + * read.c (potable): Make "octa" and "quad" call cons, not + big_cons. + (cons): Handle bignums. If given an O_constant (small integer) to + fill a big space, turn it into a bignum. + (parse_bitfield_cons): Set X_unsigned field. + (bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons): + Removed. + * read.h (big_cons): Remove prototype. + * symbols.c (resolve_symbol_value): Don't give a warning if a + symbol in expr_section can not be resolved. + (S_SET_VALUE): Clear X_unsigned. + * write.c (write_object_file): If resolve_symbol_value failed on a + symbol we are writing out, give a warning. + * config/tc-h8500.c (parse_reglist): Set X_unsigned. + * config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to + call pa_cons, not pa_big_cons. + (pa_big_cons): Remove. + * config/tc-hppa.h (pa_big_cons): Remove declaration. + * config/tc-i960.c (md_pseudo_table): Change "quad" to call cons, + not big_cons. + +Tue Oct 5 10:53:36 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com) + + * doc/as.texinfo (Copying): new node, to handle the recent changes + in the texinfo/gpl.texinfo file + Mon Oct 4 17:10:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * read.c (big_cons): Handle "0" correctly. diff --git a/gas/config/tc-h8500.c b/gas/config/tc-h8500.c index f58163f6351..021043603f3 100644 --- a/gas/config/tc-h8500.c +++ b/gas/config/tc-h8500.c @@ -421,6 +421,7 @@ parse_reglist (src, op) op->exp.X_op_symbol = 0; op->exp.X_add_number = mask; op->exp.X_op = O_constant; + op->exp.X_unsigned = 1; op->type = IMM8; return idx; diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 665606c9dae..f48a352c100 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -233,8 +233,8 @@ const pseudo_typeS {"LONG", pa_cons, 4}, {"lsym", pa_lsym, 0}, {"LSYM", pa_lsym, 0}, - {"octa", pa_big_cons, 16}, - {"OCTA", pa_big_cons, 16}, + {"octa", pa_cons, 16}, + {"OCTA", pa_cons, 16}, {"org", pa_origin, 0}, {"ORG", pa_origin, 0}, {"origin", pa_origin, 0}, @@ -245,8 +245,8 @@ const pseudo_typeS {"PROC", pa_proc, 0}, {"procend", pa_procend, 0}, {"PROCEND", pa_procend, 0}, - {"quad", pa_big_cons, 8}, - {"QUAD", pa_big_cons, 8}, + {"quad", pa_cons, 8}, + {"QUAD", pa_cons, 8}, {"reg", pa_equ, 1}, /* very similar to .equ */ {"REG", pa_equ, 1}, /* very similar to .equ */ {"short", pa_cons, 2}, @@ -732,7 +732,7 @@ md_begin () { const char *name = pa_opcodes[i].name; retval = hash_insert (op_hash, name, &pa_opcodes[i]); - if (retval != NULL && *retval != '\0') + if (retval != NULL) { as_fatal ("Internal error: can't hash `%s': %s\n", pa_opcodes[i].name, retval); @@ -4291,13 +4291,13 @@ s_seg () if (strncmp (input_line_pointer, "\"text\"", 6) == 0) { input_line_pointer += 6; - s_text (); + s_text (0); return; } if (strncmp (input_line_pointer, "\"data\"", 6) == 0) { input_line_pointer += 6; - s_data (); + s_data (0); return; } if (strncmp (input_line_pointer, "\"data1\"", 7) == 0) @@ -4317,22 +4317,14 @@ s_private () register int temp; temp = get_absolute_expression (); -#ifdef OBJ_SOM - subseg_new (SEG_DATA, (subsegT) temp); -#else - subseg_new (".data", (subsegT) temp); -#endif + subseg_set (data_section, (subsegT) temp); demand_empty_rest_of_line (); } void s_data1 () { -#ifdef OBJ_SOM - subseg_new (SEG_DATA, 1); -#else - subseg_new (".data", 1); -#endif + subseg_set (data_section, 1); demand_empty_rest_of_line (); return; } @@ -4498,7 +4490,7 @@ pa_build_unwind_subspace (call_info) save_seg = now_seg; save_subseg = now_subseg; - subseg_new ((char *) seg->name, subseg); + subseg_set (seg, subseg); unwindP = (char *) &call_info->ci_unwind; p = frag_more (4); @@ -4567,7 +4559,7 @@ pa_build_unwind_subspace (call_info) } } - subseg_new ((char *) save_seg->name, save_subseg); + subseg_set (save_seg, save_subseg); } #else @@ -4625,7 +4617,7 @@ pa_build_unwind_subspace (call_info) save_seg = now_seg; save_subseg = now_subseg; - subseg_new (seg, subseg); + subseg_set (seg, subseg); unwindP = (char *) &call_info->ci_unwind; p = frag_more (4); @@ -4710,7 +4702,7 @@ pa_build_unwind_subspace (call_info) } } - subseg_new (save_seg, save_subseg); + subseg_set (save_seg, save_subseg); } @@ -4834,13 +4826,8 @@ pa_code () } SPACE_DEFINED (sdchain) = 1; -#ifdef OBJ_SOM - subseg_new (SEG_TEXT, SUBSEG_CODE); -#else - - subseg_new (".text", SUBSEG_CODE); -#endif + subseg_set (text_section, SUBSEG_CODE); demand_empty_rest_of_line (); return; @@ -5210,7 +5197,7 @@ void seg, SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD); - subseg_new(save_seg->name, save_subseg); + subseg_set(save_seg, save_subseg); } #endif @@ -5520,7 +5507,7 @@ pa_leave () void pa_origin () { - s_org (); /* ORG actually allows another argument + s_org (0); /* ORG actually allows another argument (the fill value) but maybe this is OK? */ pa_undefine_label (); return; @@ -5787,11 +5774,7 @@ pa_parse_space_stmt (space_name, create_flag) void pa_align_subseg (seg, subseg) -#ifdef OBJ_SOM segT seg; -#else - asection *seg; -#endif subsegT subseg; { subspace_dict_chainS *now_subspace; @@ -5841,22 +5824,12 @@ pa_space () current_space = sd_chain; SPACE_DEFINED (current_space) = 1; current_space->sd_defined = 1; -#ifdef OBJ_SOM - if (now_seg != SEG_TEXT) /* no need to align if we are already there */ -#else if (now_seg != text_section) /* no need to align if we are already there */ -#endif pa_align_subseg (now_seg, now_subseg); -#ifdef OBJ_SOM - subseg_new (SEG_TEXT, sd_chain->sd_last_subseg); - current_subspace = pa_subsegment_to_subspace (SEG_TEXT, - sd_chain->sd_last_subseg); -#else - subseg_new ((char *) text_section->name, sd_chain->sd_last_subseg); + subseg_set (text_section, sd_chain->sd_last_subseg); current_subspace = pa_subsegment_to_subspace (text_section, sd_chain->sd_last_subseg); -#endif demand_empty_rest_of_line (); return; } @@ -5872,21 +5845,11 @@ pa_space () current_space = sd_chain; SPACE_DEFINED (current_space) = 1; current_space->sd_defined = 1; -#ifdef OBJ_SOM - if (now_seg != SEG_DATA) /* no need to align if we are already there */ -#else if (now_seg != data_section) /* no need to align if we are already there */ -#endif pa_align_subseg (now_seg, now_subseg); -#ifdef OBJ_SOM - subseg_new (SEG_DATA, sd_chain->sd_last_subseg); - current_subspace = pa_subsegment_to_subspace (SEG_DATA, - sd_chain->sd_last_subseg); -#else - subseg_new ((char *) data_section->name, sd_chain->sd_last_subseg); + subseg_set (data_section, sd_chain->sd_last_subseg); current_subspace = pa_subsegment_to_subspace (data_section, sd_chain->sd_last_subseg); -#endif demand_empty_rest_of_line (); return; } @@ -5903,19 +5866,22 @@ pa_space () current_space = sd_chain; SPACE_DEFINED (current_space) = 1; current_space->sd_defined = 1; + #ifdef OBJ_SOM - if (now_seg != SEG_GDB) /* no need to align if we are already there */ + if (now_seg != SEG_GDB) /* no need to align if we are already there */ + pa_align_subseg (now_seg, now_subseg); - subseg_new (SEG_GDB, sd_chain->sd_last_subseg); + subseg_set (SEG_GDB, sd_chain->sd_last_subseg); current_subspace = pa_subsegment_to_subspace (SEG_GDB, sd_chain->sd_last_subseg); #else { - asection *gdb_section - = bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME); - if (now_seg != gdb_section) /* no need to align if we are already there */ + segT gdb_section; + /* no need to align if we are already there */ + if (strcmp (segment_name (now_seg), GDB_DEBUG_SPACE_NAME) != 0) pa_align_subseg (now_seg, now_subseg); - subseg_new ((char *) gdb_section->name, sd_chain->sd_last_subseg); + gdb_section = subseg_new (GDB_DEBUG_SPACE_NAME, + sd_chain->sd_last_subseg); current_subspace = pa_subsegment_to_subspace (gdb_section, sd_chain->sd_last_subseg); } @@ -5935,11 +5901,7 @@ pa_space () current_space->sd_defined = 1; if (now_seg != sd_chain->sd_seg) /* don't align if we're already there */ pa_align_subseg (now_seg, now_subseg); -#ifdef OBJ_SOM - subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg); -#else - subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg); -#endif + subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg); current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg, sd_chain->sd_last_subseg); demand_empty_rest_of_line (); @@ -5961,11 +5923,7 @@ pa_space () current_space->sd_defined = 1; if (now_seg != sd_chain->sd_seg) /* don't align if we're already there */ pa_align_subseg (now_seg, now_subseg); -#ifdef OBJ_SOM - subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg); -#else - subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg); -#endif + subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg); current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg, sd_chain->sd_last_subseg); demand_empty_rest_of_line (); @@ -6068,7 +6026,7 @@ pa_subspace () if (ssd->ssd_defined) { #ifdef OBJ_SOM - subseg_new (now_seg, ssd->ssd_subseg); + subseg_set (now_seg, ssd->ssd_subseg); #else /* subseg_new(now_seg->name,ssd->ssd_subseg); */ subseg_new ((char *) ssd->ssd_seg->name, ssd->ssd_subseg); @@ -6202,11 +6160,7 @@ pa_subspace () SUBSPACE_SUBSPACE_START (current_subspace) = pa_subspace_start (space, quadrant); demand_empty_rest_of_line (); -#ifdef OBJ_SOM - subseg_new (current_subspace->ssd_seg, current_subspace->ssd_subseg); -#else - subseg_new ((char *) current_subspace->ssd_seg->name, current_subspace->ssd_subseg); -#endif + subseg_set (current_subspace->ssd_seg, current_subspace->ssd_subseg); } return; } @@ -6887,7 +6841,7 @@ pa_cons (nbytes) void pa_data () { - s_data (); + s_data (0); pa_undefine_label (); } @@ -6912,7 +6866,7 @@ pa_float_cons (float_type) void pa_fill () { - s_fill (); + s_fill (0); pa_undefine_label (); } @@ -6929,22 +6883,14 @@ pa_lcomm (needs_align) void pa_lsym () { - s_lsym (); - pa_undefine_label (); -} - -void -pa_big_cons (nbytes) - register int nbytes; -{ - big_cons (nbytes); + s_lsym (0); pa_undefine_label (); } void pa_text () { - s_text (); + s_text (0); pa_undefine_label (); } @@ -7043,7 +6989,7 @@ bfd * abfd; /* now, switch back to the original segment */ - subseg_new(save_seg->name, save_subseg); + subseg_set(save_seg, save_subseg); return; } @@ -7073,6 +7019,6 @@ hppa_tc_make_symextn_section() bfd_set_section_size (stdoutput, symextn_sec, size); /* now, switch back to the original segment */ - subseg_new(save_seg->name, save_subseg); + subseg_set(save_seg, save_subseg); } } diff --git a/gas/config/tc-i960.c b/gas/config/tc-i960.c index be54da49bce..4c045be4b54 100644 --- a/gas/config/tc-i960.c +++ b/gas/config/tc-i960.c @@ -201,7 +201,7 @@ const pseudo_typeS md_pseudo_table[] = {"sysproc", parse_po, S_SYSPROC}, {"word", cons, 4}, - {"quad", big_cons, 16}, + {"quad", cons, 16}, {0, 0, 0} }; @@ -508,41 +508,31 @@ md_begin () { int i; /* Loop counter */ const struct i960_opcode *oP; /* Pointer into opcode table */ - char *retval; /* Value returned by hash functions */ + const char *retval; /* Value returned by hash functions */ if (((op_hash = hash_new ()) == 0) || ((reg_hash = hash_new ()) == 0) || ((areg_hash = hash_new ()) == 0)) - { - as_fatal ("virtual memory exceeded"); - } + as_fatal ("virtual memory exceeded"); /* For some reason, the base assembler uses an empty string for "no error message", instead of a NULL pointer. */ retval = ""; - for (oP = i960_opcodes; oP->name && !*retval; oP++) - { - retval = hash_insert (op_hash, oP->name, oP); - } + for (oP = i960_opcodes; oP->name && !retval; oP++) + retval = hash_insert (op_hash, oP->name, (PTR) oP); - for (i = 0; regnames[i].reg_name && !*retval; i++) - { - retval = hash_insert (reg_hash, regnames[i].reg_name, - ®names[i].reg_num); - } + for (i = 0; regnames[i].reg_name && !retval; i++) + retval = hash_insert (reg_hash, regnames[i].reg_name, + ®names[i].reg_num); - for (i = 0; aregs[i].areg_name && !*retval; i++) - { - retval = hash_insert (areg_hash, aregs[i].areg_name, - &aregs[i].areg_num); - } + for (i = 0; aregs[i].areg_name && !retval; i++) + retval = hash_insert (areg_hash, aregs[i].areg_name, + &aregs[i].areg_num); - if (*retval) - { - as_fatal ("Hashing returned \"%s\".", retval); - } -} /* md_begin() */ + if (retval) + as_fatal ("Hashing returned \"%s\".", retval); +} /***************************************************************************** * md_end: One-time final cleanup @@ -577,7 +567,6 @@ md_assemble (textP) char *args[4]; int n_ops; /* Number of instruction operands */ - int callx; /* Pointer to instruction description */ struct i960_opcode *oP; /* TRUE iff opcode mnemonic included branch-prediction @@ -896,7 +885,7 @@ md_number_to_field (instrP, val, bfixP) if (((val < 0) && (sign != -1)) || ((val > 0) && (sign != 0))) { - as_bad ("Fixup of %d too large for field width of %d", + as_bad ("Fixup of %ld too large for field width of %d", val, numbits); } else @@ -964,14 +953,14 @@ md_parse_option (argP, cntP, vecP) }; static struct tabentry arch_tab[] = { - "KA", ARCH_KA, - "KB", ARCH_KB, - "SA", ARCH_KA, /* Synonym for KA */ - "SB", ARCH_KB, /* Synonym for KB */ - "KC", ARCH_MC, /* Synonym for MC */ - "MC", ARCH_MC, - "CA", ARCH_CA, - NULL, 0 + { "KA", ARCH_KA }, + { "KB", ARCH_KB }, + { "SA", ARCH_KA }, /* Synonym for KA */ + { "SB", ARCH_KB }, /* Synonym for KB */ + { "KC", ARCH_MC }, /* Synonym for MC */ + { "MC", ARCH_MC }, + { "CA", ARCH_CA }, + { NULL, 0 } }; struct tabentry *tp; if (!strcmp (*argP, "linkrelax")) @@ -2220,7 +2209,7 @@ parse_po (po_num) /* Advance input pointer to end of line. */ p = input_line_pointer; - while (!is_end_of_line[*input_line_pointer]) + while (!is_end_of_line[(unsigned char) *input_line_pointer]) { input_line_pointer++; } @@ -2458,22 +2447,22 @@ struct coj[] = { /* COBR OPCODE: */ - CHKBIT, BNO, /* 0x30 - bbc */ - CMPO, BG, /* 0x31 - cmpobg */ - CMPO, BE, /* 0x32 - cmpobe */ - CMPO, BGE, /* 0x33 - cmpobge */ - CMPO, BL, /* 0x34 - cmpobl */ - CMPO, BNE, /* 0x35 - cmpobne */ - CMPO, BLE, /* 0x36 - cmpoble */ - CHKBIT, BO, /* 0x37 - bbs */ - CMPI, BNO, /* 0x38 - cmpibno */ - CMPI, BG, /* 0x39 - cmpibg */ - CMPI, BE, /* 0x3a - cmpibe */ - CMPI, BGE, /* 0x3b - cmpibge */ - CMPI, BL, /* 0x3c - cmpibl */ - CMPI, BNE, /* 0x3d - cmpibne */ - CMPI, BLE, /* 0x3e - cmpible */ - CMPI, BO, /* 0x3f - cmpibo */ + { CHKBIT, BNO }, /* 0x30 - bbc */ + { CMPO, BG }, /* 0x31 - cmpobg */ + { CMPO, BE }, /* 0x32 - cmpobe */ + { CMPO, BGE }, /* 0x33 - cmpobge */ + { CMPO, BL }, /* 0x34 - cmpobl */ + { CMPO, BNE }, /* 0x35 - cmpobne */ + { CMPO, BLE }, /* 0x36 - cmpoble */ + { CHKBIT, BO }, /* 0x37 - bbs */ + { CMPI, BNO }, /* 0x38 - cmpibno */ + { CMPI, BG }, /* 0x39 - cmpibg */ + { CMPI, BE }, /* 0x3a - cmpibe */ + { CMPI, BGE }, /* 0x3b - cmpibge */ + { CMPI, BL }, /* 0x3c - cmpibl */ + { CMPI, BNE }, /* 0x3d - cmpibne */ + { CMPI, BLE }, /* 0x3e - cmpible */ + { CMPI, BO }, /* 0x3f - cmpibo */ }; static @@ -3174,10 +3163,6 @@ 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; diff --git a/gas/read.c b/gas/read.c index 762d3d8fb95..f741f465d74 100644 --- a/gas/read.c +++ b/gas/read.c @@ -133,12 +133,6 @@ char is_end_of_line[256] = static char *buffer; /* 1st char of each buffer of lines is here. */ static char *buffer_limit; /*->1 + last char in buffer. */ -static char *bignum_low; /* Lowest char of bignum. */ -static char *bignum_limit; /* 1st illegal address of bignum. */ -static char *bignum_high; /* Highest char of bignum. */ -/* May point to (bignum_start-1). */ -/* Never >= bignum_limit. */ - int target_big_endian; static char *old_buffer; /* JF a hack */ @@ -161,10 +155,7 @@ static char *demand_copy_string PARAMS ((int *lenP)); int is_it_end_of_statement PARAMS ((void)); static segT get_segmented_expression PARAMS ((expressionS *expP)); static segT get_known_segmented_expression PARAMS ((expressionS * expP)); -static void grow_bignum PARAMS ((void)); static void pobegin PARAMS ((void)); - -extern int listing; void @@ -180,10 +171,6 @@ read_begin () obstack_begin (¬es, 5090); obstack_begin (&cond_obstack, 990); -#define BIGNUM_BEGIN_SIZE (16) - bignum_low = xmalloc ((long) BIGNUM_BEGIN_SIZE); - bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE; - /* Use machine dependent syntax */ for (p = line_separator_chars; *p; p++) is_end_of_line[(unsigned char) *p] = 1; @@ -241,11 +228,11 @@ static const pseudo_typeS potable[] = {"long", cons, 4}, {"lsym", s_lsym, 0}, {"nolist", listing_list, 0}, /* Turn listing off */ - {"octa", big_cons, 16}, + {"octa", cons, 16}, {"org", s_org, 0}, {"psize", listing_psize, 0}, /* set paper size */ /* print */ - {"quad", big_cons, 8}, + {"quad", cons, 8}, {"sbttl", listing_title, 1}, /* Subtitle of listing */ /* scl */ /* sect */ @@ -281,7 +268,7 @@ pobegin () for (pop = md_pseudo_table; pop->poc_name; pop++) { errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); - if (errtxt && *errtxt) + if (errtxt) { as_fatal ("error constructing md pseudo-op table"); } /* on error */ @@ -291,7 +278,7 @@ pobegin () for (pop = obj_pseudo_table; pop->poc_name; pop++) { errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); - if (errtxt && *errtxt) + if (errtxt) { if (!strcmp (errtxt, "exists")) { @@ -311,7 +298,7 @@ pobegin () for (pop = potable; pop->poc_name; pop++) { errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop); - if (errtxt && *errtxt) + if (errtxt) { if (!strcmp (errtxt, "exists")) { @@ -1529,7 +1516,7 @@ pseudo_set (symbolP) * * CONStruct more frag of .bytes, or .words etc. * Should need_pass_2 be 1 then emit no frag(s). - * This understands EXPRESSIONS, as opposed to big_cons(). + * This understands EXPRESSIONS. * * Bug (?) * @@ -1608,6 +1595,7 @@ emit_expr (exp, nbytes) { operatorT op; register char *p; + valueT extra_digit = 0; /* Don't do anything if we are going to make another pass. */ if (need_pass_2) @@ -1615,16 +1603,46 @@ emit_expr (exp, nbytes) op = exp->X_op; + /* Handle a negative bignum. */ + if (op == O_uminus + && exp->X_add_number == 0 + && exp->X_add_symbol->sy_value.X_op == O_big + && exp->X_add_symbol->sy_value.X_add_number > 0) + { + int i; + unsigned long carry; + + exp = &exp->X_add_symbol->sy_value; + + /* Negate the bignum: one's complement each digit and add 1. */ + carry = 1; + for (i = 0; i < exp->X_add_number; i++) + { + unsigned long next; + + next = (((~ (generic_bignum[i] & LITTLENUM_MASK)) + & LITTLENUM_MASK) + + carry); + generic_bignum[i] = next & LITTLENUM_MASK; + carry = next >> LITTLENUM_NUMBER_OF_BITS; + } + + /* We can ignore any carry out, because it will be handled by + extra_digit if it is needed. */ + + extra_digit = (valueT) -1; + op = O_big; + } + if (op == O_absent || op == O_illegal) { as_warn ("zero assumed for missing expression"); exp->X_add_number = 0; op = O_constant; } - else if (op == O_big) + else if (op == O_big && exp->X_add_number <= 0) { - as_bad ("%s number invalid; zero assumed", - exp->X_add_number > 0 ? "bignum" : "floating point"); + as_bad ("floating point number invalid; zero assumed"); exp->X_add_number = 0; op = O_constant; } @@ -1658,6 +1676,28 @@ emit_expr (exp, nbytes) } #endif + /* If we have an integer, but the number of bytes is too large to + pass to md_number_to_chars, handle it as a bignum. */ + if (op == O_constant && nbytes > sizeof (valueT)) + { + valueT val; + int gencnt; + + if (! exp->X_unsigned && exp->X_add_number < 0) + extra_digit = (valueT) -1; + val = (valueT) exp->X_add_number; + gencnt = 0; + do + { + generic_bignum[gencnt] = val & LITTLENUM_MASK; + val >>= LITTLENUM_NUMBER_OF_BITS; + ++gencnt; + } + while (val != 0); + op = exp->X_op = O_big; + exp->X_add_number = gencnt; + } + if (op == O_constant) { register long get; @@ -1688,6 +1728,58 @@ emit_expr (exp, nbytes) /* put bytes in right order. */ md_number_to_chars (p, (valueT) use, (int) nbytes); } + else if (op == O_big) + { + int size; + LITTLENUM_TYPE *nums; + + know (nbytes % CHARS_PER_LITTLENUM == 0); + + size = exp->X_add_number * CHARS_PER_LITTLENUM; + if (nbytes < size) + { + as_warn ("Bignum truncated to %d bytes", nbytes); + size = nbytes; + } + + if (target_big_endian) + { + while (nbytes > size) + { + md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); + nbytes -= CHARS_PER_LITTLENUM; + p += CHARS_PER_LITTLENUM; + } + + nums = generic_bignum + size / CHARS_PER_LITTLENUM; + while (size > 0) + { + --nums; + md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); + size -= CHARS_PER_LITTLENUM; + p += CHARS_PER_LITTLENUM; + } + } + else + { + nums = generic_bignum; + while (size > 0) + { + md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); + ++nums; + size -= CHARS_PER_LITTLENUM; + p += CHARS_PER_LITTLENUM; + nbytes -= CHARS_PER_LITTLENUM; + } + + while (nbytes > 0) + { + md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); + nbytes -= CHARS_PER_LITTLENUM; + p += CHARS_PER_LITTLENUM; + } + } + } else { md_number_to_chars (p, (valueT) 0, (int) nbytes); @@ -1725,7 +1817,7 @@ emit_expr (exp, nbytes) #define TC_CONS_RELOC 0 #endif #endif - fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes, exp, 0, + fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0, TC_CONS_RELOC); #endif /* TC_CONS_FIX_NEW */ #endif /* BFD_ASSEMBLER */ @@ -1808,7 +1900,7 @@ parse_bitfield_cons (exp, nbytes) if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes)) { - as_warn ("field width %d too big to fit in %d bytes: truncated to %d bits", + as_warn ("field width %lu too big to fit in %d bytes: truncated to %d bits", width, nbytes, (BITS_PER_CHAR * nbytes)); width = BITS_PER_CHAR * nbytes; } /* too big */ @@ -1851,6 +1943,7 @@ parse_bitfield_cons (exp, nbytes) exp->X_add_number = value; exp->X_op = O_constant; + exp->X_unsigned = 1; } /* if looks like a bitfield */ } /* parse_bitfield_cons() */ @@ -1952,164 +2045,6 @@ parse_repeat_cons (exp, nbytes) #endif /* REPEAT_CONS_EXPRESSIONS */ -/* - * big_cons() - * - * CONStruct more frag(s) of .quads, or .octa etc. - * Makes 0 or more new frags. - * If need_pass_2 == 1, generate no frag. - * This understands only bignums, not expressions. Cons() understands - * expressions. - * - * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal). - * - * This creates objects with struct obstack_control objs, destroying - * any context objs held about a partially completed object. Beware! - * - * - * I think it sucks to have 2 different types of integers, with 2 - * routines to read them, store them etc. - * It would be nicer to permit bignums in expressions and only - * complain if the result overflowed. However, due to "efficiency"... - */ -/* Worker to do .quad etc statements. Clobbers input_line_pointer, checks - end-of-line. 8=.quad 16=.octa ... */ - -void -big_cons (nbytes) - register int nbytes; -{ - register char c; /* input_line_pointer->c. */ - register int radix; - register long length; /* Number of chars in an object. */ - register int digit; /* Value of 1 digit. */ - register int carry; /* For multi-precision arithmetic. */ - register int work; /* For multi-precision arithmetic. */ - register char *p; /* For multi-precision arithmetic. */ - - extern const char hex_value[]; /* In hex_value.c. */ - - /* - * The following awkward logic is to parse ZERO or more strings, - * comma seperated. Recall an expression includes its leading & - * trailing blanks. We fake a leading ',' if there is (supposed to - * be) a 1st expression, and keep demanding 1 expression for each ','. - */ - if (is_it_end_of_statement ()) - { - c = 0; /* Skip loop. */ - } - else - { - c = ','; /* Do loop. */ - --input_line_pointer; - } - while (c == ',') - { - ++input_line_pointer; - SKIP_WHITESPACE (); - c = *input_line_pointer; - /* C contains 1st non-blank character of what we hope is a number. */ - if (c == '0') - { - c = *++input_line_pointer; - if (c == 'x' || c == 'X') - { - c = *++input_line_pointer; - radix = 16; - } - else - { - radix = 8; - } - } - else - { - radix = 10; - } - /* - * This feature (?) is here to stop people worrying about - * mysterious zero constants: which is what they get when - * they completely omit digits. - */ - if (hex_value[(unsigned char) c] >= radix) - { - as_bad ("Missing digits. 0 assumed."); - } - bignum_high = bignum_low - 1; /* Start constant with 0 chars. */ - for (; - (digit = hex_value[(unsigned char) c]) < radix; - c = *++input_line_pointer) - { - /* Multiply existing number by radix, then add digit. */ - carry = digit; - for (p = bignum_low; p <= bignum_high; p++) - { - work = (*p & MASK_CHAR) * radix + carry; - *p = work & MASK_CHAR; - carry = work >> BITS_PER_CHAR; - } - if (carry) - { - grow_bignum (); - *bignum_high = carry & MASK_CHAR; - know ((carry & ~MASK_CHAR) == 0); - } - } - length = bignum_high - bignum_low + 1; - if (length > nbytes) - { - as_warn ("Most significant bits truncated in integer constant."); - } - else - { - register long leading_zeroes; - - for (leading_zeroes = nbytes - length; - leading_zeroes; - leading_zeroes--) - { - grow_bignum (); - *bignum_high = 0; - } - } - if (!need_pass_2) - { - char *src = bignum_low; - p = frag_more (nbytes); - if (target_big_endian) - { - int i; - for (i = nbytes - 1; i >= 0; i--) - p[i] = *src++; - } - else - memcpy (p, bignum_low, (unsigned int) nbytes); - } - /* C contains character after number. */ - SKIP_WHITESPACE (); - c = *input_line_pointer; - /* C contains 1st non-blank character after number. */ - } - demand_empty_rest_of_line (); -} /* big_cons() */ - -/* Extend bignum by 1 char. */ -static void -grow_bignum () -{ - register unsigned long length; - - bignum_high++; - if (bignum_high >= bignum_limit) - { - length = bignum_limit - bignum_low; - bignum_low = xrealloc (bignum_low, length + length); - bignum_high = bignum_low + length; - bignum_limit = bignum_low + length + length; - } -} /* grow_bignum(); */ - /* * float_cons() * @@ -2162,7 +2097,7 @@ float_cons (float_type) err = md_atof (float_type, temp, &length); know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); know (length > 0); - if (err && *err) + if (err) { as_bad ("Bad floating literal: %s", err); ignore_rest_of_line (); @@ -2639,7 +2574,7 @@ s_ignore (arg) return; } /* s_ignore() */ - + /* * Handle .stabX directives, which used to be open-coded. * So much creeping featurism overloaded the semantics that we decided @@ -2655,34 +2590,6 @@ s_ignore (arg) * don't need and invent information they need that you didn't supply. */ -void -change_to_section (name, len, exp) - char *name; - unsigned int len; - unsigned int exp; -{ -#ifndef BFD_ASSEMBLER -#ifdef MANY_SEGMENTS - unsigned int i; - extern segment_info_type segment_info[]; - - /* Find out if we've already got a section of this name etc */ - for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0]; i++) - { - if (strncmp (segment_info[i].scnhdr.s_name, name, len) == 0) - { - subseg_set (i, exp); - return; - } - } - /* No section, add one */ - strncpy (segment_info[i].scnhdr.s_name, name, 8); - segment_info[i].scnhdr.s_flags = 0 /* STYP_NOLOAD */; - subseg_set (i, exp); -#endif -#endif -} - /* * Build a string dictionary entry for a .stabX symbol. * The symbol is added to the .str section. @@ -2690,73 +2597,60 @@ change_to_section (name, len, exp) #ifdef SEPARATE_STAB_SECTIONS -static unsigned int +unsigned int get_stab_string_offset (string, secname) - char *string, *secname; + const char *string; + const char *secname; { - segT save_seg; - segT seg; - subsegT save_subseg; unsigned int length; - unsigned int old_gdb_string_index; - char *clengthP; - int i; - char c; - /* @@FIXME -- there should be no static data here! - This also has the effect of making all stab string tables large enough - to contain all the contents written to any of them. This only matters - with the Solaris native compiler for the moment, but it should be fixed - anyways. */ - static unsigned int gdb_string_index = 0; - - old_gdb_string_index = 0; + unsigned int retval; + + retval = 0; length = strlen (string); - clengthP = (char *) &length; if (length > 0) { /* Ordinary case. */ + segT save_seg; + subsegT save_subseg; + char *newsecname; + segT seg; + int aligned; + char *p; + save_seg = now_seg; save_subseg = now_subseg; - /* Create the stabstr sections, if they are not already created. */ - { - char *newsecname = xmalloc (strlen (secname) + 4); - strcpy (newsecname, secname); - strcat (newsecname, "str"); + /* Create the stab string section. */ + newsecname = xmalloc ((unsigned long) (strlen (secname) + 4)); + strcpy (newsecname, secname); + strcat (newsecname, "str"); + + seg = subseg_new (newsecname, 0); + + retval = seg_info (seg)->stabu.stab_string_size; + if (retval > 0) + free (newsecname); + else + { + /* Make sure the first string is empty. */ + p = frag_more (1); + *p = 0; + retval = seg_info (seg)->stabu.stab_string_size = 1; #ifdef BFD_ASSEMBLER - seg = bfd_get_section_by_name (stdoutput, newsecname); - if (seg == 0) - { - seg = bfd_make_section_old_way (stdoutput, newsecname); - bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_ALLOC); - } + bfd_set_section_flags (stdoutput, seg, SEC_READONLY); #else - subseg_new (newsecname, 0); + free (newsecname); #endif -/* free (newsecname);*/ - } - subseg_set (seg, save_subseg); - old_gdb_string_index = gdb_string_index; - i = 0; - while ((c = *string++)) - { - i++; - gdb_string_index++; - FRAG_APPEND_1_CHAR (c); - } - { - FRAG_APPEND_1_CHAR ((char) 0); - i++; - gdb_string_index++; - } - while (i % 4 != 0) - { - FRAG_APPEND_1_CHAR ((char) 0); - i++; - gdb_string_index++; } + + p = frag_more (length + 1); + strcpy (p, string); + + seg_info (seg)->stabu.stab_string_size += length + 1; + subseg_set (save_seg, save_subseg); } - return old_gdb_string_index; + + return retval; } #endif /* SEPARATE_STAB_SECTIONS */ @@ -2769,227 +2663,187 @@ s_stab_generic (what, secname) int what; char *secname; { - extern int listing; - - symbolS *symbol; - char *string; - int saved_type = 0; - int length; - int goof = 0; long longint; - segT saved_seg = now_seg; - segT seg; - subsegT saved_subseg = now_subseg; - subsegT subseg; - valueT valu; -#ifdef SEPARATE_STAB_SECTIONS - int seg_is_new = 0; -#endif - - valu = ((char *) obstack_next_free (&frags)) - frag_now->fr_literal; - -#ifdef SEPARATE_STAB_SECTIONS -#ifdef BFD_ASSEMBLER - seg = bfd_get_section_by_name (stdoutput, secname); - if (seg == 0) + char *string; + int type; + int other; + int desc; + + /* The general format is: + .stabs "STRING",TYPE,OTHER,DESC,VALUE + .stabn TYPE,OTHER,DESC,VALUE + .stabd TYPE,OTHER,DESC + At this point input_line_pointer points after the pseudo-op and + any trailing whitespace. The argument what is one of 's', 'n' or + 'd' indicating which type of .stab this is. */ + + if (what != 's') + string = ""; + else { - seg = subseg_new (secname, 0); - bfd_set_section_flags (stdoutput, seg, - SEC_READONLY | SEC_ALLOC | SEC_RELOC); - subseg_set (saved_seg, subseg); - seg_is_new = 1; - } -#else - subseg_new (secname, 0); -#endif -#endif /* SEPARATE_STAB_SECTIONS */ + int length; - /* - * Enter with input_line_pointer pointing past .stabX and any following - * whitespace. - */ - if (what == 's') - { string = demand_copy_C_string (&length); SKIP_WHITESPACE (); if (*input_line_pointer == ',') input_line_pointer++; else { - as_bad ("I need a comma after symbol's name"); - goof = 1; + as_warn (".stabs: Missing comma"); + ignore_rest_of_line (); + return; } } - else - string = ""; - /* - * Input_line_pointer->after ','. String->symbol name. - */ - if (!goof) + if (get_absolute_expression_and_terminator (&longint) != ',') { -#ifdef MAKE_STAB_SYMBOL - MAKE_STAB_SYMBOL(symbol, string, secname); -#else - symbol = symbol_new (string, undefined_section, 0, (struct frag *) 0); -#endif - /* Make sure that the rest of this is going to work. */ - if (symbol == NULL) - as_fatal ("no stab symbol created"); - - switch (what) - { - case 'd': - S_SET_NAME (symbol, NULL); /* .stabd feature. */ -#ifdef STAB_SYMBOL_SET_VALUE - STAB_SYMBOL_SET_VALUE (symbol, valu); -#else - S_SET_VALUE (symbol, valu); -#endif -#if STAB_SYMBOL_SET_SEGMENT -#else - S_SET_SEGMENT (symbol, now_seg); -#endif - symbol->sy_frag = frag_now; - break; - - case 'n': - symbol->sy_frag = &zero_address_frag; - break; - - case 's': - symbol->sy_frag = &zero_address_frag; - break; - - default: - BAD_CASE (what); - break; - } - - if (get_absolute_expression_and_terminator (&longint) == ',') - { - saved_type = longint; - S_SET_TYPE (symbol, saved_type); - } - else - { - as_bad ("I want a comma after the n_type expression"); - goof = 1; - input_line_pointer--; /* Backup over a non-',' char. */ - } + as_warn (".stab%c: Missing comma", what); + ignore_rest_of_line (); + return; } + type = longint; - if (!goof) + if (get_absolute_expression_and_terminator (&longint) != ',') { - if (get_absolute_expression_and_terminator (&longint) == ',') - S_SET_OTHER (symbol, longint); - else - { - as_bad ("I want a comma after the n_other expression"); - goof = 1; - input_line_pointer--; /* Backup over a non-',' char. */ - } + as_warn (".stab%c: Missing comma", what); + ignore_rest_of_line (); + return; } + other = longint; - if (!goof) + desc = get_absolute_expression (); + if (what == 's' || what == 'n') { - S_SET_DESC (symbol, get_absolute_expression ()); - if (what == 's' || what == 'n') + if (*input_line_pointer != ',') { - if (*input_line_pointer != ',') - { - as_bad ("I want a comma after the n_desc expression"); - goof = 1; - } - else - { - input_line_pointer++; - } + as_warn (".stab%c: Missing comma", what); + ignore_rest_of_line (); + return; } + input_line_pointer++; + SKIP_WHITESPACE (); } - /* Line is messed up - ignore it and get out of here. */ - if (goof) - { - ignore_rest_of_line (); - subseg_set (saved_seg, saved_subseg); - return; - } - - subseg_set (seg, subseg); - -#if 0 /* needed for elf only? */ - if (seg_is_new) - /* allocate and discard -- filled in later */ - (void) frag_more (12); -#endif + /* We have not gathered the type, other, and desc information. For + .stabs or .stabn, input_line_pointer is now pointing at the + value. */ #ifdef SEPARATE_STAB_SECTIONS + /* Output the stab information in a separate section. This is used + at least for COFF and ELF. */ { - char *toP; - - subseg_new (secname, 0); - toP = frag_more (8); - /* the string index portion of the stab */ - md_number_to_chars (toP, (valueT) S_GET_OFFSET_2(symbol), 4); - md_number_to_chars (toP + 4, (valueT) S_GET_TYPE(symbol), 1); - md_number_to_chars (toP + 5, (valueT) S_GET_OTHER(symbol), 1); - md_number_to_chars (toP + 6, (valueT) S_GET_DESC(symbol), 2); - } + segT saved_seg = now_seg; + subsegT saved_subseg = now_subseg; + fragS *saved_frag = frag_now; + valueT dot; + segT seg; + unsigned int stroff; + char *p; + + dot = frag_now_fix (); + + seg = subseg_new (secname, 0); + + if (! seg_info (seg)->hadone) + { +#ifdef BFD_ASSEMBLER + bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_RELOC); +#endif +#ifdef INIT_STAB_SECTION + INIT_STAB_SECTION (seg); #endif + seg_info (seg)->hadone = 1; + } -#ifdef SEPARATE_STAB_SECTIONS - if (what == 's' || what == 'n') - { - cons (4); - input_line_pointer--; - } - else - { - char *p = frag_more (4); - md_number_to_chars (p, 0, 4); - } - subseg_set (saved_seg, subseg); + stroff = get_stab_string_offset (string, secname); + + /* At least for now, stabs in a special stab section are always + output as 12 byte blocks of information. */ + p = frag_more (8); + md_number_to_chars (p, (valueT) stroff, 4); + md_number_to_chars (p + 4, (valueT) type, 1); + md_number_to_chars (p + 5, (valueT) other, 1); + md_number_to_chars (p + 6, (valueT) desc, 2); + + if (what == 's' || what == 'n') + { + /* Pick up the value from the input line. */ + cons (4); + input_line_pointer--; + } + else + { + const char *fake; + symbolS *symbol; + expressionS exp; + + /* Arrange for a value representing the current location. */ +#ifdef DOT_LABEL_PREFIX + fake = ".L0\001"; #else - if (what == 's' || what == 'n') - { - pseudo_set (symbol); - S_SET_TYPE (symbol, saved_type); - } + fake = "L0\001"; #endif + symbol = symbol_new (fake, saved_seg, dot, saved_frag); -#if 0 /* for elf only? */ - if (what == 's' && S_GET_TYPE (symbol) == N_SO) - { - fragS *fragp = seg_info (seg)->frchainP->frch_root; - while (fragp - && fragp->fr_address + fragp->fr_fix < 12) - fragp = fragp->fr_next; - assert (fragp != 0); - assert (fragp->fr_type == rs_fill); - assert (fragp->fr_address == 0 && fragp->fr_fix >= 12); - md_number_to_chars (fragp->fr_literal, (valueT) symbol->sy_name_offset, - 4); - } + exp.X_op = O_symbol; + exp.X_add_symbol = symbol; + exp.X_add_number = 0; + + emit_expr (&exp, 4); + } + +#ifdef OBJ_PROCESS_STAB + OBJ_PROCESS_STAB (seg, string, stroff, type, other, desc); #endif -#ifndef NO_LISTING - if (listing) - switch (S_GET_TYPE (symbol)) + subseg_set (saved_seg, saved_subseg); + } +#else /* ! SEPARATE_STAB_SECTIONS */ +#ifdef OBJ_PROCESS_STAB + OBJ_PROCESS_STAB (what, string, type, other, desc); +#else + /* Put the stab information in the symbol table. */ + { + symbolS *symbol; + + symbol = symbol_new (string, undefined_section, 0, + (struct frag *) NULL); + if (what == 's' || what == 'n') + { + /* Pick up the value from the input line. */ + symbol->sy_frag = &zero_address_frag; + pseudo_set (symbol); + } + else { - case N_SLINE: - listing_source_line ((unsigned int) S_GET_DESC (symbol)); - break; - case N_SO: - case N_SOL: - listing_source_file (string); - break; + /* .stabd sets the name to NULL. Why? */ + S_SET_NAME (symbol, NULL); + symbol->sy_frag = frag_now; + S_SET_VALUE (symbol, (valueT) frag_now_fix ()); } -#endif /* !NO_LISTING */ -#ifdef SEPARATE_STAB_SECTIONS - subseg_set (saved_seg, saved_subseg); -#endif + S_SET_TYPE (symbol, type); + S_SET_OTHER (symbol, other); + S_SET_DESC (symbol, desc); + } +#endif /* ! OBJ_PROCESS_STAB */ +#endif /* ! SEPARATE_STAB_SECTIONS */ + +#ifndef NO_LISTING + if (listing) + { + switch (type) + { + case N_SLINE: + listing_source_line ((unsigned int) desc); + break; + case N_SO: + case N_SOL: + listing_source_file (string); + break; + } + } +#endif /* ! NO_LISTING */ demand_empty_rest_of_line (); } diff --git a/gas/write.c b/gas/write.c index 913146e798f..ea0349cb31a 100644 --- a/gas/write.c +++ b/gas/write.c @@ -47,9 +47,12 @@ struct frag *data_last_frag; /* Last frag in segment. */ static struct frag *bss_last_frag; /* Last frag in segment. */ #endif +#if ! defined (BFD_ASSEMBLER) && ! defined (BFD) static object_headers headers; -long string_byte_count; static char *the_object_file; +#endif + +long string_byte_count; char *next_object_file_charP; /* Tracks object file bytes. */ #ifndef OBJ_VMS @@ -69,9 +72,10 @@ static fixS *fix_new_internal PARAMS ((fragS *, int where, int size, offsetT offset, int pcrel, int r_type)); #endif +#if defined (BFD_ASSEMBLER) || !defined (BFD) static long fixup_segment PARAMS ((fixS * fixP, segT this_segment_type)); +#endif static relax_addressT relax_align PARAMS ((relax_addressT addr, int align)); -void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type)); /* * fix_new() @@ -234,7 +238,7 @@ append (charPP, fromP, length) if (length == 0) return; - memcpy (*charPP, fromP, (int) length); + memcpy (*charPP, fromP, length); *charPP += length; } @@ -318,6 +322,8 @@ remove_subsegs (head, seg, root, last) #endif /* BFD */ +#if defined (BFD_ASSEMBLER) || !defined (BFD) + #ifdef BFD_ASSEMBLER static void cvt_frag_to_fill (sec, fragP) @@ -391,6 +397,8 @@ cvt_frag_to_fill (headers, fragP) } } +#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */ + #ifdef BFD_ASSEMBLER static void relax_and_size_seg (abfd, sec, xxx) @@ -514,18 +522,27 @@ adjust_reloc_syms (abfd, sec, xxx) if (symsec == &bfd_und_section || symsec == &bfd_abs_section || bfd_is_com_section (symsec)) - continue; + { + fixp->fx_addsy->sy_used_in_reloc = 1; + continue; + } /* Since we're reducing to section symbols, don't attempt to reduce anything that's already using one. */ if (sym->bsym == symsec->symbol) - continue; + { + fixp->fx_addsy->sy_used_in_reloc = 1; + continue; + } /* Is there some other reason we can't adjust this one? (E.g., call/bal links in i960-bout symbols.) */ #ifdef obj_fix_adjustable if (! obj_fix_adjustable (fixp)) - continue; + { + fixp->fx_addsy->sy_used_in_reloc = 1; + continue; + } #endif /* If the section symbol isn't going to be output, the relocs at least should still work. If not, figure out what to do @@ -545,6 +562,7 @@ adjust_reloc_syms (abfd, sec, xxx) } symseginfo->sym = fixp->fx_addsy; } + fixp->fx_addsy->sy_used_in_reloc = 1; } dump_section_relocs (abfd, sec, stderr); @@ -557,7 +575,8 @@ write_relocs (abfd, sec, xxx) char *xxx; { segment_info_type *seginfo = seg_info (sec); - int i, n; + int i; + unsigned int n; arelent **relocs; fixS *fixp; @@ -582,7 +601,6 @@ write_relocs (abfd, sec, xxx) for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next) { arelent *reloc; - extern arelent *tc_gen_reloc (); char *data; bfd_reloc_status_type s; @@ -628,7 +646,6 @@ write_relocs (abfd, sec, xxx) for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next) { arelent **reloc; - extern arelent **tc_gen_reloc (); char *data; bfd_reloc_status_type s; int j; @@ -671,7 +688,8 @@ write_relocs (abfd, sec, xxx) bfd_set_reloc (stdoutput, sec, relocs, n); else bfd_set_section_flags (abfd, sec, - bfd_get_section_flags (abfd, sec) & ~SEC_RELOC); + (bfd_get_section_flags (abfd, sec) + & (flagword) ~SEC_RELOC)); #ifdef DEBUG2 { int i; @@ -697,39 +715,39 @@ write_contents (abfd, sec, xxx) { segment_info_type *seginfo = seg_info (sec); unsigned long offset = 0; - fragS *frags; + fragS *f; /* Write out the frags. */ if (! (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS)) return; - for (frags = seginfo->frchainP->frch_root; - frags; - frags = frags->fr_next) + for (f = seginfo->frchainP->frch_root; + f; + f = f->fr_next) { int x; unsigned long fill_size; char *fill_literal; long count; - assert (frags->fr_type == rs_fill); - if (frags->fr_fix) + assert (f->fr_type == rs_fill); + if (f->fr_fix) { x = bfd_set_section_contents (stdoutput, sec, - frags->fr_literal, offset, - frags->fr_fix); + f->fr_literal, (file_ptr) offset, + (bfd_size_type) f->fr_fix); assert (x == true); - offset += frags->fr_fix; + offset += f->fr_fix; } - fill_literal = frags->fr_literal + frags->fr_fix; - fill_size = frags->fr_var; - count = frags->fr_offset; + fill_literal = f->fr_literal + f->fr_fix; + fill_size = f->fr_var; + count = f->fr_offset; assert (count >= 0); if (fill_size && count) while (count--) { x = bfd_set_section_contents (stdoutput, sec, - fill_literal, offset, + fill_literal, (file_ptr) offset, (bfd_size_type) fill_size); assert (x == true); offset += fill_size; @@ -738,7 +756,7 @@ write_contents (abfd, sec, xxx) } #endif -#if defined(BFD_ASSEMBLER) || !defined (BFD) +#if defined(BFD_ASSEMBLER) || (!defined (BFD) && !defined(OBJ_AOUT)) static void merge_data_into_text () { @@ -766,7 +784,7 @@ merge_data_into_text () data_fix_root = NULL; #endif } -#endif /* BFD_ASSEMBLER || ! BFD */ +#endif /* BFD_ASSEMBLER || (! BFD && ! OBJ_AOUT) */ #if !defined (BFD_ASSEMBLER) && !defined (BFD) static void @@ -923,11 +941,7 @@ write_object_file () #endif for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next) { -#ifdef BFD_ASSEMBLER subseg_set (frchainP->frch_seg, frchainP->frch_subseg); -#else - subseg_new (frchainP->frch_seg, frchainP->frch_subseg); -#endif frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE); /* frag_align will have left a new frag. Use this last frag for an empty ".fill". @@ -1259,7 +1273,8 @@ write_object_file () /* Set up symbol table, and write it out. */ if (symbol_rootP) { - int i = 0, n; + unsigned int i = 0; + unsigned int n; symbolS *symp; for (symp = symbol_rootP; symp; symp = symbol_next (symp)) @@ -1290,27 +1305,30 @@ write_object_file () symp->bsym->flags, segment_name (symp->bsym->section)); #endif - { -#ifdef obj_frob_symbol + if (! symp->sy_used_in_reloc) { - int punt = 0; - obj_frob_symbol (symp, punt); - if (punt) - goto punt_it; - } +#ifdef obj_frob_symbol + { + int punt = 0; + obj_frob_symbol (symp, punt); + if (punt) + goto punt_it; + } #endif #ifdef tc_frob_symbol - { - int punt = 0; - tc_frob_symbol (symp, punt); - if (punt) - goto punt_it; - } + { + int punt = 0; + tc_frob_symbol (symp, punt); + if (punt) + goto punt_it; + } #endif - } + } + /* If we don't want to keep this symbol, splice it out of the chain now. */ - if (S_IS_LOCAL (symp)) + if (! symp->sy_used_in_reloc + && S_IS_LOCAL (symp)) { symbolS *prev, *next; #if defined (obj_frob_symbol) || defined (tc_frob_symbol) @@ -1343,6 +1361,14 @@ write_object_file () continue; } + /* Make sure we really got a value for the symbol. */ + if (! symp->sy_resolved) + { + as_bad ("can't resolve value for symbol \"%s\"", + S_GET_NAME (symp)); + symp->sy_resolved = 1; + } + /* Set the value into the BFD symbol. Up til now the value has only been kept in the gas symbolS struct. */ symp->bsym->value = S_GET_VALUE (symp); @@ -1506,7 +1532,6 @@ relax_segment (segment_frag_root, segment) symbolS *symbolP; long target; long after; - long aim; was_address = fragP->fr_address; address = fragP->fr_address += stretch; @@ -1552,7 +1577,7 @@ relax_segment (segment_frag_root, segment) if (flagseen['K']) { char buf[50]; - sprint_value (buf, lie->addnum); + sprint_value (buf, (addressT) lie->addnum); as_warn (".word %s-%s+%s didn't fit", S_GET_NAME (lie->add), S_GET_NAME (lie->sub), @@ -1623,6 +1648,7 @@ relax_segment (segment_frag_root, segment) const relax_typeS *start_type; relax_substateT next_state; relax_substateT this_state; + long aim; this_state = fragP->fr_subtype; start_type = this_type = md_relax_table + this_state; @@ -1630,6 +1656,7 @@ relax_segment (segment_frag_root, segment) if (symbolP) { +#ifndef DIFF_EXPR_OK #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER) know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT (symbolP) == SEG_DATA) @@ -1637,6 +1664,7 @@ relax_segment (segment_frag_root, segment) || (S_GET_SEGMENT (symbolP) == SEG_TEXT)); #endif know (symbolP->sy_frag); +#endif know (!(S_GET_SEGMENT (symbolP) == absolute_section) || symbolP->sy_frag == &zero_address_frag); target += @@ -1733,6 +1761,8 @@ relax_segment (segment_frag_root, segment) */ } /* relax_segment() */ +#if defined (BFD_ASSEMBLER) || !defined (BFD) + /* fixup_segment() Go through all the fixS's in a segment and see which ones can be @@ -1806,6 +1836,7 @@ fixup_segment (fixP, this_segment_type) if (!add_symbolP) { /* Its just -sym */ + /* @@ Should try converting to pcrel ref to fixed addr. */ if (S_GET_SEGMENT (sub_symbolP) != absolute_section) as_bad ("Negative of non-absolute symbol %s", S_GET_NAME (sub_symbolP)); @@ -1843,6 +1874,19 @@ fixup_segment (fixP, this_segment_type) { add_number -= S_GET_VALUE (sub_symbolP); } +#ifdef DIFF_EXPR_OK + else if (!pcrel + && S_GET_SEGMENT (sub_symbolP) == this_segment_type) + { + /* Make it pc-relative. */ + add_number += (md_pcrel_from (fixP) + - S_GET_VALUE (sub_symbolP)); + pcrel = 1; + fixP->fx_pcrel = 1; + sub_symbolP = 0; + fixP->fx_subsy = 0; + } +#endif else { char buf[50]; @@ -1961,8 +2005,9 @@ fixup_segment (fixP, this_segment_type) if (!flagseen['J'] && size == 2 && add_number > 0x7fff) - as_bad ("Signed .word overflow; switch may be too large; %d at 0x%x", - add_number, fragP->fr_address + where); + as_bad ("Signed .word overflow; switch may be too large; %ld at 0x%lx", + (long) add_number, + (unsigned long) (fragP->fr_address + where)); #endif } /* not a bit fix */ @@ -1987,4 +2032,6 @@ fixup_segment (fixP, this_segment_type) return (seg_reloc_count); } +#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */ + /* end of write.c */