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.
This commit is contained in:
Ian Lance Taylor 1993-10-06 17:31:31 +00:00
parent 9978cd4dc9
commit 80aab57939
6 changed files with 514 additions and 647 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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,
&regnames[i].reg_num);
}
for (i = 0; regnames[i].reg_name && !retval; i++)
retval = hash_insert (reg_hash, regnames[i].reg_name,
&regnames[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;

View File

@ -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 (&notes, 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 .<secname>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;
unsigned int retval;
old_gdb_string_index = 0;
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
char *string;
int type;
int other;
int desc;
valu = ((char *) obstack_next_free (&frags)) - frag_now->fr_literal;
/* 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. */
#ifdef SEPARATE_STAB_SECTIONS
#ifdef BFD_ASSEMBLER
seg = bfd_get_section_by_name (stdoutput, secname);
if (seg == 0)
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;
}
}
else
string = "";
/*
* Input_line_pointer->after ','. String->symbol name.
*/
if (!goof)
{
#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 (".stabs: Missing comma");
ignore_rest_of_line ();
return;
}
}
if (!goof)
{
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. */
}
}
if (!goof)
{
S_SET_DESC (symbol, get_absolute_expression ());
if (what == 's' || what == 'n')
{
if (*input_line_pointer != ',')
{
as_bad ("I want a comma after the n_desc expression");
goof = 1;
}
else
{
input_line_pointer++;
}
}
}
/* Line is messed up - ignore it and get out of here. */
if (goof)
if (get_absolute_expression_and_terminator (&longint) != ',')
{
as_warn (".stab%c: Missing comma", what);
ignore_rest_of_line ();
subseg_set (saved_seg, saved_subseg);
return;
}
type = longint;
subseg_set (seg, subseg);
if (get_absolute_expression_and_terminator (&longint) != ',')
{
as_warn (".stab%c: Missing comma", what);
ignore_rest_of_line ();
return;
}
other = longint;
#if 0 /* needed for elf only? */
if (seg_is_new)
/* allocate and discard -- filled in later */
(void) frag_more (12);
#endif
desc = get_absolute_expression ();
if (what == 's' || what == 'n')
{
if (*input_line_pointer != ',')
{
as_warn (".stab%c: Missing comma", what);
ignore_rest_of_line ();
return;
}
input_line_pointer++;
SKIP_WHITESPACE ();
}
/* 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;
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 ();
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);
}
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);
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
#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);
}
#endif
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
{
/* .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 ());
}
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 (S_GET_TYPE (symbol))
{
case N_SLINE:
listing_source_line ((unsigned int) S_GET_DESC (symbol));
break;
case N_SO:
case N_SOL:
listing_source_file (string);
break;
}
#endif /* !NO_LISTING */
#ifdef SEPARATE_STAB_SECTIONS
subseg_set (saved_seg, saved_subseg);
#endif
{
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 ();
}

View File

@ -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 */