From: Ian Lance Taylor Date: Wed, 9 Aug 1995 19:36:25 +0000 (+0000) Subject: * read.c (abs_section_offset): New global variable. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e28c40d72519ff512fd217c6e74ef27a249b7693;p=binutils-gdb.git * read.c (abs_section_offset): New global variable. (potable): Add offset, struct. (do_org): New static function; handle changing the origin in the absolute section. (s_org): Use do_org. (s_set): Likewise. (equals): Likewise. (s_space): In absolute_section, just increase abs_section_offset. (s_struct): New function. (emit_expr): Handle absolute_section specially. * read.h (abs_section_offset): Declare. (s_struct): Declare. * read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne. Change if to pass O_ne to s_if. (read_a_source_file): Don't define an label without a colon if ignore_input returns true. * read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w, dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen, noformat. (read_a_source_file): If pseudo-op handler is s_end, quit immediately. (s_end): New function. (s_fail): New function. (s_float_space): New function. (hex_float): New static function. (float_cons): Use hex_float. * read.h (s_fail): Declare. (s_float_space): Declare. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 4955aaa7bb2..09e0b74284a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,63 @@ Wed Aug 9 10:51:48 1995 Ian Lance Taylor + * write.c (adjust_reloc_syms): Check that symbol is not NULL + before checking sy_mri_common. + (fixup_segment): Likewise. + * config/obj-coff.c (fixup_segment): Likewise. + + * read.c (abs_section_offset): New global variable. + (potable): Add offset, struct. + (do_org): New static function; handle changing the origin in the + absolute section. + (s_org): Use do_org. + (s_set): Likewise. + (equals): Likewise. + (s_space): In absolute_section, just increase abs_section_offset. + (s_struct): New function. + (emit_expr): Handle absolute_section specially. + * read.h (abs_section_offset): Declare. + (s_struct): Declare. + * frags.c (frag_more): Warn if in absolute_section. + (frag_now_fix): In absolute_section, return abs_section_offset. + * subsegs.c (subseg_change): If switching to absolute_section, + just set now_seg and now_subseg. + (subseg_set_rest): Special handling when switching to or from + absolute_section. + + * config/tc-m68k.c (m68k_float_copnum): New static variable. + (md_pseudo_table): Add fopt and mask2. + (m68k_ip): Use m68k_float_copnum, not COPNUM, when setting + coprocessor register to use. In case 'I' when checking operands, + correct coprocessor register numbers. In case 'I' when setting + operands, don't add 1. + (s_fopt): New static function. + * config/m68k-parse.h (COPNUM): Don't define. + + * read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne. + Change if to pass O_ne to s_if. + (read_a_source_file): Don't define an label without a colon if + ignore_input returns true. + * cond.c (s_if): Treat argument as an operatorT describing how to + compare the argument against zero. + (ignore_input): Don't require an initial dot in MRI mode, or if + NO_PSEUDO_DOT is defined. + + * read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w, + dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen, + noformat. + (read_a_source_file): If pseudo-op handler is s_end, quit + immediately. + (s_end): New function. + (s_fail): New function. + (s_float_space): New function. + (hex_float): New static function. + (float_cons): Use hex_float. + * read.h (s_fail): Declare. + (s_float_space): Declare. + * cond.c (s_end): Remove. + * listing.c (listing_psize): Treat argument as indicating whether + a height is expected. + * read.c (mri_pending_align): New static variable. (read_a_source_file): Handle mri_pending_align. (cons): Set mri_pending_align if appropriate. diff --git a/gas/read.c b/gas/read.c index c77f5887405..af8c775cba4 100644 --- a/gas/read.c +++ b/gas/read.c @@ -169,6 +169,11 @@ struct broken_word *broken_words; int new_broken_words; #endif +/* The current offset into the absolute section. We don't try to + build frags in the absolute section, since no data can be stored + there. We just keep track of the current offset. */ +addressT abs_section_offset; + /* If this line had an MRI style label, it is stored in this variable. This is used by some of the MRI pseudo-ops. */ static symbolS *mri_line_label; @@ -185,6 +190,8 @@ symbolS *mri_common_symbol; static int mri_pending_align; static void do_align PARAMS ((int, char *)); +static int hex_float PARAMS ((int, char *)); +static void do_org PARAMS ((segT, expressionS *, int)); char *demand_copy_string PARAMS ((int *lenP)); int is_it_end_of_statement PARAMS ((void)); static segT get_segmented_expression PARAMS ((expressionS *expP)); @@ -238,10 +245,21 @@ static const pseudo_typeS potable[] = {"dc.s", float_cons, 'f'}, {"dc.w", cons, 2}, {"dc.x", float_cons, 'x'}, + {"dcb", s_space, 2}, + {"dcb.b", s_space, 1}, + {"dcb.d", s_float_space, 'd'}, + {"dcb.l", s_space, 4}, + {"dcb.s", s_float_space, 'f'}, + {"dcb.w", s_space, 2}, + {"dcb.x", s_float_space, 'x'}, {"ds", s_space, 2}, {"ds.b", s_space, 1}, + {"ds.d", s_space, 8}, {"ds.l", s_space, 4}, + {"ds.p", s_space, 12}, + {"ds.s", s_space, 4}, {"ds.w", s_space, 2}, + {"ds.x", s_space, 12}, #ifdef S_SET_DESC {"desc", s_desc, 0}, #endif @@ -250,7 +268,9 @@ static const pseudo_typeS potable[] = /* dsect */ {"eject", listing_eject, 0}, /* Formfeed listing */ {"else", s_else, 0}, + {"elsec", s_else, 0}, {"end", s_end, 0}, + {"endc", s_endif, 0}, {"endif", s_endif, 0}, /* endef */ {"equ", s_set, 0}, @@ -259,16 +279,24 @@ static const pseudo_typeS potable[] = {"extern", s_ignore, 0}, /* We treat all undef as ext */ {"appfile", s_app_file, 1}, {"appline", s_app_line, 0}, + {"fail", s_fail, 0}, {"file", s_app_file, 0}, {"fill", s_fill, 0}, {"float", float_cons, 'f'}, + {"format", s_ignore, 0}, {"global", s_globl, 0}, {"globl", s_globl, 0}, {"hword", cons, 2}, - {"if", s_if, 0}, + {"if", s_if, (int) O_ne}, {"ifdef", s_ifdef, 0}, + {"ifeq", s_if, (int) O_eq}, {"ifeqs", s_ifeqs, 0}, + {"ifge", s_if, (int) O_ge}, + {"ifgt", s_if, (int) O_gt}, + {"ifle", s_if, (int) O_le}, + {"iflt", s_if, (int) O_lt}, {"ifndef", s_ifdef, 1}, + {"ifne", s_if, (int) O_ne}, {"ifnes", s_ifeqs, 1}, {"ifnotdef", s_ifdef, 1}, {"include", s_include, 0}, @@ -276,10 +304,13 @@ static const pseudo_typeS potable[] = {"lcomm", s_lcomm, 0}, {"lflags", listing_flags, 0}, /* Listing flags */ {"list", listing_list, 1}, /* Turn listing on */ + {"llen", listing_psize, 1}, {"long", cons, 4}, {"lsym", s_lsym, 0}, + {"noformat", s_ignore, 0}, {"nolist", listing_list, 0}, /* Turn listing off */ {"octa", cons, 16}, + {"offset", s_struct, 0}, {"org", s_org, 0}, {"p2align", s_align_ptwo, 0}, {"psize", listing_psize, 0}, /* set paper size */ @@ -297,6 +328,7 @@ static const pseudo_typeS potable[] = {"stabn", s_stab, 'n'}, {"stabs", s_stab, 's'}, {"string", stringer, 1}, + {"struct", s_struct, 0}, /* tag */ {"text", s_text, 0}, @@ -433,22 +465,28 @@ read_a_source_file (name) char *line_start = input_line_pointer; char c = get_symbol_end (); - /* In MRI mode, the EQU pseudoop must be handled - specially. */ - if (flag_mri) + if (! ignore_input ()) { - if ((strncasecmp (input_line_pointer + 1, "EQU", 3) - == 0) - && (input_line_pointer[4] == ' ' - || input_line_pointer[4] == '\t')) + /* In MRI mode, the EQU pseudoop must be + handled specially. */ + if (flag_mri) { - input_line_pointer += 4; - equals (line_start); - continue; + if (((strncasecmp (input_line_pointer + 1, + "EQU", 3) == 0) + || (strncasecmp (input_line_pointer + 1, + "SET", 3) == 0)) + && (input_line_pointer[4] == ' ' + || input_line_pointer[4] == '\t')) + { + input_line_pointer += 4; + equals (line_start); + continue; + } } + + mri_line_label = colon (line_start); } - mri_line_label = colon (line_start); *input_line_pointer = c; if (c == ':') input_line_pointer++; @@ -595,6 +633,10 @@ read_a_source_file (name) * after pseudo-operation. */ (*pop->poc_handler) (pop->poc_val); + + /* If that was .end, just get out now. */ + if (pop->poc_handler == s_end) + goto quit; } else { /* machine instruction */ @@ -810,8 +852,9 @@ read_a_source_file (name) } } } /* while (more buffers to scan) */ - input_scrub_close (); /* Close the input file */ + quit: + input_scrub_close (); /* Close the input file */ } void @@ -1173,6 +1216,39 @@ s_app_line (ignore) demand_empty_rest_of_line (); } +/* Handle the .end pseudo-op. Actually, the real work is done in + read_a_source_file. */ + +void +s_end (ignore) + int ignore; +{ + if (flag_mri) + { + /* The MRI assembler permits the start symbol to follow .end, + but we don't support that. */ + SKIP_WHITESPACE (); + if (! is_end_of_line[(unsigned char) *input_line_pointer]) + as_warn ("start address not supported"); + } +} + +/* Handle the MRI fail pseudo-op. */ + +void +s_fail (ignore) + int ignore; +{ + offsetT temp; + + temp = get_absolute_expression (); + if (temp >= 500) + as_warn (".fail %ld encountered", (long) temp); + else + as_bad (".fail %ld encountered", (long) temp); + demand_empty_rest_of_line (); +} + void s_fill (ignore) int ignore; @@ -1486,6 +1562,39 @@ s_lsym (ignore) demand_empty_rest_of_line (); } /* s_lsym() */ +/* Handle changing the location counter. */ + +static void +do_org (segment, exp, fill) + segT segment; + expressionS *exp; + int fill; +{ + if (segment != now_seg && segment != absolute_section) + as_bad ("invalid segment \"%s\"; segment \"%s\" assumed", + segment_name (segment), segment_name (now_seg)); + + if (now_seg == absolute_section) + { + if (fill != 0) + as_warn ("ignoring fill value in absolute section"); + if (exp->X_op != O_constant) + { + as_bad ("only constant offsets supported in absolute section"); + exp->X_add_number = 0; + } + abs_section_offset = exp->X_add_number; + } + else + { + char *p; + + p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol, + exp->X_add_number, (char *) NULL); + *p = fill; + } +} + void s_org (ignore) int ignore; @@ -1493,7 +1602,7 @@ s_org (ignore) register segT segment; expressionS exp; register long temp_fill; - register char *p; + /* Don't believe the documentation of BSD 4.2 AS. There is no such thing as a sub-segment-relative origin. Any absolute origin is given a warning, then assumed to be segment-relative. Any @@ -1514,15 +1623,10 @@ s_org (ignore) } else temp_fill = 0; + if (!need_pass_2) - { - if (segment != now_seg && segment != absolute_section) - as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.", - segment_name (segment), segment_name (now_seg)); - p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol, - exp.X_add_number, (char *) 0); - *p = temp_fill; - } /* if (ok to make frag) */ + do_org (segment, &exp, temp_fill); + demand_empty_rest_of_line (); } /* s_org() */ @@ -1568,15 +1672,7 @@ s_set (ignore) segment = get_known_segmented_expression (&exp); if (!need_pass_2) - { - if (segment != now_seg && segment != absolute_section) - as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.", - segment_name (segment), - segment_name (now_seg)); - ptr = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol, - exp.X_add_number, (char *) 0); - *ptr = 0; - } /* if (ok to make frag) */ + do_org (segment, &exp, 0); *end_name = delim; return; @@ -1629,6 +1725,14 @@ s_space (mult) return; } + /* If we are in the absolute section, just bump the offset. */ + if (now_seg == absolute_section) + { + abs_section_offset += repeat; + demand_empty_rest_of_line (); + return; + } + /* If we are secretly in an MRI common section, then creating space just increases the size of the common symbol. */ if (mri_common_symbol != NULL) @@ -1645,6 +1749,11 @@ s_space (mult) } else { + if (now_seg == absolute_section) + { + as_bad ("space allocation too complex in absolute section"); + subseg_set (text_section, 0); + } if (mri_common_symbol != NULL) { as_bad ("space allocation too complex in common section"); @@ -1671,6 +1780,85 @@ s_space (mult) demand_empty_rest_of_line (); } +/* This is like s_space, but the value is a floating point number with + the given precision. This is for the MRI dcb.s pseudo-op and + friends. */ + +void +s_float_space (float_type) + int float_type; +{ + offsetT count; + int flen; + char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; + + count = get_absolute_expression (); + + SKIP_WHITESPACE (); + if (*input_line_pointer != ',') + { + as_bad ("missing value"); + ignore_rest_of_line (); + return; + } + + ++input_line_pointer; + + SKIP_WHITESPACE (); + + /* Skip any 0{letter} that may be present. Don't even check if the + * letter is legal. */ + if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1])) + input_line_pointer += 2; + + /* Accept :xxxx, where the x's are hex digits, for a floating point + with the exact digits specified. */ + if (input_line_pointer[0] == ':') + { + flen = hex_float (float_type, temp); + if (flen < 0) + { + ignore_rest_of_line (); + return; + } + } + else + { + char *err; + + err = md_atof (float_type, temp, &flen); + know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT); + know (flen > 0); + if (err) + { + as_bad ("Bad floating literal: %s", err); + ignore_rest_of_line (); + return; + } + } + + while (--count >= 0) + { + char *p; + + p = frag_more (flen); + memcpy (p, temp, (unsigned int) flen); + } + + demand_empty_rest_of_line (); +} + +/* Handle the .struct pseudo-op, as found in MIPS assemblers. */ + +void +s_struct (ignore) + int ignore; +{ + abs_section_offset = get_absolute_expression (); + subseg_set (absolute_section, 0); + demand_empty_rest_of_line (); +} + void s_text (ignore) int ignore; @@ -1927,6 +2115,15 @@ emit_expr (exp, nbytes) op = exp->X_op; + /* Allow `.word 0' in the absolute section. */ + if (now_seg == absolute_section) + { + if (op != O_constant || exp->X_add_number != 0) + as_bad ("attempt to store value in absolute section"); + abs_section_offset += nbytes; + return; + } + /* Handle a negative bignum. */ if (op == O_uminus && exp->X_add_number == 0 @@ -2379,6 +2576,88 @@ parse_repeat_cons (exp, nbytes) #endif /* REPEAT_CONS_EXPRESSIONS */ +/* Parse a floating point number represented as a hex constant. This + permits users to specify the exact bits they want in the floating + point number. */ + +static int +hex_float (float_type, bytes) + int float_type; + char *bytes; +{ + int length; + int i; + + switch (float_type) + { + case 'f': + case 'F': + case 's': + case 'S': + length = 4; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + length = 8; + break; + + case 'x': + case 'X': + length = 12; + break; + + case 'p': + case 'P': + length = 12; + break; + + default: + as_bad ("Unknown floating type type '%c'", float_type); + return -1; + } + + /* It would be nice if we could go through expression to parse the + hex constant, but if we get a bignum it's a pain to sort it into + the buffer correctly. */ + i = 0; + while (hex_p (*input_line_pointer) || *input_line_pointer == '_') + { + int d; + + /* The MRI assembler accepts arbitrary underscores strewn about + through the hex constant, so we ignore them as well. */ + if (*input_line_pointer == '_') + { + ++input_line_pointer; + continue; + } + + if (i >= length) + { + as_warn ("Floating point constant too large"); + return -1; + } + d = hex_value (*input_line_pointer) << 4; + ++input_line_pointer; + while (*input_line_pointer == '_') + ++input_line_pointer; + if (hex_p (*input_line_pointer)) + { + d += hex_value (*input_line_pointer); + ++input_line_pointer; + } + bytes[i++] = d; + } + + if (i < length) + memset (bytes + i, 0, length - i); + + return length; +} + /* * float_cons() * @@ -2432,77 +2711,13 @@ float_cons (float_type) point with the exact digits specified. */ if (input_line_pointer[0] == ':') { - int i; - - switch (float_type) + ++input_line_pointer; + length = hex_float (float_type, temp); + if (length < 0) { - case 'f': - case 'F': - case 's': - case 'S': - length = 4; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - length = 8; - break; - - case 'x': - case 'X': - length = 12; - break; - - case 'p': - case 'P': - length = 12; - break; - - default: - as_bad ("Unknown floating type type '%c'", float_type); ignore_rest_of_line (); return; } - - /* It would be nice if we could go through expression to - parse the hex constant, but if we get a bignum it's a - pain to sort it into the buffer correctly. */ - i = 0; - ++input_line_pointer; - while (hex_p (*input_line_pointer) || *input_line_pointer == '_') - { - int d; - - /* The MRI assembler accepts arbitrary underscores - strewn about through the hex constant, so we ignore - them as well. */ - if (*input_line_pointer == '_') - { - ++input_line_pointer; - continue; - } - - if (i >= length) - { - as_warn ("Floating point constant too large"); - ignore_rest_of_line (); - return; - } - d = hex_value (*input_line_pointer) << 4; - ++input_line_pointer; - while (*input_line_pointer == '_') - ++input_line_pointer; - if (hex_p (*input_line_pointer)) - { - d += hex_value (*input_line_pointer); - ++input_line_pointer; - } - temp[i++] = d; - } - if (i < length) - memset (temp + i, 0, length - i); } else { @@ -2924,15 +3139,7 @@ equals (sym_name) segment = get_known_segmented_expression (&exp); if (!need_pass_2) - { - if (segment != now_seg && segment != absolute_section) - as_warn ("Illegal segment \"%s\". Segment \"%s\" assumed.", - segment_name (segment), - segment_name (now_seg)); - p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol, - exp.X_add_number, (char *) 0); - *p = 0; - } /* if (ok to make frag) */ + do_org (segment, &exp, 0); } else { diff --git a/gas/read.h b/gas/read.h index 3a3d82dfe20..4a00b327cc8 100644 --- a/gas/read.h +++ b/gas/read.h @@ -60,6 +60,9 @@ extern const char line_separator_chars[]; /* This flag whether to generate line info for asm file */ extern int generate_asm_lineno; +/* The offset in the absolute section. */ +extern addressT abs_section_offset; + /* This is used to support MRI common sections. */ extern symbolS *mri_common_symbol; @@ -86,13 +89,14 @@ void s_align_ptwo PARAMS ((int)); void s_app_file PARAMS ((int)); void s_app_line PARAMS ((int)); void s_comm PARAMS ((int)); -void s_mri_common PARAMS ((int)); void s_data PARAMS ((int)); void s_desc PARAMS ((int)); void s_else PARAMS ((int arg)); void s_end PARAMS ((int arg)); void s_endif PARAMS ((int arg)); +void s_fail PARAMS ((int)); void s_fill PARAMS ((int)); +void s_float_space PARAMS ((int mult)); void s_globl PARAMS ((int arg)); void s_if PARAMS ((int arg)); void s_ifdef PARAMS ((int arg)); @@ -101,10 +105,12 @@ void s_ignore PARAMS ((int arg)); void s_include PARAMS ((int arg)); void s_lcomm PARAMS ((int needs_align)); void s_lsym PARAMS ((int)); +void s_mri_common PARAMS ((int)); void s_org PARAMS ((int)); void s_set PARAMS ((int)); void s_space PARAMS ((int mult)); void s_stab PARAMS ((int what)); +void s_struct PARAMS ((int)); void s_text PARAMS ((int)); void stringer PARAMS ((int append_zero)); void s_xstab PARAMS ((int what));