diff options
-rw-r--r-- | gas/ChangeLog | 88 | ||||
-rw-r--r-- | gas/config/obj-aout.c | 5 | ||||
-rw-r--r-- | gas/config/obj-bout.c | 8 | ||||
-rw-r--r-- | gas/config/obj-coffbfd.c | 16 | ||||
-rw-r--r-- | gas/config/obj-elf.c | 11 | ||||
-rw-r--r-- | gas/config/obj-vms.c | 5 | ||||
-rw-r--r-- | gas/config/tc-a29k.c | 81 | ||||
-rw-r--r-- | gas/config/tc-h8300.c | 86 | ||||
-rw-r--r-- | gas/config/tc-h8500.c | 47 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 70 | ||||
-rw-r--r-- | gas/config/tc-i960.c | 190 | ||||
-rw-r--r-- | gas/config/tc-m88k.c | 78 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 82 | ||||
-rw-r--r-- | gas/config/tc-sparc.c | 51 | ||||
-rw-r--r-- | gas/config/tc-tahoe.c | 88 | ||||
-rw-r--r-- | gas/expr.c | 694 | ||||
-rw-r--r-- | gas/read.c | 325 | ||||
-rw-r--r-- | gas/symbols.c | 110 | ||||
-rw-r--r-- | gas/write.c | 124 |
19 files changed, 1001 insertions, 1158 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 0874510..6ca7c10 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,91 @@ +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 diff --git a/gas/config/obj-aout.c b/gas/config/obj-aout.c index 38fead5..9b293fc 100644 --- a/gas/config/obj-aout.c +++ b/gas/config/obj-aout.c @@ -30,11 +30,8 @@ const short seg_N_TYPE[] = 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 */ diff --git a/gas/config/obj-bout.c b/gas/config/obj-bout.c index d467715..6fc5b37 100644 --- a/gas/config/obj-bout.c +++ b/gas/config/obj-bout.c @@ -28,11 +28,11 @@ const short /* in: segT out: N_TYPE bits */ 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 */ }; diff --git a/gas/config/obj-coffbfd.c b/gas/config/obj-coffbfd.c index 88f815d..adbf2ab7d 100644 --- a/gas/config/obj-coffbfd.c +++ b/gas/config/obj-coffbfd.c @@ -1,5 +1,5 @@ /* 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. @@ -68,11 +68,8 @@ const short seg_N_TYPE[] = 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 */ @@ -879,6 +876,7 @@ DEFUN (obj_coff_def, (what), 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)) { @@ -994,7 +992,7 @@ DEFUN_VOID (obj_coff_endef) || (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))) { @@ -1242,11 +1240,11 @@ obj_coff_val () } 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 @@ -1377,7 +1375,7 @@ DEFUN_VOID (yank_symbols) /* 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) { diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 5f4f181..7d99c9a 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -530,7 +530,7 @@ obj_elf_stab_generic (what, secname) 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); @@ -718,7 +718,6 @@ obj_elf_size () char c = get_symbol_end (); char *p; expressionS exp; - segT sec; symbolS *sym; p = input_line_pointer; @@ -733,17 +732,17 @@ obj_elf_size () 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 { diff --git a/gas/config/obj-vms.c b/gas/config/obj-vms.c index 3c29d18..b8c75e2 100644 --- a/gas/config/obj-vms.c +++ b/gas/config/obj-vms.c @@ -287,11 +287,8 @@ const short seg_N_TYPE[] = 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 */ diff --git a/gas/config/tc-a29k.c b/gas/config/tc-a29k.c index f14bf96..1ed07df 100644 --- a/gas/config/tc-a29k.c +++ b/gas/config/tc-a29k.c @@ -1,5 +1,5 @@ /* 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. @@ -385,16 +385,12 @@ md_assemble (str) /* 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); } } @@ -405,15 +401,12 @@ parse_operand (s, operandp) { 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; } @@ -501,7 +494,7 @@ machine_ip (str) 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) { @@ -524,11 +517,11 @@ machine_ip (str) 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) { @@ -551,10 +544,10 @@ machine_ip (str) 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 */ @@ -583,7 +576,7 @@ machine_ip (str) 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); @@ -594,7 +587,7 @@ machine_ip (str) 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 @@ -608,8 +601,8 @@ machine_ip (str) 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 | @@ -623,7 +616,7 @@ machine_ip (str) 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; @@ -636,7 +629,7 @@ machine_ip (str) 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); @@ -645,7 +638,7 @@ machine_ip (str) 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 */ @@ -653,7 +646,7 @@ machine_ip (str) 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; @@ -666,7 +659,7 @@ machine_ip (str) 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; @@ -675,7 +668,7 @@ machine_ip (str) 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; @@ -685,7 +678,7 @@ machine_ip (str) 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; @@ -694,7 +687,7 @@ machine_ip (str) 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; @@ -703,7 +696,7 @@ machine_ip (str) 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; @@ -1031,10 +1024,10 @@ print_insn (insn) 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"); @@ -1141,22 +1134,22 @@ md_operand (expressionP) /* 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; } } diff --git a/gas/config/tc-h8300.c b/gas/config/tc-h8300.c index 4f31bb1..a7a1fc8 100644 --- a/gas/config/tc-h8300.c +++ b/gas/config/tc-h8300.c @@ -269,29 +269,13 @@ DEFUN (parse_exp, (s, op), { 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 * @@ -365,7 +349,7 @@ colonmod24 (op, src) 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; @@ -722,7 +706,7 @@ DEFUN (check_operand, (operand, width, string), 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 @@ -814,14 +798,13 @@ do_a_fix_imm (offset, operand, relaxing) } - 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); } } @@ -970,27 +953,25 @@ build_bytes (this_try, operand) 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) @@ -1009,14 +990,13 @@ build_bytes (this_try, operand) 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); } } diff --git a/gas/config/tc-h8500.c b/gas/config/tc-h8500.c index 4ad462e..404db3a 100644 --- a/gas/config/tc-h8500.c +++ b/gas/config/tc-h8500.c @@ -258,7 +258,6 @@ parse_exp (s, op, page) { char *save; char *new; - segT seg; save = input_line_pointer; @@ -284,26 +283,11 @@ parse_exp (s, op, page) 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 @@ -366,7 +350,7 @@ skip_colonthing (sign, ptr, exp, def, size8, size16, size24) /* 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))))) @@ -430,9 +414,9 @@ parse_reglist (src, op) } 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; @@ -795,7 +779,7 @@ get_specific (opcode, operands) 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 @@ -871,7 +855,7 @@ check (operand, low, high) 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) { @@ -889,14 +873,12 @@ insert (output, index, exp, reloc, pcrel) 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 @@ -1399,7 +1381,6 @@ md_convert_frag (headers, fragP) fragP->fr_fix + inst_size, 4, fragP->fr_symbol, - 0, fragP->fr_offset, 0, R_H8500_PCREL16); diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 3774d93..3694ac2 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1,5 +1,5 @@ /* 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. @@ -522,7 +522,7 @@ static void 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) @@ -531,10 +531,10 @@ pe (e) 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"); } } @@ -1254,10 +1254,10 @@ md_assemble (line) 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. */ @@ -1337,11 +1337,8 @@ md_assemble (line) 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)) { @@ -1417,7 +1414,7 @@ md_assemble (line) } 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)) @@ -1428,23 +1425,20 @@ md_assemble (line) } 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); } @@ -1510,7 +1504,7 @@ md_assemble (line) { 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)) { @@ -1532,9 +1526,8 @@ md_assemble (line) { /* 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); } } } @@ -1549,7 +1542,7 @@ md_assemble (line) { 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)) { @@ -1579,9 +1572,8 @@ md_assemble (line) 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); } } } @@ -1696,18 +1688,18 @@ i386_operand (operand_string) 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); } @@ -1937,18 +1929,18 @@ i386_operand (operand_string) 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); } @@ -2042,7 +2034,6 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_fix += 4; fix_new (fragP, old_fr_fix, 4, fragP->fr_symbol, - (symbolS *) 0, fragP->fr_offset, 1, NO_RELOC); break; @@ -2054,7 +2045,6 @@ md_estimate_size_before_relax (fragP, segment) 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; } @@ -2187,7 +2177,7 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) 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 { diff --git a/gas/config/tc-i960.c b/gas/config/tc-i960.c index 773efc0..e2ed93d 100644 --- a/gas/config/tc-i960.c +++ b/gas/config/tc-i960.c @@ -1,5 +1,5 @@ /* 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. @@ -113,7 +113,7 @@ static int get_regnum (); /* Translate text to register number */ 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 */ @@ -208,9 +208,7 @@ const pseudo_typeS md_pseudo_table[] = /* 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 */ @@ -1050,7 +1048,6 @@ md_convert_frag (headers, fragP) fragP->fr_opcode - fragP->fr_literal, 4, fragP->fr_symbol, - 0, fragP->fr_offset, 1, NO_RELOC); @@ -1239,7 +1236,6 @@ brtab_emit () symbol_find (buf), 0, 0, - 0, NO_RELOC); fixP->fx_im_disp = 2; /* 32-bit displacement fix */ } @@ -1502,51 +1498,49 @@ get_cdisp (dispP, ifmtP, instr, numbits, var_frag, callj) 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: @@ -1722,14 +1716,14 @@ mem_fmt (args, oP, callx) } /* 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 */ @@ -1740,28 +1734,24 @@ mem_fmt (args, oP, callx) 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 @@ -1775,21 +1765,15 @@ mem_fmt (args, oP, callx) * 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() */ @@ -1836,19 +1820,16 @@ mema_to_memb (opcodeP) * * 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); @@ -1856,10 +1837,9 @@ parse_expr (textP, expP) 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 { @@ -1870,13 +1850,14 @@ parse_expr (textP, expP) 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 */ @@ -1914,31 +1895,27 @@ parse_ldconst (arg) 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)) { @@ -1979,7 +1956,7 @@ parse_ldconst (arg) } break; - default: + case O_illegal: as_bad ("invalid constant"); return -1; break; @@ -2362,7 +2339,8 @@ parse_regop (regopP, optext, opdesc) } 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"); @@ -2537,7 +2515,6 @@ relax_cobr (fragP) iP + 4 - fragP->fr_literal, 4, fragP->fr_symbol, - 0, fragP->fr_offset, 1, NO_RELOC); @@ -2711,7 +2688,8 @@ s_sysproc (n_ops, args) } /* 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)) { @@ -3214,7 +3192,7 @@ i960_handle_align (fragp) } /* 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); } diff --git a/gas/config/tc-m88k.c b/gas/config/tc-m88k.c index 1092250..801748f 100644 --- a/gas/config/tc-m88k.c +++ b/gas/config/tc-m88k.c @@ -1,7 +1,7 @@ /* 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. @@ -274,9 +274,9 @@ md_assemble (op) /* 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)) @@ -306,47 +306,39 @@ md_assemble (op) 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: @@ -542,7 +534,6 @@ get_imm16 (param, insn) { enum reloc_type reloc = NO_RELOC; unsigned int val; - segT seg; char *save_ptr; if (!strncmp (param, "hi16", 4) && !isalnum (param[4])) @@ -563,13 +554,13 @@ get_imm16 (param, insn) 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) @@ -602,17 +593,16 @@ get_pcr (param, insn, 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; @@ -1148,8 +1138,7 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) ptr - frag->fr_literal, 4, to_symbol, - (symbolS *) 0, - (long int) 0, + (offsetT) 0, 0, RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */ } @@ -1171,8 +1160,7 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) ptr - frag->fr_literal, 4, to_symbol, - (symbolS *) 0, - (long int) 0, + (offsetT) 0, 0, RELOC_PC26); } diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 9075b26..db0671e 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -161,7 +161,6 @@ static void mips_ip PARAMS ((char *str, struct mips_cl_insn * ip)); 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)); @@ -336,8 +335,8 @@ md_assemble (str) 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) @@ -351,9 +350,9 @@ md_assemble (str) } 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); @@ -571,7 +570,7 @@ append_insn (ip, address_expr, reloc_type) fixp = NULL; if (address_expr != NULL) { - if (address_expr->X_seg == &bfd_abs_section) + if (address_expr->X_op == O_constant) { switch (reloc_type) { @@ -595,12 +594,10 @@ append_insn (ip, address_expr, 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); } } @@ -816,7 +813,7 @@ gp_reference (ep) 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 @@ -968,7 +965,7 @@ macro_build (counter, ep, name, fmt, va_alist) * 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; @@ -1010,7 +1007,7 @@ macro_build_lui (counter, ep, regnum) 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) @@ -1112,7 +1109,7 @@ check_absolute_expr (ip, expr) 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); } @@ -1182,8 +1179,8 @@ macro (ip) 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; @@ -1582,7 +1579,7 @@ macro (ip) 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; @@ -1598,7 +1595,7 @@ macro (ip) 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); @@ -2221,7 +2218,7 @@ macro (ip) 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); @@ -2264,7 +2261,7 @@ macro (ip) 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); @@ -2414,7 +2411,7 @@ mips_ip (str, ip) 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; @@ -2424,7 +2421,7 @@ mips_ip (str, ip) 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; @@ -2434,7 +2431,7 @@ mips_ip (str, ip) 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; @@ -2625,7 +2622,7 @@ mips_ip (str, ip) { 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') @@ -2668,8 +2665,8 @@ mips_ip (str, ip) * 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; @@ -2696,7 +2693,7 @@ mips_ip (str, ip) { 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') @@ -2797,16 +2794,16 @@ my_getSmallExpression (ep, str) 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 @@ -2829,11 +2826,10 @@ my_getExpression (ep, str) 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; } @@ -3157,20 +3153,6 @@ get_symbol () 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. */ @@ -3325,7 +3307,7 @@ s_extern (x) 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); @@ -3765,7 +3747,7 @@ s_frame (x) 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 (); diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c index 62df7b4..075308f 100644 --- a/gas/config/tc-sparc.c +++ b/gas/config/tc-sparc.c @@ -689,7 +689,7 @@ md_assemble (str) /* 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)) @@ -709,14 +709,12 @@ md_assemble (str) /* 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) @@ -725,22 +723,19 @@ md_assemble (str) 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: @@ -1545,8 +1540,8 @@ sparc_ip (str) #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", @@ -1574,7 +1569,8 @@ sparc_ip (str) 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; @@ -1793,10 +1789,7 @@ getExpression (str) || 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 { @@ -2322,9 +2315,9 @@ print_insn (insn) : "???") : "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", diff --git a/gas/config/tc-tahoe.c b/gas/config/tc-tahoe.c index 7bd97b5..5fc47d3 100644 --- a/gas/config/tc-tahoe.c +++ b/gas/config/tc-tahoe.c @@ -30,6 +30,8 @@ struct top /* tahoe instruction operand */ 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 @@ -665,7 +667,7 @@ md_estimate_size_before_relax (fragP, segment_type) *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); } @@ -684,7 +686,7 @@ md_estimate_size_before_relax (fragP, segment_type) *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); } @@ -705,7 +707,7 @@ md_estimate_size_before_relax (fragP, segment_type) *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); } @@ -726,7 +728,7 @@ md_estimate_size_before_relax (fragP, segment_type) *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); } @@ -743,7 +745,7 @@ md_estimate_size_before_relax (fragP, segment_type) *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); } @@ -1261,64 +1263,52 @@ tip_op (optex, topP) /* 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') { @@ -1706,7 +1696,7 @@ md_assemble (instruction_string) /* 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 || \ @@ -1731,7 +1721,7 @@ md_assemble (instruction_string) 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); } @@ -1810,7 +1800,7 @@ md_assemble (instruction_string) 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 @@ -1826,7 +1816,7 @@ md_assemble (instruction_string) 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; @@ -1840,7 +1830,7 @@ md_assemble (instruction_string) 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 @@ -1859,7 +1849,7 @@ md_assemble (instruction_string) 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 @@ -1916,7 +1906,7 @@ md_assemble (instruction_string) 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 @@ -2009,7 +1999,7 @@ md_assemble (instruction_string) 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; @@ -32,8 +32,41 @@ #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[]; + +/* 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; +} + /* * Build any floating-point literal here. * Also build any bignum literal here. @@ -79,13 +112,12 @@ floating_constant (expressionP) 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; @@ -233,8 +265,8 @@ integer_constant (radix, expressionP) 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 @@ -244,7 +276,7 @@ integer_constant (radix, expressionP) 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; @@ -269,9 +301,8 @@ integer_constant (radix, expressionP) 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; @@ -301,9 +332,9 @@ integer_constant (radix, expressionP) 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 '$' */ @@ -312,8 +343,8 @@ integer_constant (radix, expressionP) 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 */ @@ -325,8 +356,8 @@ integer_constant (radix, expressionP) 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() */ @@ -338,14 +369,10 @@ integer_constant (radix, expressionP) * 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. - * */ - - static segT operand (expressionP) @@ -354,6 +381,7 @@ 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. */ @@ -390,7 +418,6 @@ operand (expressionP) case '0': /* non-decimal radix */ - c = *input_line_pointer; switch (c) { @@ -404,9 +431,8 @@ operand (expressionP) 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; @@ -419,6 +445,9 @@ operand (expressionP) 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))) @@ -449,6 +478,9 @@ operand (expressionP) /* 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) && @@ -482,78 +514,70 @@ operand (expressionP) } 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. */ @@ -564,27 +588,25 @@ operand (expressionP) #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; @@ -602,25 +624,33 @@ operand (expressionP) 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; } } @@ -631,20 +661,18 @@ operand (expressionP) 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() */ - /* 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(). */ @@ -652,158 +680,38 @@ static void 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); - } - } -} - -/* - * 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); } /* Expression parser. */ @@ -824,27 +732,11 @@ expr_part (symbol_1_PP, symbol_2_P) * 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 @@ -884,17 +776,37 @@ static const operatorT op_encoding[256] = * 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 */ +}; -/* 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. */ @@ -902,223 +814,145 @@ expr (rank, resultP) 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 (); } - + } + 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; } /* @@ -1,5 +1,5 @@ /* 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. @@ -158,6 +158,7 @@ int new_broken_words; 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)); @@ -1161,6 +1162,7 @@ s_lsym () register segT segment; expressionS exp; register symbolS *symbolP; + valueT val; /* we permit ANY defined expression: BSD4.2 demands constants */ name = input_line_pointer; @@ -1177,15 +1179,7 @@ s_lsym () 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); @@ -1202,7 +1196,7 @@ s_lsym () /* 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 { @@ -1421,14 +1415,12 @@ ignore_rest_of_line () /* For suspect lines: gives warning. */ * 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 */ @@ -1439,123 +1431,76 @@ pseudo_set (symbolP) 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; } } @@ -1641,39 +1586,32 @@ emit_expr (exp, nbytes) 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); @@ -1681,7 +1619,7 @@ emit_expr (exp, 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; @@ -1692,7 +1630,7 @@ emit_expr (exp, nbytes) 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++; @@ -1700,7 +1638,7 @@ emit_expr (exp, nbytes) } #endif - if (segment == absolute_section) + if (op == O_constant) { register long get; register long use; @@ -1743,11 +1681,9 @@ emit_expr (exp, nbytes) 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); @@ -1762,9 +1698,8 @@ emit_expr (exp, nbytes) #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 */ } @@ -1793,9 +1728,8 @@ parse_bitfield_cons (exp, nbytes) { 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 */ @@ -1829,17 +1763,17 @@ parse_bitfield_cons (exp, nbytes) 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; @@ -1847,7 +1781,7 @@ parse_bitfield_cons (exp, nbytes) if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes)) { - as_warn ("Field width %d too big to fit in %d bytes: truncated to %d bits.", + as_warn ("field width %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 */ @@ -1862,19 +1796,20 @@ parse_bitfield_cons (exp, nbytes) 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 () @@ -1884,11 +1819,11 @@ parse_bitfield_cons (exp, nbytes) } /* 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() */ @@ -1930,9 +1865,8 @@ parse_mri_cons (exp, nbytes) 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] == '\'')) @@ -1964,7 +1898,6 @@ parse_repeat_cons (exp, nbytes) unsigned int nbytes; { expressionS count; - segT segment; register int i; expression (exp); @@ -1976,8 +1909,8 @@ parse_repeat_cons (exp, nbytes) } ++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"); @@ -2218,15 +2151,14 @@ float_cons (float_type) /* Worker to do .float etc statements. */ #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; @@ -2420,16 +2352,16 @@ get_segmented_expression (expP) 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 @@ -2437,53 +2369,38 @@ get_known_segmented_expression (expP) 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 */ diff --git a/gas/symbols.c b/gas/symbols.c index d305024..a5acf1f 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -1,5 +1,4 @@ /* symbols.c -symbol table- - Copyright (C) 1987, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -585,12 +584,23 @@ resolve_symbol_value (symp) } 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 @@ -602,26 +612,84 @@ resolve_symbol_value (symp) (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; } } @@ -1014,7 +1082,7 @@ valueT 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; } @@ -1026,7 +1094,7 @@ S_SET_VALUE (s, val) 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; } diff --git a/gas/write.c b/gas/write.c index 8a480f1..b527708 100644 --- a/gas/write.c +++ b/gas/write.c @@ -58,6 +58,15 @@ int magic_number_for_object_file = DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE; #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)); @@ -67,13 +76,14 @@ 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 @@ -142,6 +152,70 @@ fix_new (frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type) 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) @@ -763,11 +837,7 @@ write_object_file () 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; @@ -975,30 +1045,30 @@ write_object_file () 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 */ @@ -1191,7 +1261,7 @@ write_object_file () 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, |