+Tue Jul 20 19:28:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Extensive changes to permit symbols to contain any expression
+ type and to delay the computation of the expression until the
+ value is actually needed. This permits setting symbols to values
+ calculated based on object code size. Expressions were changed to
+ no longer be in a section, to stop the overloading of segment and
+ expression type that previously occurred.
+
+ * as.c (big_section, pass1_section, diff_section, absent_section):
+ Removed.
+ (expr_section): Added (used for dummy symbols which hold
+ intermediate expression values).
+ (perform_an_assembly_pass): Create expr_section, do not create the
+ sections now removed.
+ * as.h (segT): Removed SEG_ABSENT, SEG_PASS1, SEG_BIG, and
+ SEG_DIFFERENCE. Added SEG_EXPR.
+ (SEG_NORMAL): Corresponding changes.
+ * subsegs.c (seg_name, subsegs_begin): Changed accordingly.
+ * write.c (write_object_file): Ditto.
+ * config/obj-aout.c (seg_N_TYPE): Ditto.
+ * config/obj-bout.c (seg_N_TYPE): Ditto.
+ * config/obj-coff.c (seg_N_TYPE): Ditto.
+ * config/obj-coffbfd.c (seg_N_TYPE): Ditto.
+ * config/obj-vms.c (seg_N_TYPE): Ditto.
+
+ * expr.h (operatorT): Moved in from expr.c, added some values.
+ (expressionS): Added X_op field, removed X_seg field; renamed
+ X_subtract_symbol to X_op_symbol.
+ * expr.c: Extensive changes to assign expression types rather than
+ sections and to simplify the parsing.
+ * write.c (fix_new_internal): New static function.
+ (fix_new): Removed sub_symbol argument.
+ (fix_new_exp): New function, takes expression argument.
+ * write.h: Prototype changes for fix_new and fix_new_exp.
+ * cond.c (s_if): Changed accordingly.
+ * read.c (s_lsym, pseudo_set, emit_expr, parse_bitfield_cons,
+ parse_repeat_cons, get_segmented_expression,
+ get_known_segmented_expression, get_absolute_expression): Ditto.
+ * symbols.c (resolve_symbol_value, S_GET_VALUE, S_SET_VALUE):
+ Ditto.
+ * write.c (write_object_file): Ditto.
+ * config/obj-coff.c (obj_coff_def, obj_coff_val): Ditto.
+ * config/obj-coffbfd.c (obj_coff_def, obj_coff_val,
+ obj_coff_endef, yank_symbols): Ditto.
+ * config/obj-elf.c (obj_elf_stab_generic, obj_elf_size): Ditto.
+ * config/tc-a29k.c (md_assemble, parse_operand, machine_ip,
+ print_insn, md_operand): Ditto.
+ * config/tc-h8300.c (parse_exp, colonmod24, check_operand,
+ do_a_fix_imm, build_bytes): Ditto.
+ * config/tc-h8500.c (parse_exp, skip_colonthing, parse_reglist,
+ get_specific, check, insert, md_convert_frag): Ditto.
+ * config/tc-hppa.c (the_insn, fix_new_hppa, cons_fix_new_hppa,
+ md_assemble, pa_ip, getExpression, getAbsoluteExpression,
+ evaluateAbsolute, pa_build_unwind_subspace, pa_entry,
+ process_exit): Ditto.
+ * config/tc-hppa.h (STAB_FIXUP, is_DP_relative, is_PC_relative,
+ is_complex): Ditto.
+ * config/tc-i386.c (pe, md_assemble, i386_operand,
+ md_estimate_size_before_relax, md_create_long_jump): Ditto.
+ * config/tc-i860.c (md_assemble, getExpression, print_insn):
+ Ditto.
+ * config/tc-i960.c (parse_expr, subs, segs, md_convert_frag,
+ get_cdisp, mem_fmt, parse_ldconst, relax_cobr, s_sysproc,
+ i960_handle_align): Ditto.
+ * config/tc-m68k.c (struct m68k_exp, struct m68k_it, seg, op,
+ subs, add_fix, isvar, m68k_ip, md_assemble, md_convert_frag_1,
+ md_estimate_size_before_relax, md_create_long_jump, get_num):
+ Ditto.
+ * config/tc-m88k.c (md_assemble, get_imm16, get_pcr,
+ md_create_short_jump, md_create_long_jump): Ditto.
+ * config/tc-mips.c (md_assemble, append_insn, gp_reference,
+ macro_build, macro, my_getExpression): Ditto. Also removed
+ get_optional_absolute_expression; just use get_absolute_expression
+ instead.
+ * config/tc-ns32k.c (get_addr_mode, evaluate_expr, convert_iif,
+ fix_new_ns32k, fix_new_ns32k_exp, cons_fix_new_ns32k): Ditto.
+ * config/tc-ns32k.h (fix_new_ns32k prototype): Ditto.
+ * config/tc-sh.c (parse_exp, check, insert, md_convert_frag):
+ Ditto.
+ * config/tc-sparc.c (md_assemble, sparc_ip, getExpression,
+ print_insn): Ditto.
+ * config/tc-tahoe.c (struct top, md_estimate_size_before_relax,
+ tip_op, md_assemble): Ditto.
+ * config/tc-vax.c (seg_of_operand, md_assemble,
+ md_estimate_size_before_relax, md_create_long_jump): Ditto.
+ * config/tc-z8k.c (parse_exp, check_operand, newfix): Ditto.
+
Tue Jul 20 12:17:16 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
* configure.in: i386-lynx is the same as i386-coff
N_DATA,
N_BSS,
N_UNDF, /* unknown */
- N_UNDF, /* absent */
- N_UNDF, /* pass1 */
N_UNDF, /* error */
- N_UNDF, /* bignum/flonum */
- N_UNDF, /* difference */
+ N_UNDF, /* expression */
N_UNDF, /* debug */
N_UNDF, /* ntv */
N_UNDF, /* ptv */
N_DATA,
N_BSS,
N_UNDF, /* unknown */
- N_UNDF, /* absent */
- N_UNDF, /* pass1 */
N_UNDF, /* error */
- N_UNDF, /* bignum/flonum */
- N_UNDF, /* difference */
+ N_UNDF, /* expression */
+ N_UNDF, /* debug */
+ N_UNDF, /* ntv */
+ N_UNDF, /* ptv */
N_REGISTER, /* register */
};
/* coff object file format with bfd
- Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
This file is part of GAS.
9,
10,
C_UNDEF_SECTION, /* SEG_UNKNOWN */
- C_UNDEF_SECTION, /* SEG_ABSENT */
- C_UNDEF_SECTION, /* SEG_PASS1 */
C_UNDEF_SECTION, /* SEG_GOOF */
- C_UNDEF_SECTION, /* SEG_BIG */
- C_UNDEF_SECTION, /* SEG_DIFFERENCE */
+ C_UNDEF_SECTION, /* SEG_EXPR */
C_DEBUG_SECTION, /* SEG_DEBUG */
C_NTV_SECTION, /* SEG_NTV */
C_PTV_SECTION, /* SEG_PTV */
def_symbol_in_progress->sy_name_offset = ~0;
def_symbol_in_progress->sy_number = ~0;
def_symbol_in_progress->sy_frag = &zero_address_frag;
+ S_SET_VALUE (def_symbol_in_progress, 0);
if (S_IS_STRING (def_symbol_in_progress))
{
|| (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG
&& !SF_GET_TAG (def_symbol_in_progress))
|| S_GET_SEGMENT (def_symbol_in_progress) == SEG_ABSOLUTE
- || def_symbol_in_progress->sy_value.X_seg != absolute_section
+ || def_symbol_in_progress->sy_value.X_op != O_constant
|| (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL
|| (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP)))
{
}
else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
{
+ def_symbol_in_progress->sy_value.X_op = O_symbol;
def_symbol_in_progress->sy_value.X_add_symbol =
symbol_find_or_make (symbol_name);
- def_symbol_in_progress->sy_value.X_subtract_symbol = NULL;
+ def_symbol_in_progress->sy_value.X_op_symbol = NULL;
def_symbol_in_progress->sy_value.X_add_number = 0;
- def_symbol_in_progress->sy_value.X_seg = undefined_section;
/* If the segment is undefined when the forward reference is
resolved, then copy the segment id from the forward
/* L* and C_EFCN symbols never merge. */
if (!SF_GET_LOCAL (symbolP)
&& S_GET_STORAGE_CLASS (symbolP) != C_LABEL
- && symbolP->sy_value.X_seg == absolute_section
+ && symbolP->sy_value.X_op == O_constant
&& (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP))
&& real_symbolP != symbolP)
{
subseg_new ((char *) saved_seg->name, subseg);
if ((what == 's' || what == 'n')
- && symbolP->sy_value.X_seg == absolute_section)
+ && symbolP->sy_value.X_op == O_constant)
{
/* symbol is not needed in the regular symbol table */
symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
char c = get_symbol_end ();
char *p;
expressionS exp;
- segT sec;
symbolS *sym;
p = input_line_pointer;
return;
}
input_line_pointer++;
- sec = expression (&exp);
- if (sec == absent_section)
+ expression (&exp);
+ if (exp.X_op == O_absent)
{
as_bad ("missing expression in .size directive");
- exp.X_seg = absolute_section;
+ exp.X_op = O_constant;
exp.X_add_number = 0;
}
*p = 0;
sym = symbol_find_or_make (name);
*p = c;
- if (sec == absolute_section)
+ if (exp.X_op == O_constant)
S_SET_SIZE (sym, exp.X_add_number);
else
{
N_DATA,
N_BSS,
N_UNDF, /* unknown */
- N_UNDF, /* absent */
- N_UNDF, /* pass1 */
N_UNDF, /* error */
- N_UNDF, /* bignum/flonum */
- N_UNDF, /* difference */
+ N_UNDF, /* expression */
N_UNDF, /* debug */
N_UNDF, /* ntv */
N_UNDF, /* ptv */
/* tc-a29k.c -- Assemble for the AMD 29000.
- Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
/* put out the symbol-dependent stuff */
if (the_insn.reloc != NO_RELOC)
{
- fix_new (
- frag_now, /* which frag */
- (toP - frag_now->fr_literal + the_insn.reloc_offset), /* where */
- 4, /* size */
- the_insn.exp.X_add_symbol,
- the_insn.exp.X_subtract_symbol,
- the_insn.exp.X_add_number,
- the_insn.pcrel,
- the_insn.reloc
- );
+ fix_new_exp (frag_now,
+ (toP - frag_now->fr_literal + the_insn.reloc_offset),
+ 4, /* size */
+ &the_insn.exp,
+ the_insn.pcrel,
+ the_insn.reloc);
}
}
{
char *save = input_line_pointer;
char *new;
- segT seg;
input_line_pointer = s;
- seg = expr (0, operandp);
+ if (expression (operandp) == O_absent)
+ as_bad ("missing operand");
new = input_line_pointer;
input_line_pointer = save;
-
- if (seg == SEG_ABSENT)
- as_bad ("Missing operand");
return new;
}
break;
case 'v': /* Trap numbers (immediate field) */
- if (operand->X_seg == SEG_ABSOLUTE)
+ if (operand->X_op == O_constant)
{
if (operand->X_add_number < 256)
{
case 'i':
/* We treat the two cases identically since we mashed
them together in the opcode table. */
- if (operand->X_seg == SEG_REGISTER)
+ if (operand->X_op == O_register)
goto general_reg;
opcode |= IMMEDIATE_BIT;
- if (operand->X_seg == SEG_ABSOLUTE)
+ if (operand->X_op == O_constant)
{
if (operand->X_add_number < 256)
{
case 'c':
general_reg:
/* lrNNN or grNNN or %%expr or a user-def register name */
- if (operand->X_seg != SEG_REGISTER)
+ if (operand->X_op != O_register)
break; /* Only registers */
know (operand->X_add_symbol == 0);
- know (operand->X_subtract_symbol == 0);
+ know (operand->X_op_symbol == 0);
reg = operand->X_add_number;
if (reg >= SREG)
break; /* No special registers */
case 'x': /* 16 bit constant, zero-extended */
case 'X': /* 16 bit constant, one-extended */
- if (operand->X_seg == SEG_ABSOLUTE)
+ if (operand->X_op == O_constant)
{
opcode |= (operand->X_add_number & 0xFF) << 0 |
((operand->X_add_number & 0xFF00) << 8);
continue;
case 'h':
- if (operand->X_seg == SEG_ABSOLUTE)
+ if (operand->X_op == O_constant)
{
opcode |= (operand->X_add_number & 0x00FF0000) >> 16 |
(((unsigned long) operand->X_add_number
case 'P': /* PC-relative jump address */
case 'A': /* Absolute jump address */
/* These two are treated together since we folded the
- opcode table entries together. */
- if (operand->X_seg == SEG_ABSOLUTE)
+ opcode table entries together. */
+ if (operand->X_op == O_constant)
{
opcode |= ABSOLUTE_BIT |
(operand->X_add_number & 0x0003FC00) << 6 |
continue;
case 'e': /* Coprocessor enable bit for LOAD/STORE insn */
- if (operand->X_seg == SEG_ABSOLUTE)
+ if (operand->X_op == O_constant)
{
if (operand->X_add_number == 0)
continue;
break;
case 'n': /* Control bits for LOAD/STORE instructions */
- if (operand->X_seg == SEG_ABSOLUTE &&
+ if (operand->X_op == O_constant &&
operand->X_add_number < 128)
{
opcode |= (operand->X_add_number << 16);
break;
case 's': /* Special register number */
- if (operand->X_seg != SEG_REGISTER)
+ if (operand->X_op != O_register)
break; /* Only registers */
if (operand->X_add_number < SREG)
break; /* Not a special register */
continue;
case 'u': /* UI bit of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE)
+ if (operand->X_op == O_constant)
{
if (operand->X_add_number == 0)
continue;
break;
case 'r': /* RND bits of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE &&
+ if (operand->X_op == O_constant &&
operand->X_add_number < 8)
{
opcode |= operand->X_add_number << 4;
break;
case 'd': /* FD bits of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE &&
+ if (operand->X_op == O_constant &&
operand->X_add_number < 4)
{
opcode |= operand->X_add_number << 2;
case 'f': /* FS bits of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE &&
+ if (operand->X_op == O_constant &&
operand->X_add_number < 4)
{
opcode |= operand->X_add_number << 0;
break;
case 'C':
- if (operand->X_seg == SEG_ABSOLUTE &&
+ if (operand->X_op == O_constant &&
operand->X_add_number < 4)
{
opcode |= operand->X_add_number << 16;
break;
case 'F':
- if (operand->X_seg == SEG_ABSOLUTE &&
+ if (operand->X_op == O_constant &&
operand->X_add_number < 16)
{
opcode |= operand->X_add_number << 18;
insn->exp.X_add_symbol ?
(S_GET_NAME (insn->exp.X_add_symbol) ?
S_GET_NAME (insn->exp.X_add_symbol) : "???") : "0");
- fprintf (stderr, "\t\tX_sub_symbol = %s\n",
- insn->exp.X_subtract_symbol ?
- (S_GET_NAME (insn->exp.X_subtract_symbol) ?
- S_GET_NAME (insn->exp.X_subtract_symbol) : "???") : "0");
+ fprintf (stderr, "\t\tX_op_symbol = %s\n",
+ insn->exp.X_op_symbol ?
+ (S_GET_NAME (insn->exp.X_op_symbol) ?
+ S_GET_NAME (insn->exp.X_op_symbol) : "???") : "0");
fprintf (stderr, "\t\tX_add_number = %d\n",
insn->exp.X_add_number);
fprintf (stderr, "}\n");
/* We have a numeric register expression. No biggy. */
input_line_pointer += 2; /* Skip %% */
(void) expression (expressionP);
- if (expressionP->X_seg != SEG_ABSOLUTE
+ if (expressionP->X_op != O_constant
|| expressionP->X_add_number > 255)
as_bad ("Invalid expression after %%%%\n");
- expressionP->X_seg = SEG_REGISTER;
+ expressionP->X_op = O_register;
}
else if (input_line_pointer[0] == '&')
{
/* We are taking the 'address' of a register...this one is not
- in the manual, but it *is* in traps/fpsymbol.h! What they
- seem to want is the register number, as an absolute number. */
+ in the manual, but it *is* in traps/fpsymbol.h! What they
+ seem to want is the register number, as an absolute number. */
input_line_pointer++; /* Skip & */
(void) expression (expressionP);
- if (expressionP->X_seg != SEG_REGISTER)
+ if (expressionP->X_op != O_register)
as_bad ("Invalid register in & expression");
else
- expressionP->X_seg = SEG_ABSOLUTE;
+ expressionP->X_op = O_constant;
}
}
{
char *save = input_line_pointer;
char *new;
- segT seg;
input_line_pointer = s;
- seg = expr (0, op);
+ if (expression (op) == O_absent)
+ as_bad ("missing operand");
new = input_line_pointer;
input_line_pointer = save;
- if (SEG_NORMAL (seg))
- return new;
- switch (seg)
- {
- case SEG_ABSOLUTE:
- case SEG_UNKNOWN:
- case SEG_DIFFERENCE:
- case SEG_BIG:
- case SEG_REGISTER:
- return new;
- case SEG_ABSENT:
- as_bad ("Missing operand");
- return new;
- default:
- as_bad ("Don't understand operand of type %s", segment_name (seg));
- return new;
- }
+ return new;
}
static char *
mode = L_16;
}
else if (op->exp.X_add_symbol
- || op->exp.X_subtract_symbol)
+ || op->exp.X_op_symbol)
mode = DSYMMODE;
else
mode = DMODE;
char *string)
{
if (operand->exp.X_add_symbol == 0
- && operand->exp.X_subtract_symbol == 0)
+ && operand->exp.X_op_symbol == 0)
{
/* No symbol involved, let's look at offset, it's dangerous if any of
}
- fix_new (frag_now,
- offset + where,
- size,
- operand->exp.X_add_symbol,
- operand->exp.X_subtract_symbol,
- (short) (operand->exp.X_add_number),
- 0,
- idx);
+ operand->exp.X_add_number = (short) operand->exp.X_add_number;
+ fix_new_exp (frag_now,
+ offset + where,
+ size,
+ &operand->exp,
+ 0,
+ idx);
}
}
operand->exp.X_add_number);
}
- fix_new (frag_now,
- output - frag_now->fr_literal + where,
- size,
- operand[i].exp.X_add_symbol,
- operand[i].exp.X_subtract_symbol,
- (char) (operand[i].exp.X_add_number - 1),
- 1,
- type);
+ oeprand[i].exp.X_add_number =
+ (char) (operand[i].exp.X_add_number - 1);
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal + where,
+ size,
+ &operand[i].exp,
+ 1,
+ type);
}
else if (x & MEMIND)
{
check_operand (operand + i, 0xff, "@@");
- fix_new (frag_now,
- output - frag_now->fr_literal + 1,
- 1,
- operand[i].exp.X_add_symbol,
- operand[i].exp.X_subtract_symbol,
- operand[i].exp.X_add_number,
- 0,
- R_RELBYTE);
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ &operand[i].exp,
+ 0,
+ R_RELBYTE);
}
else if (x & ABSMOV)
as_warn ("branch operand has odd offset (%x)\n",
operand->exp.X_add_number);
}
- fix_new (frag_now,
- output - frag_now->fr_literal,
- 4,
- operand[i].exp.X_add_symbol,
- operand[i].exp.X_subtract_symbol,
- (short) (operand[i].exp.X_add_number),
- 0,
- R_JMPL1);
+ operand[i].exp = (short) operand[i].exp.X_add_number;
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal,
+ 4,
+ &operand[i].exp,
+ 0,
+ R_JMPL1);
}
}
{
char *save;
char *new;
- segT seg;
save = input_line_pointer;
input_line_pointer = s;
- seg = expr (0, op);
+ if (expression (op) == O_absent)
+ as_bad ("missing operand");
new = input_line_pointer;
input_line_pointer = save;
- if (SEG_NORMAL (seg))
- return new;
- switch (seg)
- {
- case SEG_ABSOLUTE:
- case SEG_UNKNOWN:
- case SEG_DIFFERENCE:
- case SEG_BIG:
- case SEG_REGISTER:
- return new;
- case SEG_ABSENT:
- as_bad ("Missing operand");
- return new;
- default:
- as_bad ("Don't understand operand of type %s", segment_name (seg));
- return new;
- }
+ return new;
}
typedef enum
/* Let's work out the size from the context */
int n = exp->exp.X_add_number;
if (size8
- && exp->exp.X_seg == SEG_ABSOLUTE
+ && exp->exp.X_op == O_constant
&& ((sign == exp_signed && (n >= -128 && n <= 127))
|| (sign == exp_unsigned && (n >= 0 && (n <= 255)))
|| (sign == exp_sandu && (n >= -128 && (n <= 255)))))
}
idx++;
op->exp.X_add_symbol = 0;
- op->exp.X_subtract_symbol = 0;
+ op->exp.X_op_symbol = 0;
op->exp.X_add_number = mask;
- op->exp.X_seg = SEG_ABSOLUTE;
+ op->exp.X_op = O_constant;
op->type = IMM8;
return idx;
break;
case QIM:
if (user->type == IMM8
- && user->exp.X_seg == SEG_ABSOLUTE
+ && user->exp.X_op == O_constant
&&
(user->exp.X_add_number == -2
|| user->exp.X_add_number == -1
int low;
int high;
{
- if (operand->X_seg != SEG_ABSOLUTE
+ if (operand->X_op != O_constant
|| operand->X_add_number < low
|| operand->X_add_number > high)
{
int reloc;
int pcrel;
{
- fix_new (frag_now,
- output - frag_now->fr_literal + index,
- 4, /* always say size is 4, but we know better */
- exp->X_add_symbol,
- exp->X_subtract_symbol,
- exp->X_add_number,
- pcrel,
- reloc);
+ fix_new_exp (frag_now,
+ output - frag_now->fr_literal + index,
+ 4, /* always say size is 4, but we know better */
+ &exp,
+ pcrel,
+ reloc);
}
void
fragP->fr_fix + inst_size,
4,
fragP->fr_symbol,
- 0,
fragP->fr_offset,
0,
R_H8500_PCREL16);
/* i386.c -- Assemble code for the Intel 80386
- Copyright (C) 1989, 1991, 1992 Free Software Foundation.
+ Copyright (C) 1989, 1991, 1992, 1993 Free Software Foundation.
This file is part of GAS, the GNU Assembler.
pe (e)
expressionS *e;
{
- fprintf (stdout, " segment %s\n", segment_name (e->X_seg));
+ fprintf (stdout, " operation %d\n", e->X_op);
fprintf (stdout, " add_number %d (%x)\n",
e->X_add_number, e->X_add_number);
if (e->X_add_symbol)
ps (e->X_add_symbol);
fprintf (stdout, "\n");
}
- if (e->X_subtract_symbol)
+ if (e->X_op_symbol)
{
- fprintf (stdout, " sub_symbol ");
- ps (e->X_subtract_symbol);
+ fprintf (stdout, " op_symbol ");
+ ps (e->X_op_symbol);
fprintf (stdout, "\n");
}
}
holds the correct displacement size. */
exp = &disp_expressions[i.disp_operands++];
i.disps[o] = exp;
- exp->X_seg = absolute_section;
+ exp->X_op = O_constant;
exp->X_add_number = 0;
exp->X_add_symbol = (symbolS *) 0;
- exp->X_subtract_symbol = (symbolS *) 0;
+ exp->X_op_symbol = (symbolS *) 0;
}
/* Select the correct segment for the memory operand. */
if (t->opcode_modifier & Jump)
{
int n = i.disps[0]->X_add_number;
- segT seg;
- seg = i.disps[0]->X_seg;
-
- if (seg == absolute_section)
+ if (i.disps[0]->X_op == O_constant)
{
if (fits_in_signed_byte (n))
{
}
p = frag_more (size);
- if (i.disps[0]->X_seg == absolute_section)
+ if (i.disps[0]->X_op == O_constant)
{
md_number_to_chars (p, n, size);
if (size == 1 && !fits_in_signed_byte (n))
}
else
{
- fix_new (frag_now, p - frag_now->fr_literal, size,
- i.disps[0]->X_add_symbol, i.disps[0]->X_subtract_symbol,
- i.disps[0]->X_add_number, 1, NO_RELOC);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+ i.disps[0], 1, NO_RELOC);
}
}
else if (t->opcode_modifier & JumpInterSegment)
{
p = frag_more (1 + 2 + 4); /* 1 opcode; 2 segment; 4 offset */
p[0] = t->base_opcode;
- if (i.imms[1]->X_seg == absolute_section)
+ if (i.imms[1]->X_op == O_constant)
md_number_to_chars (p + 1, i.imms[1]->X_add_number, 4);
else
- fix_new (frag_now, p + 1 - frag_now->fr_literal, 4,
- i.imms[1]->X_add_symbol,
- i.imms[1]->X_subtract_symbol,
- i.imms[1]->X_add_number, 0, NO_RELOC);
- if (i.imms[0]->X_seg != absolute_section)
+ fix_new_exp (frag_now, p + 1 - frag_now->fr_literal, 4,
+ i.imms[1], 0, NO_RELOC);
+ if (i.imms[0]->X_op != O_constant)
as_bad ("can't handle non absolute segment in long call/jmp");
md_number_to_chars (p + 5, i.imms[0]->X_add_number, 2);
}
{
if (i.disps[n])
{
- if (i.disps[n]->X_seg == absolute_section)
+ if (i.disps[n]->X_op == O_constant)
{
if (i.types[n] & (Disp8 | Abs8))
{
{ /* not absolute_section */
/* need a 32-bit fixup (don't support 8bit non-absolute disps) */
p = frag_more (4);
- fix_new (frag_now, p - frag_now->fr_literal, 4,
- i.disps[n]->X_add_symbol, i.disps[n]->X_subtract_symbol,
- i.disps[n]->X_add_number, 0, NO_RELOC);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 4,
+ i.disps[n], 0, NO_RELOC);
}
}
}
{
if (i.imms[n])
{
- if (i.imms[n]->X_seg == absolute_section)
+ if (i.imms[n]->X_op == O_constant)
{
if (i.types[n] & (Imm8 | Imm8S))
{
else
size = 4;
p = frag_more (size);
- fix_new (frag_now, p - frag_now->fr_literal, size,
- i.imms[n]->X_add_symbol, i.imms[n]->X_subtract_symbol,
- i.imms[n]->X_add_number, 0, NO_RELOC);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, size,
+ i.imms[n], 0, NO_RELOC);
}
}
}
exp_seg = expression (exp);
input_line_pointer = save_input_line_pointer;
- if (exp_seg == absent_section)
+ if (exp.X_op == O_absent)
{
/* missing or bad expr becomes absolute 0 */
as_bad ("missing or invalid immediate expression '%s' taken as 0",
operand_string);
- exp->X_seg = absolute_section;
+ exp->X_op = O_constant;
exp->X_add_number = 0;
exp->X_add_symbol = (symbolS *) 0;
- exp->X_subtract_symbol = (symbolS *) 0;
+ exp->X_op_symbol = (symbolS *) 0;
i.types[this_operand] |= Imm;
}
- else if (exp_seg == absolute_section)
+ else if (exp.X_op == O_constant)
{
i.types[this_operand] |= smallest_imm_type (exp->X_add_number);
}
as_bad ("Ignoring junk '%s' after expression", input_line_pointer);
RESTORE_END_STRING (displacement_string_end);
input_line_pointer = save_input_line_pointer;
- if (exp_seg == absent_section)
+ if (exp.X_op == O_absent)
{
/* missing expr becomes absolute 0 */
as_bad ("missing or invalid displacement '%s' taken as 0",
operand_string);
i.types[this_operand] |= (Disp | Abs);
- exp->X_seg = absolute_section;
+ exp->X_op = O_constant;
exp->X_add_number = 0;
exp->X_add_symbol = (symbolS *) 0;
- exp->X_subtract_symbol = (symbolS *) 0;
+ exp->X_op_symbol = (symbolS *) 0;
}
- else if (exp_seg == absolute_section)
+ else if (exp.X_op == O_constant)
{
i.types[this_operand] |= SMALLEST_DISP_TYPE (exp->X_add_number);
}
fragP->fr_fix += 4;
fix_new (fragP, old_fr_fix, 4,
fragP->fr_symbol,
- (symbolS *) 0,
fragP->fr_offset, 1, NO_RELOC);
break;
fragP->fr_fix += 1 + 4; /* we've added an opcode byte */
fix_new (fragP, old_fr_fix + 1, 4,
fragP->fr_symbol,
- (symbolS *) 0,
fragP->fr_offset, 1, NO_RELOC);
break;
}
md_number_to_chars (ptr, 0xe9, 1); /* opcode for long jmp */
md_number_to_chars (ptr + 1, offset, 4);
fix_new (frag, (ptr + 1) - frag->fr_literal, 4,
- to_symbol, (symbolS *) 0, (long) 0, 0, NO_RELOC);
+ to_symbol, (offsetT) 0, 0, NO_RELOC);
}
else
{
/* tc-i960.c - All the i80960-specific stuff
- Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This file is part of GAS.
static int i_scan (); /* Lexical scan of instruction source */
static void mem_fmt (); /* Generate MEMA or MEMB instruction */
static void mema_to_memb (); /* Convert MEMA instruction to MEMB format */
-static segT parse_expr (); /* Parse an expression */
+static void parse_expr (); /* Parse an expression */
static int parse_ldconst (); /* Parse and replace a 'ldconst' pseudo-op */
static void parse_memop (); /* Parse a memory operand */
static void parse_po (); /* Parse machine-dependent pseudo-op */
\f
/* Macros to extract info from an 'expressionS' structure 'e' */
#define adds(e) e.X_add_symbol
-#define subs(e) e.X_subtract_symbol
#define offs(e) e.X_add_number
-#define segs(e) e.X_seg
/* Branch-prediction bits for CTRL/COBR format opcodes */
fragP->fr_opcode - fragP->fr_literal,
4,
fragP->fr_symbol,
- 0,
fragP->fr_offset,
1,
NO_RELOC);
symbol_find (buf),
0,
0,
- 0,
NO_RELOC);
fixP->fx_im_disp = 2; /* 32-bit displacement fix */
}
fixP = NULL;
- switch (parse_expr (dispP, &e))
+ parse_expr (dispP, &e);
+ switch (e.X_op)
{
-
- case SEG_GOOF:
+ case O_illegal:
as_bad ("expression syntax error");
- break;
- case SEG_TEXT:
- case SEG_UNKNOWN:
- if (var_frag)
- {
- outP = frag_more (8); /* Allocate worst-case storage */
- md_number_to_chars (outP, instr, 4);
- frag_variant (rs_machine_dependent, 4, 4, 1,
- adds (e), offs (e), outP, 0, 0);
+ case O_symbol:
+ if (S_GET_SEGMENT (e.X_add_symbol) == text_section
+ || S_GET_SEGMENT (e.X_add_symbol) == undefined_section)
+ {
+ if (var_frag)
+ {
+ outP = frag_more (8); /* Allocate worst-case storage */
+ md_number_to_chars (outP, instr, 4);
+ frag_variant (rs_machine_dependent, 4, 4, 1,
+ adds (e), offs (e), outP, 0, 0);
+ }
+ else
+ {
+ /* Set up a new fix structure, so address can be updated
+ * when all symbol values are known.
+ */
+ outP = emit (instr);
+ fixP = fix_new (frag_now,
+ outP - frag_now->fr_literal,
+ 4,
+ adds (e),
+ offs (e),
+ 1,
+ NO_RELOC);
+
+ fixP->fx_callj = callj;
+
+ /* We want to modify a bit field when the address is
+ * known. But we don't need all the garbage in the
+ * bit_fix structure. So we're going to lie and store
+ * the number of bits affected instead of a pointer.
+ */
+ fixP->fx_bit_fixP = (bit_fixS *) numbits;
+ }
}
else
- {
- /* Set up a new fix structure, so address can be updated
- * when all symbol values are known.
- */
- outP = emit (instr);
- fixP = fix_new (frag_now,
- outP - frag_now->fr_literal,
- 4,
- adds (e),
- 0,
- offs (e),
- 1,
- NO_RELOC);
-
- fixP->fx_callj = callj;
-
- /* We want to modify a bit field when the address is
- * known. But we don't need all the garbage in the
- * bit_fix structure. So we're going to lie and store
- * the number of bits affected instead of a pointer.
- */
- fixP->fx_bit_fixP = (bit_fixS *) numbits;
- }
- break;
-
- case SEG_DATA:
- case SEG_BSS:
- as_bad ("attempt to branch into different segment");
+ as_bad ("attempt to branch into different segment");
break;
default:
}
/* Parse and process the displacement */
- switch (parse_expr (instr.e, &expr))
+ parse_expr (instr.e, &expr);
+ switch (expr.X_op)
{
-
- case SEG_GOOF:
+ case O_illegal:
as_bad ("expression syntax error");
break;
- case SEG_ABSOLUTE:
+ case O_constant:
if (instr.disp == 32)
{
(void) emit (offs (expr)); /* Output displacement */
if (offs (expr) & ~0xfff)
{
/* Won't fit in 12 bits: convert already-output
- * instruction to MEMB format, output
- * displacement.
- */
+ * instruction to MEMB format, output
+ * displacement.
+ */
mema_to_memb (outP);
(void) emit (offs (expr));
}
else
{
/* WILL fit in 12 bits: OR into opcode and
- * overwrite the binary we already put out
- */
+ * overwrite the binary we already put out
+ */
instr.opcode |= offs (expr);
md_number_to_chars (outP, instr.opcode, 4);
}
}
break;
- case SEG_DIFFERENCE:
- case SEG_TEXT:
- case SEG_DATA:
- case SEG_BSS:
- case SEG_UNKNOWN:
+ default:
if (instr.disp == 12)
{
/* Displacement is dependent on a symbol, whose value
* this symbol's value becomes known.
*/
outP = emit ((long) 0);
- fixP = fix_new (frag_now,
- outP - frag_now->fr_literal,
- 4,
- adds (expr),
- subs (expr),
- offs (expr),
- 0,
- NO_RELOC);
+ fixP = fix_new_exp (frag_now,
+ outP - frag_now->fr_literal,
+ 4,
+ &expr,
+ 0,
+ NO_RELOC);
fixP->fx_im_disp = 2; /* 32-bit displacement fix */
fixP->fx_bsr = callx; /*SAC LD RELAX HACK *//* Mark reloc as being in i stream */
break;
-
- default:
- BAD_CASE (segs (expr));
- break;
}
} /* memfmt() */
*
* An empty expression string is treated as an absolute 0.
*
- * Return "segment" to which the expression evaluates.
- * Return SEG_GOOF regardless of expression evaluation if entire input
+ * Sets O_illegal regardless of expression evaluation if entire input
* string is not consumed in the evaluation -- tolerate no dangling junk!
*
**************************************************************************** */
-static
- segT
+static void
parse_expr (textP, expP)
char *textP; /* Text of expression to be parsed */
expressionS *expP; /* Where to put the results of parsing */
{
char *save_in; /* Save global here */
- segT seg; /* Segment to which expression evaluates */
symbolS *symP;
know (textP);
if (*textP == '\0')
{
/* Treat empty string as absolute 0 */
- expP->X_add_symbol = expP->X_subtract_symbol = NULL;
+ expP->X_add_symbol = expP->X_op_symbol = NULL;
expP->X_add_number = 0;
- seg = expP->X_seg = SEG_ABSOLUTE;
-
+ exp->X_op = O_constant;
}
else
{
if (input_line_pointer - textP != strlen (textP))
{
/* Did not consume all of the input */
- seg = SEG_GOOF;
+ expP->X_op = O_illegal;
}
symP = expP->X_add_symbol;
if (symP && (hash_find (reg_hash, S_GET_NAME (symP))))
{
/* Register name in an expression */
- seg = SEG_GOOF;
+ /* FIXME: this isn't much of a check any more. */
+ expP->X_op = O_illegal;
}
input_line_pointer = save_in; /* Restore global */
arg[3] = NULL; /* So we can tell at the end if it got used or not */
- switch (parse_expr (arg[1], &e))
+ parse_expr (arg[1], &e);
+ switch (e.X_op)
{
-
- case SEG_TEXT:
- case SEG_DATA:
- case SEG_BSS:
- case SEG_UNKNOWN:
- case SEG_DIFFERENCE:
+ default:
/* We're dependent on one or more symbols -- use "lda" */
arg[0] = "lda";
break;
- case SEG_ABSOLUTE:
+ case O_constant:
/* Try the following mappings:
- * ldconst 0,<reg> ->mov 0,<reg>
- * ldconst 31,<reg> ->mov 31,<reg>
- * ldconst 32,<reg> ->addo 1,31,<reg>
- * ldconst 62,<reg> ->addo 31,31,<reg>
- * ldconst 64,<reg> ->shlo 8,3,<reg>
- * ldconst -1,<reg> ->subo 1,0,<reg>
- * ldconst -31,<reg>->subo 31,0,<reg>
- *
- * anthing else becomes:
- * lda xxx,<reg>
- */
+ * ldconst 0,<reg> ->mov 0,<reg>
+ * ldconst 31,<reg> ->mov 31,<reg>
+ * ldconst 32,<reg> ->addo 1,31,<reg>
+ * ldconst 62,<reg> ->addo 31,31,<reg>
+ * ldconst 64,<reg> ->shlo 8,3,<reg>
+ * ldconst -1,<reg> ->subo 1,0,<reg>
+ * ldconst -31,<reg>->subo 31,0,<reg>
+ *
+ * anthing else becomes:
+ * lda xxx,<reg>
+ */
n = offs (e);
if ((0 <= n) && (n <= 31))
{
}
break;
- default:
+ case O_illegal:
as_bad ("invalid constant");
return -1;
break;
}
else
{ /* fixed point literal acceptable */
- if ((parse_expr (optext, &e) != SEG_ABSOLUTE)
+ parse_expr (optext, &e);
+ if (e.X_op != O_constant
|| (offs (e) < 0) || (offs (e) > 31))
{
as_bad ("illegal literal");
iP + 4 - fragP->fr_literal,
4,
fragP->fr_symbol,
- 0,
fragP->fr_offset,
1,
NO_RELOC);
} /* bad arg count */
/* Parse "entry_num" argument and check it for validity. */
- if ((parse_expr (args[2], &exp) != SEG_ABSOLUTE)
+ parse_expr (args[2], &exp);
+ if (exp.X_op != O_constant
|| (offs (exp) < 0)
|| (offs (exp) > 31))
{
}
/* alignment directive */
- fixp = fix_new (fragp, fragp->fr_fix, fragp->fr_offset, 0, 0, 0, 0,
+ fixp = fix_new (fragp, fragp->fr_fix, fragp->fr_offset, 0, 0, 0,
(int) fragp->fr_type);
}
/* m88k.c -- Assembler for the Motorola 88000
Contributed by Devon Bowen of Buffalo University
and Torbjorn Granlund of the Swedish Institute of Computer Science.
- Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
/* try parsing this instruction into insn */
insn.exp.X_add_symbol = 0;
- insn.exp.X_subtract_symbol = 0;
+ insn.exp.X_op_symbol = 0;
insn.exp.X_add_number = 0;
- insn.exp.X_seg = 0;
+ insn.exp.X_op = O_illegal;
insn.reloc = NO_RELOC;
while (!calcop (format, param, &insn))
case RELOC_LO16:
case RELOC_HI16:
- fix_new (frag_now,
- thisfrag - frag_now->fr_literal + 2,
- 2,
- insn.exp.X_add_symbol,
- insn.exp.X_subtract_symbol,
- insn.exp.X_add_number,
- 0,
- insn.reloc);
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal + 2,
+ 2,
+ &insn.exp,
+ 0,
+ insn.reloc);
break;
case RELOC_IW16:
- fix_new (frag_now,
- thisfrag - frag_now->fr_literal,
- 4,
- insn.exp.X_add_symbol,
- insn.exp.X_subtract_symbol,
- insn.exp.X_add_number,
- 0,
- insn.reloc);
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal,
+ 4,
+ &insn.exp,
+ 0,
+ insn.reloc);
break;
case RELOC_PC16:
- fix_new (frag_now,
- thisfrag - frag_now->fr_literal + 2,
- 2,
- insn.exp.X_add_symbol,
- insn.exp.X_subtract_symbol,
- insn.exp.X_add_number,
- 1,
- insn.reloc);
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal + 2,
+ 2,
+ &insn.exp,
+ 1,
+ insn.reloc);
break;
case RELOC_PC26:
- fix_new (frag_now,
- thisfrag - frag_now->fr_literal,
- 4,
- insn.exp.X_add_symbol,
- insn.exp.X_subtract_symbol,
- insn.exp.X_add_number,
- 1,
- insn.reloc);
+ fix_new_exp (frag_now,
+ thisfrag - frag_now->fr_literal,
+ 4,
+ &insn.exp,
+ 1,
+ insn.reloc);
break;
default:
{
enum reloc_type reloc = NO_RELOC;
unsigned int val;
- segT seg;
char *save_ptr;
if (!strncmp (param, "hi16", 4) && !isalnum (param[4]))
save_ptr = input_line_pointer;
input_line_pointer = param;
- seg = expression (&insn->exp);
+ expression (&insn->exp);
param = input_line_pointer;
input_line_pointer = save_ptr;
val = insn->exp.X_add_number;
- if (seg == SEG_ABSOLUTE)
+ if (insn->exp.X_op == O_constant)
{
/* Insert the value now, and reset reloc to NO_RELOC. */
if (reloc == NO_RELOC)
enum reloc_type reloc;
{
char *saveptr, *saveparam;
- segT seg;
saveptr = input_line_pointer;
input_line_pointer = param;
- seg = expression (&insn->exp);
+ expression (&insn->exp);
saveparam = input_line_pointer;
input_line_pointer = saveptr;
- /* Botch: We should relocate now if SEG_ABSOLUTE. */
+ /* Botch: We should relocate now if O_constant. */
insn->reloc = reloc;
return saveparam;
ptr - frag->fr_literal,
4,
to_symbol,
- (symbolS *) 0,
- (long int) 0,
+ (offsetT) 0,
0,
RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */
}
ptr - frag->fr_literal,
4,
to_symbol,
- (symbolS *) 0,
- (long int) 0,
+ (offsetT) 0,
0,
RELOC_PC26);
}
static int my_getSmallExpression PARAMS ((expressionS * ep, char *str));
static void my_getExpression PARAMS ((expressionS * ep, char *str));
static symbolS *get_symbol PARAMS ((void));
-static long get_optional_absolute_expression PARAMS ((void));
static void mips_align PARAMS ((int to, int fill));
static void s_align PARAMS ((int));
static void s_stringer PARAMS ((int));
init = 1;
}
- imm_expr.X_seg = absent_section;
- offset_expr.X_seg = absent_section;
+ imm_expr.X_op = O_absent;
+ offset_expr.X_op = O_absent;
mips_ip (str, &insn);
if (insn_error)
}
else
{
- if (imm_expr.X_seg != absent_section)
+ if (imm_expr.X_op != O_absent)
append_insn (&insn, &imm_expr, imm_reloc);
- else if (offset_expr.X_seg != absent_section)
+ else if (offset_expr.X_op != O_absent)
append_insn (&insn, &offset_expr, offset_reloc);
else
append_insn (&insn, NULL, BFD_RELOC_UNUSED);
fixp = NULL;
if (address_expr != NULL)
{
- if (address_expr->X_seg == &bfd_abs_section)
+ if (address_expr->X_op == O_constant)
{
switch (reloc_type)
{
{
assert (reloc_type != BFD_RELOC_UNUSED);
need_reloc:
- fixp = fix_new (frag_now, f - frag_now->fr_literal, 4,
- address_expr->X_add_symbol,
- address_expr->X_subtract_symbol,
- address_expr->X_add_number,
- reloc_type == BFD_RELOC_16_PCREL_S2,
- reloc_type);
+ fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
+ address_expr,
+ reloc_type == BFD_RELOC_16_PCREL_S2,
+ reloc_type);
}
}
sym = ep->X_add_symbol;
if (sym == (symbolS *) NULL
- || ep->X_subtract_symbol != (symbolS *) NULL)
+ || ep->X_op_symbol != (symbolS *) NULL)
return 0;
/* Certain symbols can not be referenced off the GP, although it
* input, in which case the value is not checked for range nor
* is a relocation entry generated (yuck).
*/
- if (ep->X_add_symbol == NULL && ep->X_seg == &bfd_abs_section)
+ if (ep->X_op == O_constant)
{
insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff;
ep = NULL;
high_expr = *ep;
- if (high_expr.X_seg == &bfd_abs_section)
+ if (high_expr.X_op == O_constant)
{
/* we can compute the instruction now without a relocation entry */
if (high_expr.X_add_number & 0x8000)
expressionS *expr;
{
- if (expr->X_seg != &bfd_abs_section)
+ if (expr->X_op != O_constant)
as_warn ("Instruction %s requires absolute expression", ip->insn_mo->name);
}
sreg = breg = (ip->insn_opcode >> 21) & 0x1f;
mask = ip->insn_mo->mask;
- expr1.X_seg = &bfd_abs_section;
- expr1.X_subtract_symbol = NULL;
+ expr1.X_op = O_constant;
+ expr1.X_op_symbol = NULL;
expr1.X_add_symbol = NULL;
expr1.X_add_number = 1;
return;
case M_LA:
- if (offset_expr.X_seg == &bfd_abs_section)
+ if (offset_expr.X_op == O_constant)
{
load_register (&icnt, ip, treg, &offset_expr);
return;
case M_LA_AB:
tempreg = (breg == treg) ? AT : treg;
- if (offset_expr.X_seg == &bfd_abs_section)
+ if (offset_expr.X_op == O_constant)
load_register (&icnt, ip, tempreg, &offset_expr);
else if (gp_reference (&offset_expr))
macro_build (&icnt, &offset_expr, "addiu", "t,r,j", tempreg, GP);
case M_ULH_A:
case M_ULHU_A:
case M_ULW_A:
- if (offset_expr.X_seg == &bfd_abs_section)
+ if (offset_expr.X_op == O_constant)
load_register (&icnt, ip, AT, &offset_expr);
else if (gp_reference (&offset_expr))
macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, GP);
case M_USH_A:
case M_USW_A:
- if (offset_expr.X_seg == &bfd_abs_section)
+ if (offset_expr.X_op == O_constant)
load_register (&icnt, ip, AT, &offset_expr);
else if (gp_reference (&offset_expr))
macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, GP);
imm_expr.X_add_number = imm_expr.X_add_number % 32;
}
ip->insn_opcode |= imm_expr.X_add_number << 6;
- imm_expr.X_seg = absent_section;
+ imm_expr.X_op = O_absent;
s = expr_end;
continue;
if ((unsigned) imm_expr.X_add_number > 1023)
as_warn ("Illegal break code (%d)", imm_expr.X_add_number);
ip->insn_opcode |= imm_expr.X_add_number << 16;
- imm_expr.X_seg = absent_section;
+ imm_expr.X_op = O_absent;
s = expr_end;
continue;
if ((unsigned) imm_expr.X_add_number > 0xfffff)
as_warn ("Illegal syscall code (%d)", imm_expr.X_add_number);
ip->insn_opcode |= imm_expr.X_add_number << 6;
- imm_expr.X_seg = absent_section;
+ imm_expr.X_op = O_absent;
s = expr_end;
continue;
{
if (c != 'l')
{
- if (imm_expr.X_seg == &bfd_abs_section)
+ if (imm_expr.X_op == O_constant)
imm_expr.X_add_number =
(imm_expr.X_add_number >> 16) & 0xffff;
else if (c == 'h')
* code pattern.
*/
if ((offset_expr.X_add_symbol
- && offset_expr.X_seg != &bfd_abs_section)
- || offset_expr.X_subtract_symbol
+ && offset_expr.X_op != O_constant)
+ || offset_expr.X_op_symbol
|| offset_expr.X_add_number > 32767
|| offset_expr.X_add_number < -32768)
break;
{
if (c != 'l')
{
- if (imm_expr.X_seg == &bfd_abs_section)
+ if (imm_expr.X_op == O_constant)
imm_expr.X_add_number =
(imm_expr.X_add_number >> 16) & 0xffff;
else if (c == 'h')
if (c)
{
/* %xx(reg) is an error */
- ep->X_seg = absent_section;
+ ep->X_op = O_absent;
expr_end = str - 3;
}
else
{
- ep->X_seg = &bfd_abs_section;
+ ep->X_op = O_absent;
expr_end = sp;
}
ep->X_add_symbol = NULL;
- ep->X_subtract_symbol = NULL;
+ ep->X_op_symbol = NULL;
ep->X_add_number = 0;
}
else
char *str;
{
char *save_in;
- asection *seg;
save_in = input_line_pointer;
input_line_pointer = str;
- seg = expression (ep);
+ expression (ep);
expr_end = input_line_pointer;
input_line_pointer = save_in;
}
return p;
}
-static long
-get_optional_absolute_expression ()
-{
- expressionS exp;
- asection *s;
-
- s = expression (&exp);
- if (!(s == &bfd_abs_section || s == big_section || s == absent_section))
- {
- as_bad ("Bad Absolute Expression.");
- }
- return exp.X_add_number;
-}
-
/* Align the current frag to a given power of two. The MIPS assembler
also automatically adjusts any preceding label. */
symbolP = get_symbol ();
if (*input_line_pointer == ',')
input_line_pointer++;
- size = get_optional_absolute_expression ();
+ size = get_absolute_expression ();
S_SET_VALUE (symbolP, size);
S_SET_EXTERNAL (symbolP);
frame_reg = tc_get_register ();
if (*input_line_pointer == ',')
input_line_pointer++;
- frame_off = get_optional_absolute_expression ();
+ frame_off = get_absolute_expression ();
if (*input_line_pointer == ',')
input_line_pointer++;
pcreg = tc_get_register ();
/* See if "set" operand is absolute and small; skip sethi if so. */
if (special_case == SPECIAL_CASE_SET
- && the_insn.exp.X_seg == absolute_section)
+ && the_insn.exp.X_op == O_constant)
{
if (the_insn.exp.X_add_number >= -(1 << 12)
&& the_insn.exp.X_add_number < (1 << 12))
/* put out the symbol-dependent stuff */
if (the_insn.reloc != BFD_RELOC_NONE)
{
- fix_new (frag_now, /* which frag */
- (toP - frag_now->fr_literal), /* where */
- 4, /* size */
- the_insn.exp.X_add_symbol,
- the_insn.exp.X_subtract_symbol,
- the_insn.exp.X_add_number,
- the_insn.pcrel,
- the_insn.reloc);
+ fix_new_exp (frag_now, /* which frag */
+ (toP - frag_now->fr_literal), /* where */
+ 4, /* size */
+ &the_insn.exp,
+ the_insn.pcrel,
+ the_insn.reloc);
}
switch (special_case)
special_case = 0;
assert (the_insn.reloc == BFD_RELOC_HI22);
/* See if "set" operand has no low-order bits; skip OR if so. */
- if (the_insn.exp.X_seg == absolute_section
+ if (the_insn.exp.X_op == O_constant
&& ((the_insn.exp.X_add_number & 0x3FF) == 0))
return;
toP = frag_more (4);
rsd = (the_insn.opcode >> 25) & 0x1f;
the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14);
md_number_to_chars (toP, (valueT) the_insn.opcode, 4);
- fix_new (frag_now, /* which frag */
- (toP - frag_now->fr_literal), /* where */
- 4, /* size */
- the_insn.exp.X_add_symbol,
- the_insn.exp.X_subtract_symbol,
- the_insn.exp.X_add_number,
- the_insn.pcrel,
- BFD_RELOC_LO10
- );
+ fix_new_exp (frag_now, /* which frag */
+ (toP - frag_now->fr_literal), /* where */
+ 4, /* size */
+ &the_insn.exp,
+ the_insn.pcrel,
+ BFD_RELOC_LO10);
return;
case SPECIAL_CASE_FDIV:
#endif
/* end-sanitize-v9 */
&& the_insn.exp.X_add_symbol == 0
- && the_insn.exp.X_subtract_symbol == 0
- && the_insn.exp.X_seg == absolute_section
+ && the_insn.exp.X_op_symbol == 0
+ && the_insn.exp.X_op == O_constant
&& (the_insn.exp.X_add_number > immediate_max
|| the_insn.exp.X_add_number < ~immediate_max))
as_bad ("constant value must be between %ld and %ld",
input_line_pointer = s;
- if (expression (&e) == absolute_section)
+ expression (&e);
+ if (e.X_op == O_constant)
{
opcode |= e.X_add_number << 5;
s = input_line_pointer;
|| seg == text_section
|| seg == data_section
|| seg == bss_section
- || seg == undefined_section
- || seg == diff_section
- || seg == big_section
- || seg == absent_section)
+ || seg == undefined_section)
/* ok */;
else
{
: "???")
: "0"));
fprintf (stderr, "\t\tX_sub_symbol = %s\n",
- ((insn->exp.X_subtract_symbol != NULL)
- ? (S_GET_NAME (insn->exp.X_subtract_symbol)
- ? S_GET_NAME (insn->exp.X_subtract_symbol)
+ ((insn->exp.X_op_symbol != NULL)
+ ? (S_GET_NAME (insn->exp.X_op_symbol)
+ ? S_GET_NAME (insn->exp.X_op_symbol)
: "???")
: "0"));
fprintf (stderr, "\t\tX_add_number = %d\n",
char *top_error; /* Say if operand is inappropriate */
+ segT seg_of_operand; /* segment as returned by expression()*/
+
expressionS exp_of_operand; /* The expression as parsed by expression()*/
byte top_dispsize; /* Number of bytes in the displacement if we
*p |= TAHOE_PC_OR_LONG;
/* We now know how big it will be, one long word. */
fragP->fr_fix += 1 + 4;
- fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol, 0,
+ fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol,
fragP->fr_offset, FX_PCREL32, NULL);
frag_wane (fragP);
}
*p++ = TAHOE_JMP;
*p++ = TAHOE_PC_REL_LONG;
fragP->fr_fix += 1 + 1 + 1 + 4;
- fix_new (fragP, old_fr_fix + 3, fragP->fr_symbol, 0,
+ fix_new (fragP, old_fr_fix + 3, fragP->fr_symbol,
fragP->fr_offset, FX_PCREL32, NULL);
frag_wane (fragP);
}
*p++ = TAHOE_JMP;
*p++ = TAHOE_PC_REL_LONG;
fragP->fr_fix += 2 + 2 + 4;
- fix_new (fragP, old_fr_fix + 4, fragP->fr_symbol, 0,
+ fix_new (fragP, old_fr_fix + 4, fragP->fr_symbol,
fragP->fr_offset, FX_PCREL32, NULL);
frag_wane (fragP);
}
*p++ = TAHOE_JMP;
*p++ = TAHOE_PC_REL_LONG;
fragP->fr_fix += 2 + 2 + 2 + 4;
- fix_new (fragP, old_fr_fix + 6, fragP->fr_symbol, 0,
+ fix_new (fragP, old_fr_fix + 6, fragP->fr_symbol,
fragP->fr_offset, FX_PCREL32, NULL);
frag_wane (fragP);
}
*fragP->fr_opcode = TAHOE_JMP;
*p++ = TAHOE_PC_REL_LONG;
fragP->fr_fix += 1 + 4;
- fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol, 0,
+ fix_new (fragP, old_fr_fix + 1, fragP->fr_symbol,
fragP->fr_offset, FX_PCREL32, NULL);
frag_wane (fragP);
}
/* statement has no syntax goofs yet: lets sniff the expression */
input_line_pointer = point;
expP = &(topP->exp_of_operand);
- switch (expression (expP))
+ topP->seg_of_operand = expression (expP);
+ switch (expP->X_op)
{
- /* If expression == SEG_PASS1, expression() will have set
- need_pass_2 = 1. */
- case SEG_ABSENT:
+ case O_absent:
/* No expression. For BSD4.2 compatibility, missing expression is
- absolute 0 */
- expP->X_seg = SEG_ABSOLUTE;
+ absolute 0 */
+ expP->X_op = O_constant;
expP->X_add_number = 0;
really_none = 1;
- case SEG_ABSOLUTE:
- /* for SEG_ABSOLUTE, we shouldnt need to set X_subtract_symbol,
- X_add_symbol to any particular value. */
+ case O_constant:
+ /* for SEG_ABSOLUTE, we shouldnt need to set X_op_symbol,
+ X_add_symbol to any particular value. */
/* But, we will program defensively. Since this situation occurs
- rarely so it costs us little to do so. */
+ rarely so it costs us little to do so. */
expP->X_add_symbol = NULL;
- expP->X_subtract_symbol = NULL;
+ expP->X_op_symbol = NULL;
/* How many bytes are needed to express this abs value? */
abs_width =
((((expP->X_add_number & 0xFFFFFF80) == 0) ||
((expP->X_add_number & 0xFFFFFF80) == 0xFFFFFF80)) ? 1 :
(((expP->X_add_number & 0xFFFF8000) == 0) ||
((expP->X_add_number & 0xFFFF8000) == 0xFFFF8000)) ? 2 : 4);
- case SEG_TEXT:
- case SEG_DATA:
- case SEG_BSS:
- case SEG_UNKNOWN:
+
+ case O_symbol:
break;
- case SEG_DIFFERENCE:
+ default:
/*
- * Major bug. We can't handle the case of a
- * SEG_DIFFERENCE expression in a synthetic opcode
- * variable-length instruction.
- * We don't have a frag type that is smart enough to
- * relax a SEG_DIFFERENCE, and so we just force all
- * SEG_DIFFERENCEs to behave like SEG_PASS1s.
- * Clearly, if there is a demand we can invent a new or
- * modified frag type and then coding up a frag for this
- * case will be easy. SEG_DIFFERENCE was invented for the
- * .words after a CASE opcode, and was never intended for
- * instruction operands.
- */
+ * Major bug. We can't handle the case of a operator
+ * expression in a synthetic opcode variable-length
+ * instruction. We don't have a frag type that is smart
+ * enough to relax a operator, and so we just force all
+ * operators to behave like SEG_PASS1s. Clearly, if there is
+ * a demand we can invent a new or modified frag type and
+ * then coding up a frag for this case will be easy.
+ */
need_pass_2 = 1;
- case SEG_PASS1:
op_bad = "Can't relocate expression error.";
break;
- case SEG_BIG:
+ case O_big:
/* This is an error. Tahoe doesn't allow any expressions
- bigger that a 32 bit long word. Any bigger has to be referenced
- by address. */
+ bigger that a 32 bit long word. Any bigger has to be referenced
+ by address. */
op_bad = "Expression is too large for a 32 bits.";
break;
-
- default:
- as_fatal ("Complier Bug: I got segment %d in tip_op.", expP->X_seg);
- break;
}
if (*input_line_pointer != '\0')
{
/* Here to make main operand frag(s). */
this_add_number = expP->X_add_number;
this_add_symbol = expP->X_add_symbol;
- to_seg = expP->X_seg;
+ to_seg = operandP->seg_of_operand;
know (to_seg == SEG_UNKNOWN || \
to_seg == SEG_ABSOLUTE || \
to_seg == SEG_DATA || \
branch), so I set up the frag, and let GAS do the rest. */
p = frag_more (dispsize);
fix_new (frag_now, p - frag_now->fr_literal,
- this_add_symbol, 0, this_add_number,
+ this_add_symbol, this_add_number,
size_to_fx (dispsize, 1),
NULL);
}
TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
TAHOE_PC_REL_LONG);
fix_new (frag_now, p - frag_now->fr_literal,
- this_add_symbol, 0, this_add_number,
+ this_add_symbol, this_add_number,
(to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
/*
* Now (eg) BLEQ 1f
TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
TAHOE_PC_REL_LONG);
fix_new (frag_now, p - frag_now->fr_literal,
- this_add_symbol, 0, this_add_number,
+ this_add_symbol, this_add_number,
(to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
/* Now (eg) JMP foo */
break;
TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
TAHOE_PC_REL_LONG);
fix_new (frag_now, p - frag_now->fr_literal,
- this_add_symbol, 0, this_add_number,
+ this_add_symbol, this_add_number,
(to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
/*
* Now (eg) ACBx 1f
TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
TAHOE_PC_REL_LONG);
fix_new (frag_now, p - frag_now->fr_literal,
- this_add_symbol, 0, this_add_number,
+ this_add_symbol, this_add_number,
(to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);
/*
* Now (eg) xOBxxx 1f
p = frag_more (5);
*p++ = TAHOE_IMMEDIATE_LONGWORD;
fix_new (frag_now, p - frag_now->fr_literal,
- this_add_symbol, 0, this_add_number,
+ this_add_symbol, this_add_number,
FX_32, NULL);
}
else
break;
};
fix_new (frag_now, p + 1 - frag_now->fr_literal,
- this_add_symbol, 0, this_add_number,
+ this_add_symbol, this_add_number,
size_to_fx (dispsize, pc_rel), NULL);
}
break;
#include "obstack.h"
static void clean_up_expression PARAMS ((expressionS * expressionP));
+static symbolS *make_expr_symbol PARAMS ((expressionS * expressionP));
+
extern const char EXP_CHARS[], FLT_CHARS[];
+\f
+/* Build a dummy symbol to hold a complex expression. This is how we
+ build expressions up out of other expressions. The symbol is put
+ into the fake section expr_section. */
+
+static symbolS *
+make_expr_symbol (expressionP)
+ expressionS *expressionP;
+{
+ const char *fake;
+ symbolS *symbolP;
+ /* FIXME: This should be something which decode_local_label_name
+ will handle. */
+#ifdef DOT_LABEL_PREFIX
+ fake = ".L0\001";
+#else
+ fake = "L0\001";
+#endif
+ /* Putting constant symbols in absolute_section rather than
+ expr_section is convenient for the old a.out code, for which
+ S_GET_SEGMENT does not always retrieve the value put in by
+ S_SET_SEGMENT. */
+ symbolP = symbol_new (fake,
+ (expressionP->X_op == O_constant
+ ? absolute_section
+ : expr_section),
+ 0, &zero_address_frag);
+ symbolP->sy_value = *expressionP;
+ return symbolP;
+}
+\f
/*
* Build any floating-point literal here.
* Also build any bignum literal here.
as_bad ("bad floating-point constant: unknown error code=%d.", error_code);
}
}
- expressionP->X_seg = big_section;
+ expressionP->X_op = O_big;
/* input_line_pointer->just after constant, */
/* which may point to whitespace. */
expressionP->X_add_number = -1;
}
-
void
integer_constant (radix, expressionP)
int radix;
checking absoluteness. */
know (SEG_NORMAL (S_GET_SEGMENT (symbolP)));
+ expressionP->X_op = O_symbol;
expressionP->X_add_symbol = symbolP;
- expressionP->X_seg = S_GET_SEGMENT (symbolP);
}
else
the parsed number. */
as_bad ("backw. ref to unknown label \"%d:\", 0 assumed.",
(int) number);
- expressionP->X_seg = absolute_section;
+ expressionP->X_op = O_constant;
}
expressionP->X_add_number = 0;
can't have newlines in the argument. */
know (S_GET_SEGMENT (symbolP) == undefined_section || S_GET_SEGMENT (symbolP) == text_section || S_GET_SEGMENT (symbolP) == data_section);
#endif
+ expressionP->X_op = O_symbol;
expressionP->X_add_symbol = symbolP;
- expressionP->X_seg = undefined_section;
- expressionP->X_subtract_symbol = NULL;
expressionP->X_add_number = 0;
break;
symbolP = symbol_find_or_make (name);
}
+ expressionP->X_op = O_symbol;
expressionP->X_add_symbol = symbolP;
expressionP->X_add_number = 0;
- expressionP->X_seg = S_GET_SEGMENT (symbolP);
break;
} /* case '$' */
default:
{
+ expressionP->X_op = O_constant;
expressionP->X_add_number = number;
- expressionP->X_seg = absolute_section;
input_line_pointer--; /* restore following character. */
break;
} /* really just a number */
else
{
/* not a small number */
+ expressionP->X_op = O_big;
expressionP->X_add_number = number;
- expressionP->X_seg = big_section;
input_line_pointer--; /*->char following number. */
}
} /* integer_constant() */
* in: Input_line_pointer points to 1st char of operand, which may
* be a space.
*
- * out: A expressionS. X_seg determines how to understand the rest of the
- * expressionS.
- * The operand may have been empty: in this case X_seg == SEG_ABSENT.
+ * out: A expressionS.
+ * The operand may have been empty: in this case X_op == O_absent.
* Input_line_pointer->(next non-blank) char after operand.
- *
*/
-\f
-
static segT
operand (expressionP)
char c;
symbolS *symbolP; /* points to symbol */
char *name; /* points to name of symbol */
+ segT retval = absolute_section;
/* digits, assume it is a bignum. */
case '0':
/* non-decimal radix */
-
c = *input_line_pointer;
switch (c)
{
else
{
/* The string was only zero */
- expressionP->X_add_symbol = 0;
+ expressionP->X_op = O_constant;
expressionP->X_add_number = 0;
- expressionP->X_seg = absolute_section;
}
break;
case 'b':
#ifdef LOCAL_LABELS_FB
+ /* FIXME: This seems to be nonsense. At this point we know
+ for sure that *input_line_pointer is 'b'. So why are we
+ checking it? What is this code supposed to do? */
if (!*input_line_pointer
|| (!strchr ("+-.0123456789", *input_line_pointer)
&& !strchr (EXP_CHARS, *input_line_pointer)))
/* if it says '0f' and the line ends or it doesn't look like
a floating point #, its a local label ref. dtrt */
/* likewise for the b's. xoxorich. */
+ /* FIXME: As in the 'b' case, we know that the
+ *input_line_pointer is 'f'. What is this code really
+ trying to do? */
if (c == 'f'
&& (!*input_line_pointer ||
(!strchr ("+-.0123456789", *input_line_pointer) &&
}
break;
+
case '(':
/* didn't begin with digit & not a name */
- {
- (void) expression (expressionP);
- /* Expression() will pass trailing whitespace */
- if (*input_line_pointer++ != ')')
- {
- as_bad ("Missing ')' assumed");
- input_line_pointer--;
- }
- /* here with input_line_pointer->char after "(...)" */
- }
- return expressionP->X_seg;
-
+ retval = expression (expressionP);
+ /* Expression() will pass trailing whitespace */
+ if (*input_line_pointer++ != ')')
+ {
+ as_bad ("Missing ')' assumed");
+ input_line_pointer--;
+ }
+ /* here with input_line_pointer->char after "(...)" */
+ return retval;
case '\'':
/* Warning: to conform to other people's assemblers NO ESCAPEMENT is
permitted for a single quote. The next character, parity errors and
all, is taken as the value of the operand. VERY KINKY. */
+ expressionP->X_op = O_constant;
expressionP->X_add_number = *input_line_pointer++;
- expressionP->X_seg = absolute_section;
break;
case '+':
- operand (expressionP);
+ retval = operand (expressionP);
break;
case '~':
case '-':
{
- /* unary operator: hope for SEG_ABSOLUTE */
- segT opseg = operand (expressionP);
- if (opseg == absolute_section)
+ /* When computing - foo, ignore the segment of foo. It has
+ nothing to do with the segment of the result, which is
+ ill-defined. */
+ operand (expressionP);
+ if (expressionP->X_op == O_constant)
{
/* input_line_pointer -> char after operand */
if (c == '-')
{
- expressionP->X_add_number = -expressionP->X_add_number;
+ expressionP->X_add_number = - expressionP->X_add_number;
/* Notice: '-' may overflow: no warning is given. This is
compatible with other people's assemblers. Sigh. */
}
else
- {
- expressionP->X_add_number = ~expressionP->X_add_number;
- }
+ expressionP->X_add_number = ~ expressionP->X_add_number;
}
- else if (opseg == text_section
- || opseg == data_section
- || opseg == bss_section
- || opseg == pass1_section
- || opseg == undefined_section)
+ else if (expressionP->X_op != O_illegal
+ && expressionP->X_op != O_absent)
{
+ expressionP->X_add_symbol = make_expr_symbol (expressionP);
if (c == '-')
- {
- expressionP->X_subtract_symbol = expressionP->X_add_symbol;
- expressionP->X_add_symbol = 0;
- expressionP->X_seg = diff_section;
- }
+ expressionP->X_op = O_uminus;
else
- as_warn ("Unary operator %c ignored because bad operand follows",
- c);
+ expressionP->X_op = O_bit_not;
+ expressionP->X_add_number = 0;
}
else
- as_warn ("Unary operator %c ignored because bad operand follows", c);
+ as_warn ("Unary operator %c ignored because bad operand follows",
+ c);
}
break;
case '.':
if (!is_part_of_name (*input_line_pointer))
{
- char *fake;
- extern struct obstack frags;
+ const char *fake;
/* JF: '.' is pseudo symbol with value of current location
in current segment. */
#endif
symbolP = symbol_new (fake,
now_seg,
- (valueT) ((char*)obstack_next_free (&frags) - frag_now->fr_literal),
+ (valueT) frag_now_fix (),
frag_now);
- expressionP->X_add_number = 0;
+ expressionP->X_op = O_symbol;
expressionP->X_add_symbol = symbolP;
- expressionP->X_seg = now_seg;
+ expressionP->X_add_number = 0;
+ retval = now_seg;
break;
-
}
else
{
goto isname;
-
-
}
case ',':
case '\n':
case '\0':
eol:
/* can't imagine any other kind of operand */
- expressionP->X_seg = absent_section;
+ expressionP->X_op = O_absent;
input_line_pointer--;
md_operand (expressionP);
break;
name = --input_line_pointer;
c = get_symbol_end ();
symbolP = symbol_find_or_make (name);
- /* If we have an absolute symbol or a reg, then we know its value
- now. */
- expressionP->X_seg = S_GET_SEGMENT (symbolP);
- if (expressionP->X_seg == absolute_section
- || expressionP->X_seg == reg_section)
- expressionP->X_add_number = S_GET_VALUE (symbolP);
+
+ /* If we have an absolute symbol or a reg, then we know its
+ value now. */
+ retval = S_GET_SEGMENT (symbolP);
+ if (retval == absolute_section)
+ {
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = S_GET_VALUE (symbolP);
+ }
+ else if (retval == reg_section)
+ {
+ expressionP->X_op = O_register;
+ expressionP->X_add_number = S_GET_VALUE (symbolP);
+ }
else
{
- expressionP->X_add_number = 0;
+ expressionP->X_op = O_symbol;
expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_number = 0;
}
*input_line_pointer = c;
- expressionP->X_subtract_symbol = NULL;
}
else
{
as_bad ("Bad expression");
+ expressionP->X_op = O_constant;
expressionP->X_add_number = 0;
- expressionP->X_seg = absolute_section;
}
}
clean_up_expression (expressionP);
SKIP_WHITESPACE (); /*->1st char after operand. */
know (*input_line_pointer != ' ');
- return (expressionP->X_seg);
+ return expressionP->X_op == O_constant ? absolute_section : retval;
} /* operand() */
\f
-
/* Internal. Simplify a struct expression for use by expr() */
/*
* In: address of a expressionS.
- * The X_seg field of the expressionS may only take certain values.
- * Now, we permit SEG_PASS1 to make code smaller & faster.
+ * The X_op field of the expressionS may only take certain values.
* Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT.
* Out: expressionS may have been modified:
* 'foo-foo' symbol references cancelled to 0,
- * which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
+ * which changes X_op from O_subtract to O_constant.
* Unused fields zeroed to help expr().
*/
clean_up_expression (expressionP)
expressionS *expressionP;
{
- segT s = expressionP->X_seg;
- if (s == absent_section
- || s == pass1_section)
+ switch (expressionP->X_op)
{
- expressionP->X_add_symbol = NULL;
- expressionP->X_subtract_symbol = NULL;
+ case O_illegal:
+ case O_absent:
expressionP->X_add_number = 0;
- }
- else if (s == big_section
- || s == absolute_section)
- {
- expressionP->X_subtract_symbol = NULL;
+ /* Fall through. */
+ case O_big:
+ case O_constant:
+ case O_register:
expressionP->X_add_symbol = NULL;
- }
- else if (s == undefined_section)
- expressionP->X_subtract_symbol = NULL;
- else if (s == diff_section)
- {
- /*
- * It does not hurt to 'cancel' NULL==NULL
- * when comparing symbols for 'eq'ness.
- * It is faster to re-cancel them to NULL
- * than to check for this special case.
- */
- if (expressionP->X_subtract_symbol == expressionP->X_add_symbol
- || (expressionP->X_subtract_symbol
- && expressionP->X_add_symbol
- && (expressionP->X_subtract_symbol->sy_frag
- == expressionP->X_add_symbol->sy_frag)
+ /* Fall through. */
+ case O_symbol:
+ case O_uminus:
+ case O_bit_not:
+ expressionP->X_op_symbol = NULL;
+ break;
+ case O_subtract:
+ if (expressionP->X_op_symbol == expressionP->X_add_symbol
+ || ((expressionP->X_op_symbol->sy_frag
+ == expressionP->X_add_symbol->sy_frag)
&& SEG_NORMAL (S_GET_SEGMENT (expressionP->X_add_symbol))
- && (S_GET_VALUE (expressionP->X_subtract_symbol)
+ && (S_GET_VALUE (expressionP->X_op_symbol)
== S_GET_VALUE (expressionP->X_add_symbol))))
{
- expressionP->X_subtract_symbol = NULL;
+ expressionP->X_op = O_constant;
expressionP->X_add_symbol = NULL;
- expressionP->X_seg = absolute_section;
- }
- }
- else if (s == reg_section)
- {
- expressionP->X_add_symbol = NULL;
- expressionP->X_subtract_symbol = NULL;
- }
- else
- {
- if (SEG_NORMAL (expressionP->X_seg))
- {
- expressionP->X_subtract_symbol = NULL;
- }
- else
- {
- BAD_CASE (expressionP->X_seg);
- }
- }
-}
-\f
-/*
- * expr_part ()
- *
- * Internal. Made a function because this code is used in 2 places.
- * Generate error or correct X_?????_symbol of expressionS.
- */
-
-/*
- * symbol_1 += symbol_2 ... well ... sort of.
- */
-
-static segT
-expr_part (symbol_1_PP, symbol_2_P)
- symbolS **symbol_1_PP;
- symbolS *symbol_2_P;
-{
- segT return_value;
-
-#if !defined (BFD_ASSEMBLER) && (defined (OBJ_AOUT) || defined (OBJ_BOUT))
- int test = ((*symbol_1_PP) == NULL
- || (S_GET_SEGMENT (*symbol_1_PP) == text_section)
- || (S_GET_SEGMENT (*symbol_1_PP) == data_section)
- || (S_GET_SEGMENT (*symbol_1_PP) == bss_section)
- || (!S_IS_DEFINED (*symbol_1_PP)));
- assert (test);
- test = (symbol_2_P == NULL
- || (S_GET_SEGMENT (symbol_2_P) == text_section)
- || (S_GET_SEGMENT (symbol_2_P) == data_section)
- || (S_GET_SEGMENT (symbol_2_P) == bss_section)
- || (!S_IS_DEFINED (symbol_2_P)));
- assert (test);
-#endif
- if (*symbol_1_PP)
- {
- if (!S_IS_DEFINED (*symbol_1_PP))
- {
- if (symbol_2_P)
- {
- return_value = pass1_section;
- *symbol_1_PP = NULL;
- }
- else
- {
- know (!S_IS_DEFINED (*symbol_1_PP));
- return_value = undefined_section;
- }
- }
- else
- {
- if (symbol_2_P)
- {
- if (!S_IS_DEFINED (symbol_2_P))
- {
- *symbol_1_PP = NULL;
- return_value = pass1_section;
- }
- else
- {
- /* {seg1} - {seg2} */
- as_bad ("Expression too complex, 2 symbolS forgotten: \"%s\" \"%s\"",
- S_GET_NAME (*symbol_1_PP), S_GET_NAME (symbol_2_P));
- *symbol_1_PP = NULL;
- return_value = absolute_section;
- }
- }
- else
- {
- return_value = S_GET_SEGMENT (*symbol_1_PP);
- }
- }
- }
- else
- { /* (* symbol_1_PP) == NULL */
- if (symbol_2_P)
- {
- *symbol_1_PP = symbol_2_P;
- return_value = S_GET_SEGMENT (symbol_2_P);
- }
- else
- {
- *symbol_1_PP = NULL;
- return_value = absolute_section;
+ expressionP->X_op_symbol = NULL;
}
+ break;
+ default:
+ break;
}
-#if defined (OBJ_AOUT) && !defined (BFD_ASSEMBLER)
- test = (return_value == absolute_section
- || return_value == text_section
- || return_value == data_section
- || return_value == bss_section
- || return_value == undefined_section
- || return_value == pass1_section);
- assert (test);
-#endif
- know ((*symbol_1_PP) == NULL
- || (S_GET_SEGMENT (*symbol_1_PP) == return_value));
- return (return_value);
}
\f
/* Expression parser. */
* After expr(RANK,resultP) input_line_pointer->operator of rank <= RANK.
* Also, we have consumed any leading or trailing spaces (operand does that)
* and done all intervening operators.
+ *
+ * This returns the segment of the result, which will be
+ * absolute_section or the segment of a symbol.
*/
-typedef enum
-{
- O_illegal, /* (0) what we get for illegal op */
-
- O_multiply, /* (1) * */
- O_divide, /* (2) / */
- O_modulus, /* (3) % */
- O_left_shift, /* (4) < */
- O_right_shift, /* (5) > */
- O_bit_inclusive_or, /* (6) | */
- O_bit_or_not, /* (7) ! */
- O_bit_exclusive_or, /* (8) ^ */
- O_bit_and, /* (9) & */
- O_add, /* (10) + */
- O_subtract /* (11) - */
-}
-
-operatorT;
-
#undef __
#define __ O_illegal
* 1 + -
* 2 & ^ ! |
* 3 * / % << >>
+ * 4 unary - unary ~
*/
-static const operator_rankT
- op_rank[] =
-{0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1};
+static const operator_rankT op_rank[] =
+{
+ 0, /* O_illegal */
+ 0, /* O_absent */
+ 0, /* O_constant */
+ 0, /* O_symbol */
+ 0, /* O_register */
+ 0, /* O_bit */
+ 4, /* O_uminus */
+ 4, /* O_bit_now */
+ 3, /* O_multiply */
+ 3, /* O_divide */
+ 3, /* O_modulus */
+ 3, /* O_left_shift */
+ 3, /* O_right_shift */
+ 2, /* O_bit_inclusive_or */
+ 2, /* O_bit_or_not */
+ 2, /* O_bit_exclusive_or */
+ 2, /* O_bit_and */
+ 1, /* O_add */
+ 1, /* O_subtract */
+};
\f
-/* Return resultP->X_seg. */
-segT
+segT
expr (rank, resultP)
operator_rankT rank; /* Larger # is higher rank. */
expressionS *resultP; /* Deliver result here. */
{
+ segT retval;
expressionS right;
operatorT op_left;
char c_left; /* 1st operator character. */
char c_right;
know (rank >= 0);
- (void) operand (resultP);
+
+ retval = operand (resultP);
+
know (*input_line_pointer != ' '); /* Operand() gobbles spaces. */
+
c_left = *input_line_pointer; /* Potential operator character. */
op_left = op_encoding[c_left];
while (op_left != O_illegal && op_rank[(int) op_left] > rank)
{
+ segT rightseg;
+
input_line_pointer++; /*->after 1st character of operator. */
/* Operators "<<" and ">>" have 2 characters. */
if (*input_line_pointer == c_left && (c_left == '<' || c_left == '>'))
+ ++input_line_pointer;
+
+ rightseg = expr (op_rank[(int) op_left], &right);
+ if (right.X_op == O_absent)
{
- input_line_pointer++;
- } /*->after operator. */
- if (absent_section == expr (op_rank[(int) op_left], &right))
- {
- as_warn ("Missing operand value assumed absolute 0.");
- resultP->X_add_number = 0;
- resultP->X_subtract_symbol = NULL;
+ as_warn ("missing operand; zero assumed");
+ right.X_op = O_constant;
+ right.X_add_number = 0;
resultP->X_add_symbol = NULL;
- resultP->X_seg = absolute_section;
+ resultP->X_op_symbol = NULL;
}
+
know (*input_line_pointer != ' ');
+
+ if (! SEG_NORMAL (retval))
+ retval = rightseg;
+ else if (SEG_NORMAL (rightseg)
+ && retval != rightseg)
+ as_bad ("operation combines symbols in different segments");
+
c_right = *input_line_pointer;
op_right = op_encoding[c_right];
if (*input_line_pointer == c_right && (c_right == '<' || c_right == '>'))
- {
- input_line_pointer++;
- } /*->after operator. */
- know ((int) op_right == 0 || op_rank[(int) op_right] <= op_rank[(int) op_left]);
+ ++input_line_pointer;
+
+ know (op_right == O_illegal || op_rank[(int) op_right] <= op_rank[(int) op_left]);
+ know ((int) op_left >= (int) O_multiply && (int) op_left <= (int) O_subtract);
+
/* input_line_pointer->after right-hand quantity. */
/* left-hand quantity in resultP */
/* right-hand quantity in right. */
/* operator in op_left. */
- if (resultP->X_seg == pass1_section || right.X_seg == pass1_section)
+
+ if (resultP->X_op == O_big)
{
- resultP->X_seg = pass1_section;
+ as_warn ("left operand of %c is a %s; integer 0 assumed",
+ c_left, resultP->X_add_number > 0 ? "bignum" : "float");
+ resultP->X_op = O_constant;
+ resultP->X_add_number = 0;
+ resultP->X_add_symbol = NULL;
+ resultP->X_op_symbol = NULL;
}
- else
+ if (right.X_op == O_big)
{
- if (resultP->X_seg == big_section)
- {
- as_warn ("Left operand of %c is a %s. Integer 0 assumed.",
- c_left, resultP->X_add_number > 0 ? "bignum" : "float");
- resultP->X_seg = absolute_section;
- resultP->X_add_symbol = 0;
- resultP->X_subtract_symbol = 0;
- resultP->X_add_number = 0;
- }
- if (right.X_seg == big_section)
+ as_warn ("right operand of %c is a %s; integer 0 assumed",
+ c_left, right.X_add_number > 0 ? "bignum" : "float");
+ right.X_op = O_constant;
+ right.X_add_number = 0;
+ right.X_add_symbol = NULL;
+ right.X_op_symbol = NULL;
+ }
+
+ /* Optimize common cases. */
+ if (op_left == O_add && right.X_op == O_constant)
+ {
+ /* X + constant. */
+ resultP->X_add_number += right.X_add_number;
+ }
+ else if (op_left == O_subtract && right.X_op == O_constant)
+ {
+ /* X - constant. */
+ resultP->X_add_number -= right.X_add_number;
+ }
+ else if (op_left == O_add && resultP->X_op == O_constant)
+ {
+ /* Constant + X. */
+ resultP->X_op = right.X_op;
+ resultP->X_add_symbol = right.X_add_symbol;
+ resultP->X_op_symbol = right.X_op_symbol;
+ resultP->X_add_number += right.X_add_number;
+ retval = rightseg;
+ }
+ else if (resultP->X_op == O_constant && right.X_op == O_constant)
+ {
+ /* Constant OP constant. */
+ offsetT v = right.X_add_number;
+ if (v == 0 && (op_left == O_divide || op_left == O_modulus))
{
- as_warn ("Right operand of %c is a %s. Integer 0 assumed.",
- c_left, right.X_add_number > 0 ? "bignum" : "float");
- right.X_seg = absolute_section;
- right.X_add_symbol = 0;
- right.X_subtract_symbol = 0;
- right.X_add_number = 0;
+ as_warn ("division by zero");
+ v = 1;
}
- if (op_left == O_subtract)
+ switch (op_left)
{
- /*
- * Convert - into + by exchanging symbolS and negating number.
- * I know -infinity can't be negated in 2's complement:
- * but then it can't be subtracted either. This trick
- * does not cause any further inaccuracy.
- */
-
- symbolS *symbolP;
-
- right.X_add_number = -right.X_add_number;
- symbolP = right.X_add_symbol;
- right.X_add_symbol = right.X_subtract_symbol;
- right.X_subtract_symbol = symbolP;
- if (symbolP)
- {
- right.X_seg = diff_section;
- }
- op_left = O_add;
+ case O_multiply: resultP->X_add_number *= v; break;
+ case O_divide: resultP->X_add_number /= v; break;
+ case O_modulus: resultP->X_add_number %= v; break;
+ case O_left_shift: resultP->X_add_number <<= v; break;
+ case O_right_shift: resultP->X_add_number >>= v; break;
+ case O_bit_inclusive_or: resultP->X_add_number |= v; break;
+ case O_bit_or_not: resultP->X_add_number |= ~v; break;
+ case O_bit_exclusive_or: resultP->X_add_number ^= v; break;
+ case O_bit_and: resultP->X_add_number &= v; break;
+ case O_add: resultP->X_add_number += v; break;
+ case O_subtract: resultP->X_add_number -= v; break;
+ default: abort ();
}
-\f
+ }
+ else if (resultP->X_op == O_symbol
+ && right.X_op == O_symbol
+ && (op_left == O_add
+ || op_left == O_subtract
+ || (resultP->X_add_number == 0
+ && right.X_add_number == 0)))
+ {
+ /* Symbol OP symbol. */
+ resultP->X_op = op_left;
+ resultP->X_op_symbol = right.X_add_symbol;
if (op_left == O_add)
- {
- segT seg1;
- segT seg2;
-#if 0 /* @@ This rejects stuff in common sections too. Figure out some
- reasonable test, and make it clean... */
-#if !defined (MANY_SEGMENTS) && !defined (OBJ_ECOFF)
- know (resultP->X_seg == data_section || resultP->X_seg == text_section || resultP->X_seg == bss_section || resultP->X_seg == undefined_section || resultP->X_seg == diff_section || resultP->X_seg == absolute_section || resultP->X_seg == pass1_section || resultP->X_seg == reg_section);
-
- know (right.X_seg == data_section || right.X_seg == text_section || right.X_seg == bss_section || right.X_seg == undefined_section || right.X_seg == diff_section || right.X_seg == absolute_section || right.X_seg == pass1_section);
-#endif
-#endif /* 0 */
- clean_up_expression (&right);
- clean_up_expression (resultP);
-
- seg1 = expr_part (&resultP->X_add_symbol, right.X_add_symbol);
- seg2 = expr_part (&resultP->X_subtract_symbol, right.X_subtract_symbol);
- if (seg1 == pass1_section || seg2 == pass1_section)
- {
- need_pass_2 = 1;
- resultP->X_seg = pass1_section;
- }
- else if (seg2 == absolute_section)
- resultP->X_seg = seg1;
- else if (seg1 != undefined_section
- && seg1 != absolute_section
- && seg2 != undefined_section
- && seg1 != seg2)
- {
- know (seg2 != absolute_section);
- know (resultP->X_subtract_symbol);
-#ifndef MANY_SEGMENTS
-#ifndef OBJ_ECOFF
- know (seg1 == text_section || seg1 == data_section || seg1 == bss_section);
- know (seg2 == text_section || seg2 == data_section || seg2 == bss_section);
-#endif
-#endif
- know (resultP->X_add_symbol);
- know (resultP->X_subtract_symbol);
- as_bad ("Expression too complex: forgetting %s - %s",
- S_GET_NAME (resultP->X_add_symbol),
- S_GET_NAME (resultP->X_subtract_symbol));
- resultP->X_seg = absolute_section;
- /* Clean_up_expression() will do the rest. */
- }
- else
- resultP->X_seg = diff_section;
-
- resultP->X_add_number += right.X_add_number;
- clean_up_expression (resultP);
- }
- else
- { /* Not +. */
- if (resultP->X_seg == undefined_section || right.X_seg == undefined_section)
- {
- resultP->X_seg = pass1_section;
- need_pass_2 = 1;
- }
- else
- {
- resultP->X_subtract_symbol = NULL;
- resultP->X_add_symbol = NULL;
- /* Will be absolute_section. */
- if (resultP->X_seg != absolute_section || right.X_seg != absolute_section)
- {
- as_bad ("Relocation error: Symbolic expressions may only involve");
- as_bad (" addition and subtraction. Absolute 0 assumed.");
- resultP->X_seg = absolute_section;
- resultP->X_add_number = 0;
- }
- else
- {
- switch (op_left)
- {
- case O_bit_inclusive_or:
- resultP->X_add_number |= right.X_add_number;
- break;
-
- case O_modulus:
- if (right.X_add_number)
- {
- resultP->X_add_number %= right.X_add_number;
- }
- else
- {
- as_warn ("Division by 0. Result of 0 substituted.");
- resultP->X_add_number = 0;
- }
- break;
-
- case O_bit_and:
- resultP->X_add_number &= right.X_add_number;
- break;
-
- case O_multiply:
- resultP->X_add_number *= right.X_add_number;
- break;
-
- case O_divide:
- if (right.X_add_number)
- {
- resultP->X_add_number /= right.X_add_number;
- }
- else
- {
- as_warn ("Division by 0. 0 assumed.");
- resultP->X_add_number = 0;
- }
- break;
-
- case O_left_shift:
- resultP->X_add_number <<= right.X_add_number;
- break;
-
- case O_right_shift:
- /* @@ We should distinguish signed versus
- unsigned here somehow. */
- resultP->X_add_number >>= right.X_add_number;
- break;
-
- case O_bit_exclusive_or:
- resultP->X_add_number ^= right.X_add_number;
- break;
-
- case O_bit_or_not:
- resultP->X_add_number |= ~right.X_add_number;
- break;
-
- default:
- BAD_CASE (op_left);
- break;
- } /* switch(operator) */
- }
- } /* If we have to force need_pass_2. */
- } /* If operator was +. */
- } /* If we didn't set need_pass_2. */
+ resultP->X_add_number += right.X_add_number;
+ else if (op_left == O_subtract)
+ resultP->X_add_number -= right.X_add_number;
+ }
+ else
+ {
+ /* The general case. */
+ resultP->X_add_symbol = make_expr_symbol (resultP);
+ resultP->X_op_symbol = make_expr_symbol (&right);
+ resultP->X_op = op_left;
+ resultP->X_add_number = 0;
+ }
+
op_left = op_right;
} /* While next operator is >= this rank. */
- return (resultP->X_seg);
+
+ return resultP->X_op == O_constant ? absolute_section : retval;
}
\f
/*
/* read.c - read a source file -
- Copyright (C) 1986, 1987, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1986, 1987, 1990, 1991, 1993 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
static char *demand_copy_string PARAMS ((int *lenP));
int is_it_end_of_statement PARAMS ((void));
unsigned int next_char_of_string 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));
register segT segment;
expressionS exp;
register symbolS *symbolP;
+ valueT val;
/* we permit ANY defined expression: BSD4.2 demands constants */
name = input_line_pointer;
return;
}
input_line_pointer++;
- segment = expression (&exp);
- if (segment != absolute_section
- && segment != reg_section
- && ! SEG_NORMAL (segment))
- {
- as_bad ("Bad expression: %s", segment_name (segment));
- ignore_rest_of_line ();
- return;
- }
+ val = get_absolute_expression ();
*p = 0;
symbolP = symbol_find_or_make (name);
/* The name might be an undefined .global symbol; be sure to
keep the "external" bit. */
S_SET_SEGMENT (symbolP, segment);
- S_SET_VALUE (symbolP, (valueT) (exp.X_add_number));
+ S_SET_VALUE (symbolP, val);
}
else
{
* Out: Input_line_pointer->just after any whitespace after expression.
* Tried to set symbol to value of expression.
* Will change symbols type, value, and frag;
- * May set need_pass_2 == 1.
*/
void
pseudo_set (symbolP)
symbolS *symbolP;
{
expressionS exp;
- register segT segment;
#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
int ext;
#endif /* OBJ_AOUT or OBJ_BOUT */
ext = S_IS_EXTERNAL (symbolP);
#endif /* OBJ_AOUT or OBJ_BOUT */
- if ((segment = expression (&exp)) == absent_section)
- {
- as_bad ("Missing expression: absolute 0 assumed");
- exp.X_seg = absolute_section;
- exp.X_add_number = 0;
- }
+ (void) expression (&exp);
- if (segment == reg_section)
- {
- S_SET_SEGMENT (symbolP, reg_section);
- S_SET_VALUE (symbolP, exp.X_add_number);
- symbolP->sy_frag = &zero_address_frag;
- }
- else if (segment == big_section)
+ if (exp.X_op == O_illegal)
+ as_bad ("illegal expression; zero assumed");
+ else if (exp.X_op == O_absent)
+ as_bad ("missing expression; zero assumed");
+ else if (exp.X_op == O_big)
+ as_bad ("%s number invalid; zero assumed",
+ exp.X_add_number > 0 ? "bignum" : "floating point");
+ else if (exp.X_op == O_subtract
+ && (S_GET_SEGMENT (exp.X_add_symbol)
+ == S_GET_SEGMENT (exp.X_op_symbol))
+ && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
+ && exp.X_add_symbol->sy_frag == exp.X_op_symbol->sy_frag)
{
- as_bad ("%s number invalid. Absolute 0 assumed.",
- exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
- S_SET_SEGMENT (symbolP, absolute_section);
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
- /* @@ Fix this right for BFD. */
- ext ? S_SET_EXTERNAL (symbolP) :
- S_CLEAR_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
- S_SET_VALUE (symbolP, 0);
- symbolP->sy_frag = &zero_address_frag;
+ exp.X_op = O_constant;
+ exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
+ - S_GET_VALUE (exp.X_op_symbol));
}
- else if (segment == absent_section)
+
+ switch (exp.X_op)
{
- as_warn ("No expression: Using absolute 0");
+ case O_illegal:
+ case O_absent:
+ case O_big:
+ exp.X_add_number = 0;
+ /* Fall through. */
+ case O_constant:
S_SET_SEGMENT (symbolP, absolute_section);
#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
/* @@ Fix this right for BFD. */
- ext ? S_SET_EXTERNAL (symbolP) :
- S_CLEAR_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
- S_SET_VALUE (symbolP, 0);
- symbolP->sy_frag = &zero_address_frag;
- }
- else if (segment == diff_section)
- {
- if (exp.X_add_symbol && exp.X_subtract_symbol
- && (S_GET_SEGMENT (exp.X_add_symbol) ==
- S_GET_SEGMENT (exp.X_subtract_symbol)))
- {
- if (exp.X_add_symbol->sy_frag == exp.X_subtract_symbol->sy_frag)
- {
- exp.X_add_number += S_GET_VALUE (exp.X_add_symbol) -
- S_GET_VALUE (exp.X_subtract_symbol);
- goto abs;
- }
- symbolP->sy_value = exp;
- }
+ if (ext)
+ S_SET_EXTERNAL (symbolP);
else
- {
- as_bad ("Complex expression. Absolute segment assumed.");
- goto abs;
- }
- }
- else if (segment == absolute_section)
- {
- abs:
- S_SET_SEGMENT (symbolP, absolute_section);
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
- /* @@ Fix this right for BFD. */
- ext ? S_SET_EXTERNAL (symbolP) :
S_CLEAR_EXTERNAL (symbolP);
#endif /* OBJ_AOUT or OBJ_BOUT */
S_SET_VALUE (symbolP, exp.X_add_number);
symbolP->sy_frag = &zero_address_frag;
- }
- else if (segment == pass1_section)
- {
- symbolP->sy_value.X_add_symbol = exp.X_add_symbol;
- symbolP->sy_value.X_subtract_symbol = NULL;
- symbolP->sy_value.X_add_number = 0;
- symbolP->sy_value.X_seg = undefined_section;
- as_bad ("Unknown expression");
- know (need_pass_2 == 1);
- }
- else if (segment == undefined_section)
- {
- symbolP->sy_value.X_add_symbol = exp.X_add_symbol;
- symbolP->sy_value.X_subtract_symbol = NULL;
- symbolP->sy_value.X_add_number = 0;
- symbolP->sy_value.X_seg = undefined_section;
- }
- else
- {
-#ifndef BFD_ASSEMBLER
-#ifndef MANY_SEGMENTS
- switch (segment)
- {
- case SEG_DATA:
- case SEG_TEXT:
- case SEG_BSS:
- break;
+ break;
- default:
- as_fatal ("failed sanity check.");
- } /* switch on segment */
-#endif
-#endif
- S_SET_SEGMENT (symbolP, segment);
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
- /* @@ Fix this right for BFD! */
- if (ext)
- {
- S_SET_EXTERNAL (symbolP);
- }
+ case O_register:
+ S_SET_SEGMENT (symbolP, reg_section);
+ S_SET_VALUE (symbolP, exp.X_add_number);
+ symbolP->sy_frag = &zero_address_frag;
+ break;
+
+ case O_symbol:
+ if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section)
+ symbolP->sy_value = exp;
else
{
- S_CLEAR_EXTERNAL (symbolP);
- } /* if external */
+ S_SET_SEGMENT (symbolP, S_GET_SEGMENT (exp.X_add_symbol));
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ /* @@ Fix this right for BFD! */
+ if (ext)
+ S_SET_EXTERNAL (symbolP);
+ else
+ S_CLEAR_EXTERNAL (symbolP);
#endif /* OBJ_AOUT or OBJ_BOUT */
+ S_SET_VALUE (symbolP,
+ exp.X_add_number + S_GET_VALUE (exp.X_add_symbol));
+ symbolP->sy_frag = exp.X_add_symbol->sy_frag;
+ }
+ break;
- S_SET_VALUE (symbolP, exp.X_add_number + S_GET_VALUE (exp.X_add_symbol));
- symbolP->sy_frag = exp.X_add_symbol->sy_frag;
+ default:
+ /* The value is some complex expression.
+ FIXME: Should we set the segment to anything? */
+ symbolP->sy_value = exp;
+ break;
}
}
\f
expressionS *exp;
unsigned int nbytes;
{
- segT segment;
+ operatorT op;
register char *p;
/* Don't do anything if we are going to make another pass. */
if (need_pass_2)
return;
- segment = exp->X_seg;
-
- /* Don't call this if we are going to junk this pass anyway! */
- know (segment != pass1_section);
+ op = exp->X_op;
- if (segment == diff_section && exp->X_add_symbol == NULL)
+ if (op == O_absent || op == O_illegal)
{
- as_bad ("Subtracting symbol \"%s\" (segment \"%s\") is too hard. Absolute segment assumed.",
- S_GET_NAME (exp->X_subtract_symbol),
- segment_name (S_GET_SEGMENT (exp->X_subtract_symbol)));
- segment = absolute_section;
- /* Leave exp->X_add_number alone. */
+ as_warn ("zero assumed for missing expression");
+ exp->X_add_number = 0;
+ op = O_constant;
}
- else if (segment == absent_section)
+ else if (op == O_big)
{
- as_warn ("0 assumed for missing expression");
+ as_bad ("%s number invalid; zero assumed",
+ exp->X_add_number > 0 ? "bignum" : "floating point");
exp->X_add_number = 0;
- know (exp->X_add_symbol == NULL);
- segment = absolute_section;
+ op = O_constant;
}
- else if (segment == big_section)
+ else if (op == O_register)
{
- as_bad ("%s number invalid. Absolute 0 assumed.",
- exp->X_add_number > 0 ? "Bignum" : "Floating-Point");
- exp->X_add_number = 0;
- segment = absolute_section;
+ as_warn ("register value used as expression");
+ op = O_constant;
}
p = frag_more (nbytes);
#ifndef WORKING_DOT_WORD
/* If we have the difference of two symbols in a word, save it on
the broken_words list. See the code in write.c. */
- if (segment == diff_section && nbytes == 2)
+ if (op == O_subtract && nbytes == 2)
{
struct broken_word *x;
x->word_goes_here = p;
x->dispfrag = 0;
x->add = exp->X_add_symbol;
- x->sub = exp->X_subtract_symbol;
+ x->sub = exp->X_op_symbol;
x->addnum = exp->X_add_number;
x->added = 0;
new_broken_words++;
}
#endif
- if (segment == absolute_section)
+ if (op == O_constant)
{
register long get;
register long use;
defined, and otherwise uses 0. */
#ifdef BFD_ASSEMBLER
- fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- exp->X_add_symbol, exp->X_subtract_symbol,
- exp->X_add_number, 0,
- /* @@ Should look at CPU word size. */
- BFD_RELOC_32);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes, exp, 0,
+ /* @@ Should look at CPU word size. */
+ BFD_RELOC_32);
#else
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
#define TC_CONS_RELOC 0
#endif
#endif
- fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- exp->X_add_symbol, exp->X_subtract_symbol,
- exp->X_add_number, 0, TC_CONS_RELOC);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes, exp, 0,
+ TC_CONS_RELOC);
#endif /* TC_CONS_FIX_NEW */
#endif /* BFD_ASSEMBLER */
}
{
unsigned int bits_available = BITS_PER_CHAR * nbytes;
char *hold = input_line_pointer;
- segT segment;
- segment = expression (exp);
+ (void) expression (exp);
if (*input_line_pointer == ':')
{ /* bitfields */
you can use a previous .set or
.equ type symbol. xoxorich. */
- if (segment == absent_section)
+ if (exp->X_op == O_absent)
{
- as_warn ("Using a bit field width of zero.");
+ as_warn ("using a bit field width of zero");
exp->X_add_number = 0;
- segment = absolute_section;
+ exp->X_op = O_constant;
} /* implied zero width bitfield */
- if (segment != absolute_section)
+ if (exp->X_op != O_constant)
{
*input_line_pointer = '\0';
- as_bad ("Field width \"%s\" too complex for a bitfield.\n", hold);
+ as_bad ("field width \"%s\" too complex for a bitfield", hold);
*input_line_pointer = ':';
demand_empty_rest_of_line ();
return;
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 %d too big to fit in %d bytes: truncated to %d bits",
width, nbytes, (BITS_PER_CHAR * nbytes));
width = BITS_PER_CHAR * nbytes;
} /* too big */
hold = ++input_line_pointer; /* skip ':' */
- if ((segment = expression (exp)) != absolute_section)
+ (void) expression (exp);
+ if (exp->X_op != O_constant)
{
char cache = *input_line_pointer;
*input_line_pointer = '\0';
- as_bad ("Field value \"%s\" too complex for a bitfield.\n", hold);
+ as_bad ("field value \"%s\" too complex for a bitfield", hold);
*input_line_pointer = cache;
demand_empty_rest_of_line ();
return;
} /* too complex */
- value |= (~(-1 << width) & exp->X_add_number)
- << ((BITS_PER_CHAR * nbytes) - bits_available);
+ value |= ((~(-1 << width) & exp->X_add_number)
+ << ((BITS_PER_CHAR * nbytes) - bits_available));
if ((bits_available -= width) == 0
|| is_it_end_of_statement ()
} /* all the bitfields we're gonna get */
hold = ++input_line_pointer;
- segment = expression (exp);
+ (void) expression (exp);
} /* forever loop */
exp->X_add_number = value;
- exp->X_seg = absolute_section;
+ exp->X_op = O_constant;
} /* if looks like a bitfield */
} /* parse_bitfield_cons() */
scan++;
}
/* Create correct expression */
- exp->X_add_symbol = 0;
+ exp->X_op = O_constant;
exp->X_add_number = result;
- exp->X_seg = absolute_section;
/* Fake it so that we can read the next char too */
if (input_line_pointer[0] != '\'' ||
(input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
unsigned int nbytes;
{
expressionS count;
- segT segment;
register int i;
expression (exp);
}
++input_line_pointer;
- segment = expression (&count);
- if (segment != absolute_section
+ expression (&count);
+ if (count.X_op != O_constant
|| count.X_add_number <= 0)
{
as_warn ("Unresolvable or nonpositive repeat count; using 1");
#ifdef REPEAT_CONS_EXPRESSIONS
if (*input_line_pointer == ':')
{
- segT segment;
expressionS count_exp;
++input_line_pointer;
- segment = expression (&count_exp);
- if (segment != absolute_section
+ expression (&count_exp);
+ if (count_exp.X_op != O_constant
|| count_exp.X_add_number <= 0)
{
- as_warn ("Unresolvable or nonpositive repeat count; using 1");
+ as_warn ("unresolvable or nonpositive repeat count; using 1");
}
else
count = count_exp.X_add_number;
register segT retval;
retval = expression (expP);
- if (retval == pass1_section
- || retval == absent_section
- || retval == big_section)
+ if (expP->X_op == O_illegal
+ || expP->X_op == O_absent
+ || expP->X_op == O_big)
{
- as_bad ("Expected address expression: absolute 0 assumed");
- retval = expP->X_seg = absolute_section;
+ as_bad ("expected address expression; zero assumed");
+ expP->X_op = O_constant;
expP->X_add_number = 0;
- expP->X_add_symbol = expP->X_subtract_symbol = 0;
+ retval = absolute_section;
}
- return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */
+ return retval;
}
static segT
register expressionS *expP;
{
register segT retval;
- register CONST char *name1;
- register CONST char *name2;
if ((retval = get_segmented_expression (expP)) == undefined_section)
{
- name1 = expP->X_add_symbol ? S_GET_NAME (expP->X_add_symbol) : "";
- name2 = expP->X_subtract_symbol ?
- S_GET_NAME (expP->X_subtract_symbol) :
- "";
- if (name1 && name2)
- {
- as_warn ("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.",
- name1, name2);
- }
+ /* There is no easy way to extract the undefined symbol from the
+ expression. */
+ if (expP->X_add_symbol != NULL
+ && S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
+ as_warn ("symbol \"%s\" undefined; zero assumed",
+ S_GET_NAME (expP->X_add_symbol));
else
- {
- as_warn ("Symbol \"%s\" undefined: absolute 0 assumed.",
- name1 ? name1 : name2);
- }
- retval = expP->X_seg = absolute_section;
+ as_warn ("some symbol undefined; zero assumed");
+ retval = absolute_section;
+ expP->X_op = O_constant;
expP->X_add_number = 0;
- expP->X_add_symbol = expP->X_subtract_symbol = NULL;
}
- know (retval == absolute_section
- || retval == diff_section
- || SEG_NORMAL (retval));
+ know (retval == absolute_section || SEG_NORMAL (retval));
return (retval);
-
} /* get_known_segmented_expression() */
-
-
/* static */ long /* JF was static, but can't be if the MD pseudos are to use it */
get_absolute_expression ()
{
expressionS exp;
- register segT s;
- if ((s = expression (&exp)) != absolute_section)
+ expression (&exp);
+ if (exp.X_op != O_constant)
{
- if (s != absent_section)
- {
- as_bad ("Bad Absolute Expression, absolute 0 assumed.");
- }
+ if (exp.X_op != O_absent)
+ as_bad ("bad absolute expression; zero assumed");
exp.X_add_number = 0;
}
- return (exp.X_add_number);
+ return exp.X_add_number;
}
char /* return terminator */
/* symbols.c -symbol table-
-
Copyright (C) 1987, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
}
else
{
+ offsetT left, right, val;
+ segT seg_left, seg_right;
+
symp->sy_resolving = 1;
- if (symp->sy_value.X_seg == absolute_section)
- S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
- else if (symp->sy_value.X_seg == undefined_section)
+ switch (symp->sy_value.X_op)
{
+ case O_absent:
+ S_SET_VALUE (symp, 0);
+ /* Fall through. */
+ case O_constant:
+ S_SET_VALUE (symp, S_GET_VALUE (symp) + symp->sy_frag->fr_address);
+ if (S_GET_SEGMENT (symp) == expr_section)
+ S_SET_SEGMENT (symp, absolute_section);
+ break;
+
+ case O_symbol:
resolve_symbol_value (symp->sy_value.X_add_symbol);
#ifdef obj_frob_forward_symbol
(symp->sy_value.X_add_number
+ symp->sy_frag->fr_address
+ S_GET_VALUE (symp->sy_value.X_add_symbol)));
- }
- else if (symp->sy_value.X_seg == diff_section)
- {
+ if (S_GET_SEGMENT (symp) == expr_section
+ || S_GET_SEGMENT (symp) == undefined_section)
+ S_SET_SEGMENT (symp,
+ S_GET_SEGMENT (symp->sy_value.X_add_symbol));
+ break;
+
+ case O_uminus:
+ case O_bit_not:
+ resolve_symbol_value (symp->sy_value.X_add_symbol);
+ if (symp->sy_value.X_op == O_uminus)
+ val = - S_GET_VALUE (symp->sy_value.X_add_symbol);
+ else
+ val = ~ S_GET_VALUE (symp->sy_value.X_add_symbol);
+ S_SET_VALUE (symp,
+ (val
+ + symp->sy_value.X_add_number
+ + symp->sy_frag->fr_address));
+ if (S_GET_SEGMENT (symp) == expr_section
+ || S_GET_SEGMENT (symp) == undefined_section)
+ S_SET_SEGMENT (symp, absolute_section);
+ break;
+
+ case O_multiply:
+ case O_divide:
+ case O_modulus:
+ case O_left_shift:
+ case O_right_shift:
+ case O_bit_inclusive_or:
+ case O_bit_or_not:
+ case O_bit_exclusive_or:
+ case O_bit_and:
+ case O_add:
+ case O_subtract:
resolve_symbol_value (symp->sy_value.X_add_symbol);
- resolve_symbol_value (symp->sy_value.X_subtract_symbol);
- if (S_GET_SEGMENT (symp->sy_value.X_add_symbol)
- != S_GET_SEGMENT (symp->sy_value.X_subtract_symbol))
- as_bad ("%s is difference of symbols in different sections",
+ resolve_symbol_value (symp->sy_value.X_op_symbol);
+ seg_left = S_GET_SEGMENT (symp->sy_value.X_add_symbol);
+ seg_right = S_GET_SEGMENT (symp->sy_value.X_op_symbol);
+ if (seg_left != seg_right
+ && seg_left != undefined_section
+ && seg_right != undefined_section)
+ as_bad ("%s is operation on symbols in different sections",
S_GET_NAME (symp));
+ if ((S_GET_SEGMENT (symp->sy_value.X_add_symbol)
+ != absolute_section)
+ && symp->sy_value.X_op != O_subtract)
+ as_bad ("%s is illegal operation on non-absolute symbols",
+ S_GET_NAME (symp));
+ left = S_GET_VALUE (symp->sy_value.X_add_symbol);
+ right = S_GET_VALUE (symp->sy_value.X_op_symbol);
+ switch (symp->sy_value.X_op)
+ {
+ case O_multiply: val = left * right; break;
+ case O_divide: val = left / right; break;
+ case O_modulus: val = left % right; break;
+ case O_left_shift: val = left << right; break;
+ case O_right_shift: val = left >> right; break;
+ case O_bit_inclusive_or: val = left | right; break;
+ case O_bit_or_not: val = left |~ right; break;
+ case O_bit_exclusive_or: val = left ^ right; break;
+ case O_bit_and: val = left & right; break;
+ case O_add: val = left + right; break;
+ case O_subtract: val = left - right; break;
+ default: abort ();
+ }
S_SET_VALUE (symp,
(symp->sy_value.X_add_number
+ symp->sy_frag->fr_address
- + S_GET_VALUE (symp->sy_value.X_add_symbol)
- - S_GET_VALUE (symp->sy_value.X_subtract_symbol)));
- S_SET_SEGMENT (symp, absolute_section);
- }
- else
- {
- /* More cases need to be added here. */
- abort ();
+ + val));
+ if (S_GET_SEGMENT (symp) == expr_section
+ || S_GET_SEGMENT (symp) == undefined_section)
+ S_SET_SEGMENT (symp, absolute_section);
+ break;
+
+ case O_register:
+ case O_big:
+ case O_illegal:
+ as_bad ("bad value for symbol \"%s\"", S_GET_NAME (symp));
+ break;
}
}
S_GET_VALUE (s)
symbolS *s;
{
- if (s->sy_value.X_seg != absolute_section)
+ if (s->sy_value.X_op != O_constant)
as_bad ("Attempt to get value of unresolved symbol %s", S_GET_NAME (s));
return (valueT) s->sy_value.X_add_number;
}
symbolS *s;
valueT val;
{
- s->sy_value.X_seg = absolute_section;
+ s->sy_value.X_op = O_constant;
s->sy_value.X_add_number = (offsetT) val;
}
#endif /* BFD_ASSEMBLER */
+static fixS *fix_new_internal PARAMS ((fragS *, int where, short int size,
+ symbolS *add, symbolS *sub,
+ offsetT offset, int pcrel,
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type
+#else
+ int r_type
+#endif
+ ));
static long fixup_segment PARAMS ((fixS * fixP, segT this_segment_type));
static relax_addressT relax_align PARAMS ((relax_addressT addr, int align));
void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type));
*
* Create a fixS in obstack 'notes'.
*/
-fixS *
-fix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type)
+static fixS *
+fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
+ r_type)
fragS *frag; /* Which frag? */
int where; /* Where in that frag? */
short int size; /* 1, 2, or 4 usually. */
symbolS *add_symbol; /* X_add_symbol. */
- symbolS *sub_symbol; /* X_subtract_symbol. */
+ symbolS *sub_symbol; /* X_op_symbol. */
offsetT offset; /* X_add_number. */
int pcrel; /* TRUE if PC-relative relocation. */
#ifdef BFD_ASSEMBLER
return fixP;
}
+/* Create a fixup relative to a symbol (plus a constant). */
+
+fixS *
+fix_new (frag, where, size, add_symbol, offset, pcrel, r_type)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ short int size; /* 1, 2, or 4 usually. */
+ symbolS *add_symbol; /* X_add_symbol. */
+ offsetT offset; /* X_add_number. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type; /* Relocation type */
+#else
+ int r_type; /* Relocation type */
+#endif
+{
+ return fix_new_internal (frag, where, size, add_symbol,
+ (symbolS *) NULL, offset, pcrel, r_type);
+}
+
+/* Create a fixup for an expression. Currently we only support fixups
+ for difference expressions. That is itself more than most object
+ file formats support anyhow. */
+
+fixS *
+fix_new_exp (frag, where, size, exp, pcrel, r_type)
+ fragS *frag; /* Which frag? */
+ int where; /* Where in that frag? */
+ short int size; /* 1, 2, or 4 usually. */
+ expressionS *exp; /* Expression. */
+ int pcrel; /* TRUE if PC-relative relocation. */
+#ifdef BFD_ASSEMBLER
+ bfd_reloc_code_real_type r_type; /* Relocation type */
+#else
+ int r_type; /* Relocation type */
+#endif
+{
+ symbolS *add = NULL;
+ symbolS *sub = NULL;
+ offsetT off = 0;
+
+ switch (exp->X_op)
+ {
+ case O_absent:
+ break;
+
+ case O_subtract:
+ sub = exp->X_op_symbol;
+ /* Fall through. */
+ case O_symbol:
+ add = exp->X_add_symbol;
+ /* Fall through. */
+ case O_constant:
+ off = exp->X_add_number;
+ break;
+
+ default:
+ as_bad ("expression too complex for fixup");
+ }
+
+ return fix_new_internal (frag, where, size, add, sub, off,
+ pcrel, r_type);
+}
+
/* Append a string onto another string, bumping the pointer along. */
void
append (charPP, fromP, length)
while (seclist && *seclist)
{
sec = *seclist;
- while (sec == big_section
- || sec == reg_section
- || sec == pass1_section
- || sec == diff_section
- || sec == absent_section)
+ while (sec == reg_section || sec == expr_section)
{
sec = sec->next;
*seclist = sec;
for (lie = broken_words; lie; lie = lie->next_broken_word)
if (!lie->added)
{
+ expressionS exp;
+
+ exp.X_op = O_subtract;
+ exp.X_add_symbol = lie->add;
+ exp.X_op_symbol = lie->sub;
+ exp.X_add_number = lie->addnum;
#ifdef BFD_ASSEMBLER
- fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
- 2, lie->add, lie->sub, lie->addnum, 0,
- BFD_RELOC_NONE);
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, BFD_RELOC_NONE);
#else
#if defined(TC_SPARC) || defined(TC_A29K) || defined(NEED_FX_R_TYPE)
- fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
- 2, lie->add,
- lie->sub, lie->addnum,
- 0, NO_RELOC);
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, NO_RELOC);
#else
#ifdef TC_NS32K
- fix_new_ns32k (lie->frag,
- lie->word_goes_here - lie->frag->fr_literal,
- 2,
- lie->add,
- lie->sub,
- lie->addnum,
- 0, 0, 2, 0, 0);
+ fix_new_ns32k_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, 0, 2, 0, 0);
#else
- fix_new (lie->frag, lie->word_goes_here - lie->frag->fr_literal,
- 2, lie->add,
- lie->sub, lie->addnum,
- 0, 0);
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, 0);
#endif /* TC_NS32K */
#endif /* TC_SPARC|TC_A29K|NEED_FX_R_TYPE */
#endif /* BFD_ASSEMBLER */
if (! symp->sy_resolved)
{
- if (symp->sy_value.X_seg == absolute_section)
+ if (symp->sy_value.X_op == O_constant)
{
/* This is the normal case; skip the call. */
S_SET_VALUE (symp,