From ea1562b345338540cf9a3c8fa28fbcb6da78fd3e Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 24 Mar 2005 20:40:28 +0000 Subject: [PATCH] Convert unmaintained files over to ISO-C90 and fix formatting. --- gas/ChangeLog | 59 + gas/config/atof-ieee.c | 42 +- gas/config/obj-aout.c | 300 +- gas/config/obj-aout.h | 134 +- gas/config/obj-bout.c | 131 +- gas/config/obj-bout.h | 288 +- gas/config/obj-ecoff.c | 207 +- gas/config/obj-ecoff.h | 7 +- gas/config/obj-som.c | 39 +- gas/config/obj-som.h | 14 +- gas/config/tc-a29k.c | 452 +-- gas/config/tc-a29k.h | 44 +- gas/config/tc-alpha.c | 7772 ++++++++++++++++++------------------- gas/config/tc-alpha.h | 37 +- gas/config/tc-arc.c | 1782 +++++---- gas/config/tc-arc.h | 21 +- gas/config/tc-d10v.c | 1022 +++-- gas/config/tc-d10v.h | 26 +- gas/config/tc-d30v.c | 1673 ++++---- gas/config/tc-d30v.h | 28 +- gas/config/tc-dlx.c | 500 +-- gas/config/tc-dlx.h | 32 +- gas/config/tc-fr30.c | 91 +- gas/config/tc-fr30.h | 12 +- gas/config/tc-h8500.c | 409 +- gas/config/tc-h8500.h | 19 +- gas/config/tc-i370.c | 1147 +++--- gas/config/tc-i370.h | 13 +- gas/config/tc-i960.c | 3517 ++++++++--------- gas/config/tc-ip2k.c | 169 +- gas/config/tc-ip2k.h | 8 +- gas/config/tc-m32r.c | 323 +- gas/config/tc-m32r.h | 36 +- gas/config/tc-m88k.c | 1065 +++-- gas/config/tc-m88k.h | 50 +- gas/config/tc-mcore.c | 725 ++-- gas/config/tc-mcore.h | 14 +- gas/config/tc-mn10200.c | 469 ++- gas/config/tc-ns32k.c | 1516 ++++---- gas/config/tc-ns32k.h | 16 +- gas/config/tc-openrisc.c | 75 +- gas/config/tc-openrisc.h | 6 +- gas/config/tc-or32.c | 245 +- gas/config/tc-or32.h | 12 +- gas/config/tc-pdp11.h | 4 +- gas/config/tc-pj.c | 100 +- gas/config/tc-pj.h | 8 +- gas/config/tc-tahoe.c | 1135 +++--- gas/config/tc-tic80.c | 296 +- gas/config/tc-tic80.h | 4 +- gas/config/tc-v850.c | 310 +- gas/config/tc-v850.h | 14 +- gas/config/tc-w65.c | 248 +- gas/config/tc-w65.h | 9 +- gas/config/tc-xstormy16.c | 109 +- gas/config/tc-xstormy16.h | 14 +- gas/write.h | 3 - 57 files changed, 12322 insertions(+), 14479 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index ac6496ebf66..3e2347a62dd 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,62 @@ +2005-03-24 Nick Clifton + + * write.h (bit_fix_new): Remove redundant prototype. + * config/atof-ieee.c: Convert to ISO-C90 and fix formatting. + * config/obj-aout.c: Convert to ISO-C90 and fix formatting. + * config/obj-aout.h: Convert to ISO-C90 and fix formatting. + * config/obj-bout.c: Convert to ISO-C90 and fix formatting. + * config/obj-bout.h: Convert to ISO-C90 and fix formatting. + * config/obj-ecoff.c: Convert to ISO-C90 and fix formatting. + * config/obj-ecoff.h: Convert to ISO-C90 and fix formatting. + * config/obj-som.c: Convert to ISO-C90 and fix formatting. + * config/obj-som.h: Convert to ISO-C90 and fix formatting. + * config/tc-a29k.c: Convert to ISO-C90 and fix formatting. + * config/tc-a29k.h: Convert to ISO-C90 and fix formatting. + * config/tc-alpha.c: Convert to ISO-C90 and fix formatting. + * config/tc-alpha.h: Convert to ISO-C90 and fix formatting. + * config/tc-arc.c: Convert to ISO-C90 and fix formatting. + * config/tc-arc.h: Convert to ISO-C90 and fix formatting. + * config/tc-d10v.c: Convert to ISO-C90 and fix formatting. + * config/tc-d10v.h: Convert to ISO-C90 and fix formatting. + * config/tc-d30v.c: Convert to ISO-C90 and fix formatting. + * config/tc-d30v.h: Convert to ISO-C90 and fix formatting. + * config/tc-dlx.c: Convert to ISO-C90 and fix formatting. + * config/tc-dlx.h: Convert to ISO-C90 and fix formatting. + * config/tc-fr30.c: Convert to ISO-C90 and fix formatting. + * config/tc-fr30.h: Convert to ISO-C90 and fix formatting. + * config/tc-h8500.c: Convert to ISO-C90 and fix formatting. + * config/tc-h8500.h: Convert to ISO-C90 and fix formatting. + * config/tc-i370.c: Convert to ISO-C90 and fix formatting. + * config/tc-i370.h: Convert to ISO-C90 and fix formatting. + * config/tc-i960.c: Convert to ISO-C90 and fix formatting. + * config/tc-ip2k.c: Convert to ISO-C90 and fix formatting. + * config/tc-ip2k.h: Convert to ISO-C90 and fix formatting. + * config/tc-m32r.c: Convert to ISO-C90 and fix formatting. + * config/tc-m32r.h: Convert to ISO-C90 and fix formatting. + * config/tc-m88k.c: Convert to ISO-C90 and fix formatting. + * config/tc-m88k.h: Convert to ISO-C90 and fix formatting. + * config/tc-mcore.c: Convert to ISO-C90 and fix formatting. + * config/tc-mcore.h: Convert to ISO-C90 and fix formatting. + * config/tc-mn10200.c: Convert to ISO-C90 and fix formatting. + * config/tc-ns32k.c: Convert to ISO-C90 and fix formatting. + * config/tc-ns32k.h: Convert to ISO-C90 and fix formatting. + * config/tc-openrisc.c: Convert to ISO-C90 and fix formatting. + * config/tc-openrisc.h: Convert to ISO-C90 and fix formatting. + * config/tc-or32.c: Convert to ISO-C90 and fix formatting. + * config/tc-or32.h: Convert to ISO-C90 and fix formatting. + * config/tc-pdp11.h: Convert to ISO-C90 and fix formatting. + * config/tc-pj.c: Convert to ISO-C90 and fix formatting. + * config/tc-pj.h: Convert to ISO-C90 and fix formatting. + * config/tc-tahoe.c: Convert to ISO-C90 and fix formatting. + * config/tc-tic80.c: Convert to ISO-C90 and fix formatting. + * config/tc-tic80.h: Convert to ISO-C90 and fix formatting. + * config/tc-v850.c: Convert to ISO-C90 and fix formatting. + * config/tc-v850.h: Convert to ISO-C90 and fix formatting. + * config/tc-w65.c: Convert to ISO-C90 and fix formatting. + * config/tc-w65.h: Convert to ISO-C90 and fix formatting. + * config/tc-xstormy16.c: Convert to ISO-C90 and fix formatting. + * config/tc-xstormy16.h: Convert to ISO-C90 and fix formatting. + 2005-03-23 Jim Blandy * config/tc-arm.c (arm_adjust_symtab): Fetch elf_sym's binding diff --git a/gas/config/atof-ieee.c b/gas/config/atof-ieee.c index d7a54b0cde0..7df3186f26c 100644 --- a/gas/config/atof-ieee.c +++ b/gas/config/atof-ieee.c @@ -24,21 +24,17 @@ /* Flonums returned here. */ extern FLONUM_TYPE generic_floating_point_number; -static int next_bits PARAMS ((int)); -static void unget_bits PARAMS ((int)); -static void make_invalid_floating_point_number PARAMS ((LITTLENUM_TYPE *)); - extern const char EXP_CHARS[]; /* Precision in LittleNums. */ /* Don't count the gap in the m68k extended precision format. */ -#define MAX_PRECISION (5) -#define F_PRECISION (2) -#define D_PRECISION (4) -#define X_PRECISION (5) -#define P_PRECISION (5) +#define MAX_PRECISION 5 +#define F_PRECISION 2 +#define D_PRECISION 4 +#define X_PRECISION 5 +#define P_PRECISION 5 /* Length in LittleNums of guard bits. */ -#define GUARD (2) +#define GUARD 2 #ifndef TC_LARGEST_EXPONENT_IS_NORMAL #define TC_LARGEST_EXPONENT_IS_NORMAL(PRECISION) 0 @@ -86,13 +82,13 @@ static int littlenums_left; static LITTLENUM_TYPE *littlenum_pointer; static int -next_bits (number_of_bits) - int number_of_bits; +next_bits (int number_of_bits) { int return_value; if (!littlenums_left) - return (0); + return 0; + if (number_of_bits >= bits_left_in_littlenum) { return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; @@ -120,8 +116,7 @@ next_bits (number_of_bits) /* Num had better be less than LITTLENUM_NUMBER_OF_BITS. */ static void -unget_bits (num) - int num; +unget_bits (int num) { if (!littlenums_left) { @@ -141,8 +136,7 @@ unget_bits (num) } static void -make_invalid_floating_point_number (words) - LITTLENUM_TYPE *words; +make_invalid_floating_point_number (LITTLENUM_TYPE *words) { as_bad (_("cannot create floating-point number")); /* Zero the leftmost bit. */ @@ -165,10 +159,9 @@ make_invalid_floating_point_number (words) /* Returns pointer past text consumed. */ char * -atof_ieee (str, what_kind, words) - char *str; /* Text to convert to binary. */ - int what_kind; /* 'd', 'f', 'g', 'h'. */ - LITTLENUM_TYPE *words; /* Build the binary here. */ +atof_ieee (char *str, /* Text to convert to binary. */ + int what_kind, /* 'd', 'f', 'g', 'h'. */ + LITTLENUM_TYPE *words) /* Build the binary here. */ { /* Extra bits for zeroed low-order bits. The 1st MAX_PRECISION are zeroed, the last contain flonum bits. */ @@ -242,7 +235,7 @@ atof_ieee (str, what_kind, words) &generic_floating_point_number)) { make_invalid_floating_point_number (words); - return (NULL); + return NULL; } gen_to_words (words, precision, exponent_bits); @@ -256,10 +249,7 @@ atof_ieee (str, what_kind, words) /* Turn generic_floating_point_number into a real float/double/extended. */ int -gen_to_words (words, precision, exponent_bits) - LITTLENUM_TYPE *words; - int precision; - long exponent_bits; +gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) { int return_value = 0; diff --git a/gas/config/obj-aout.c b/gas/config/obj-aout.c index 6a47a9bd3e4..720d09c6c2d 100644 --- a/gas/config/obj-aout.c +++ b/gas/config/obj-aout.c @@ -2,22 +2,22 @@ Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. -This file is part of GAS, the GNU Assembler. + This file is part of GAS, the GNU Assembler. -GAS is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2, -or (at your option) any later version. + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, + or (at your option) any later version. -GAS is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See -the GNU General Public License for more details. + GAS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + the GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GAS; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ #define OBJ_HEADER "obj-aout.h" @@ -29,20 +29,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "obstack.h" #ifndef BFD_ASSEMBLER -/* in: segT out: N_TYPE bits */ +/* in: segT out: N_TYPE bits. */ const short seg_N_TYPE[] = { N_ABS, N_TEXT, N_DATA, N_BSS, - N_UNDF, /* unknown */ - N_UNDF, /* error */ - N_UNDF, /* expression */ - N_UNDF, /* debug */ - N_UNDF, /* ntv */ - N_UNDF, /* ptv */ - N_REGISTER, /* register */ + N_UNDF, /* Unknown. */ + N_UNDF, /* Error. */ + N_UNDF, /* Expression. */ + N_UNDF, /* Debug. */ + N_UNDF, /* Ntv. */ + N_UNDF, /* Ptv. */ + N_REGISTER, /* Register. */ }; const segT N_TYPE_seg[N_TYPE + 2] = @@ -60,51 +60,15 @@ const segT N_TYPE_seg[N_TYPE + 2] = SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, - SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */ + SEG_REGISTER, /* Dummy N_REGISTER for regs = 30. */ SEG_GOOF, }; #endif -static void obj_aout_line PARAMS ((int)); -static void obj_aout_weak PARAMS ((int)); -static void obj_aout_type PARAMS ((int)); - -const pseudo_typeS aout_pseudo_table[] = -{ - {"line", obj_aout_line, 0}, /* source code line number */ - {"ln", obj_aout_line, 0}, /* coff line number that we use anyway */ - - {"weak", obj_aout_weak, 0}, /* mark symbol as weak. */ - - {"type", obj_aout_type, 0}, - - /* coff debug pseudos (ignored) */ - {"def", s_ignore, 0}, - {"dim", s_ignore, 0}, - {"endef", s_ignore, 0}, - {"ident", s_ignore, 0}, - {"line", s_ignore, 0}, - {"ln", s_ignore, 0}, - {"scl", s_ignore, 0}, - {"size", s_ignore, 0}, - {"tag", s_ignore, 0}, - {"val", s_ignore, 0}, - {"version", s_ignore, 0}, - - {"optim", s_ignore, 0}, /* For sun386i cc (?) */ - - /* other stuff */ - {"ABORT", s_abort, 0}, - - {NULL, NULL, 0} /* end sentinel */ -}; /* aout_pseudo_table */ - #ifdef BFD_ASSEMBLER void -obj_aout_frob_symbol (sym, punt) - symbolS *sym; - int *punt ATTRIBUTE_UNUSED; +obj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED) { flagword flags; asection *sec; @@ -184,23 +148,18 @@ obj_aout_frob_symbol (sym, punt) } } else - { - symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING; - } + symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING; aout_symbol (symbol_get_bfdsym (sym))->type = type; /* Double check weak symbols. */ - if (S_IS_WEAK (sym)) - { - if (S_IS_COMMON (sym)) - as_bad (_("Symbol `%s' can not be both weak and common"), - S_GET_NAME (sym)); - } + if (S_IS_WEAK (sym) && S_IS_COMMON (sym)) + as_bad (_("Symbol `%s' can not be both weak and common"), + S_GET_NAME (sym)); } void -obj_aout_frob_file_before_fix () +obj_aout_frob_file_before_fix (void) { /* Relocation processing may require knowing the VMAs of the sections. Since writing to a section will cause the BFD back end to compute the @@ -208,15 +167,12 @@ obj_aout_frob_file_before_fix () bfd_byte b = 0; bfd_boolean x = TRUE; if (bfd_section_size (stdoutput, text_section) != 0) - { - x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0, - (bfd_size_type) 1); - } + x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0, + (bfd_size_type) 1); else if (bfd_section_size (stdoutput, data_section) != 0) - { - x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0, - (bfd_size_type) 1); - } + x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0, + (bfd_size_type) 1); + assert (x); } @@ -224,16 +180,12 @@ obj_aout_frob_file_before_fix () /* Relocation. */ -/* - * emit_relocations() - * - * Crawl along a fixS chain. Emit the segment's relocations. - */ +/** Crawl along a fixS chain. Emit the segment's relocations. */ + void -obj_emit_relocations (where, fixP, segment_address_in_file) - char **where; - fixS *fixP; /* Fixup chain for this segment. */ - relax_addressT segment_address_in_file; +obj_emit_relocations (char **where, + fixS *fixP, /* Fixup chain for this segment. */ + relax_addressT segment_address_in_file) { for (; fixP; fixP = fixP->fx_next) if (fixP->fx_done == 0) @@ -264,14 +216,12 @@ obj_emit_relocations (where, fixP, segment_address_in_file) } #ifndef obj_header_append -/* Aout file generation & utilities */ +/* Aout file generation & utilities. */ /* An AOUT header on disk is laid out in target byte order. */ void -obj_header_append (where, headers) - char **where; - object_headers *headers; +obj_header_append (char **where, object_headers *headers) { char *p; @@ -302,9 +252,7 @@ obj_header_append (where, headers) #endif /* ! defined (obj_header_append) */ void -obj_symbol_to_chars (where, symbolP) - char **where; - symbolS *symbolP; +obj_symbol_to_chars (char **where, symbolS *symbolP) { char *p = *where; md_number_to_chars (p, S_GET_OFFSET (symbolP), 4); @@ -320,9 +268,7 @@ obj_symbol_to_chars (where, symbolP) } void -obj_emit_symbols (where, symbol_rootP) - char **where; - symbolS *symbol_rootP; +obj_emit_symbols (char **where, symbolS *symbol_rootP) { symbolS *symbolP; @@ -331,7 +277,7 @@ obj_emit_symbols (where, symbol_rootP) { /* Used to save the offset of the name. It is used to point to the string in memory but must be a file offset. */ - register char *temp; + char *temp; temp = S_GET_NAME (symbolP); S_SET_OFFSET (symbolP, symbolP->sy_name_offset); @@ -362,21 +308,19 @@ obj_emit_symbols (where, symbol_rootP) #endif /* ! BFD_ASSEMBLER */ static void -obj_aout_line (ignore) - int ignore ATTRIBUTE_UNUSED; +obj_aout_line (int ignore ATTRIBUTE_UNUSED) { /* Assume delimiter is part of expression. BSD4.2 as fails with delightful bug, so we are not being incompatible here. */ new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); demand_empty_rest_of_line (); -} /* obj_aout_line() */ +} /* Handle .weak. This is a GNU extension. */ static void -obj_aout_weak (ignore) - int ignore ATTRIBUTE_UNUSED; +obj_aout_weak (int ignore ATTRIBUTE_UNUSED) { char *name; int c; @@ -408,8 +352,7 @@ obj_aout_weak (ignore) we can't parse it. */ static void -obj_aout_type (ignore) - int ignore ATTRIBUTE_UNUSED; +obj_aout_type (int ignore ATTRIBUTE_UNUSED) { char *name; int c; @@ -441,8 +384,7 @@ obj_aout_type (ignore) #ifndef BFD_ASSEMBLER void -obj_crawl_symbol_chain (headers) - object_headers *headers; +obj_crawl_symbol_chain (object_headers *headers) { symbolS *symbolP; symbolS **symbolPP; @@ -465,7 +407,7 @@ obj_crawl_symbol_chain (headers) if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA)) { S_SET_SEGMENT (symbolP, SEG_TEXT); - } /* if pushing data into text */ + } resolve_symbol_value (symbolP); @@ -525,25 +467,21 @@ obj_crawl_symbol_chain (headers) /* This warning should never get triggered any more. Well, maybe if you're doing twisted things with register names... */ - { - as_bad (_("Local symbol %s never defined."), decode_local_label_name (S_GET_NAME (symbolP))); - } /* oops. */ + as_bad (_("Local symbol %s never defined."), + decode_local_label_name (S_GET_NAME (symbolP))); /* Unhook it from the chain */ *symbolPP = symbol_next (symbolP); - } /* if this symbol should be in the output */ - } /* for each symbol */ + } + } H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); } -/* - * Find strings by crawling along symbol table chain. - */ +/* Find strings by crawling along symbol table chain. */ void -obj_emit_strings (where) - char **where; +obj_emit_strings (char **where) { symbolS *symbolP; @@ -551,11 +489,9 @@ obj_emit_strings (where) *where += 4; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - if (S_GET_NAME (symbolP)) - append (where, S_GET_NAME (symbolP), - (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); - } /* walk symbol chain */ + if (S_GET_NAME (symbolP)) + append (where, S_GET_NAME (symbolP), + (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); } #ifndef AOUT_VERSION @@ -563,8 +499,7 @@ obj_emit_strings (where) #endif void -obj_pre_write_hook (headers) - object_headers *headers; +obj_pre_write_hook (object_headers *headers) { H_SET_DYNAMIC (headers, 0); H_SET_VERSION (headers, AOUT_VERSION); @@ -578,126 +513,135 @@ obj_pre_write_hook (headers) /* Support for an AOUT emulation. */ -static void aout_pop_insert PARAMS ((void)); -static int obj_aout_s_get_other PARAMS ((symbolS *)); -static void obj_aout_s_set_other PARAMS ((symbolS *, int)); -static int obj_aout_s_get_desc PARAMS ((symbolS *)); -static void obj_aout_s_set_desc PARAMS ((symbolS *, int)); -static int obj_aout_s_get_type PARAMS ((symbolS *)); -static void obj_aout_s_set_type PARAMS ((symbolS *, int)); -static int obj_aout_separate_stab_sections PARAMS ((void)); -static int obj_aout_sec_sym_ok_for_reloc PARAMS ((asection *)); -static void obj_aout_process_stab PARAMS ((segT, int, const char *, int, int, int)); - static void -aout_pop_insert () +aout_pop_insert (void) { pop_insert (aout_pseudo_table); } static int -obj_aout_s_get_other (sym) - symbolS *sym; +obj_aout_s_get_other (symbolS *sym) { return aout_symbol (symbol_get_bfdsym (sym))->other; } static void -obj_aout_s_set_other (sym, o) - symbolS *sym; - int o; +obj_aout_s_set_other (symbolS *sym, int o) { aout_symbol (symbol_get_bfdsym (sym))->other = o; } static int -obj_aout_sec_sym_ok_for_reloc (sec) - asection *sec ATTRIBUTE_UNUSED; +obj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED) { return obj_sec_sym_ok_for_reloc (sec); } static void -obj_aout_process_stab (seg, w, s, t, o, d) - segT seg ATTRIBUTE_UNUSED; - int w; - const char *s; - int t; - int o; - int d; +obj_aout_process_stab (segT seg ATTRIBUTE_UNUSED, + int w, + const char *s, + int t, + int o, + int d) { aout_process_stab (w, s, t, o, d); } static int -obj_aout_s_get_desc (sym) - symbolS *sym; +obj_aout_s_get_desc (symbolS *sym) { return aout_symbol (symbol_get_bfdsym (sym))->desc; } static void -obj_aout_s_set_desc (sym, d) - symbolS *sym; - int d; +obj_aout_s_set_desc (symbolS *sym, int d) { aout_symbol (symbol_get_bfdsym (sym))->desc = d; } static int -obj_aout_s_get_type (sym) - symbolS *sym; +obj_aout_s_get_type (symbolS *sym) { return aout_symbol (symbol_get_bfdsym (sym))->type; } static void -obj_aout_s_set_type (sym, t) - symbolS *sym; - int t; +obj_aout_s_set_type (symbolS *sym, int t) { aout_symbol (symbol_get_bfdsym (sym))->type = t; } static int -obj_aout_separate_stab_sections () +obj_aout_separate_stab_sections (void) { return 0; } /* When changed, make sure these table entries match the single-format definitions in obj-aout.h. */ + const struct format_ops aout_format_ops = { bfd_target_aout_flavour, - 1, /* dfl_leading_underscore */ - 0, /* emit_section_symbols */ - 0, /* begin */ - 0, /* app_file */ + 1, /* dfl_leading_underscore. */ + 0, /* emit_section_symbols. */ + 0, /* begin. */ + 0, /* app_file. */ obj_aout_frob_symbol, - 0, /* frob_file */ - 0, /* frob_file_before_adjust */ + 0, /* frob_file. */ + 0, /* frob_file_before_adjust. */ obj_aout_frob_file_before_fix, - 0, /* frob_file_after_relocs */ - 0, /* s_get_size */ - 0, /* s_set_size */ - 0, /* s_get_align */ - 0, /* s_set_align */ + 0, /* frob_file_after_relocs. */ + 0, /* s_get_size. */ + 0, /* s_set_size. */ + 0, /* s_get_align. */ + 0, /* s_set_align. */ obj_aout_s_get_other, obj_aout_s_set_other, obj_aout_s_get_desc, obj_aout_s_set_desc, obj_aout_s_get_type, obj_aout_s_set_type, - 0, /* copy_symbol_attributes */ - 0, /* generate_asm_lineno */ + 0, /* copy_symbol_attributes. */ + 0, /* generate_asm_lineno. */ obj_aout_process_stab, obj_aout_separate_stab_sections, - 0, /* init_stab_section */ + 0, /* init_stab_section. */ obj_aout_sec_sym_ok_for_reloc, aout_pop_insert, - 0, /* ecoff_set_ext */ - 0, /* read_begin_hook */ - 0 /* symbol_new_hook */ + 0, /* ecoff_set_ext. */ + 0, /* read_begin_hook. */ + 0 /* symbol_new_hook. */ }; #endif /* BFD_ASSEMBLER */ + +const pseudo_typeS aout_pseudo_table[] = +{ + {"line", obj_aout_line, 0}, /* Source code line number. */ + {"ln", obj_aout_line, 0}, /* COFF line number that we use anyway. */ + + {"weak", obj_aout_weak, 0}, /* Mark symbol as weak. */ + + {"type", obj_aout_type, 0}, + + /* coff debug pseudos (ignored) */ + {"def", s_ignore, 0}, + {"dim", s_ignore, 0}, + {"endef", s_ignore, 0}, + {"ident", s_ignore, 0}, + {"line", s_ignore, 0}, + {"ln", s_ignore, 0}, + {"scl", s_ignore, 0}, + {"size", s_ignore, 0}, + {"tag", s_ignore, 0}, + {"val", s_ignore, 0}, + {"version", s_ignore, 0}, + + {"optim", s_ignore, 0}, /* For sun386i cc (?). */ + + /* other stuff */ + {"ABORT", s_abort, 0}, + + {NULL, NULL, 0} +}; diff --git a/gas/config/obj-aout.h b/gas/config/obj-aout.h index 271868691a5..8852cf1fcbc 100644 --- a/gas/config/obj-aout.h +++ b/gas/config/obj-aout.h @@ -57,10 +57,9 @@ extern const pseudo_typeS aout_pseudo_table[]; #define obj_pop_insert() pop_insert (aout_pseudo_table) #endif -/* SYMBOL TABLE */ -/* Symbol table entry data type */ +/* Symbol table entry data type. */ -typedef struct nlist obj_symbol_type; /* Symbol table entry */ +typedef struct nlist obj_symbol_type; /* Symbol table entry. */ /* Symbol table macros and constants */ @@ -83,26 +82,25 @@ asection *text_section, *data_section, *bss_section; #define obj_frob_symbol(S,PUNT) obj_aout_frob_symbol (S, &PUNT) #define obj_frob_file_before_fix() obj_aout_frob_file_before_fix () -extern void obj_aout_frob_symbol PARAMS ((symbolS *, int *)); -extern void obj_aout_frob_file_before_fix PARAMS ((void)); -#define obj_sec_sym_ok_for_reloc(SEC) (1) +extern void obj_aout_frob_symbol (symbolS *, int *); +extern void obj_aout_frob_file_before_fix (void); + +#define obj_sec_sym_ok_for_reloc(SEC) 1 #else /* We use the sy_obj field to record whether a symbol is weak. */ #define OBJ_SYMFIELD_TYPE char -/* - * Macros to extract information from a symbol table entry. - * This syntactic indirection allows independence regarding a.out or coff. - * The argument (s) of all these macros is a pointer to a symbol table entry. - */ +/* Macros to extract information from a symbol table entry. + This syntactic indirection allows independence regarding a.out or coff. + The argument (s) of all these macros is a pointer to a symbol table entry. */ -/* True if the symbol is external */ +/* True if the symbol is external. */ #define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) -/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ +/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT. */ #define S_IS_DEFINED(s) \ (S_GET_TYPE (s) != N_UNDF || S_GET_DESC (s) != 0) @@ -117,9 +115,9 @@ extern void obj_aout_frob_file_before_fix PARAMS ((void)); #define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) -/* True if a debug special symbol entry */ +/* True if a debug special symbol entry. */ #define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) -/* True if a symbol is local symbol name */ +/* True if a symbol is local symbol name. */ #define S_IS_LOCAL(s) \ ((S_GET_NAME (s) \ && !S_IS_DEBUG (s) \ @@ -129,59 +127,59 @@ extern void obj_aout_frob_file_before_fix PARAMS ((void)); || (flag_strip_local_absolute \ && ! S_IS_EXTERNAL(s) \ && S_GET_SEGMENT (s) == absolute_section)) -/* True if a symbol is not defined in this file */ +/* True if a symbol is not defined in this file. */ #define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) -/* True if the symbol has been generated because of a .stabd directive */ -#define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0) +/* True if the symbol has been generated because of a .stabd directive. */ +#define S_IS_STABD(s) (S_GET_NAME(s) == NULL) -/* Accessors */ -/* The name of the symbol */ +/* Accessors. */ +/* The name of the symbol. */ #define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) -/* The pointer to the string table */ +/* The pointer to the string table. */ #define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) -/* The type of the symbol */ +/* The type of the symbol. */ #define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) -/* The numeric value of the segment */ +/* The numeric value of the segment. */ #define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) -/* The n_other expression value */ +/* The n_other expression value. */ #define S_GET_OTHER(s) ((s)->sy_symbol.n_other) -/* The n_desc expression value */ +/* The n_desc expression value. */ #define S_GET_DESC(s) ((s)->sy_symbol.n_desc) /* Whether the symbol is weak. */ #define S_GET_WEAK(s) ((s)->sy_obj) -/* Modifiers */ -/* Assume that a symbol cannot be simultaneously in more than on segment */ -/* set segment */ -#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) -/* The symbol is external */ +/* Modifiers. */ +/* Assume that a symbol cannot be simultaneously in more than on segment. */ +/* Set segment. */ +#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE (seg)) +/* The symbol is external. */ #define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) -/* The symbol is not external */ +/* The symbol is not external. */ #define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) -/* Set the name of the symbol */ +/* Set the name of the symbol. */ #define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v)) -/* Set the offset in the string table */ +/* Set the offset in the string table. */ #define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) -/* Set the n_type field */ +/* Set the n_type field. */ #define S_SET_TYPE(s,t) ((s)->sy_symbol.n_type = (t)) -/* Set the n_other expression value */ +/* Set the n_other expression value. */ #define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) -/* Set the n_desc expression value */ +/* Set the n_desc expression value. */ #define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) /* Mark the symbol as weak. This causes n_type to be adjusted when the symbol is written out. */ #define S_SET_WEAK(s) ((s)->sy_obj = 1) -/* File header macro and type definition */ +/* File header macro and type definition. */ -#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \ - + H_GET_TEXT_SIZE(h) \ - + H_GET_DATA_SIZE(h) \ - + H_GET_TEXT_RELOCATION_SIZE(h) \ - + H_GET_DATA_RELOCATION_SIZE(h) \ - + H_GET_LINENO_SIZE(h) \ - + H_GET_SYMBOL_TABLE_SIZE(h) \ - + H_GET_STRING_SIZE(h)) +#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE (h) \ + + H_GET_TEXT_SIZE (h) \ + + H_GET_DATA_SIZE (h) \ + + H_GET_TEXT_RELOCATION_SIZE (h) \ + + H_GET_DATA_RELOCATION_SIZE (h) \ + + H_GET_LINENO_SIZE (h) \ + + H_GET_SYMBOL_TABLE_SIZE (h) \ + + H_GET_STRING_SIZE (h)) #define H_GET_HEADER_SIZE(h) (EXEC_BYTES_SIZE) #define H_GET_TEXT_SIZE(h) ((h)->header.a_text) @@ -200,31 +198,31 @@ extern void obj_aout_frob_file_before_fix PARAMS ((void)); #define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info & 0xffff) #define H_SET_DYNAMIC(h,v) ((h)->header.a_info = (((v) << 31) \ - | (H_GET_VERSION(h) << 24) \ - | (H_GET_MACHTYPE(h) << 16) \ - | (H_GET_MAGIC_NUMBER(h)))) + | (H_GET_VERSION (h) << 24) \ + | (H_GET_MACHTYPE (h) << 16) \ + | (H_GET_MAGIC_NUMBER (h)))) -#define H_SET_VERSION(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ +#define H_SET_VERSION(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC (h) << 31) \ | ((v) << 24) \ - | (H_GET_MACHTYPE(h) << 16) \ - | (H_GET_MAGIC_NUMBER(h)))) + | (H_GET_MACHTYPE (h) << 16) \ + | (H_GET_MAGIC_NUMBER (h)))) -#define H_SET_MACHTYPE(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ - | (H_GET_VERSION(h) << 24) \ +#define H_SET_MACHTYPE(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC (h) << 31) \ + | (H_GET_VERSION (h) << 24) \ | ((v) << 16) \ - | (H_GET_MAGIC_NUMBER(h)))) + | (H_GET_MAGIC_NUMBER (h)))) -#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC(h) << 31) \ - | (H_GET_VERSION(h) << 24) \ - | (H_GET_MACHTYPE(h) << 16) \ +#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_info = ((H_GET_DYNAMIC (h) << 31) \ + | (H_GET_VERSION (h) << 24) \ + | (H_GET_MACHTYPE (h) << 16) \ | ((v)))) -#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v))) -#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v))) -#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v))) +#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align (SEG_TEXT, (v))) +#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align (SEG_DATA, (v))) +#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align (SEG_BSS, (v))) -#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\ - H_SET_DATA_RELOCATION_SIZE((h),(d))) +#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE ((h),(t)),\ + H_SET_DATA_RELOCATION_SIZE ((h),(d))) #define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v)) #define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v)) @@ -234,18 +232,18 @@ extern void obj_aout_frob_file_before_fix PARAMS ((void)); #define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) typedef struct - { - struct exec header; /* a.out header */ - long string_table_size; /* names + '\0' + sizeof (int) */ - } +{ + struct exec header; /* a.out header. */ + long string_table_size; /* names + '\0' + sizeof (int). */ +} object_headers; -/* line numbering stuff. */ +/* Line numbering stuff. */ #define OBJ_EMIT_LINENO(a, b, c) {;} struct fix; -void tc_aout_fix_to_chars PARAMS ((char *where, struct fix *fixP, relax_addressT segment_address)); +extern void tc_aout_fix_to_chars (char *, struct fix *, relax_addressT); #endif diff --git a/gas/config/obj-bout.c b/gas/config/obj-bout.c index a8b818be647..82383595f9f 100644 --- a/gas/config/obj-bout.c +++ b/gas/config/obj-bout.c @@ -22,20 +22,20 @@ #include "as.h" #include "obstack.h" -/* In: segT Out: N_TYPE bits */ +/* In: segT Out: N_TYPE bits. */ const short seg_N_TYPE[] = { N_ABS, N_TEXT, N_DATA, N_BSS, - N_UNDF, /* unknown */ - N_UNDF, /* error */ - N_UNDF, /* expression */ - N_UNDF, /* debug */ - N_UNDF, /* ntv */ - N_UNDF, /* ptv */ - N_REGISTER, /* register */ + N_UNDF, /* Unknown. */ + N_UNDF, /* Error. */ + N_UNDF, /* Expression. */ + N_UNDF, /* Debug. */ + N_UNDF, /* Ntv. */ + N_UNDF, /* Ptv. */ + N_REGISTER, /* Register. */ }; const segT N_TYPE_seg[N_TYPE + 2] = @@ -53,43 +53,18 @@ const segT N_TYPE_seg[N_TYPE + 2] = SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, - SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */ + SEG_REGISTER, /* Dummy N_REGISTER for regs = 30. */ SEG_GOOF, }; -static void obj_bout_line PARAMS ((int)); - -const pseudo_typeS obj_pseudo_table[] = -{ - {"line", obj_bout_line, 0}, /* Source code line number. */ - -/* coff debugging directives. Currently ignored silently. */ - {"def", s_ignore, 0}, - {"dim", s_ignore, 0}, - {"endef", s_ignore, 0}, - {"ln", s_ignore, 0}, - {"scl", s_ignore, 0}, - {"size", s_ignore, 0}, - {"tag", s_ignore, 0}, - {"type", s_ignore, 0}, - {"val", s_ignore, 0}, - -/* other stuff we don't handle */ - {"ABORT", s_ignore, 0}, - {"ident", s_ignore, 0}, - - {NULL, NULL, 0} /* End sentinel. */ -}; - /* Relocation. */ /* Crawl along a fixS chain. Emit the segment's relocations. */ void -obj_emit_relocations (where, fixP, segment_address_in_file) - char **where; - fixS *fixP; /* Fixup chain for this segment. */ - relax_addressT segment_address_in_file; +obj_emit_relocations (char **where, + fixS *fixP, /* Fixup chain for this segment. */ + relax_addressT segment_address_in_file) { for (; fixP; fixP = fixP->fx_next) { @@ -106,8 +81,8 @@ obj_emit_relocations (where, fixP, segment_address_in_file) tc_bout_fix_to_chars (*where, fixP, segment_address_in_file); *where += md_reloc_size; - } /* if there's a symbol */ - } /* for each fixup */ + } + } } /* Aout file generation & utilities . */ @@ -115,9 +90,7 @@ obj_emit_relocations (where, fixP, segment_address_in_file) /* Convert a lvalue to machine dependent data. */ void -obj_header_append (where, headers) - char **where; - object_headers *headers; +obj_header_append (char **where, object_headers *headers) { /* Always leave in host byte order. */ char *p; @@ -126,9 +99,7 @@ obj_header_append (where, headers) /* Force to at least 2. */ if (headers->header.a_talign < 2) - { - headers->header.a_talign = 2; - } + headers->header.a_talign = 2; headers->header.a_dalign = section_alignment[SEG_DATA]; headers->header.a_balign = section_alignment[SEG_BSS]; @@ -168,11 +139,10 @@ obj_header_append (where, headers) } void -obj_symbol_to_chars (where, symbolP) - char **where; - symbolS *symbolP; +obj_symbol_to_chars (char **where, symbolS *symbolP) { char *p = *where; + host_number_to_chars (p, S_GET_OFFSET (symbolP), 4); p += 4; /* Can't use S_GET_TYPE here as it masks. */ @@ -186,9 +156,7 @@ obj_symbol_to_chars (where, symbolP) } void -obj_emit_symbols (where, symbol_rootP) - char **where; - symbolS *symbol_rootP; +obj_emit_symbols (char **where, symbolS *symbol_rootP) { symbolS *symbolP; @@ -212,32 +180,29 @@ obj_emit_symbols (where, symbol_rootP) } void -obj_symbol_new_hook (symbolP) - symbolS *symbolP; +obj_symbol_new_hook (symbolS *symbolP) { S_SET_OTHER (symbolP, 0); S_SET_DESC (symbolP, 0); } static void -obj_bout_line (ignore) - int ignore ATTRIBUTE_UNUSED; +obj_bout_line (int ignore ATTRIBUTE_UNUSED) { /* Assume delimiter is part of expression. */ /* BSD4.2 as fails with delightful bug, so we are not being incompatible here. */ - new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); + new_logical_line (NULL, (int) (get_absolute_expression ())); demand_empty_rest_of_line (); } void -obj_read_begin_hook () +obj_read_begin_hook (void) { } void -obj_crawl_symbol_chain (headers) - object_headers *headers; +obj_crawl_symbol_chain (object_headers *headers) { symbolS **symbolPP; symbolS *symbolP; @@ -251,7 +216,7 @@ obj_crawl_symbol_chain (headers) if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA)) { S_SET_SEGMENT (symbolP, SEG_TEXT); - } /* if pushing data into text */ + } resolve_symbol_value (symbolP); @@ -287,7 +252,7 @@ obj_crawl_symbol_chain (headers) /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */ || !S_IS_DEFINED (symbolP) || S_IS_EXTERNAL (symbolP) -#endif /* TC_I960 */ +#endif || (S_GET_NAME (symbolP)[0] != '\001' && (flag_keep_locals || !S_LOCAL_NAME (symbolP))))) { @@ -308,15 +273,13 @@ obj_crawl_symbol_chain (headers) else { if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) - { - as_bad (_("Local symbol %s never defined"), - S_GET_NAME (symbolP)); - } /* Oops. */ + as_bad (_("Local symbol %s never defined"), + S_GET_NAME (symbolP)); /* Unhook it from the chain. */ *symbolPP = symbol_next (symbolP); - } /* if this symbol should be in the output */ - } /* for each symbol */ + } + } H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number); } @@ -324,8 +287,7 @@ obj_crawl_symbol_chain (headers) /* Find strings by crawling along symbol table chain. */ void -obj_emit_strings (where) - char **where; +obj_emit_strings (char **where) { symbolS *symbolP; @@ -333,9 +295,30 @@ obj_emit_strings (where) *where += 4; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - if (S_GET_NAME (symbolP)) - append (where, S_GET_NAME (symbolP), - (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); - } /* Walk symbol chain. */ + if (S_GET_NAME (symbolP)) + append (where, S_GET_NAME (symbolP), + (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); } + +const pseudo_typeS obj_pseudo_table[] = +{ + {"line", obj_bout_line, 0}, /* Source code line number. */ + + /* COFF debugging directives. Currently ignored silently. */ + {"def", s_ignore, 0}, + {"dim", s_ignore, 0}, + {"endef", s_ignore, 0}, + {"ln", s_ignore, 0}, + {"scl", s_ignore, 0}, + {"size", s_ignore, 0}, + {"tag", s_ignore, 0}, + {"type", s_ignore, 0}, + {"val", s_ignore, 0}, + + /* Other stuff we don't handle. */ + {"ABORT", s_ignore, 0}, + {"ident", s_ignore, 0}, + + {NULL, NULL, 0} +}; + diff --git a/gas/config/obj-bout.h b/gas/config/obj-bout.h index 278fcc4a70f..f51b8784c04 100644 --- a/gas/config/obj-bout.h +++ b/gas/config/obj-bout.h @@ -19,42 +19,40 @@ to the Free Software Foundation, 59 Temple Place - Suite 330, Cambridge, MA 02139, USA. */ -/* - * This file is a modified version of 'a.out.h'. It is to be used in all GNU - * tools modified to support the i80960 b.out format (or tools that operate on - * object files created by such tools). - * - * All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e., - * object code is generated on, and executed under the direction of a symbolic - * debugger running on, a host system. We do not want to be subject to the - * vagaries of which host it is or whether it supports COFF or a.out format, or - * anything else. We DO want to: - * - * o always generate the same format object files, regardless of host. - * - * o have an 'a.out' header that we can modify for our own purposes - * (the 80960 is typically an embedded processor and may require - * enhanced linker support that the normal a.out.h header can't - * accommodate). - * - * As for byte-ordering, the following rules apply: - * - * o Text and data that is actually downloaded to the target is always - * in i80960 (little-endian) order. - * - * o All other numbers (in the header, symbols, relocation directives) - * are in host byte-order: object files CANNOT be lifted from a - * little-end host and used on a big-endian (or vice versa) without - * modification. - * ==> THIS IS NO LONGER TRUE USING BFD. WE CAN GENERATE ANY BYTE ORDER - * FOR THE HEADER, AND READ ANY BYTE ORDER. PREFERENCE WOULD BE TO - * USE LITTLE-ENDIAN BYTE ORDER THROUGHOUT, REGARDLESS OF HOST. <== - * - * o The downloader ('comm960') takes care to generate a pseudo-header - * with correct (i80960) byte-ordering before shipping text and data - * off to the NINDY monitor in the target systems. Symbols and - * relocation info are never sent to the target. - */ +/* This file is a modified version of 'a.out.h'. It is to be used in all GNU + tools modified to support the i80960 b.out format (or tools that operate on + object files created by such tools). + + All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e., + object code is generated on, and executed under the direction of a symbolic + debugger running on, a host system. We do not want to be subject to the + vagaries of which host it is or whether it supports COFF or a.out format, or + anything else. We DO want to: + + o always generate the same format object files, regardless of host. + + o have an 'a.out' header that we can modify for our own purposes + (the 80960 is typically an embedded processor and may require + enhanced linker support that the normal a.out.h header can't + accommodate). + + As for byte-ordering, the following rules apply: + + o Text and data that is actually downloaded to the target is always + in i80960 (little-endian) order. + + o All other numbers (in the header, symbols, relocation directives) + are in host byte-order: object files CANNOT be lifted from a + little-end host and used on a big-endian (or vice versa) without + modification. + ==> This is no longer true using BFD. We can generate any byte order + for the header, and read any byte order. Preference would be to + use little-endian byte order throughout, regardless of host. <== + + o The downloader ('comm960') takes care to generate a pseudo-header + with correct (i80960) byte-ordering before shipping text and data + off to the NINDY monitor in the target systems. Symbols and + relocation info are never sent to the target. */ #define OBJ_BOUT 1 @@ -69,46 +67,44 @@ extern const segT N_TYPE_seg[]; #define BMAGIC 0415 /* We don't accept the following (see N_BADMAG macro). - * They're just here so GNU code will compile. - */ -#define OMAGIC 0407 /* old impure format */ -#define NMAGIC 0410 /* read-only text */ -#define ZMAGIC 0413 /* demand load format */ + They're just here so GNU code will compile. */ +#define OMAGIC 0407 /* Old impure format. */ +#define NMAGIC 0410 /* Read-only text. */ +#define ZMAGIC 0413 /* Demand load format. */ #ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE -#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (BMAGIC) -#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */ - -/* FILE HEADER - * All 'lengths' are given as a number of bytes. - * All 'alignments' are for relinkable files only; an alignment of - * 'n' indicates the corresponding segment must begin at an - * address that is a multiple of (2**n). - */ +#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE BMAGIC +#endif + +/* File header: + All 'lengths' are given as a number of bytes. + All 'alignments' are for relinkable files only; an alignment of + 'n' indicates the corresponding segment must begin at an + address that is a multiple of (2**n). */ struct exec - { - /* Standard stuff */ - unsigned long a_magic; /* Identifies this as a b.out file */ - unsigned long a_text; /* Length of text */ - unsigned long a_data; /* Length of data */ - unsigned long a_bss; /* Length of runtime uninitialized data area */ - unsigned long a_syms; /* Length of symbol table */ - unsigned long a_entry; /* Runtime start address */ - unsigned long a_trsize; /* Length of text relocation info */ - unsigned long a_drsize; /* Length of data relocation info */ - - /* Added for i960 */ - unsigned long a_tload; /* Text runtime load address */ - unsigned long a_dload; /* Data runtime load address */ - unsigned char a_talign; /* Alignment of text segment */ - unsigned char a_dalign; /* Alignment of data segment */ - unsigned char a_balign; /* Alignment of bss segment */ - unsigned char a_relaxable; /* Contains enough info to relax */ - }; +{ + /* Standard stuff. */ + unsigned long a_magic; /* Identifies this as a b.out file. */ + unsigned long a_text; /* Length of text. */ + unsigned long a_data; /* Length of data. */ + unsigned long a_bss; /* Length of runtime uninitialized data area. */ + unsigned long a_syms; /* Length of symbol table. */ + unsigned long a_entry; /* Runtime start address. */ + unsigned long a_trsize; /* Length of text relocation info. */ + unsigned long a_drsize; /* Length of data relocation info. */ + + /* Added for i960 */ + unsigned long a_tload; /* Text runtime load address. */ + unsigned long a_dload; /* Data runtime load address. */ + unsigned char a_talign; /* Alignment of text segment. */ + unsigned char a_dalign; /* Alignment of data segment. */ + unsigned char a_balign; /* Alignment of bss segment. */ + unsigned char a_relaxable; /* Contains enough info to relax. */ +}; #define EXEC_BYTES_SIZE (10 * 4 + 4 * 1) -#define N_BADMAG(x) (((x).a_magic)!=BMAGIC) +#define N_BADMAG(x) (((x).a_magic) != BMAGIC) #define N_TXTOFF(x) EXEC_BYTES_SIZE #define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) #define N_TROFF(x) ( N_DATOFF(x) + (x).a_data ) @@ -116,72 +112,66 @@ struct exec #define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize ) #define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) -/* A single entry in the symbol table - */ +/* A single entry in the symbol table. */ struct nlist { union { char *n_name; struct nlist *n_next; - long n_strx; /* Index into string table */ + long n_strx; /* Index into string table. */ } n_un; - unsigned char n_type; /* See below */ - char n_other; /* Used in i80960 support -- see below */ + unsigned char n_type; /* See below. */ + char n_other; /* Used in i80960 support -- see below. */ short n_desc; unsigned long n_value; }; typedef struct nlist obj_symbol_type; -/* Legal values of n_type - */ -#define N_UNDF 0 /* Undefined symbol */ -#define N_ABS 2 /* Absolute symbol */ -#define N_TEXT 4 /* Text symbol */ -#define N_DATA 6 /* Data symbol */ -#define N_BSS 8 /* BSS symbol */ -#define N_FN 31 /* Filename symbol */ +/* Legal values of n_type. */ +#define N_UNDF 0 /* Undefined symbol. */ +#define N_ABS 2 /* Absolute symbol. */ +#define N_TEXT 4 /* Text symbol. */ +#define N_DATA 6 /* Data symbol. */ +#define N_BSS 8 /* BSS symbol. */ +#define N_FN 31 /* Filename symbol. */ -#define N_EXT 1 /* External symbol (OR'd in with one of above) */ -#define N_TYPE 036 /* Mask for all the type bits */ -#define N_STAB 0340 /* Mask for all bits used for SDB entries */ +#define N_EXT 1 /* External symbol (OR'd in with one of above). */ +#define N_TYPE 036 /* Mask for all the type bits. */ +#define N_STAB 0340 /* Mask for all bits used for SDB entries. */ #ifndef CUSTOM_RELOC_FORMAT struct relocation_info { - int r_address; /* File address of item to be relocated */ + int r_address; /* File address of item to be relocated. */ unsigned - r_index:24, /* Index of symbol on which relocation is based*/ + r_index:24, /* Index of symbol on which relocation is based. */ r_pcrel:1, /* 1 => relocate PC-relative; else absolute - * On i960, pc-relative implies 24-bit - * address, absolute implies 32-bit. - */ + On i960, pc-relative implies 24-bit + address, absolute implies 32-bit. */ r_length:2, /* Number of bytes to relocate: - * 0 => 1 byte - * 1 => 2 bytes - * 2 => 4 bytes -- only value used for i960 - */ - r_extern:1, r_bsr:1, /* Something for the GNU NS32K assembler */ - r_disp:1, /* Something for the GNU NS32K assembler */ - r_callj:1, /* 1 if relocation target is an i960 'callj' */ - nuthin:1; /* Unused */ + 0 => 1 byte + 1 => 2 bytes + 2 => 4 bytes -- only value used for i960. */ + r_extern:1, r_bsr:1, /* Something for the GNU NS32K assembler. */ + r_disp:1, /* Something for the GNU NS32K assembler. */ + r_callj:1, /* 1 if relocation target is an i960 'callj'. */ + nuthin:1; /* Unused. */ }; #endif /* CUSTOM_RELOC_FORMAT */ -/* - * Macros to extract information from a symbol table entry. - * This syntactic indirection allows independence regarding a.out or coff. - * The argument (s) of all these macros is a pointer to a symbol table entry. - */ +/* Macros to extract information from a symbol table entry. + This syntactic indirection allows independence regarding a.out or coff. + The argument (s) of all these macros is a pointer to a symbol table entry. */ -/* Predicates */ -/* True if the symbol is external */ +/* Predicates. */ +/* True if the symbol is external. */ #define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT) -/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */ +/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT. */ #define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_DESC(s) != 0)) /* Return true for symbols that should not be reduced to section @@ -195,9 +185,9 @@ struct relocation_info #define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) -/* True if a debug special symbol entry */ +/* True if a debug special symbol entry. */ #define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB) -/* True if a symbol is local symbol name */ +/* True if a symbol is local symbol name. */ #define S_IS_LOCAL(s) \ ((S_GET_NAME (s) \ && !S_IS_DEBUG (s) \ @@ -207,52 +197,53 @@ struct relocation_info || (flag_strip_local_absolute \ && !S_IS_EXTERNAL(s) \ && S_GET_SEGMENT(s) == absolute_section)) -/* True if a symbol is not defined in this file */ +/* True if a symbol is not defined in this file. */ #define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT) -/* True if the symbol has been generated because of a .stabd directive */ +/* True if the symbol has been generated because of a .stabd directive. */ #define S_IS_STABD(s) (S_GET_NAME(s) == NULL) -/* Accessors */ -/* The name of the symbol */ +/* Accessors. */ +/* The name of the symbol. */ #define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) -/* The pointer to the string table */ +/* The pointer to the string table. */ #define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) -/* The type of the symbol */ +/* The type of the symbol. */ #define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) -/* The numeric value of the segment */ +/* The numeric value of the segment. */ #define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) -/* The n_other expression value */ +/* The n_other expression value. */ #define S_GET_OTHER(s) ((s)->sy_symbol.n_other) -/* The n_desc expression value */ +/* The n_desc expression value. */ #define S_GET_DESC(s) ((s)->sy_symbol.n_desc) -/* Modifiers */ -/* Assume that a symbol cannot be simultaneously in more than on segment */ -/* set segment */ -#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg)) -/* The symbol is external */ +/* Modifiers. */ +/* Assume that a symbol cannot be simultaneously in more than on segment. */ +/* Set segment. */ +#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE (seg)) +/* The symbol is external. */ #define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) -/* The symbol is not external */ +/* The symbol is not external. */ #define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) -/* Set the name of the symbol */ +/* Set the name of the symbol. */ #define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v)) -/* Set the offset in the string table */ +/* Set the offset in the string table. */ #define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) -/* Set the n_other expression value */ +/* Set the n_other expression value. */ #define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) -/* Set the n_desc expression value */ +/* Set the n_desc expression value. */ #define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v)) -/* Set the n_type value */ +/* Set the n_type value. */ #define S_SET_TYPE(s,v) ((s)->sy_symbol.n_type = (v)) -/* File header macro and type definition */ +/* File header macro and type definition. */ -#define H_GET_FILE_SIZE(h) (EXEC_BYTES_SIZE + \ - H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ - H_GET_SYMBOL_TABLE_SIZE(h) + \ - H_GET_TEXT_RELOCATION_SIZE(h) + \ - H_GET_DATA_RELOCATION_SIZE(h) + \ - (h)->string_table_size) +#define H_GET_FILE_SIZE(h) (EXEC_BYTES_SIZE \ + + H_GET_TEXT_SIZE (h) \ + + H_GET_DATA_SIZE(h) \ + + H_GET_SYMBOL_TABLE_SIZE (h) \ + + H_GET_TEXT_RELOCATION_SIZE (h) \ + + H_GET_DATA_RELOCATION_SIZE (h) \ + + (h)->string_table_size) #define H_GET_HEADER_SIZE(h) EXEC_BYTES_SIZE #define H_GET_TEXT_SIZE(h) ((h)->header.a_text) @@ -268,10 +259,10 @@ struct relocation_info #ifdef EXEC_MACHINE_TYPE #define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype) -#endif /* EXEC_MACHINE_TYPE */ +#endif /* EXEC_MACHINE_TYPE. */ #ifdef EXEC_VERSION #define H_GET_VERSION(h) ((h)->header.a_version) -#endif /* EXEC_VERSION */ +#endif /* EXEC_VERSION. */ #define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = (v)) #define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = (v)) @@ -290,20 +281,20 @@ struct relocation_info #define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) #ifdef EXEC_MACHINE_TYPE #define H_SET_MACHINE_TYPE(h,v) ((h)->header.a_machtype = (v)) -#endif /* EXEC_MACHINE_TYPE */ +#endif /* EXEC_MACHINE_TYPE. */ #ifdef EXEC_VERSION #define H_SET_VERSION(h,v) ((h)->header.a_version = (v)) -#endif /* EXEC_VERSION */ +#endif /* EXEC_VERSION. */ typedef struct { - struct exec header; /* a.out header */ - long string_table_size; /* names + '\0' + sizeof (int) */ + struct exec header; /* a.out header. */ + long string_table_size; /* names + '\0' + sizeof (int). */ } object_headers; -/* unused hooks. */ +/* Unused hooks. */ #define OBJ_EMIT_LINENO(a, b, c) {;} #define obj_pre_write_hook(a) {;} @@ -313,14 +304,9 @@ object_headers; #define host_number_to_chars number_to_chars_littleendian #endif -#if __STDC__ struct fix; -#endif -extern void tc_aout_fix_to_chars PARAMS ((char *where, - struct fix *fixP, - relax_addressT segment_address)); -extern void tc_bout_fix_to_chars PARAMS ((char *where, - struct fix *fixP, - relax_addressT segment_address)); + +extern void tc_aout_fix_to_chars (char *, struct fix *, relax_addressT); +extern void tc_bout_fix_to_chars (char *, struct fix *, relax_addressT); #define AOUT_STABS diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c index 69f8d9a89ab..71aade07083 100644 --- a/gas/config/obj-ecoff.c +++ b/gas/config/obj-ecoff.c @@ -1,6 +1,6 @@ /* ECOFF object file format. - Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, + 2005 Free Software Foundation, Inc. Contributed by Cygnus Support. This file was put together by Ian Lance Taylor . @@ -31,77 +31,10 @@ gas directory. This file mostly just arranges to call that one at the right times. */ -static int ecoff_sec_sym_ok_for_reloc PARAMS ((asection *)); -static void obj_ecoff_frob_symbol PARAMS ((symbolS *, int *)); -static void ecoff_pop_insert PARAMS ((void)); -static int ecoff_separate_stab_sections PARAMS ((void)); - -/* These are the pseudo-ops we support in this file. Only those - relating to debugging information are supported here. - - The following pseudo-ops from the Kane and Heinrich MIPS book - should be defined here, but are currently unsupported: .aent, - .bgnb, .endb, .verstamp, .vreg. - - The following pseudo-ops from the Kane and Heinrich MIPS book are - MIPS CPU specific, and should be defined by tc-mips.c: .alias, - .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option, - .rdata, .sdata, .set. - - The following pseudo-ops from the Kane and Heinrich MIPS book are - not MIPS CPU specific, but are also not ECOFF specific. I have - only listed the ones which are not already in read.c. It's not - completely clear where these should be defined, but tc-mips.c is - probably the most reasonable place: .asciiz, .asm0, .endr, .err, - .half, .lab, .repeat, .struct, .weakext. */ - -const pseudo_typeS obj_pseudo_table[] = -{ - /* COFF style debugging information. .ln is not used; .loc is used - instead. */ - { "def", ecoff_directive_def, 0 }, - { "dim", ecoff_directive_dim, 0 }, - { "endef", ecoff_directive_endef, 0 }, - { "file", ecoff_directive_file, 0 }, - { "scl", ecoff_directive_scl, 0 }, - { "size", ecoff_directive_size, 0 }, - { "esize", ecoff_directive_size, 0 }, - { "tag", ecoff_directive_tag, 0 }, - { "type", ecoff_directive_type, 0 }, - { "etype", ecoff_directive_type, 0 }, - { "val", ecoff_directive_val, 0 }, - - /* ECOFF specific debugging information. */ - { "begin", ecoff_directive_begin, 0 }, - { "bend", ecoff_directive_bend, 0 }, - { "end", ecoff_directive_end, 0 }, - { "ent", ecoff_directive_ent, 0 }, - { "fmask", ecoff_directive_fmask, 0 }, - { "frame", ecoff_directive_frame, 0 }, - { "loc", ecoff_directive_loc, 0 }, - { "mask", ecoff_directive_mask, 0 }, - - /* Other ECOFF directives. */ - { "extern", ecoff_directive_extern, 0 }, - -#ifndef TC_MIPS - /* For TC_MIPS, tc-mips.c adds this. */ - { "weakext", ecoff_directive_weakext, 0 }, -#endif - - /* These are used on Irix. I don't know how to implement them. */ - { "bgnb", s_ignore, 0 }, - { "endb", s_ignore, 0 }, - { "verstamp", s_ignore, 0 }, - - /* Sentinel. */ - { NULL, s_ignore, 0 } -}; - /* Set section VMAs and GP values before reloc processing. */ void -ecoff_frob_file_before_fix () +ecoff_frob_file_before_fix (void) { bfd_vma addr; asection **sec; @@ -128,7 +61,8 @@ ecoff_frob_file_before_fix () I don't know if section ordering on the MIPS is important. */ - static const char *const names[] = { + static const char *const names[] = + { /* text segment */ ".text", ".rdata", ".init", ".fini", /* data segment */ @@ -146,7 +80,7 @@ ecoff_frob_file_before_fix () for (i = 0; i < n_names; i++) secs[i] = 0; - for (sec = &stdoutput->sections; *sec != (asection *) NULL; ) + for (sec = &stdoutput->sections; *sec != NULL;) { for (i = 0; i < n_names; i++) if (!strcmp ((*sec)->name, names[i])) @@ -203,7 +137,7 @@ ecoff_frob_file_before_fix () /* Swap out the symbols and debugging information for BFD. */ void -ecoff_frob_file () +ecoff_frob_file (void) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (stdoutput)->debug_swap; @@ -221,7 +155,7 @@ ecoff_frob_file () set = buf; #define SET(ptr, count, type, size) \ if (hdr->count == 0) \ - ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \ + ecoff_data (stdoutput)->debug_info.ptr = NULL; \ else \ { \ ecoff_data (stdoutput)->debug_info.ptr = (type) set; \ @@ -229,16 +163,16 @@ ecoff_frob_file () } SET (line, cbLine, unsigned char *, sizeof (unsigned char)); - SET (external_dnr, idnMax, PTR, debug_swap->external_dnr_size); - SET (external_pdr, ipdMax, PTR, debug_swap->external_pdr_size); - SET (external_sym, isymMax, PTR, debug_swap->external_sym_size); - SET (external_opt, ioptMax, PTR, debug_swap->external_opt_size); + SET (external_dnr, idnMax, void *, debug_swap->external_dnr_size); + SET (external_pdr, ipdMax, void *, debug_swap->external_pdr_size); + SET (external_sym, isymMax, void *, debug_swap->external_sym_size); + SET (external_opt, ioptMax, void *, debug_swap->external_opt_size); SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext)); SET (ss, issMax, char *, sizeof (char)); SET (ssext, issExtMax, char *, sizeof (char)); - SET (external_rfd, crfd, PTR, debug_swap->external_rfd_size); - SET (external_fdr, ifdMax, PTR, debug_swap->external_fdr_size); - SET (external_ext, iextMax, PTR, debug_swap->external_ext_size); + SET (external_rfd, crfd, void *, debug_swap->external_rfd_size); + SET (external_fdr, ifdMax, void *, debug_swap->external_fdr_size); + SET (external_ext, iextMax, void *, debug_swap->external_ext_size); #undef SET } @@ -247,9 +181,7 @@ ecoff_frob_file () information to be stored in the native field of the symbol. */ void -obj_ecoff_set_ext (sym, ext) - symbolS *sym; - EXTR *ext; +obj_ecoff_set_ext (symbolS *sym, EXTR *ext) { const struct ecoff_debug_swap * const debug_swap = &ecoff_backend (stdoutput)->debug_swap; @@ -264,62 +196,121 @@ obj_ecoff_set_ext (sym, ext) } static int -ecoff_sec_sym_ok_for_reloc (sec) - asection *sec ATTRIBUTE_UNUSED; +ecoff_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED) { return 1; } static void -obj_ecoff_frob_symbol (sym, puntp) - symbolS *sym; - int *puntp ATTRIBUTE_UNUSED; +obj_ecoff_frob_symbol (symbolS *sym, int *puntp ATTRIBUTE_UNUSED) { ecoff_frob_symbol (sym); } static void -ecoff_pop_insert () +ecoff_pop_insert (void) { pop_insert (obj_pseudo_table); } static int -ecoff_separate_stab_sections () +ecoff_separate_stab_sections (void) { return 0; } +/* These are the pseudo-ops we support in this file. Only those + relating to debugging information are supported here. + + The following pseudo-ops from the Kane and Heinrich MIPS book + should be defined here, but are currently unsupported: .aent, + .bgnb, .endb, .verstamp, .vreg. + + The following pseudo-ops from the Kane and Heinrich MIPS book are + MIPS CPU specific, and should be defined by tc-mips.c: .alias, + .extern, .galive, .gjaldef, .gjrlive, .livereg, .noalias, .option, + .rdata, .sdata, .set. + + The following pseudo-ops from the Kane and Heinrich MIPS book are + not MIPS CPU specific, but are also not ECOFF specific. I have + only listed the ones which are not already in read.c. It's not + completely clear where these should be defined, but tc-mips.c is + probably the most reasonable place: .asciiz, .asm0, .endr, .err, + .half, .lab, .repeat, .struct, .weakext. */ + +const pseudo_typeS obj_pseudo_table[] = +{ + /* COFF style debugging information. .ln is not used; .loc is used + instead. */ + { "def", ecoff_directive_def, 0 }, + { "dim", ecoff_directive_dim, 0 }, + { "endef", ecoff_directive_endef, 0 }, + { "file", ecoff_directive_file, 0 }, + { "scl", ecoff_directive_scl, 0 }, + { "size", ecoff_directive_size, 0 }, + { "esize", ecoff_directive_size, 0 }, + { "tag", ecoff_directive_tag, 0 }, + { "type", ecoff_directive_type, 0 }, + { "etype", ecoff_directive_type, 0 }, + { "val", ecoff_directive_val, 0 }, + + /* ECOFF specific debugging information. */ + { "begin", ecoff_directive_begin, 0 }, + { "bend", ecoff_directive_bend, 0 }, + { "end", ecoff_directive_end, 0 }, + { "ent", ecoff_directive_ent, 0 }, + { "fmask", ecoff_directive_fmask, 0 }, + { "frame", ecoff_directive_frame, 0 }, + { "loc", ecoff_directive_loc, 0 }, + { "mask", ecoff_directive_mask, 0 }, + + /* Other ECOFF directives. */ + { "extern", ecoff_directive_extern, 0 }, + +#ifndef TC_MIPS + /* For TC_MIPS, tc-mips.c adds this. */ + { "weakext", ecoff_directive_weakext, 0 }, +#endif + + /* These are used on Irix. I don't know how to implement them. */ + { "bgnb", s_ignore, 0 }, + { "endb", s_ignore, 0 }, + { "verstamp", s_ignore, 0 }, + + /* Sentinel. */ + { NULL, s_ignore, 0 } +}; + const struct format_ops ecoff_format_ops = { bfd_target_ecoff_flavour, - 0, /* dfl_leading_underscore */ + 0, /* dfl_leading_underscore. */ /* FIXME: A comment why emit_section_symbols is different here (1) from the single-format definition (0) would be in order. */ - 1, /* emit_section_symbols */ - 0, /* begin */ + 1, /* emit_section_symbols. */ + 0, /* begin. */ ecoff_new_file, obj_ecoff_frob_symbol, ecoff_frob_file, - 0, /* frob_file_before_adjust */ + 0, /* frob_file_before_adjust. */ ecoff_frob_file_before_fix, - 0, /* frob_file_after_relocs */ - 0, /* s_get_size */ - 0, /* s_set_size */ - 0, /* s_get_align */ - 0, /* s_set_align */ - 0, /* s_get_other */ - 0, /* s_set_other */ - 0, /* s_get_desc */ - 0, /* s_set_desc */ - 0, /* s_get_type */ - 0, /* s_set_type */ - 0, /* copy_symbol_attributes */ + 0, /* frob_file_after_relocs. */ + 0, /* s_get_size. */ + 0, /* s_set_size. */ + 0, /* s_get_align. */ + 0, /* s_set_align. */ + 0, /* s_get_other. */ + 0, /* s_set_other. */ + 0, /* s_get_desc. */ + 0, /* s_set_desc. */ + 0, /* s_get_type. */ + 0, /* s_set_type. */ + 0, /* copy_symbol_attributes. */ ecoff_generate_asm_lineno, ecoff_stab, ecoff_separate_stab_sections, - 0, /* init_stab_section */ + 0, /* init_stab_section. */ ecoff_sec_sym_ok_for_reloc, ecoff_pop_insert, ecoff_set_ext, diff --git a/gas/config/obj-ecoff.h b/gas/config/obj-ecoff.h index 9f14d3b4ea6..b6e4a542143 100644 --- a/gas/config/obj-ecoff.h +++ b/gas/config/obj-ecoff.h @@ -50,12 +50,10 @@ struct ecoff_sy_obj #define obj_frob_symbol(symp, punt) ecoff_frob_symbol (symp) /* Set section VMAs and GP. */ -extern void ecoff_frob_file_before_fix PARAMS ((void)); #define obj_frob_file_before_fix() ecoff_frob_file_before_fix () /* This is used to write the symbolic data in the format that BFD expects it. */ -extern void ecoff_frob_file PARAMS ((void)); #define obj_frob_file() ecoff_frob_file () /* We use the ECOFF functions as our hooks. */ @@ -73,4 +71,7 @@ extern void ecoff_frob_file PARAMS ((void)); #define obj_sec_sym_ok_for_reloc(SEC) 1 #define obj_ecoff_set_ext ecoff_set_ext -extern void obj_ecoff_set_ext PARAMS ((symbolS *, EXTR *)); + +extern void ecoff_frob_file_before_fix (void); +extern void ecoff_frob_file (void); +extern void obj_ecoff_set_ext (symbolS *, EXTR *); diff --git a/gas/config/obj-som.c b/gas/config/obj-som.c index e9596cf51b6..2daa15389b4 100644 --- a/gas/config/obj-som.c +++ b/gas/config/obj-som.c @@ -27,15 +27,6 @@ #include "aout/stab_gnu.h" #include "obstack.h" -static void obj_som_weak PARAMS ((int)); -static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR)); - -const pseudo_typeS obj_pseudo_table[] = -{ - {"weak", obj_som_weak, 0}, - {NULL, NULL, 0} -}; - static int version_seen = 0; static int copyright_seen = 0; static int compiler_seen = 0; @@ -43,7 +34,7 @@ static int compiler_seen = 0; /* Unused by SOM. */ void -obj_read_begin_hook () +obj_read_begin_hook (void) { } @@ -53,8 +44,7 @@ obj_read_begin_hook () string is "sourcefile language version" and is delimited by blanks. */ void -obj_som_compiler (unused) - int unused ATTRIBUTE_UNUSED; +obj_som_compiler (int unused ATTRIBUTE_UNUSED) { char *buf; char c; @@ -130,8 +120,7 @@ obj_som_compiler (unused) /* Handle a .version directive. */ void -obj_som_version (unused) - int unused ATTRIBUTE_UNUSED; +obj_som_version (int unused ATTRIBUTE_UNUSED) { char *version, c; @@ -176,8 +165,7 @@ obj_som_version (unused) If you care about copyright strings that much, you fix it. */ void -obj_som_copyright (unused) - int unused ATTRIBUTE_UNUSED; +obj_som_copyright (int unused ATTRIBUTE_UNUSED) { char *copyright, c; @@ -225,8 +213,7 @@ obj_som_copyright (unused) which BFD does not understand. */ void -obj_som_init_stab_section (seg) - segT seg; +obj_som_init_stab_section (segT seg) { segT saved_seg = now_seg; segT space; @@ -282,10 +269,7 @@ obj_som_init_stab_section (seg) /* Fill in the counts in the first entry in a .stabs section. */ static void -adjust_stab_sections (abfd, sec, xxx) - bfd *abfd; - asection *sec; - PTR xxx ATTRIBUTE_UNUSED; +adjust_stab_sections (bfd *abfd, asection *sec, PTR xxx ATTRIBUTE_UNUSED) { asection *strsec; char *p; @@ -312,14 +296,13 @@ adjust_stab_sections (abfd, sec, xxx) stab entry and to set the starting address for each code subspace. */ void -som_frob_file () +som_frob_file (void) { bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0); } static void -obj_som_weak (ignore) - int ignore ATTRIBUTE_UNUSED; +obj_som_weak (int ignore ATTRIBUTE_UNUSED) { char *name; int c; @@ -344,3 +327,9 @@ obj_som_weak (ignore) while (c == ','); demand_empty_rest_of_line (); } + +const pseudo_typeS obj_pseudo_table[] = +{ + {"weak", obj_som_weak, 0}, + {NULL, NULL, 0} +}; diff --git a/gas/config/obj-som.h b/gas/config/obj-som.h index a3814927a4f..2b122da6370 100644 --- a/gas/config/obj-som.h +++ b/gas/config/obj-som.h @@ -1,5 +1,5 @@ /* SOM object file format. - Copyright 1993, 1994, 1995, 1998, 2000, 2004 + Copyright 1993, 1994, 1995, 1998, 2000, 2004, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -39,12 +39,12 @@ /* should be conditional on address size! */ #define som_symbol(asymbol) ((som_symbol_type *) (&(asymbol)->the_bfd)) -extern void som_file_symbol PARAMS ((char *)); -extern void som_frob_file PARAMS ((void)); -extern void obj_som_version PARAMS ((int)); -extern void obj_som_init_stab_section PARAMS ((segT)); -extern void obj_som_copyright PARAMS ((int)); -extern void obj_som_compiler PARAMS ((int)); +extern void som_file_symbol (char *); +extern void som_frob_file (void); +extern void obj_som_version (int); +extern void obj_som_init_stab_section (segT); +extern void obj_som_copyright (int); +extern void obj_som_compiler (int); #define obj_symbol_new_hook(s) {;} diff --git a/gas/config/tc-a29k.c b/gas/config/tc-a29k.c index 9e3fb44a0cb..900871c09cc 100644 --- a/gas/config/tc-a29k.c +++ b/gas/config/tc-a29k.c @@ -35,103 +35,72 @@ #define machine_ip a29k_ip #define machine_it a29k_it -#define IMMEDIATE_BIT 0x01000000 /* Turns RB into Immediate */ -#define ABSOLUTE_BIT 0x01000000 /* Turns PC-relative to Absolute */ -#define CE_BIT 0x00800000 /* Coprocessor enable in LOAD */ -#define UI_BIT 0x00000080 /* Unsigned integer in CONVERT */ +#define IMMEDIATE_BIT 0x01000000 /* Turns RB into Immediate. */ +#define ABSOLUTE_BIT 0x01000000 /* Turns PC-relative to Absolute. */ +#define CE_BIT 0x00800000 /* Coprocessor enable in LOAD. */ +#define UI_BIT 0x00000080 /* Unsigned integer in CONVERT. */ -/* handle of the OPCODE hash table */ +/* handle of the OPCODE hash table. */ static struct hash_control *op_hash = NULL; struct machine_it - { - char *error; - unsigned long opcode; - struct nlist *nlistp; - expressionS exp; - int pcrel; - int reloc_offset; /* Offset of reloc within insn */ - - int reloc; - } -the_insn; - -static void machine_ip PARAMS ((char *str)); -/* static void print_insn PARAMS ((struct machine_it *insn)); */ -#ifndef OBJ_COFF -static void s_data1 PARAMS ((void)); -static void s_use PARAMS ((int)); -#endif -static void insert_sreg PARAMS ((char *, int)); -static void define_some_regs PARAMS ((void)); -static char *parse_operand PARAMS ((char *, expressionS *, int)); - -const pseudo_typeS -md_pseudo_table[] = { - {"align", s_align_bytes, 4}, - {"block", s_space, 0}, - {"cputype", s_ignore, 0}, /* CPU as 29000 or 29050 */ - {"reg", s_lsym, 0}, /* Register equate, same as equ */ - {"space", s_ignore, 0}, /* Listing control */ - {"sect", s_ignore, 0}, /* Creation of coff sections */ -#ifndef OBJ_COFF - /* We can do this right with coff. */ - {"use", s_use, 0}, -#endif - {"word", cons, 4}, - {NULL, 0, 0}, -}; + char *error; + unsigned long opcode; + struct nlist *nlistp; + expressionS exp; + int pcrel; + int reloc_offset; /* Offset of reloc within insn. */ + int reloc; +} +the_insn; #if defined(BFD_HEADERS) #ifdef RELSZ -const int md_reloc_size = RELSZ; /* Coff headers */ +const int md_reloc_size = RELSZ; /* Coff headers. */ #else -const int md_reloc_size = 12; /* something else headers */ +const int md_reloc_size = 12; /* Something else headers. */ #endif #else -const int md_reloc_size = 12; /* Not bfdized*/ +const int md_reloc_size = 12; /* Not bfdized. */ #endif /* This array holds the chars that always start a comment. If the - pre-processor is disabled, these aren't very useful */ + pre-processor is disabled, these aren't very useful. */ const char comment_chars[] = ";"; /* This array holds the chars that only start a comment at the beginning of a line. If the line seems to have the form '# 123 filename' - .line and .file directives will appear in the pre-processed output */ + .line and .file directives will appear in the pre-processed output. */ /* Note that input_file.c hand checks for '#' at the beginning of the first line of the input file. This is because the compiler outputs #NO_APP at the beginning of its output. */ -/* Also note that comments like this one will always work */ +/* Also note that comments like this one will always work. */ const char line_comment_chars[] = "#"; /* We needed an unused char for line separation to work around the lack of macros, using sed and such. */ const char line_separator_chars[] = "@"; -/* Chars that can be used to separate mant from exp in floating point nums */ +/* Chars that can be used to separate mant from exp in floating point nums. */ const char EXP_CHARS[] = "eE"; -/* Chars that mean this number is a floating point constant */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ +/* Chars that mean this number is a floating point constant. + As in 0f12.456 + or 0d1.2345e12. */ const char FLT_CHARS[] = "rRsSfFdDxXpP"; /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be changed in read.c. Ideally it shouldn't have to know about it at all, but nothing is ideal around here. */ -/* - * anull bit - causes the branch delay slot instructions to not be executed - */ +/* anull bit - causes the branch delay slot instructions to not be executed. */ #define ANNUL (1 << 29) #ifndef OBJ_COFF static void -s_use (ignore) - int ignore; +s_use (int ignore) { if (strncmp (input_line_pointer, ".text", 5) == 0) { @@ -166,7 +135,7 @@ s_use (ignore) } static void -s_data1 () +s_data1 (void) { subseg_set (SEG_DATA, 1); demand_empty_rest_of_line (); @@ -178,9 +147,7 @@ s_data1 () FIXME-SOON: These are not recognized in mixed case. */ static void -insert_sreg (regname, regnum) - char *regname; - int regnum; +insert_sreg (char *regname, int regnum) { /* FIXME-SOON, put something in these syms so they won't be output to the symbol table of the resulting object file. */ @@ -203,11 +170,11 @@ insert_sreg (regname, regnum) See ASM29K Ref page 2-9. */ static void -define_some_regs () +define_some_regs (void) { #define SREG 256 - /* Protected special-purpose register names */ + /* Protected special-purpose register names. */ insert_sreg ("vab", SREG + 0); insert_sreg ("ops", SREG + 1); insert_sreg ("cps", SREG + 2); @@ -224,7 +191,7 @@ define_some_regs () insert_sreg ("mmu", SREG + 13); insert_sreg ("lru", SREG + 14); - /* Additional protected special-purpose registers for the 29050 */ + /* Additional protected special-purpose registers for the 29050. */ insert_sreg ("rsn", SREG + 15); insert_sreg ("rma0", SREG + 16); insert_sreg ("rmc0", SREG + 17); @@ -244,7 +211,7 @@ define_some_regs () insert_sreg ("cir", SREG + 29); insert_sreg ("cdr", SREG + 30); - /* Unprotected special-purpose register names */ + /* Unprotected special-purpose register names. */ insert_sreg ("ipc", SREG + 128); insert_sreg ("ipa", SREG + 129); insert_sreg ("ipb", SREG + 130); @@ -263,14 +230,15 @@ define_some_regs () /* This function is called once, at assembler startup time. It should set up all the tables, etc., that the MD part of the assembler will need. */ + void -md_begin () +md_begin (void) { - register const char *retval = NULL; + const char *retval = NULL; int lose = 0; - register int skipnext = 0; - register unsigned int i; - register char *strend, *strend2; + int skipnext = 0; + unsigned int i; + char *strend, *strend2; /* Hash up all the opcodes for fast use later. */ @@ -288,7 +256,6 @@ md_begin () /* Hack to avoid multiple opcode entries. We pre-locate all the variations (b/i field and P/A field) and handle them. */ - if (!strcmp (name, machine_opcodes[i + 1].name)) { if ((machine_opcodes[i].opcode & 0x01000000) != 0 @@ -296,18 +263,22 @@ md_begin () || ((machine_opcodes[i].opcode | 0x01000000) != machine_opcodes[i + 1].opcode)) goto bad_table; + strend = machine_opcodes[i].args + strlen (machine_opcodes[i].args) - 1; strend2 = machine_opcodes[i + 1].args + strlen (machine_opcodes[i + 1].args) - 1; + switch (*strend) { case 'b': if (*strend2 != 'i') goto bad_table; break; + case 'P': if (*strend2 != 'A') goto bad_table; break; + default: bad_table: fprintf (stderr, "internal error: can't handle opcode %s\n", @@ -321,7 +292,7 @@ md_begin () skipnext = 1; } - retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]); + retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]); if (retval != NULL) { fprintf (stderr, "internal error: can't hash `%s': %s\n", @@ -336,39 +307,8 @@ md_begin () define_some_regs (); } -/* Assemble a single instruction. Its label has already been handled - by the generic front end. We just parse opcode and operands, and - produce the bytes of data and relocation. */ - -void -md_assemble (str) - char *str; -{ - char *toP; - - know (str); - machine_ip (str); - toP = frag_more (4); - /* put out the opcode */ - md_number_to_chars (toP, the_insn.opcode, 4); - - /* put out the symbol-dependent stuff */ - if (the_insn.reloc != NO_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); - } -} - static char * -parse_operand (s, operandp, opt) - char *s; - expressionS *operandp; - int opt; +parse_operand (char *s, expressionS *operandp, int opt) { char *save = input_line_pointer; char *new; @@ -387,8 +327,7 @@ parse_operand (s, operandp, opt) Warnings or errors are generated. */ static void -machine_ip (str) - char *str; +machine_ip (char *str) { char *s; const char *args; @@ -410,7 +349,7 @@ machine_ip (str) case '\0': break; - case ' ': /* FIXME-SOMEDAY more whitespace */ + case ' ': /* FIXME-SOMEDAY more whitespace. */ *s++ = '\0'; break; @@ -433,19 +372,15 @@ machine_ip (str) If an operand matches, we modify the_insn or opcode appropriately, and do a "continue". If an operand fails to match, we "break". */ - if (insn->args[0] != '\0') - { - /* Prime the pump. */ - s = parse_operand (s, operand, insn->args[0] == 'I'); - } + /* Prime the pump. */ + s = parse_operand (s, operand, insn->args[0] == 'I'); for (args = insn->args;; ++args) { switch (*args) { - - case '\0': /* end of args */ + case '\0': if (*s == '\0') { /* We are truly done. */ @@ -455,7 +390,7 @@ machine_ip (str) as_bad (_("Too many operands: %s"), s); break; - case ',': /* Must match a comma */ + case ',': if (*s++ == ',') { /* Parse next operand. */ @@ -464,27 +399,24 @@ machine_ip (str) } break; - case 'v': /* Trap numbers (immediate field) */ + case 'v': + /* Trap numbers (immediate field). */ if (operand->X_op == O_constant) { if (operand->X_add_number < 256) - { - opcode |= (operand->X_add_number << 16); - continue; - } + opcode |= (operand->X_add_number << 16); else - { - as_bad (_("Immediate value of %ld is too large"), - (long) operand->X_add_number); - continue; - } + as_bad (_("Immediate value of %ld is too large"), + (long) operand->X_add_number); + continue; } the_insn.reloc = RELOC_8; - the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */ + /* BIG-ENDIAN Byte 1 of insn. */ + the_insn.reloc_offset = 1; the_insn.exp = *operand; continue; - case 'b': /* A general register or 8-bit immediate */ + case 'b': /* A general register or 8-bit immediate. */ case 'i': /* We treat the two cases identically since we mashed them together in the opcode table. */ @@ -499,33 +431,28 @@ machine_ip (str) if (operand->X_op == O_constant) { if (operand->X_add_number < 256) - { - opcode |= operand->X_add_number; - continue; - } + opcode |= operand->X_add_number; else - { - as_bad (_("Immediate value of %ld is too large"), - (long) operand->X_add_number); - continue; - } + as_bad (_("Immediate value of %ld is too large"), + (long) operand->X_add_number); + continue; } the_insn.reloc = RELOC_8; - the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */ + the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn. */ the_insn.exp = *operand; continue; - case 'a': /* next operand must be a register */ + case 'a': /* Next operand must be a register. */ case 'c': general_reg: - /* lrNNN or grNNN or %%expr or a user-def register name */ + /* lrNNN or grNNN or %%expr or a user-def register name. */ if (operand->X_op != O_register) - break; /* Only registers */ + break; know (operand->X_add_symbol == 0); know (operand->X_op_symbol == 0); reg = operand->X_add_number; if (reg >= SREG) - break; /* No special registers */ + break; /* Got the register, now figure out where it goes in the opcode. */ @@ -547,12 +474,12 @@ machine_ip (str) as_fatal (_("failed sanity check.")); break; - case 'x': /* 16 bit constant, zero-extended */ - case 'X': /* 16 bit constant, one-extended */ + case 'x': /* 16 bit constant, zero-extended. */ + case 'X': /* 16 bit constant, one-extended. */ if (operand->X_op == O_constant) { - opcode |= (operand->X_add_number & 0xFF) << 0 | - ((operand->X_add_number & 0xFF00) << 8); + opcode |= (operand->X_add_number & 0xFF) << 0 + | ((operand->X_add_number & 0xFF00) << 8); continue; } the_insn.reloc = RELOC_CONST; @@ -562,17 +489,17 @@ machine_ip (str) case 'h': if (operand->X_op == O_constant) { - opcode |= (operand->X_add_number & 0x00FF0000) >> 16 | - (((unsigned long) operand->X_add_number - /* avoid sign ext */ & 0xFF000000) >> 8); + opcode |= (operand->X_add_number & 0x00FF0000) >> 16 + | (((unsigned long) operand->X_add_number + /* Avoid sign ext. */ & 0xFF000000) >> 8); continue; } the_insn.reloc = RELOC_CONSTH; the_insn.exp = *operand; continue; - case 'P': /* PC-relative jump address */ - case 'A': /* Absolute jump address */ + 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_op == O_constant) @@ -580,26 +507,30 @@ machine_ip (str) /* Make sure the 'A' case really exists. */ if ((insn->opcode | ABSOLUTE_BIT) != (insn + 1)->opcode) break; + { bfd_vma v, mask; + mask = 0x1ffff; v = operand->X_add_number & ~ mask; if (v) as_bad ("call/jmp target out of range"); } - opcode |= ABSOLUTE_BIT | - (operand->X_add_number & 0x0003FC00) << 6 | - ((operand->X_add_number & 0x000003FC) >> 2); + + opcode |= ABSOLUTE_BIT + | (operand->X_add_number & 0x0003FC00) << 6 + | ((operand->X_add_number & 0x000003FC) >> 2); continue; } + the_insn.reloc = RELOC_JUMPTARG; the_insn.exp = *operand; - the_insn.pcrel = 1; /* Assume PC-relative jump */ + the_insn.pcrel = 1; /* Assume PC-relative jump. */ /* FIXME-SOON, Do we figure out whether abs later, after - know sym val? */ + know sym val? */ continue; - case 'e': /* Coprocessor enable bit for LOAD/STORE insn */ + case 'e': /* Coprocessor enable bit for LOAD/STORE insn. */ if (operand->X_op == O_constant) { if (operand->X_add_number == 0) @@ -612,24 +543,24 @@ machine_ip (str) } break; - case 'n': /* Control bits for LOAD/STORE instructions */ - if (operand->X_op == O_constant && - operand->X_add_number < 128) + case 'n': /* Control bits for LOAD/STORE instructions. */ + if (operand->X_op == O_constant + && operand->X_add_number < 128) { opcode |= (operand->X_add_number << 16); continue; } break; - case 's': /* Special register number */ + case 's': /* Special register number. */ if (operand->X_op != O_register) - break; /* Only registers */ + break; if (operand->X_add_number < SREG) - break; /* Not a special register */ + break; opcode |= (operand->X_add_number & 0xFF) << 8; continue; - case 'u': /* UI bit of CONVERT */ + case 'u': /* UI bit of CONVERT. */ if (operand->X_op == O_constant) { if (operand->X_add_number == 0) @@ -642,16 +573,16 @@ machine_ip (str) } break; - case 'r': /* RND bits of CONVERT */ - if (operand->X_op == O_constant && - operand->X_add_number < 8) + case 'r': /* RND bits of CONVERT. */ + if (operand->X_op == O_constant + && operand->X_add_number < 8) { opcode |= operand->X_add_number << 4; continue; } break; - case 'I': /* ID bits of INV and IRETINV. */ + case 'I': /* ID bits of INV and IRETINV. */ /* This operand is optional. */ if (operand->X_op == O_absent) continue; @@ -663,18 +594,18 @@ machine_ip (str) } break; - case 'd': /* FD bits of CONVERT */ - if (operand->X_op == O_constant && - operand->X_add_number < 4) + case 'd': /* FD bits of CONVERT. */ + if (operand->X_op == O_constant + && operand->X_add_number < 4) { opcode |= operand->X_add_number << 2; continue; } break; - case 'f': /* FS bits of CONVERT */ - if (operand->X_op == O_constant && - operand->X_add_number < 4) + case 'f': /* FS bits of CONVERT. */ + if (operand->X_op == O_constant + && operand->X_add_number < 4) { opcode |= operand->X_add_number << 0; continue; @@ -682,8 +613,8 @@ machine_ip (str) break; case 'C': - if (operand->X_op == O_constant && - operand->X_add_number < 4) + if (operand->X_op == O_constant + && operand->X_add_number < 4) { opcode |= operand->X_add_number << 16; continue; @@ -691,8 +622,8 @@ machine_ip (str) break; case 'F': - if (operand->X_op == O_constant && - operand->X_add_number < 16) + if (operand->X_op == O_constant + && operand->X_add_number < 16) { opcode |= operand->X_add_number << 18; continue; @@ -708,6 +639,28 @@ machine_ip (str) } } +/* Assemble a single instruction. Its label has already been handled + by the generic front end. We just parse opcode and operands, and + produce the bytes of data and relocation. */ + +void +md_assemble (char *str) +{ + char *toP; + + know (str); + machine_ip (str); + toP = frag_more (4); + /* Put out the opcode. */ + md_number_to_chars (toP, the_insn.opcode, 4); + + /* Put out the symbol-dependent stuff. */ + if (the_insn.reloc != NO_RELOC) + fix_new_exp (frag_now, + (toP - frag_now->fr_literal + the_insn.reloc_offset), + 4, & the_insn.exp, the_insn.pcrel, the_insn.reloc); +} + /* This is identical to the md_atof in m68k.c. I think this is right, but I'm not sure. @@ -720,10 +673,7 @@ machine_ip (str) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -773,23 +723,16 @@ md_atof (type, litP, sizeP) return 0; } -/* - * Write out big-endian. - */ +/* Write out big-endian. */ + void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { number_to_chars_bigendian (buf, val, n); } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { valueT val = *valP; char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; @@ -849,7 +792,7 @@ md_apply_fix3 (fixP, valP, seg) buf[3] = val; break; - case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */ + case RELOC_JUMPTARG: /* 00XX00XX pattern in a word. */ if (!fixP->fx_done) { /* The linker tries to support both AMD and old GNU style @@ -872,17 +815,18 @@ md_apply_fix3 (fixP, valP, seg) else /* This case was supposed to be handled in machine_ip. */ abort (); - buf[1] = val >> 10; /* Holds bits 0003FFFC of address */ + + buf[1] = val >> 10; /* Holds bits 0003FFFC of address. */ buf[3] = val >> 2; break; - case RELOC_CONST: /* 00XX00XX pattern in a word */ - buf[1] = val >> 8; /* Holds bits 0000XXXX */ + case RELOC_CONST: /* 00XX00XX pattern in a word. */ + buf[1] = val >> 8; /* Holds bits 0000XXXX. */ buf[3] = val; break; - case RELOC_CONSTH: /* 00XX00XX pattern in a word */ - buf[1] = val >> 24; /* Holds bits XXXX0000 */ + case RELOC_CONSTH: /* 00XX00XX pattern in a word. */ + buf[1] = val >> 24; /* Holds bits XXXX0000. */ buf[3] = val >> 16; break; @@ -898,47 +842,40 @@ md_apply_fix3 (fixP, valP, seg) #ifdef OBJ_COFF short -tc_coff_fix2rtype (fixP) - fixS *fixP; +tc_coff_fix2rtype (fixS *fixP) { - switch (fixP->fx_r_type) { - case RELOC_32: - return (R_WORD); - case RELOC_8: - return (R_BYTE); - case RELOC_CONST: - return (R_ILOHALF); - case RELOC_CONSTH: - return (R_IHIHALF); - case RELOC_JUMPTARG: - return (R_IREL); + case RELOC_32: return R_WORD; + case RELOC_8: return R_BYTE; + case RELOC_CONST: return R_ILOHALF; + case RELOC_CONSTH: return R_IHIHALF; + case RELOC_JUMPTARG: return R_IREL; default: printf (_("need %o3\n"), fixP->fx_r_type); abort (); - } /* switch on type */ + } - return (0); + return 0; } #endif /* OBJ_COFF */ -/* should never be called for 29k */ +/* Should never be called for 29k. */ + void -md_convert_frag (headers, seg, fragP) - object_headers *headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - register fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (object_headers *headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) { as_fatal (_("a29k_convert_frag\n")); } -/* should never be called for a29k */ +/* Should never be called for a29k. */ + int -md_estimate_size_before_relax (fragP, segtype) - register fragS *fragP ATTRIBUTE_UNUSED; - segT segtype ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, + segT segtype ATTRIBUTE_UNUSED) { as_fatal (_("a29k_estimate_size_before_relax\n")); return 0; @@ -950,15 +887,15 @@ md_estimate_size_before_relax (fragP, segtype) bytes are index, most sig. byte first. Byte 7 is broken up with bit 7 as external, bits 6 & 5 unused, and the lower five bits as relocation type. Next 4 bytes are long addend. */ -/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ + +/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com. */ #ifdef OBJ_AOUT void -tc_aout_fix_to_chars (where, fixP, segment_address_in_file) - char *where; - fixS *fixP; - relax_addressT segment_address_in_file; +tc_aout_fix_to_chars (char *where, + fixS *fixP, + relax_addressT segment_address_in_file) { long r_symbolnum; @@ -977,29 +914,30 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) where[5] = (r_symbolnum >> 8) & 0x0ff; where[6] = r_symbolnum & 0x0ff; where[7] = (((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F); - /* Also easy */ + + /* Also easy. */ md_number_to_chars (&where[8], fixP->fx_addnumber, 4); } #endif /* OBJ_AOUT */ const char *md_shortopts = ""; -struct option md_longopts[] = { + +struct option md_longopts[] = +{ {NULL, no_argument, NULL, 0} }; + size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED) { return 0; } void -md_show_usage (stream) - FILE *stream ATTRIBUTE_UNUSED; +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) { } @@ -1007,8 +945,7 @@ md_show_usage (stream) definitions of a29k style local labels. */ int -a29k_unrecognized_line (c) - int c; +a29k_unrecognized_line (int c) { int lab; char *s; @@ -1050,8 +987,7 @@ a29k_unrecognized_line (c) are a lot of them. */ symbolS * -md_undefined_symbol (name) - char *name; +md_undefined_symbol (char *name) { long regnum; char testbuf[5 + /*SLOP*/ 5]; @@ -1060,7 +996,7 @@ md_undefined_symbol (name) || name[0] == 'l' || name[0] == 'L' || name[0] == 's' || name[0] == 'S') { - /* Perhaps a global or local register name */ + /* Perhaps a global or local register name. */ if (name[1] == 'r' || name[1] == 'R') { long maxreg; @@ -1078,7 +1014,7 @@ md_undefined_symbol (name) sprintf (testbuf, "%ld", regnum); if (strcmp (testbuf, &name[2]) != 0) - return NULL; /* gr007 or lr7foo or whatever */ + return NULL; /* gr007 or lr7foo or whatever. */ /* We have a wiener! Define and return a new symbol for it. */ if (name[0] == 'l' || name[0] == 'L') @@ -1096,10 +1032,8 @@ md_undefined_symbol (name) /* Parse an operand that is machine-specific. */ void -md_operand (expressionP) - expressionS *expressionP; +md_operand (expressionS *expressionP) { - if (input_line_pointer[0] == '%' && input_line_pointer[1] == '%') { /* We have a numeric register expression. No biggy. */ @@ -1181,15 +1115,14 @@ md_operand (expressionP) fieldlimit = 4; } else - { - return; - } + return; if (ISDIGIT (*s)) { fieldnum = *s - '0'; ++s; } + if (fieldnum >= fieldlimit) return; @@ -1220,20 +1153,35 @@ md_operand (expressionP) } /* Round up a section size to the appropriate boundary. */ + valueT -md_section_align (segment, size) - segT segment ATTRIBUTE_UNUSED; - valueT size; +md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) { - return size; /* Byte alignment is fine */ + return size; /* Byte alignment is fine. */ } /* Exactly what point is a PC-relative offset relative TO? On the 29000, they're relative to the address of the instruction, which we have set up as the address of the fixup too. */ + long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { return fixP->fx_where + fixP->fx_frag->fr_address; } + +const pseudo_typeS +md_pseudo_table[] = +{ + {"align", s_align_bytes, 4}, + {"block", s_space, 0}, + {"cputype", s_ignore, 0}, /* CPU as 29000 or 29050. */ + {"reg", s_lsym, 0}, /* Register equate, same as equ. */ + {"space", s_ignore, 0}, /* Listing control. */ + {"sect", s_ignore, 0}, /* Creation of coff sections. */ +#ifndef OBJ_COFF + {"use", s_use, 0}, /* We can do this right with coff. */ +#endif + {"word", cons, 4}, + {NULL, 0, 0}, +}; diff --git a/gas/config/tc-a29k.h b/gas/config/tc-a29k.h index 05924253883..9a09ab9bbbc 100644 --- a/gas/config/tc-a29k.h +++ b/gas/config/tc-a29k.h @@ -1,23 +1,23 @@ /* tc-a29k.h -- Assemble for the AMD 29000. - Copyright 1989, 1990, 1991, 1992, 1993, 1995, 1998, 2003 + Copyright 1989, 1990, 1991, 1992, 1993, 1995, 1998, 2003, 2005 Free Software Foundation, Inc. -This file is part of GAS, the GNU Assembler. + This file is part of GAS, the GNU Assembler. -GAS is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. -GAS is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GAS; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ #define TC_A29K @@ -28,21 +28,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #define LEX_DOLLAR 1 #define tc_unrecognized_line(c) a29k_unrecognized_line (c) -extern int a29k_unrecognized_line PARAMS ((int)); +extern int a29k_unrecognized_line (int); -#define tc_headers_hook(a) ; /* not used */ -#define tc_headers_hook(a) ; /* not used */ -#define tc_crawl_symbol_chain(a) ; /* not used */ -#define tc_coff_symbol_emit_hook(a) ; /* not used */ +#define tc_headers_hook(a) ; /* Not used. */ +#define tc_headers_hook(a) ; /* Not used. */ +#define tc_crawl_symbol_chain(a) ; /* Not used. */ +#define tc_coff_symbol_emit_hook(a) ; /* Not used. */ #define AOUT_MACHTYPE 101 -#define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype(fix_ptr) +#define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype (fix_ptr) #define BFD_ARCH bfd_arch_a29k #define COFF_MAGIC SIPFBOMAGIC /* Should the reloc be output ? on the 29k, this is true only if there is a symbol attached. - on the h8, this is always true, since no fixup is done -*/ + on the h8, this is always true, since no fixup is done. */ #define TC_COUNT_RELOC(x) (x->fx_addsy) #define TC_CONS_RELOC RELOC_32 @@ -52,4 +51,3 @@ extern int a29k_unrecognized_line PARAMS ((int)); #define ZERO_BASED_SEGMENTS -/* end of tc-a29k.h */ diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index dff7bac6e1e..08826ecd1df 100644 --- a/gas/config/tc-alpha.c +++ b/gas/config/tc-alpha.c @@ -24,31 +24,29 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* - * Mach Operating System - * Copyright (c) 1993 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ +/* Mach Operating System + Copyright (c) 1993 Carnegie Mellon University + All Rights Reserved. + + Permission to use, copy, modify and distribute this software and its + documentation is hereby granted, provided that both the copyright + notice and this permission notice appear in all copies of the + software, derivative works or modified versions, and any portions + thereof, and that both notices appear in supporting documentation. + + CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + + Carnegie Mellon requests users of this software to return to + + Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + School of Computer Science + Carnegie Mellon University + Pittsburgh PA 15213-3890 + + any improvements or extensions that they make and grant Carnegie the + rights to redistribute these changes. */ #include "as.h" #include "subsegs.h" @@ -60,18 +58,17 @@ #ifdef OBJ_ELF #include "elf/alpha.h" #include "dwarf2dbg.h" -#include "dw2gencfi.h" #endif +#include "dw2gencfi.h" #include "safe-ctype.h" /* Local types. */ -#define TOKENIZE_ERROR -1 -#define TOKENIZE_ERROR_REPORT -2 - -#define MAX_INSN_FIXUPS 2 -#define MAX_INSN_ARGS 5 +#define TOKENIZE_ERROR -1 +#define TOKENIZE_ERROR_REPORT -2 +#define MAX_INSN_FIXUPS 2 +#define MAX_INSN_ARGS 5 struct alpha_fixup { @@ -101,39 +98,39 @@ enum alpha_macro_arg struct alpha_macro { const char *name; - void (*emit) PARAMS ((const expressionS *, int, const PTR)); - const PTR arg; + void (*emit) (const expressionS *, int, const void *); + const void * arg; enum alpha_macro_arg argsets[16]; }; /* Extra expression types. */ -#define O_pregister O_md1 /* O_register, in parentheses */ -#define O_cpregister O_md2 /* + a leading comma */ +#define O_pregister O_md1 /* O_register, in parentheses. */ +#define O_cpregister O_md2 /* + a leading comma. */ /* The alpha_reloc_op table below depends on the ordering of these. */ -#define O_literal O_md3 /* !literal relocation */ -#define O_lituse_addr O_md4 /* !lituse_addr relocation */ -#define O_lituse_base O_md5 /* !lituse_base relocation */ -#define O_lituse_bytoff O_md6 /* !lituse_bytoff relocation */ -#define O_lituse_jsr O_md7 /* !lituse_jsr relocation */ -#define O_lituse_tlsgd O_md8 /* !lituse_tlsgd relocation */ -#define O_lituse_tlsldm O_md9 /* !lituse_tlsldm relocation */ -#define O_gpdisp O_md10 /* !gpdisp relocation */ -#define O_gprelhigh O_md11 /* !gprelhigh relocation */ -#define O_gprellow O_md12 /* !gprellow relocation */ -#define O_gprel O_md13 /* !gprel relocation */ -#define O_samegp O_md14 /* !samegp relocation */ -#define O_tlsgd O_md15 /* !tlsgd relocation */ -#define O_tlsldm O_md16 /* !tlsldm relocation */ -#define O_gotdtprel O_md17 /* !gotdtprel relocation */ -#define O_dtprelhi O_md18 /* !dtprelhi relocation */ -#define O_dtprello O_md19 /* !dtprello relocation */ -#define O_dtprel O_md20 /* !dtprel relocation */ -#define O_gottprel O_md21 /* !gottprel relocation */ -#define O_tprelhi O_md22 /* !tprelhi relocation */ -#define O_tprello O_md23 /* !tprello relocation */ -#define O_tprel O_md24 /* !tprel relocation */ +#define O_literal O_md3 /* !literal relocation. */ +#define O_lituse_addr O_md4 /* !lituse_addr relocation. */ +#define O_lituse_base O_md5 /* !lituse_base relocation. */ +#define O_lituse_bytoff O_md6 /* !lituse_bytoff relocation. */ +#define O_lituse_jsr O_md7 /* !lituse_jsr relocation. */ +#define O_lituse_tlsgd O_md8 /* !lituse_tlsgd relocation. */ +#define O_lituse_tlsldm O_md9 /* !lituse_tlsldm relocation. */ +#define O_gpdisp O_md10 /* !gpdisp relocation. */ +#define O_gprelhigh O_md11 /* !gprelhigh relocation. */ +#define O_gprellow O_md12 /* !gprellow relocation. */ +#define O_gprel O_md13 /* !gprel relocation. */ +#define O_samegp O_md14 /* !samegp relocation. */ +#define O_tlsgd O_md15 /* !tlsgd relocation. */ +#define O_tlsldm O_md16 /* !tlsldm relocation. */ +#define O_gotdtprel O_md17 /* !gotdtprel relocation. */ +#define O_dtprelhi O_md18 /* !dtprelhi relocation. */ +#define O_dtprello O_md19 /* !dtprello relocation. */ +#define O_dtprel O_md20 /* !dtprel relocation. */ +#define O_gottprel O_md21 /* !gottprel relocation. */ +#define O_tprelhi O_md22 /* !tprelhi relocation. */ +#define O_tprello O_md23 /* !tprello relocation. */ +#define O_tprel O_md24 /* !tprel relocation. */ #define DUMMY_RELOC_LITUSE_ADDR (BFD_RELOC_UNUSED + 1) #define DUMMY_RELOC_LITUSE_BASE (BFD_RELOC_UNUSED + 2) @@ -206,89 +203,6 @@ struct alpha_macro (t).X_op = O_constant, \ (t).X_add_number = (n)) -/* Prototypes for all local functions. */ - -static struct alpha_reloc_tag *get_alpha_reloc_tag PARAMS ((long)); -static void alpha_adjust_relocs PARAMS ((bfd *, asection *, PTR)); - -static int tokenize_arguments PARAMS ((char *, expressionS *, int)); -static const struct alpha_opcode *find_opcode_match - PARAMS ((const struct alpha_opcode *, const expressionS *, int *, int *)); -static const struct alpha_macro *find_macro_match - PARAMS ((const struct alpha_macro *, const expressionS *, int *)); -static unsigned insert_operand - PARAMS ((unsigned, const struct alpha_operand *, offsetT, char *, unsigned)); -static void assemble_insn - PARAMS ((const struct alpha_opcode *, const expressionS *, int, - struct alpha_insn *, bfd_reloc_code_real_type)); -static void emit_insn PARAMS ((struct alpha_insn *)); -static void assemble_tokens_to_insn - PARAMS ((const char *, const expressionS *, int, struct alpha_insn *)); -static void assemble_tokens - PARAMS ((const char *, const expressionS *, int, int)); - -static long load_expression - PARAMS ((int, const expressionS *, int *, expressionS *)); - -static void emit_ldgp PARAMS ((const expressionS *, int, const PTR)); -static void emit_division PARAMS ((const expressionS *, int, const PTR)); -static void emit_lda PARAMS ((const expressionS *, int, const PTR)); -static void emit_ldah PARAMS ((const expressionS *, int, const PTR)); -static void emit_ir_load PARAMS ((const expressionS *, int, const PTR)); -static void emit_loadstore PARAMS ((const expressionS *, int, const PTR)); -static void emit_jsrjmp PARAMS ((const expressionS *, int, const PTR)); -static void emit_ldX PARAMS ((const expressionS *, int, const PTR)); -static void emit_ldXu PARAMS ((const expressionS *, int, const PTR)); -static void emit_uldX PARAMS ((const expressionS *, int, const PTR)); -static void emit_uldXu PARAMS ((const expressionS *, int, const PTR)); -static void emit_ldil PARAMS ((const expressionS *, int, const PTR)); -static void emit_stX PARAMS ((const expressionS *, int, const PTR)); -static void emit_ustX PARAMS ((const expressionS *, int, const PTR)); -static void emit_sextX PARAMS ((const expressionS *, int, const PTR)); -static void emit_retjcr PARAMS ((const expressionS *, int, const PTR)); - -static void s_alpha_text PARAMS ((int)); -static void s_alpha_data PARAMS ((int)); -#ifndef OBJ_ELF -static void s_alpha_comm PARAMS ((int)); -static void s_alpha_rdata PARAMS ((int)); -#endif -#ifdef OBJ_ECOFF -static void s_alpha_sdata PARAMS ((int)); -#endif -#ifdef OBJ_ELF -static void s_alpha_section PARAMS ((int)); -static void s_alpha_ent PARAMS ((int)); -static void s_alpha_end PARAMS ((int)); -static void s_alpha_mask PARAMS ((int)); -static void s_alpha_frame PARAMS ((int)); -static void s_alpha_prologue PARAMS ((int)); -static void s_alpha_file PARAMS ((int)); -static void s_alpha_loc PARAMS ((int)); -static void s_alpha_stab PARAMS ((int)); -static void s_alpha_coff_wrapper PARAMS ((int)); -static void s_alpha_usepv PARAMS ((int)); -#endif -#ifdef OBJ_EVAX -static void s_alpha_section PARAMS ((int)); -#endif -static void s_alpha_gprel32 PARAMS ((int)); -static void s_alpha_float_cons PARAMS ((int)); -static void s_alpha_proc PARAMS ((int)); -static void s_alpha_set PARAMS ((int)); -static void s_alpha_base PARAMS ((int)); -static void s_alpha_align PARAMS ((int)); -static void s_alpha_stringer PARAMS ((int)); -static void s_alpha_space PARAMS ((int)); -static void s_alpha_ucons PARAMS ((int)); -static void s_alpha_arch PARAMS ((int)); - -static void create_literal_section PARAMS ((const char *, segT *, symbolS **)); -#ifndef OBJ_ELF -static void select_gp_value PARAMS ((void)); -#endif -static void alpha_align PARAMS ((int, char *, symbolS *, int)); - /* Generic assembler global variables which must be defined by all targets. */ @@ -450,11 +364,12 @@ static int g_switch_value = 8; #ifdef OBJ_EVAX /* Collect information about current procedure here. */ -static struct { - symbolS *symbol; /* proc pdesc symbol */ +static struct +{ + symbolS *symbol; /* Proc pdesc symbol. */ int pdsckind; - int framereg; /* register for frame pointer */ - int framesize; /* size of frame */ + int framereg; /* Register for frame pointer. */ + int framesize; /* Size of frame. */ int rsa_offset; int ra_save; int fp_save; @@ -487,37 +402,37 @@ static int alpha_flag_show_after_trunc = 0; /* -H */ static const struct alpha_reloc_op_tag { - const char *name; /* string to lookup */ - size_t length; /* size of the string */ - operatorT op; /* which operator to use */ - bfd_reloc_code_real_type reloc; /* relocation before frob */ - unsigned int require_seq : 1; /* require a sequence number */ - unsigned int allow_seq : 1; /* allow a sequence number */ + const char *name; /* String to lookup. */ + size_t length; /* Size of the string. */ + operatorT op; /* Which operator to use. */ + bfd_reloc_code_real_type reloc; /* Relocation before frob. */ + unsigned int require_seq : 1; /* Require a sequence number. */ + unsigned int allow_seq : 1; /* Allow a sequence number. */ } alpha_reloc_op[] = { - DEF(literal, BFD_RELOC_ALPHA_ELF_LITERAL, 0, 1), - DEF(lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1, 1), - DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1), - DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1), - DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1), - DEF(lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1), - DEF(lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1), - DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1), - DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0), - DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0), - DEF(gprel, BFD_RELOC_GPREL16, 0, 0), - DEF(samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0), - DEF(tlsgd, BFD_RELOC_ALPHA_TLSGD, 0, 1), - DEF(tlsldm, BFD_RELOC_ALPHA_TLSLDM, 0, 1), - DEF(gotdtprel, BFD_RELOC_ALPHA_GOTDTPREL16, 0, 0), - DEF(dtprelhi, BFD_RELOC_ALPHA_DTPREL_HI16, 0, 0), - DEF(dtprello, BFD_RELOC_ALPHA_DTPREL_LO16, 0, 0), - DEF(dtprel, BFD_RELOC_ALPHA_DTPREL16, 0, 0), - DEF(gottprel, BFD_RELOC_ALPHA_GOTTPREL16, 0, 0), - DEF(tprelhi, BFD_RELOC_ALPHA_TPREL_HI16, 0, 0), - DEF(tprello, BFD_RELOC_ALPHA_TPREL_LO16, 0, 0), - DEF(tprel, BFD_RELOC_ALPHA_TPREL16, 0, 0), + DEF (literal, BFD_RELOC_ALPHA_ELF_LITERAL, 0, 1), + DEF (lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1, 1), + DEF (lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1), + DEF (lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1), + DEF (lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1), + DEF (lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1), + DEF (lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1), + DEF (gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1), + DEF (gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0), + DEF (gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0), + DEF (gprel, BFD_RELOC_GPREL16, 0, 0), + DEF (samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0), + DEF (tlsgd, BFD_RELOC_ALPHA_TLSGD, 0, 1), + DEF (tlsldm, BFD_RELOC_ALPHA_TLSLDM, 0, 1), + DEF (gotdtprel, BFD_RELOC_ALPHA_GOTDTPREL16, 0, 0), + DEF (dtprelhi, BFD_RELOC_ALPHA_DTPREL_HI16, 0, 0), + DEF (dtprello, BFD_RELOC_ALPHA_DTPREL_LO16, 0, 0), + DEF (dtprel, BFD_RELOC_ALPHA_DTPREL16, 0, 0), + DEF (gottprel, BFD_RELOC_ALPHA_GOTTPREL16, 0, 0), + DEF (tprelhi, BFD_RELOC_ALPHA_TPREL_HI16, 0, 0), + DEF (tprello, BFD_RELOC_ALPHA_TPREL_LO16, 0, 0), + DEF (tprel, BFD_RELOC_ALPHA_TPREL16, 0, 0), }; #undef DEF @@ -526,27 +441,27 @@ static const int alpha_num_reloc_op = sizeof (alpha_reloc_op) / sizeof (*alpha_reloc_op); #endif /* RELOC_OP_P */ -/* Maximum # digits needed to hold the largest sequence # */ +/* Maximum # digits needed to hold the largest sequence #. */ #define ALPHA_RELOC_DIGITS 25 /* Structure to hold explicit sequence information. */ struct alpha_reloc_tag { - fixS *master; /* the literal reloc */ - fixS *slaves; /* head of linked list of lituses */ - segT segment; /* segment relocs are in or undefined_section*/ - long sequence; /* sequence # */ - unsigned n_master; /* # of literals */ - unsigned n_slaves; /* # of lituses */ - unsigned saw_tlsgd : 1; /* true if ... */ + fixS *master; /* The literal reloc. */ + fixS *slaves; /* Head of linked list of lituses. */ + segT segment; /* Segment relocs are in or undefined_section. */ + long sequence; /* Sequence #. */ + unsigned n_master; /* # of literals. */ + unsigned n_slaves; /* # of lituses. */ + unsigned saw_tlsgd : 1; /* True if ... */ unsigned saw_tlsldm : 1; unsigned saw_lu_tlsgd : 1; unsigned saw_lu_tlsldm : 1; - unsigned multi_section_p : 1; /* true if more than one section was used */ - char string[1]; /* printable form of sequence to hash with */ + unsigned multi_section_p : 1; /* True if more than one section was used. */ + char string[1]; /* Printable form of sequence to hash with. */ }; -/* Hash table to link up literals with the appropriate lituse */ +/* Hash table to link up literals with the appropriate lituse. */ static struct hash_control *alpha_literal_hash; /* Sequence numbers for internal use by macros. */ @@ -595,1766 +510,1315 @@ cpu_types[] = { 0, 0 } }; -/* The macro table */ +/* Some instruction sets indexed by lg(size). */ +static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL }; +static const char * const insXl_op[] = { "insbl", "inswl", "insll", "insql" }; +static const char * const insXh_op[] = { NULL, "inswh", "inslh", "insqh" }; +static const char * const extXl_op[] = { "extbl", "extwl", "extll", "extql" }; +static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" }; +static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" }; +static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" }; +static const char * const stX_op[] = { "stb", "stw", "stl", "stq" }; +static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL }; -static const struct alpha_macro alpha_macros[] = +static void assemble_insn (const struct alpha_opcode *, const expressionS *, int, struct alpha_insn *, bfd_reloc_code_real_type); +static void emit_insn (struct alpha_insn *); +static void assemble_tokens (const char *, const expressionS *, int, int); + +static struct alpha_reloc_tag * +get_alpha_reloc_tag (long sequence) { -/* Load/Store macros */ - { "lda", emit_lda, NULL, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldah", emit_ldah, NULL, - { MACRO_IR, MACRO_EXP, MACRO_EOA } }, - - { "ldl", emit_ir_load, "ldl", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldl_l", emit_ir_load, "ldl_l", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldq", emit_ir_load, "ldq", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldq_l", emit_ir_load, "ldq_l", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldq_u", emit_ir_load, "ldq_u", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldf", emit_loadstore, "ldf", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldg", emit_loadstore, "ldg", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "lds", emit_loadstore, "lds", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldt", emit_loadstore, "ldt", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - - { "ldb", emit_ldX, (PTR) 0, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldbu", emit_ldXu, (PTR) 0, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldw", emit_ldX, (PTR) 1, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ldwu", emit_ldXu, (PTR) 1, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + char buffer[ALPHA_RELOC_DIGITS]; + struct alpha_reloc_tag *info; - { "uldw", emit_uldX, (PTR) 1, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "uldwu", emit_uldXu, (PTR) 1, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "uldl", emit_uldX, (PTR) 2, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "uldlu", emit_uldXu, (PTR) 2, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "uldq", emit_uldXu, (PTR) 3, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + sprintf (buffer, "!%ld", sequence); - { "ldgp", emit_ldgp, NULL, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } }, + info = (struct alpha_reloc_tag *) hash_find (alpha_literal_hash, buffer); + if (! info) + { + size_t len = strlen (buffer); + const char *errmsg; - { "ldi", emit_lda, NULL, - { MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldil", emit_ldil, NULL, - { MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldiq", emit_lda, NULL, - { MACRO_IR, MACRO_EXP, MACRO_EOA } }, + info = xcalloc (sizeof (struct alpha_reloc_tag) + len, 1); - { "stl", emit_loadstore, "stl", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stl_c", emit_loadstore, "stl_c", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stq", emit_loadstore, "stq", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stq_c", emit_loadstore, "stq_c", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stq_u", emit_loadstore, "stq_u", - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stf", emit_loadstore, "stf", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stg", emit_loadstore, "stg", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "sts", emit_loadstore, "sts", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stt", emit_loadstore, "stt", - { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + info->segment = now_seg; + info->sequence = sequence; + strcpy (info->string, buffer); + errmsg = hash_insert (alpha_literal_hash, info->string, (void *) info); + if (errmsg) + as_fatal (errmsg); + } - { "stb", emit_stX, (PTR) 0, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "stw", emit_stX, (PTR) 1, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ustw", emit_ustX, (PTR) 1, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ustl", emit_ustX, (PTR) 2, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - { "ustq", emit_ustX, (PTR) 3, - { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + return info; +} -/* Arithmetic macros */ +static void +alpha_adjust_relocs (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + void * ptr ATTRIBUTE_UNUSED) +{ + segment_info_type *seginfo = seg_info (sec); + fixS **prevP; + fixS *fixp; + fixS *next; + fixS *slave; - { "sextb", emit_sextX, (PTR) 0, - { MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EOA, - /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, - { "sextw", emit_sextX, (PTR) 1, - { MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EOA, - /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, + /* If seginfo is NULL, we did not create this section; don't do + anything with it. By using a pointer to a pointer, we can update + the links in place. */ + if (seginfo == NULL) + return; - { "divl", emit_division, "__divl", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - { "divlu", emit_division, "__divlu", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - { "divq", emit_division, "__divq", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - { "divqu", emit_division, "__divqu", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - { "reml", emit_division, "__reml", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - { "remlu", emit_division, "__remlu", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - { "remq", emit_division, "__remq", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - { "remqu", emit_division, "__remqu", - { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_IR, MACRO_EOA, - /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + /* If there are no relocations, skip the section. */ + if (! seginfo->fix_root) + return; - { "jsr", emit_jsrjmp, "jsr", - { MACRO_PIR, MACRO_EXP, MACRO_EOA, - MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA, - MACRO_EXP, MACRO_EOA } }, - { "jmp", emit_jsrjmp, "jmp", - { MACRO_PIR, MACRO_EXP, MACRO_EOA, - MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA, - MACRO_EXP, MACRO_EOA } }, - { "ret", emit_retjcr, "ret", - { MACRO_IR, MACRO_EXP, MACRO_EOA, - MACRO_IR, MACRO_EOA, - MACRO_PIR, MACRO_EXP, MACRO_EOA, - MACRO_PIR, MACRO_EOA, - MACRO_EXP, MACRO_EOA, - MACRO_EOA } }, - { "jcr", emit_retjcr, "jcr", - { MACRO_IR, MACRO_EXP, MACRO_EOA, - MACRO_IR, MACRO_EOA, - MACRO_PIR, MACRO_EXP, MACRO_EOA, - MACRO_PIR, MACRO_EOA, - MACRO_EXP, MACRO_EOA, - MACRO_EOA } }, - { "jsr_coroutine", emit_retjcr, "jcr", - { MACRO_IR, MACRO_EXP, MACRO_EOA, - MACRO_IR, MACRO_EOA, - MACRO_PIR, MACRO_EXP, MACRO_EOA, - MACRO_PIR, MACRO_EOA, - MACRO_EXP, MACRO_EOA, - MACRO_EOA } }, -}; + /* First rebuild the fixup chain without the explicit lituse and + gpdisp_lo16 relocs. */ + prevP = &seginfo->fix_root; + for (fixp = seginfo->fix_root; fixp; fixp = next) + { + next = fixp->fx_next; + fixp->fx_next = (fixS *) 0; -static const unsigned int alpha_num_macros - = sizeof (alpha_macros) / sizeof (*alpha_macros); - -/* Public interface functions */ + switch (fixp->fx_r_type) + { + case BFD_RELOC_ALPHA_LITUSE: + if (fixp->tc_fix_data.info->n_master == 0) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("No !literal!%ld was found"), + fixp->tc_fix_data.info->sequence); +#ifdef RELOC_OP_P + if (fixp->fx_offset == LITUSE_ALPHA_TLSGD) + { + if (! fixp->tc_fix_data.info->saw_tlsgd) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("No !tlsgd!%ld was found"), + fixp->tc_fix_data.info->sequence); + } + else if (fixp->fx_offset == LITUSE_ALPHA_TLSLDM) + { + if (! fixp->tc_fix_data.info->saw_tlsldm) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("No !tlsldm!%ld was found"), + fixp->tc_fix_data.info->sequence); + } +#endif + break; -/* This function is called once, at assembler startup time. It sets - up all the tables, etc. that the MD part of the assembler will - need, that can be determined before arguments are parsed. */ + case BFD_RELOC_ALPHA_GPDISP_LO16: + if (fixp->tc_fix_data.info->n_master == 0) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("No ldah !gpdisp!%ld was found"), + fixp->tc_fix_data.info->sequence); + break; -void -md_begin () -{ - unsigned int i; + case BFD_RELOC_ALPHA_ELF_LITERAL: + if (fixp->tc_fix_data.info + && (fixp->tc_fix_data.info->saw_tlsgd + || fixp->tc_fix_data.info->saw_tlsldm)) + break; + /* FALLTHRU */ - /* Verify that X_op field is wide enough. */ - { - expressionS e; - e.X_op = O_max; - assert (e.X_op == O_max); - } - - /* Create the opcode hash table. */ - alpha_opcode_hash = hash_new (); - for (i = 0; i < alpha_num_opcodes;) - { - const char *name, *retval, *slash; - - name = alpha_opcodes[i].name; - retval = hash_insert (alpha_opcode_hash, name, (PTR) &alpha_opcodes[i]); - if (retval) - as_fatal (_("internal error: can't hash opcode `%s': %s"), - name, retval); - - /* Some opcodes include modifiers of various sorts with a "/mod" - syntax, like the architecture manual suggests. However, for - use with gcc at least, we also need access to those same opcodes - without the "/". */ - - if ((slash = strchr (name, '/')) != NULL) - { - char *p = xmalloc (strlen (name)); - memcpy (p, name, slash - name); - strcpy (p + (slash - name), slash + 1); - - (void) hash_insert (alpha_opcode_hash, p, (PTR) &alpha_opcodes[i]); - /* Ignore failures -- the opcode table does duplicate some - variants in different forms, like "hw_stq" and "hw_st/q". */ + default: + *prevP = fixp; + prevP = &fixp->fx_next; + break; } - - while (++i < alpha_num_opcodes - && (alpha_opcodes[i].name == name - || !strcmp (alpha_opcodes[i].name, name))) - continue; } - /* Create the macro hash table. */ - alpha_macro_hash = hash_new (); - for (i = 0; i < alpha_num_macros;) - { - const char *name, *retval; + /* Go back and re-chain dependent relocations. They are currently + linked through the next_reloc field in reverse order, so as we + go through the next_reloc chain, we effectively reverse the chain + once again. - name = alpha_macros[i].name; - retval = hash_insert (alpha_macro_hash, name, (PTR) &alpha_macros[i]); - if (retval) - as_fatal (_("internal error: can't hash macro `%s': %s"), - name, retval); + Except if there is more than one !literal for a given sequence + number. In that case, the programmer and/or compiler is not sure + how control flows from literal to lituse, and we can't be sure to + get the relaxation correct. - while (++i < alpha_num_macros - && (alpha_macros[i].name == name - || !strcmp (alpha_macros[i].name, name))) - continue; - } + ??? Well, actually we could, if there are enough lituses such that + we can make each literal have at least one of each lituse type + present. Not implemented. - /* Construct symbols for each of the registers. */ - for (i = 0; i < 32; ++i) - { - char name[4]; + Also suppress the optimization if the !literals/!lituses are spread + in different segments. This can happen with "intersting" uses of + inline assembly; examples are present in the Linux kernel semaphores. */ - sprintf (name, "$%d", i); - alpha_register_table[i] = symbol_create (name, reg_section, i, - &zero_address_frag); - } - for (; i < 64; ++i) + for (fixp = seginfo->fix_root; fixp; fixp = next) { - char name[5]; - - sprintf (name, "$f%d", i - 32); - alpha_register_table[i] = symbol_create (name, reg_section, i, - &zero_address_frag); - } - - /* Create the special symbols and sections we'll be using. */ - - /* So .sbss will get used for tiny objects. */ - bfd_set_gp_size (stdoutput, g_switch_value); + next = fixp->fx_next; + switch (fixp->fx_r_type) + { + case BFD_RELOC_ALPHA_TLSGD: + case BFD_RELOC_ALPHA_TLSLDM: + if (!fixp->tc_fix_data.info) + break; + if (fixp->tc_fix_data.info->n_master == 0) + break; + else if (fixp->tc_fix_data.info->n_master > 1) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("too many !literal!%ld for %s"), + fixp->tc_fix_data.info->sequence, + (fixp->fx_r_type == BFD_RELOC_ALPHA_TLSGD + ? "!tlsgd" : "!tlsldm")); + break; + } -#ifdef OBJ_ECOFF - create_literal_section (".lita", &alpha_lita_section, &alpha_lita_symbol); + fixp->tc_fix_data.info->master->fx_next = fixp->fx_next; + fixp->fx_next = fixp->tc_fix_data.info->master; + fixp = fixp->fx_next; + /* Fall through. */ - /* For handling the GP, create a symbol that won't be output in the - symbol table. We'll edit it out of relocs later. */ - alpha_gp_symbol = symbol_create ("", alpha_lita_section, 0x8000, - &zero_address_frag); -#endif + case BFD_RELOC_ALPHA_ELF_LITERAL: + if (fixp->tc_fix_data.info + && fixp->tc_fix_data.info->n_master == 1 + && ! fixp->tc_fix_data.info->multi_section_p) + { + for (slave = fixp->tc_fix_data.info->slaves; + slave != (fixS *) 0; + slave = slave->tc_fix_data.next_reloc) + { + slave->fx_next = fixp->fx_next; + fixp->fx_next = slave; + } + } + break; -#ifdef OBJ_EVAX - create_literal_section (".link", &alpha_link_section, &alpha_link_symbol); -#endif + case BFD_RELOC_ALPHA_GPDISP_HI16: + if (fixp->tc_fix_data.info->n_slaves == 0) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("No lda !gpdisp!%ld was found"), + fixp->tc_fix_data.info->sequence); + else + { + slave = fixp->tc_fix_data.info->slaves; + slave->fx_next = next; + fixp->fx_next = slave; + } + break; -#ifdef OBJ_ELF - if (ECOFF_DEBUGGING) - { - segT sec = subseg_new (".mdebug", (subsegT) 0); - bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY); - bfd_set_section_alignment (stdoutput, sec, 3); + default: + break; + } } -#endif /* OBJ_ELF */ - - /* Create literal lookup hash table. */ - alpha_literal_hash = hash_new (); - - subseg_set (text_section, 0); } -/* The public interface to the instruction assembler. */ +/* Before the relocations are written, reorder them, so that user + supplied !lituse relocations follow the appropriate !literal + relocations, and similarly for !gpdisp relocations. */ void -md_assemble (str) - char *str; -{ - char opname[32]; /* Current maximum is 13. */ - expressionS tok[MAX_INSN_ARGS]; - int ntok, trunclen; - size_t opnamelen; - - /* Split off the opcode. */ - opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/46819"); - trunclen = (opnamelen < sizeof (opname) - 1 - ? opnamelen - : sizeof (opname) - 1); - memcpy (opname, str, trunclen); - opname[trunclen] = '\0'; - - /* Tokenize the rest of the line. */ - if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0) - { - if (ntok != TOKENIZE_ERROR_REPORT) - as_bad (_("syntax error")); - - return; - } - - /* Finish it off. */ - assemble_tokens (opname, tok, ntok, alpha_macros_on); -} - -/* Round up a section's size to the appropriate boundary. */ - -valueT -md_section_align (seg, size) - segT seg; - valueT size; +alpha_before_fix (void) { - int align = bfd_get_section_alignment (stdoutput, seg); - valueT mask = ((valueT) 1 << align) - 1; - - return (size + mask) & ~mask; + if (alpha_literal_hash) + bfd_map_over_sections (stdoutput, alpha_adjust_relocs, NULL); } - -/* Turn a string in input_line_pointer into a floating point constant - of type TYPE, and store the appropriate bytes in *LITP. The number - of LITTLENUMS emitted is stored in *SIZEP. An error message is - returned, or NULL on OK. */ - -/* Equal to MAX_PRECISION in atof-ieee.c. */ -#define MAX_LITTLENUMS 6 - -extern char *vax_md_atof PARAMS ((int, char *, int *)); - -char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; + +#ifdef DEBUG_ALPHA +static void +debug_exp (expressionS tok[], int ntok) { - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; + int i; - switch (type) + fprintf (stderr, "debug_exp: %d tokens", ntok); + for (i = 0; i < ntok; i++) { - /* VAX floats */ - case 'G': - /* VAX md_atof doesn't like "G" for some reason. */ - type = 'g'; - case 'F': - case 'D': - return vax_md_atof (type, litP, sizeP); - - /* IEEE floats */ - case 'f': - prec = 2; - break; - - case 'd': - prec = 4; - break; - - case 'x': - case 'X': - prec = 6; - break; - - case 'p': - case 'P': - prec = 6; - break; + expressionS *t = &tok[i]; + const char *name; - default: - *sizeP = 0; - return _("Bad call to MD_ATOF()"); - } - t = atof_ieee (input_line_pointer, type, words); - if (t) - input_line_pointer = t; - *sizeP = prec * sizeof (LITTLENUM_TYPE); + switch (t->X_op) + { + default: name = "unknown"; break; + case O_illegal: name = "O_illegal"; break; + case O_absent: name = "O_absent"; break; + case O_constant: name = "O_constant"; break; + case O_symbol: name = "O_symbol"; break; + case O_symbol_rva: name = "O_symbol_rva"; break; + case O_register: name = "O_register"; break; + case O_big: name = "O_big"; break; + case O_uminus: name = "O_uminus"; break; + case O_bit_not: name = "O_bit_not"; break; + case O_logical_not: name = "O_logical_not"; break; + case O_multiply: name = "O_multiply"; break; + case O_divide: name = "O_divide"; break; + case O_modulus: name = "O_modulus"; break; + case O_left_shift: name = "O_left_shift"; break; + case O_right_shift: name = "O_right_shift"; break; + case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break; + case O_bit_or_not: name = "O_bit_or_not"; break; + case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break; + case O_bit_and: name = "O_bit_and"; break; + case O_add: name = "O_add"; break; + case O_subtract: name = "O_subtract"; break; + case O_eq: name = "O_eq"; break; + case O_ne: name = "O_ne"; break; + case O_lt: name = "O_lt"; break; + case O_le: name = "O_le"; break; + case O_ge: name = "O_ge"; break; + case O_gt: name = "O_gt"; break; + case O_logical_and: name = "O_logical_and"; break; + case O_logical_or: name = "O_logical_or"; break; + case O_index: name = "O_index"; break; + case O_pregister: name = "O_pregister"; break; + case O_cpregister: name = "O_cpregister"; break; + case O_literal: name = "O_literal"; break; + case O_lituse_addr: name = "O_lituse_addr"; break; + case O_lituse_base: name = "O_lituse_base"; break; + case O_lituse_bytoff: name = "O_lituse_bytoff"; break; + case O_lituse_jsr: name = "O_lituse_jsr"; break; + case O_lituse_tlsgd: name = "O_lituse_tlsgd"; break; + case O_lituse_tlsldm: name = "O_lituse_tlsldm"; break; + case O_gpdisp: name = "O_gpdisp"; break; + case O_gprelhigh: name = "O_gprelhigh"; break; + case O_gprellow: name = "O_gprellow"; break; + case O_gprel: name = "O_gprel"; break; + case O_samegp: name = "O_samegp"; break; + case O_tlsgd: name = "O_tlsgd"; break; + case O_tlsldm: name = "O_tlsldm"; break; + case O_gotdtprel: name = "O_gotdtprel"; break; + case O_dtprelhi: name = "O_dtprelhi"; break; + case O_dtprello: name = "O_dtprello"; break; + case O_dtprel: name = "O_dtprel"; break; + case O_gottprel: name = "O_gottprel"; break; + case O_tprelhi: name = "O_tprelhi"; break; + case O_tprello: name = "O_tprello"; break; + case O_tprel: name = "O_tprel"; break; + } - for (wordP = words + prec - 1; prec--;) - { - md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); + fprintf (stderr, ", %s(%s, %s, %d)", name, + (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--", + (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--", + (int) t->X_add_number); } - - return 0; + fprintf (stderr, "\n"); + fflush (stderr); } +#endif -/* Take care of the target-specific command-line options. */ +/* Parse the arguments to an opcode. */ -int -md_parse_option (c, arg) - int c; - char *arg; +static int +tokenize_arguments (char *str, + expressionS tok[], + int ntok) { - switch (c) - { - case 'F': - alpha_nofloats_on = 1; - break; + expressionS *end_tok = tok + ntok; + char *old_input_line_pointer; + int saw_comma = 0, saw_arg = 0; +#ifdef DEBUG_ALPHA + expressionS *orig_tok = tok; +#endif +#ifdef RELOC_OP_P + char *p; + const struct alpha_reloc_op_tag *r; + int c, i; + size_t len; + int reloc_found_p = 0; +#endif - case OPTION_32ADDR: - alpha_addr32_on = 1; - break; + memset (tok, 0, sizeof (*tok) * ntok); - case 'g': - alpha_debug = 1; - break; + /* Save and restore input_line_pointer around this function. */ + old_input_line_pointer = input_line_pointer; + input_line_pointer = str; - case 'G': - g_switch_value = atoi (arg); - break; +#ifdef RELOC_OP_P + /* ??? Wrest control of ! away from the regular expression parser. */ + is_end_of_line[(unsigned char) '!'] = 1; +#endif - case 'm': - { - const struct cpu_type *p; - for (p = cpu_types; p->name; ++p) - if (strcmp (arg, p->name) == 0) + while (tok < end_tok && *input_line_pointer) + { + SKIP_WHITESPACE (); + switch (*input_line_pointer) + { + case '\0': + goto fini; + +#ifdef RELOC_OP_P + case '!': + /* A relocation operand can be placed after the normal operand on an + assembly language statement, and has the following form: + !relocation_type!sequence_number. */ + if (reloc_found_p) { - alpha_target_name = p->name, alpha_target = p->flags; - goto found; + /* Only support one relocation op per insn. */ + as_bad (_("More than one relocation op per insn")); + goto err_report; } - as_warn (_("Unknown CPU identifier `%s'"), arg); - found:; - } - break; -#ifdef OBJ_EVAX - case '+': /* For g++. Hash any name > 63 chars long. */ - alpha_flag_hash_long_names = 1; - break; + if (!saw_arg) + goto err; - case 'H': /* Show new symbol after hash truncation */ - alpha_flag_show_after_trunc = 1; - break; + ++input_line_pointer; + SKIP_WHITESPACE (); + p = input_line_pointer; + c = get_symbol_end (); - case 'h': /* for gnu-c/vax compatibility. */ - break; -#endif + /* Parse !relocation_type. */ + len = input_line_pointer - p; + if (len == 0) + { + as_bad (_("No relocation operand")); + goto err_report; + } - case OPTION_RELAX: - alpha_flag_relax = 1; - break; + r = &alpha_reloc_op[0]; + for (i = alpha_num_reloc_op - 1; i >= 0; i--, r++) + if (len == r->length && memcmp (p, r->name, len) == 0) + break; + if (i < 0) + { + as_bad (_("Unknown relocation operand: !%s"), p); + goto err_report; + } -#ifdef OBJ_ELF - case OPTION_MDEBUG: - alpha_flag_mdebug = 1; - break; - case OPTION_NO_MDEBUG: - alpha_flag_mdebug = 0; - break; -#endif + *input_line_pointer = c; + SKIP_WHITESPACE (); + if (*input_line_pointer != '!') + { + if (r->require_seq) + { + as_bad (_("no sequence number after !%s"), p); + goto err_report; + } - default: - return 0; - } + tok->X_add_number = 0; + } + else + { + if (! r->allow_seq) + { + as_bad (_("!%s does not use a sequence number"), p); + goto err_report; + } - return 1; -} + input_line_pointer++; -/* Print a description of the command-line options that we accept. */ + /* Parse !sequence_number. */ + expression (tok); + if (tok->X_op != O_constant || tok->X_add_number <= 0) + { + as_bad (_("Bad sequence number: !%s!%s"), + r->name, input_line_pointer); + goto err_report; + } + } -void -md_show_usage (stream) - FILE *stream; -{ - fputs (_("\ -Alpha options:\n\ --32addr treat addresses as 32-bit values\n\ --F lack floating point instructions support\n\ --mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mev67 | -mev68 | -mall\n\ - specify variant of Alpha architecture\n\ --m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264 | -m21264a | -m21264b\n\ - these variants include PALcode opcodes\n"), - stream); -#ifdef OBJ_EVAX - fputs (_("\ -VMS options:\n\ --+ hash encode (don't truncate) names longer than 64 characters\n\ --H show new symbol after hash truncation\n"), - stream); -#endif -} + tok->X_op = r->op; + reloc_found_p = 1; + ++tok; + break; +#endif /* RELOC_OP_P */ -/* Decide from what point a pc-relative relocation is relative to, - relative to the pc-relative fixup. Er, relatively speaking. */ + case ',': + ++input_line_pointer; + if (saw_comma || !saw_arg) + goto err; + saw_comma = 1; + break; -long -md_pcrel_from (fixP) - fixS *fixP; -{ - valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; - switch (fixP->fx_r_type) - { - case BFD_RELOC_23_PCREL_S2: - case BFD_RELOC_ALPHA_HINT: - case BFD_RELOC_ALPHA_BRSGP: - return addr + 4; - default: - return addr; - } -} + case '(': + { + char *hold = input_line_pointer++; -/* Attempt to simplify or even eliminate a fixup. The return value is - ignored; perhaps it was once meaningful, but now it is historical. - To indicate that a fixup has been eliminated, set fixP->fx_done. + /* First try for parenthesized register ... */ + expression (tok); + if (*input_line_pointer == ')' && tok->X_op == O_register) + { + tok->X_op = (saw_comma ? O_cpregister : O_pregister); + saw_comma = 0; + saw_arg = 1; + ++input_line_pointer; + ++tok; + break; + } - For ELF, here it is that we transform the GPDISP_HI16 reloc we used - internally into the GPDISP reloc used externally. We had to do - this so that we'd have the GPDISP_LO16 reloc as a tag to compute - the distance to the "lda" instruction for setting the addend to - GPDISP. */ + /* ... then fall through to plain expression. */ + input_line_pointer = hold; + } -void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg; -{ - char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; - valueT value = * valP; - unsigned image, size; + default: + if (saw_arg && !saw_comma) + goto err; - switch (fixP->fx_r_type) - { - /* The GPDISP relocations are processed internally with a symbol - referring to the current function's section; we need to drop - in a value which, when added to the address of the start of - the function, gives the desired GP. */ - case BFD_RELOC_ALPHA_GPDISP_HI16: - { - fixS *next = fixP->fx_next; + expression (tok); + if (tok->X_op == O_illegal || tok->X_op == O_absent) + goto err; - /* With user-specified !gpdisp relocations, we can be missing - the matching LO16 reloc. We will have already issued an - error message. */ - if (next) - fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where - - fixP->fx_frag->fr_address - fixP->fx_where); + saw_comma = 0; + saw_arg = 1; + ++tok; + break; + } + } - value = (value - sign_extend_16 (value)) >> 16; - } -#ifdef OBJ_ELF - fixP->fx_r_type = BFD_RELOC_ALPHA_GPDISP; -#endif - goto do_reloc_gp; +fini: + if (saw_comma) + goto err; + input_line_pointer = old_input_line_pointer; - case BFD_RELOC_ALPHA_GPDISP_LO16: - value = sign_extend_16 (value); - fixP->fx_offset = 0; -#ifdef OBJ_ELF - fixP->fx_done = 1; +#ifdef DEBUG_ALPHA + debug_exp (orig_tok, ntok - (end_tok - tok)); #endif - - do_reloc_gp: - fixP->fx_addsy = section_symbol (seg); - md_number_to_chars (fixpos, value, 2); - break; - - case BFD_RELOC_16: - if (fixP->fx_pcrel) - fixP->fx_r_type = BFD_RELOC_16_PCREL; - size = 2; - goto do_reloc_xx; - case BFD_RELOC_32: - if (fixP->fx_pcrel) - fixP->fx_r_type = BFD_RELOC_32_PCREL; - size = 4; - goto do_reloc_xx; - case BFD_RELOC_64: - if (fixP->fx_pcrel) - fixP->fx_r_type = BFD_RELOC_64_PCREL; - size = 8; - do_reloc_xx: - if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) - { - md_number_to_chars (fixpos, value, size); - goto done; - } - return; - -#ifdef OBJ_ECOFF - case BFD_RELOC_GPREL32: - assert (fixP->fx_subsy == alpha_gp_symbol); - fixP->fx_subsy = 0; - /* FIXME: inherited this obliviousness of `value' -- why? */ - md_number_to_chars (fixpos, -alpha_gp_value, 4); - break; -#else - case BFD_RELOC_GPREL32: +#ifdef RELOC_OP_P + is_end_of_line[(unsigned char) '!'] = 0; #endif - case BFD_RELOC_GPREL16: - case BFD_RELOC_ALPHA_GPREL_HI16: - case BFD_RELOC_ALPHA_GPREL_LO16: - return; - - case BFD_RELOC_23_PCREL_S2: - if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) - { - image = bfd_getl32 (fixpos); - image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF); - goto write_done; - } - return; - - case BFD_RELOC_ALPHA_HINT: - if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) - { - image = bfd_getl32 (fixpos); - image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF); - goto write_done; - } - return; -#ifdef OBJ_ELF - case BFD_RELOC_ALPHA_BRSGP: - return; + return ntok - (end_tok - tok); - case BFD_RELOC_ALPHA_TLSGD: - case BFD_RELOC_ALPHA_TLSLDM: - case BFD_RELOC_ALPHA_GOTDTPREL16: - case BFD_RELOC_ALPHA_DTPREL_HI16: - case BFD_RELOC_ALPHA_DTPREL_LO16: - case BFD_RELOC_ALPHA_DTPREL16: - case BFD_RELOC_ALPHA_GOTTPREL16: - case BFD_RELOC_ALPHA_TPREL_HI16: - case BFD_RELOC_ALPHA_TPREL_LO16: - case BFD_RELOC_ALPHA_TPREL16: - if (fixP->fx_addsy) - S_SET_THREAD_LOCAL (fixP->fx_addsy); - return; +err: +#ifdef RELOC_OP_P + is_end_of_line[(unsigned char) '!'] = 0; #endif + input_line_pointer = old_input_line_pointer; + return TOKENIZE_ERROR; -#ifdef OBJ_ECOFF - case BFD_RELOC_ALPHA_LITERAL: - md_number_to_chars (fixpos, value, 2); - return; +#ifdef RELOC_OP_P +err_report: + is_end_of_line[(unsigned char) '!'] = 0; #endif - case BFD_RELOC_ALPHA_ELF_LITERAL: - case BFD_RELOC_ALPHA_LITUSE: - case BFD_RELOC_ALPHA_LINKAGE: - case BFD_RELOC_ALPHA_CODEADDR: - return; - - case BFD_RELOC_VTABLE_INHERIT: - case BFD_RELOC_VTABLE_ENTRY: - return; - - default: - { - const struct alpha_operand *operand; - - if ((int) fixP->fx_r_type >= 0) - as_fatal (_("unhandled relocation type %s"), - bfd_get_reloc_code_name (fixP->fx_r_type)); - - assert (-(int) fixP->fx_r_type < (int) alpha_num_operands); - operand = &alpha_operands[-(int) fixP->fx_r_type]; - - /* The rest of these fixups only exist internally during symbol - resolution and have no representation in the object file. - Therefore they must be completely resolved as constants. */ + input_line_pointer = old_input_line_pointer; + return TOKENIZE_ERROR_REPORT; +} - if (fixP->fx_addsy != 0 - && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section) - as_bad_where (fixP->fx_file, fixP->fx_line, - _("non-absolute expression in constant field")); +/* Search forward through all variants of an opcode looking for a + syntax match. */ - image = bfd_getl32 (fixpos); - image = insert_operand (image, operand, (offsetT) value, - fixP->fx_file, fixP->fx_line); - } - goto write_done; - } +static const struct alpha_opcode * +find_opcode_match (const struct alpha_opcode *first_opcode, + const expressionS *tok, + int *pntok, + int *pcpumatch) +{ + const struct alpha_opcode *opcode = first_opcode; + int ntok = *pntok; + int got_cpu_match = 0; - if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0) - return; - else + do { - as_warn_where (fixP->fx_file, fixP->fx_line, - _("type %d reloc done?\n"), (int) fixP->fx_r_type); - goto done; - } - -write_done: - md_number_to_chars (fixpos, image, 4); - -done: - fixP->fx_done = 1; -} + const unsigned char *opidx; + int tokidx = 0; -/* Look for a register name in the given symbol. */ + /* Don't match opcodes that don't exist on this architecture. */ + if (!(opcode->flags & alpha_target)) + goto match_failed; -symbolS * -md_undefined_symbol (name) - char *name; -{ - if (*name == '$') - { - int is_float = 0, num; + got_cpu_match = 1; - switch (*++name) + for (opidx = opcode->operands; *opidx; ++opidx) { - case 'f': - if (name[1] == 'p' && name[2] == '\0') - return alpha_register_table[AXP_REG_FP]; - is_float = 32; - /* FALLTHRU */ + const struct alpha_operand *operand = &alpha_operands[*opidx]; - case 'r': - if (!ISDIGIT (*++name)) - break; - /* FALLTHRU */ + /* Only take input from real operands. */ + if (operand->flags & AXP_OPERAND_FAKE) + continue; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (name[1] == '\0') - num = name[0] - '0'; - else if (name[0] != '0' && ISDIGIT (name[1]) && name[2] == '\0') + /* When we expect input, make sure we have it. */ + if (tokidx >= ntok) { - num = (name[0] - '0') * 10 + name[1] - '0'; - if (num >= 32) - break; + if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0) + goto match_failed; + continue; } - else - break; - - if (!alpha_noat_on && (num + is_float) == AXP_REG_AT) - as_warn (_("Used $at without \".set noat\"")); - return alpha_register_table[num + is_float]; - case 'a': - if (name[1] == 't' && name[2] == '\0') + /* Match operand type with expression type. */ + switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK) { - if (!alpha_noat_on) - as_warn (_("Used $at without \".set noat\"")); - return alpha_register_table[AXP_REG_AT]; - } - break; + case AXP_OPERAND_IR: + if (tok[tokidx].X_op != O_register + || !is_ir_num (tok[tokidx].X_add_number)) + goto match_failed; + break; + case AXP_OPERAND_FPR: + if (tok[tokidx].X_op != O_register + || !is_fpr_num (tok[tokidx].X_add_number)) + goto match_failed; + break; + case AXP_OPERAND_IR | AXP_OPERAND_PARENS: + if (tok[tokidx].X_op != O_pregister + || !is_ir_num (tok[tokidx].X_add_number)) + goto match_failed; + break; + case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA: + if (tok[tokidx].X_op != O_cpregister + || !is_ir_num (tok[tokidx].X_add_number)) + goto match_failed; + break; - case 'g': - if (name[1] == 'p' && name[2] == '\0') - return alpha_register_table[alpha_gp_register]; - break; + case AXP_OPERAND_RELATIVE: + case AXP_OPERAND_SIGNED: + case AXP_OPERAND_UNSIGNED: + switch (tok[tokidx].X_op) + { + case O_illegal: + case O_absent: + case O_register: + case O_pregister: + case O_cpregister: + goto match_failed; - case 's': - if (name[1] == 'p' && name[2] == '\0') - return alpha_register_table[AXP_REG_SP]; - break; + default: + break; + } + break; + + default: + /* Everything else should have been fake. */ + abort (); + } + ++tokidx; } + + /* Possible match -- did we use all of our input? */ + if (tokidx == ntok) + { + *pntok = ntok; + return opcode; + } + + match_failed:; } - return NULL; -} + while (++opcode - alpha_opcodes < (int) alpha_num_opcodes + && !strcmp (opcode->name, first_opcode->name)); -#ifdef OBJ_ECOFF -/* @@@ Magic ECOFF bits. */ + if (*pcpumatch) + *pcpumatch = got_cpu_match; -void -alpha_frob_ecoff_data () -{ - select_gp_value (); - /* $zero and $f31 are read-only */ - alpha_gprmask &= ~1; - alpha_fprmask &= ~1; + return NULL; } -#endif -/* Hook to remember a recently defined label so that the auto-align - code can adjust the symbol after we know what alignment will be - required. */ +/* Given an opcode name and a pre-tokenized set of arguments, assemble + the insn, but do not emit it. -void -alpha_define_label (sym) - symbolS *sym; + Note that this implies no macros allowed, since we can't store more + than one insn in an insn structure. */ + +static void +assemble_tokens_to_insn (const char *opname, + const expressionS *tok, + int ntok, + struct alpha_insn *insn) { - alpha_insn_label = sym; + const struct alpha_opcode *opcode; + + /* Search opcodes. */ + opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname); + if (opcode) + { + int cpumatch; + opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); + if (opcode) + { + assemble_insn (opcode, tok, ntok, insn, BFD_RELOC_UNUSED); + return; + } + else if (cpumatch) + as_bad (_("inappropriate arguments for opcode `%s'"), opname); + else + as_bad (_("opcode `%s' not supported for target %s"), opname, + alpha_target_name); + } + else + as_bad (_("unknown opcode `%s'"), opname); } -/* Return true if we must always emit a reloc for a type and false if - there is some hope of resolving it at assembly time. */ +/* Build a BFD section with its flags set appropriately for the .lita, + .lit8, or .lit4 sections. */ -int -alpha_force_relocation (f) - fixS *f; +static void +create_literal_section (const char *name, + segT *secp, + symbolS **symp) { - if (alpha_flag_relax) - return 1; - - switch (f->fx_r_type) - { - case BFD_RELOC_ALPHA_GPDISP_HI16: - case BFD_RELOC_ALPHA_GPDISP_LO16: - case BFD_RELOC_ALPHA_GPDISP: - case BFD_RELOC_ALPHA_LITERAL: - case BFD_RELOC_ALPHA_ELF_LITERAL: - case BFD_RELOC_ALPHA_LITUSE: - case BFD_RELOC_GPREL16: - case BFD_RELOC_GPREL32: - case BFD_RELOC_ALPHA_GPREL_HI16: - case BFD_RELOC_ALPHA_GPREL_LO16: - case BFD_RELOC_ALPHA_LINKAGE: - case BFD_RELOC_ALPHA_CODEADDR: - case BFD_RELOC_ALPHA_BRSGP: - case BFD_RELOC_ALPHA_TLSGD: - case BFD_RELOC_ALPHA_TLSLDM: - case BFD_RELOC_ALPHA_GOTDTPREL16: - case BFD_RELOC_ALPHA_DTPREL_HI16: - case BFD_RELOC_ALPHA_DTPREL_LO16: - case BFD_RELOC_ALPHA_DTPREL16: - case BFD_RELOC_ALPHA_GOTTPREL16: - case BFD_RELOC_ALPHA_TPREL_HI16: - case BFD_RELOC_ALPHA_TPREL_LO16: - case BFD_RELOC_ALPHA_TPREL16: - return 1; + segT current_section = now_seg; + int current_subsec = now_subseg; + segT new_sec; - default: - break; - } + *secp = new_sec = subseg_new (name, 0); + subseg_set (current_section, current_subsec); + bfd_set_section_alignment (stdoutput, new_sec, 4); + bfd_set_section_flags (stdoutput, new_sec, + SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY + | SEC_DATA); - return generic_force_reloc (f); + S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec)); } -/* Return true if we can partially resolve a relocation now. */ +/* Load a (partial) expression into a target register. -int -alpha_fix_adjustable (f) - fixS *f; -{ - /* Are there any relocation types for which we must generate a reloc - but we can adjust the values contained within it? */ - switch (f->fx_r_type) - { - case BFD_RELOC_ALPHA_GPDISP_HI16: - case BFD_RELOC_ALPHA_GPDISP_LO16: - case BFD_RELOC_ALPHA_GPDISP: - return 0; + If poffset is not null, after the call it will either contain + O_constant 0, or a 16-bit offset appropriate for any MEM format + instruction. In addition, pbasereg will be modified to point to + the base register to use in that MEM format instruction. - case BFD_RELOC_ALPHA_LITERAL: - case BFD_RELOC_ALPHA_ELF_LITERAL: - case BFD_RELOC_ALPHA_LITUSE: - case BFD_RELOC_ALPHA_LINKAGE: - case BFD_RELOC_ALPHA_CODEADDR: - return 1; + In any case, *pbasereg should contain a base register to add to the + expression. This will normally be either AXP_REG_ZERO or + alpha_gp_register. Symbol addresses will always be loaded via $gp, + so "foo($0)" is interpreted as adding the address of foo to $0; + i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps, + but this is what OSF/1 does. - case BFD_RELOC_VTABLE_ENTRY: - case BFD_RELOC_VTABLE_INHERIT: - return 0; + If explicit relocations of the form !literal! are allowed, + and used, then explicit_reloc with be an expression pointer. - case BFD_RELOC_GPREL16: - case BFD_RELOC_GPREL32: - case BFD_RELOC_ALPHA_GPREL_HI16: - case BFD_RELOC_ALPHA_GPREL_LO16: - case BFD_RELOC_23_PCREL_S2: - case BFD_RELOC_32: - case BFD_RELOC_64: - case BFD_RELOC_ALPHA_HINT: - return 1; + Finally, the return value is nonzero if the calling macro may emit + a LITUSE reloc if otherwise appropriate; the return value is the + sequence number to use. */ - case BFD_RELOC_ALPHA_TLSGD: - case BFD_RELOC_ALPHA_TLSLDM: - case BFD_RELOC_ALPHA_GOTDTPREL16: - case BFD_RELOC_ALPHA_DTPREL_HI16: - case BFD_RELOC_ALPHA_DTPREL_LO16: - case BFD_RELOC_ALPHA_DTPREL16: - case BFD_RELOC_ALPHA_GOTTPREL16: - case BFD_RELOC_ALPHA_TPREL_HI16: - case BFD_RELOC_ALPHA_TPREL_LO16: - case BFD_RELOC_ALPHA_TPREL16: - /* ??? No idea why we can't return a reference to .tbss+10, but - we're preventing this in the other assemblers. Follow for now. */ - return 0; +static long +load_expression (int targreg, + const expressionS *exp, + int *pbasereg, + expressionS *poffset) +{ + long emit_lituse = 0; + offsetT addend = exp->X_add_number; + int basereg = *pbasereg; + struct alpha_insn insn; + expressionS newtok[3]; -#ifdef OBJ_ELF - case BFD_RELOC_ALPHA_BRSGP: - /* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and - let it get resolved at assembly time. */ + switch (exp->X_op) + { + case O_symbol: { - symbolS *sym = f->fx_addsy; - const char *name; - int offset = 0; - - if (generic_force_reloc (f)) - return 0; +#ifdef OBJ_ECOFF + offsetT lit; - switch (S_GET_OTHER (sym) & STO_ALPHA_STD_GPLOAD) + /* Attempt to reduce .lit load by splitting the offset from + its symbol when possible, but don't create a situation in + which we'd fail. */ + if (!range_signed_32 (addend) && + (alpha_noat_on || targreg == AXP_REG_AT)) { - case STO_ALPHA_NOPV: - break; - case STO_ALPHA_STD_GPLOAD: - offset = 8; - break; - default: - if (S_IS_LOCAL (sym)) - name = ""; - else - name = S_GET_NAME (sym); - as_bad_where (f->fx_file, f->fx_line, - _("!samegp reloc against symbol without .prologue: %s"), - name); - break; + lit = add_to_literal_pool (exp->X_add_symbol, addend, + alpha_lita_section, 8); + addend = 0; } - f->fx_r_type = BFD_RELOC_23_PCREL_S2; - f->fx_offset += offset; - return 1; - } -#endif - - default: - return 1; - } - /*NOTREACHED*/ -} + else + lit = add_to_literal_pool (exp->X_add_symbol, 0, + alpha_lita_section, 8); -/* Generate the BFD reloc to be stuck in the object file from the - fixup used internally in the assembler. */ + if (lit >= 0x8000) + as_fatal (_("overflow in literal (.lita) table")); -arelent * -tc_gen_reloc (sec, fixp) - asection *sec ATTRIBUTE_UNUSED; - fixS *fixp; -{ - arelent *reloc; + /* Emit "ldq r, lit(gp)". */ - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); - *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); - reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + if (basereg != alpha_gp_register && targreg == basereg) + { + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); + if (targreg == AXP_REG_AT) + as_bad (_("macro requires $at while $at in use")); - /* Make sure none of our internal relocations make it this far. - They'd better have been fully resolved by this point. */ - assert ((int) fixp->fx_r_type > 0); + set_tok_reg (newtok[0], AXP_REG_AT); + } + else + set_tok_reg (newtok[0], targreg); - reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); - if (reloc->howto == NULL) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - _("cannot represent `%s' relocation in object file"), - bfd_get_reloc_code_name (fixp->fx_r_type)); - return NULL; - } + set_tok_sym (newtok[1], alpha_lita_symbol, lit); + set_tok_preg (newtok[2], alpha_gp_register); - if (!fixp->fx_pcrel != !reloc->howto->pc_relative) - { - as_fatal (_("internal error? cannot generate `%s' relocation"), - bfd_get_reloc_code_name (fixp->fx_r_type)); - } - assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); + assemble_tokens_to_insn ("ldq", newtok, 3, &insn); -#ifdef OBJ_ECOFF - if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL) - { - /* Fake out bfd_perform_relocation. sigh. */ - reloc->addend = -alpha_gp_value; - } - else -#endif - { - reloc->addend = fixp->fx_offset; + assert (insn.nfixups == 1); + insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL; + insn.sequence = emit_lituse = next_sequence_num--; +#endif /* OBJ_ECOFF */ #ifdef OBJ_ELF - /* Ohhh, this is ugly. The problem is that if this is a local global - symbol, the relocation will entirely be performed at link time, not - at assembly time. bfd_perform_reloc doesn't know about this sort - of thing, and as a result we need to fake it out here. */ - if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy) - || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) - || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL)) - && !S_IS_COMMON (fixp->fx_addsy)) - reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value; -#endif - } - - return reloc; -} + /* Emit "ldq r, gotoff(gp)". */ -/* Parse a register name off of the input_line and return a register - number. Gets md_undefined_symbol above to do the register name - matching for us. + if (basereg != alpha_gp_register && targreg == basereg) + { + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); + if (targreg == AXP_REG_AT) + as_bad (_("macro requires $at while $at in use")); - Only called as a part of processing the ECOFF .frame directive. */ + set_tok_reg (newtok[0], AXP_REG_AT); + } + else + set_tok_reg (newtok[0], targreg); -int -tc_get_register (frame) - int frame ATTRIBUTE_UNUSED; -{ - int framereg = AXP_REG_SP; + /* XXX: Disable this .got minimizing optimization so that we can get + better instruction offset knowledge in the compiler. This happens + very infrequently anyway. */ + if (1 + || (!range_signed_32 (addend) + && (alpha_noat_on || targreg == AXP_REG_AT))) + { + newtok[1] = *exp; + addend = 0; + } + else + set_tok_sym (newtok[1], exp->X_add_symbol, 0); - SKIP_WHITESPACE (); - if (*input_line_pointer == '$') - { - char *s = input_line_pointer; - char c = get_symbol_end (); - symbolS *sym = md_undefined_symbol (s); + set_tok_preg (newtok[2], alpha_gp_register); - *strchr (s, '\0') = c; - if (sym && (framereg = S_GET_VALUE (sym)) <= 31) - goto found; - } - as_warn (_("frame reg expected, using $%d."), framereg); + assemble_tokens_to_insn ("ldq", newtok, 3, &insn); -found: - note_gpreg (framereg); - return framereg; -} + assert (insn.nfixups == 1); + insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; + insn.sequence = emit_lituse = next_sequence_num--; +#endif /* OBJ_ELF */ +#ifdef OBJ_EVAX + offsetT link; -/* This is called before the symbol table is processed. In order to - work with gcc when using mips-tfile, we must keep all local labels. - However, in other cases, we want to discard them. If we were - called with -g, but we didn't see any debugging information, it may - mean that gcc is smuggling debugging information through to - mips-tfile, in which case we must generate all local labels. */ + /* Find symbol or symbol pointer in link section. */ -#ifdef OBJ_ECOFF + if (exp->X_add_symbol == alpha_evax_proc.symbol) + { + if (range_signed_16 (addend)) + { + set_tok_reg (newtok[0], targreg); + set_tok_const (newtok[1], addend); + set_tok_preg (newtok[2], basereg); + assemble_tokens_to_insn ("lda", newtok, 3, &insn); + addend = 0; + } + else + { + set_tok_reg (newtok[0], targreg); + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], basereg); + assemble_tokens_to_insn ("lda", newtok, 3, &insn); + } + } + else + { + if (!range_signed_32 (addend)) + { + link = add_to_link_pool (alpha_evax_proc.symbol, + exp->X_add_symbol, addend); + addend = 0; + } + else + link = add_to_link_pool (alpha_evax_proc.symbol, + exp->X_add_symbol, 0); -void -alpha_frob_file_before_adjust () -{ - if (alpha_debug != 0 - && ! ecoff_debugging_seen) - flag_keep_locals = 1; -} + set_tok_reg (newtok[0], targreg); + set_tok_const (newtok[1], link); + set_tok_preg (newtok[2], basereg); + assemble_tokens_to_insn ("ldq", newtok, 3, &insn); + } +#endif /* OBJ_EVAX */ -#endif /* OBJ_ECOFF */ - -static struct alpha_reloc_tag * -get_alpha_reloc_tag (sequence) - long sequence; -{ - char buffer[ALPHA_RELOC_DIGITS]; - struct alpha_reloc_tag *info; + emit_insn (&insn); - sprintf (buffer, "!%ld", sequence); +#ifndef OBJ_EVAX + if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO) + { + /* Emit "addq r, base, r". */ - info = (struct alpha_reloc_tag *) hash_find (alpha_literal_hash, buffer); - if (! info) - { - size_t len = strlen (buffer); - const char *errmsg; + set_tok_reg (newtok[1], basereg); + set_tok_reg (newtok[2], targreg); + assemble_tokens ("addq", newtok, 3, 0); + } +#endif + basereg = targreg; + } + break; - info = (struct alpha_reloc_tag *) - xcalloc (sizeof (struct alpha_reloc_tag) + len, 1); + case O_constant: + break; - info->segment = now_seg; - info->sequence = sequence; - strcpy (info->string, buffer); - errmsg = hash_insert (alpha_literal_hash, info->string, (PTR) info); - if (errmsg) - as_fatal (errmsg); - } + case O_subtract: + /* Assume that this difference expression will be resolved to an + absolute value and that that value will fit in 16 bits. */ - return info; -} + set_tok_reg (newtok[0], targreg); + newtok[1] = *exp; + set_tok_preg (newtok[2], basereg); + assemble_tokens ("lda", newtok, 3, 0); -/* Before the relocations are written, reorder them, so that user - supplied !lituse relocations follow the appropriate !literal - relocations, and similarly for !gpdisp relocations. */ + if (poffset) + set_tok_const (*poffset, 0); + return 0; -void -alpha_before_fix () -{ - if (alpha_literal_hash) - bfd_map_over_sections (stdoutput, alpha_adjust_relocs, NULL); -} + case O_big: + if (exp->X_add_number > 0) + as_bad (_("bignum invalid; zero assumed")); + else + as_bad (_("floating point number invalid; zero assumed")); + addend = 0; + break; -static void -alpha_adjust_relocs (abfd, sec, ptr) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec; - PTR ptr ATTRIBUTE_UNUSED; -{ - segment_info_type *seginfo = seg_info (sec); - fixS **prevP; - fixS *fixp; - fixS *next; - fixS *slave; - - /* If seginfo is NULL, we did not create this section; don't do - anything with it. By using a pointer to a pointer, we can update - the links in place. */ - if (seginfo == NULL) - return; - - /* If there are no relocations, skip the section. */ - if (! seginfo->fix_root) - return; + default: + as_bad (_("can't handle expression")); + addend = 0; + break; + } - /* First rebuild the fixup chain without the explicit lituse and - gpdisp_lo16 relocs. */ - prevP = &seginfo->fix_root; - for (fixp = seginfo->fix_root; fixp; fixp = next) + if (!range_signed_32 (addend)) { - next = fixp->fx_next; - fixp->fx_next = (fixS *) 0; + offsetT lit; + long seq_num = next_sequence_num--; - switch (fixp->fx_r_type) + /* For 64-bit addends, just put it in the literal pool. */ +#ifdef OBJ_EVAX + /* Emit "ldq targreg, lit(basereg)". */ + lit = add_to_link_pool (alpha_evax_proc.symbol, + section_symbol (absolute_section), addend); + set_tok_reg (newtok[0], targreg); + set_tok_const (newtok[1], lit); + set_tok_preg (newtok[2], alpha_gp_register); + assemble_tokens ("ldq", newtok, 3, 0); +#else + + if (alpha_lit8_section == NULL) { - case BFD_RELOC_ALPHA_LITUSE: - if (fixp->tc_fix_data.info->n_master == 0) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("No !literal!%ld was found"), - fixp->tc_fix_data.info->sequence); -#ifdef RELOC_OP_P - if (fixp->fx_offset == LITUSE_ALPHA_TLSGD) - { - if (! fixp->tc_fix_data.info->saw_tlsgd) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("No !tlsgd!%ld was found"), - fixp->tc_fix_data.info->sequence); - } - else if (fixp->fx_offset == LITUSE_ALPHA_TLSLDM) - { - if (! fixp->tc_fix_data.info->saw_tlsldm) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("No !tlsldm!%ld was found"), - fixp->tc_fix_data.info->sequence); - } + create_literal_section (".lit8", + &alpha_lit8_section, + &alpha_lit8_symbol); + +#ifdef OBJ_ECOFF + alpha_lit8_literal = add_to_literal_pool (alpha_lit8_symbol, 0x8000, + alpha_lita_section, 8); + if (alpha_lit8_literal >= 0x8000) + as_fatal (_("overflow in literal (.lita) table")); #endif - break; + } - case BFD_RELOC_ALPHA_GPDISP_LO16: - if (fixp->tc_fix_data.info->n_master == 0) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("No ldah !gpdisp!%ld was found"), - fixp->tc_fix_data.info->sequence); - break; + lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000; + if (lit >= 0x8000) + as_fatal (_("overflow in literal (.lit8) table")); - case BFD_RELOC_ALPHA_ELF_LITERAL: - if (fixp->tc_fix_data.info - && (fixp->tc_fix_data.info->saw_tlsgd - || fixp->tc_fix_data.info->saw_tlsldm)) - break; - /* FALLTHRU */ + /* Emit "lda litreg, .lit8+0x8000". */ - default: - *prevP = fixp; - prevP = &fixp->fx_next; - break; + if (targreg == basereg) + { + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); + if (targreg == AXP_REG_AT) + as_bad (_("macro requires $at while $at in use")); + + set_tok_reg (newtok[0], AXP_REG_AT); } - } + else + set_tok_reg (newtok[0], targreg); +#ifdef OBJ_ECOFF + set_tok_sym (newtok[1], alpha_lita_symbol, alpha_lit8_literal); +#endif +#ifdef OBJ_ELF + set_tok_sym (newtok[1], alpha_lit8_symbol, 0x8000); +#endif + set_tok_preg (newtok[2], alpha_gp_register); - /* Go back and re-chain dependent relocations. They are currently - linked through the next_reloc field in reverse order, so as we - go through the next_reloc chain, we effectively reverse the chain - once again. + assemble_tokens_to_insn ("ldq", newtok, 3, &insn); - Except if there is more than one !literal for a given sequence - number. In that case, the programmer and/or compiler is not sure - how control flows from literal to lituse, and we can't be sure to - get the relaxation correct. + assert (insn.nfixups == 1); +#ifdef OBJ_ECOFF + insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL; +#endif +#ifdef OBJ_ELF + insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; +#endif + insn.sequence = seq_num; - ??? Well, actually we could, if there are enough lituses such that - we can make each literal have at least one of each lituse type - present. Not implemented. + emit_insn (&insn); - Also suppress the optimization if the !literals/!lituses are spread - in different segments. This can happen with "intersting" uses of - inline assembly; examples are present in the Linux kernel semaphores. */ + /* Emit "ldq litreg, lit(litreg)". */ - for (fixp = seginfo->fix_root; fixp; fixp = next) + set_tok_const (newtok[1], lit); + set_tok_preg (newtok[2], newtok[0].X_add_number); + + assemble_tokens_to_insn ("ldq", newtok, 3, &insn); + + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = seq_num; + emit_lituse = 0; + + emit_insn (&insn); + + /* Emit "addq litreg, base, target". */ + + if (basereg != AXP_REG_ZERO) + { + set_tok_reg (newtok[1], basereg); + set_tok_reg (newtok[2], targreg); + assemble_tokens ("addq", newtok, 3, 0); + } +#endif /* !OBJ_EVAX */ + + if (poffset) + set_tok_const (*poffset, 0); + *pbasereg = targreg; + } + else { - next = fixp->fx_next; - switch (fixp->fx_r_type) + offsetT low, high, extra, tmp; + + /* For 32-bit operands, break up the addend. */ + + low = sign_extend_16 (addend); + tmp = addend - low; + high = sign_extend_16 (tmp >> 16); + + if (tmp - (high << 16)) { - case BFD_RELOC_ALPHA_TLSGD: - case BFD_RELOC_ALPHA_TLSLDM: - if (!fixp->tc_fix_data.info) - break; - if (fixp->tc_fix_data.info->n_master == 0) - break; - else if (fixp->tc_fix_data.info->n_master > 1) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - _("too many !literal!%ld for %s"), - fixp->tc_fix_data.info->sequence, - (fixp->fx_r_type == BFD_RELOC_ALPHA_TLSGD - ? "!tlsgd" : "!tlsldm")); - break; - } + extra = 0x4000; + tmp -= 0x40000000; + high = sign_extend_16 (tmp >> 16); + } + else + extra = 0; - fixp->tc_fix_data.info->master->fx_next = fixp->fx_next; - fixp->fx_next = fixp->tc_fix_data.info->master; - fixp = fixp->fx_next; - /* FALLTHRU */ + set_tok_reg (newtok[0], targreg); + set_tok_preg (newtok[2], basereg); - case BFD_RELOC_ALPHA_ELF_LITERAL: - if (fixp->tc_fix_data.info - && fixp->tc_fix_data.info->n_master == 1 - && ! fixp->tc_fix_data.info->multi_section_p) - { - for (slave = fixp->tc_fix_data.info->slaves; - slave != (fixS *) 0; - slave = slave->tc_fix_data.next_reloc) - { - slave->fx_next = fixp->fx_next; - fixp->fx_next = slave; - } - } - break; + if (extra) + { + /* Emit "ldah r, extra(r). */ + set_tok_const (newtok[1], extra); + assemble_tokens ("ldah", newtok, 3, 0); + set_tok_preg (newtok[2], basereg = targreg); + } - case BFD_RELOC_ALPHA_GPDISP_HI16: - if (fixp->tc_fix_data.info->n_slaves == 0) - as_bad_where (fixp->fx_file, fixp->fx_line, - _("No lda !gpdisp!%ld was found"), - fixp->tc_fix_data.info->sequence); - else - { - slave = fixp->tc_fix_data.info->slaves; - slave->fx_next = next; - fixp->fx_next = slave; - } - break; + if (high) + { + /* Emit "ldah r, high(r). */ + set_tok_const (newtok[1], high); + assemble_tokens ("ldah", newtok, 3, 0); + basereg = targreg; + set_tok_preg (newtok[2], basereg); + } - default: - break; + if ((low && !poffset) || (!poffset && basereg != targreg)) + { + /* Emit "lda r, low(base)". */ + set_tok_const (newtok[1], low); + assemble_tokens ("lda", newtok, 3, 0); + basereg = targreg; + low = 0; } + + if (poffset) + set_tok_const (*poffset, low); + *pbasereg = basereg; } + + return emit_lituse; } - -#ifdef DEBUG_ALPHA -static void -debug_exp (tok, ntok) - expressionS tok[]; - int ntok; -{ - int i; - fprintf (stderr, "debug_exp: %d tokens", ntok); - for (i = 0; i < ntok; i++) - { - expressionS *t = &tok[i]; - const char *name; +/* The lda macro differs from the lda instruction in that it handles + most simple expressions, particularly symbol address loads and + large constants. */ - switch (t->X_op) - { - default: name = "unknown"; break; - case O_illegal: name = "O_illegal"; break; - case O_absent: name = "O_absent"; break; - case O_constant: name = "O_constant"; break; - case O_symbol: name = "O_symbol"; break; - case O_symbol_rva: name = "O_symbol_rva"; break; - case O_register: name = "O_register"; break; - case O_big: name = "O_big"; break; - case O_uminus: name = "O_uminus"; break; - case O_bit_not: name = "O_bit_not"; break; - case O_logical_not: name = "O_logical_not"; break; - case O_multiply: name = "O_multiply"; break; - case O_divide: name = "O_divide"; break; - case O_modulus: name = "O_modulus"; break; - case O_left_shift: name = "O_left_shift"; break; - case O_right_shift: name = "O_right_shift"; break; - case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break; - case O_bit_or_not: name = "O_bit_or_not"; break; - case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break; - case O_bit_and: name = "O_bit_and"; break; - case O_add: name = "O_add"; break; - case O_subtract: name = "O_subtract"; break; - case O_eq: name = "O_eq"; break; - case O_ne: name = "O_ne"; break; - case O_lt: name = "O_lt"; break; - case O_le: name = "O_le"; break; - case O_ge: name = "O_ge"; break; - case O_gt: name = "O_gt"; break; - case O_logical_and: name = "O_logical_and"; break; - case O_logical_or: name = "O_logical_or"; break; - case O_index: name = "O_index"; break; - case O_pregister: name = "O_pregister"; break; - case O_cpregister: name = "O_cpregister"; break; - case O_literal: name = "O_literal"; break; - case O_lituse_addr: name = "O_lituse_addr"; break; - case O_lituse_base: name = "O_lituse_base"; break; - case O_lituse_bytoff: name = "O_lituse_bytoff"; break; - case O_lituse_jsr: name = "O_lituse_jsr"; break; - case O_lituse_tlsgd: name = "O_lituse_tlsgd"; break; - case O_lituse_tlsldm: name = "O_lituse_tlsldm"; break; - case O_gpdisp: name = "O_gpdisp"; break; - case O_gprelhigh: name = "O_gprelhigh"; break; - case O_gprellow: name = "O_gprellow"; break; - case O_gprel: name = "O_gprel"; break; - case O_samegp: name = "O_samegp"; break; - case O_tlsgd: name = "O_tlsgd"; break; - case O_tlsldm: name = "O_tlsldm"; break; - case O_gotdtprel: name = "O_gotdtprel"; break; - case O_dtprelhi: name = "O_dtprelhi"; break; - case O_dtprello: name = "O_dtprello"; break; - case O_dtprel: name = "O_dtprel"; break; - case O_gottprel: name = "O_gottprel"; break; - case O_tprelhi: name = "O_tprelhi"; break; - case O_tprello: name = "O_tprello"; break; - case O_tprel: name = "O_tprel"; break; - } +static void +emit_lda (const expressionS *tok, + int ntok, + const void * unused ATTRIBUTE_UNUSED) +{ + int basereg; - fprintf (stderr, ", %s(%s, %s, %d)", name, - (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--", - (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--", - (int) t->X_add_number); - } - fprintf (stderr, "\n"); - fflush (stderr); + if (ntok == 2) + basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register); + else + basereg = tok[2].X_add_number; + + (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL); } -#endif -/* Parse the arguments to an opcode. */ +/* The ldah macro differs from the ldah instruction in that it has $31 + as an implied base register. */ -static int -tokenize_arguments (str, tok, ntok) - char *str; - expressionS tok[]; - int ntok; +static void +emit_ldah (const expressionS *tok, + int ntok ATTRIBUTE_UNUSED, + const void * unused ATTRIBUTE_UNUSED) { - expressionS *end_tok = tok + ntok; - char *old_input_line_pointer; - int saw_comma = 0, saw_arg = 0; -#ifdef DEBUG_ALPHA - expressionS *orig_tok = tok; -#endif -#ifdef RELOC_OP_P - char *p; - const struct alpha_reloc_op_tag *r; - int c, i; - size_t len; - int reloc_found_p = 0; -#endif - - memset (tok, 0, sizeof (*tok) * ntok); + expressionS newtok[3]; - /* Save and restore input_line_pointer around this function. */ - old_input_line_pointer = input_line_pointer; - input_line_pointer = str; + newtok[0] = tok[0]; + newtok[1] = tok[1]; + set_tok_preg (newtok[2], AXP_REG_ZERO); -#ifdef RELOC_OP_P - /* ??? Wrest control of ! away from the regular expression parser. */ - is_end_of_line[(unsigned char) '!'] = 1; -#endif + assemble_tokens ("ldah", newtok, 3, 0); +} - while (tok < end_tok && *input_line_pointer) - { - SKIP_WHITESPACE (); - switch (*input_line_pointer) - { - case '\0': - goto fini; +/* Called internally to handle all alignment needs. This takes care + of eliding calls to frag_align if'n the cached current alignment + says we've already got it, as well as taking care of the auto-align + feature wrt labels. */ -#ifdef RELOC_OP_P - case '!': - /* A relocation operand can be placed after the normal operand on an - assembly language statement, and has the following form: - !relocation_type!sequence_number. */ - if (reloc_found_p) - { - /* Only support one relocation op per insn. */ - as_bad (_("More than one relocation op per insn")); - goto err_report; - } +static void +alpha_align (int n, + char *pfill, + symbolS *label, + int force ATTRIBUTE_UNUSED) +{ + if (alpha_current_align >= n) + return; - if (!saw_arg) - goto err; + if (pfill == NULL) + { + if (subseg_text_p (now_seg)) + frag_align_code (n, 0); + else + frag_align (n, 0, 0); + } + else + frag_align (n, *pfill, 0); - ++input_line_pointer; - SKIP_WHITESPACE (); - p = input_line_pointer; - c = get_symbol_end (); + alpha_current_align = n; - /* Parse !relocation_type. */ - len = input_line_pointer - p; - if (len == 0) - { - as_bad (_("No relocation operand")); - goto err_report; - } + if (label != NULL && S_GET_SEGMENT (label) == now_seg) + { + symbol_set_frag (label, frag_now); + S_SET_VALUE (label, (valueT) frag_now_fix ()); + } - r = &alpha_reloc_op[0]; - for (i = alpha_num_reloc_op - 1; i >= 0; i--, r++) - if (len == r->length && memcmp (p, r->name, len) == 0) - break; - if (i < 0) - { - as_bad (_("Unknown relocation operand: !%s"), p); - goto err_report; - } + record_alignment (now_seg, n); - *input_line_pointer = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != '!') - { - if (r->require_seq) - { - as_bad (_("no sequence number after !%s"), p); - goto err_report; - } + /* ??? If alpha_flag_relax && force && elf, record the requested alignment + in a reloc for the linker to see. */ +} - tok->X_add_number = 0; - } - else - { - if (! r->allow_seq) - { - as_bad (_("!%s does not use a sequence number"), p); - goto err_report; - } +/* Actually output an instruction with its fixup. */ - input_line_pointer++; +static void +emit_insn (struct alpha_insn *insn) +{ + char *f; + int i; - /* Parse !sequence_number. */ - expression (tok); - if (tok->X_op != O_constant || tok->X_add_number <= 0) - { - as_bad (_("Bad sequence number: !%s!%s"), - r->name, input_line_pointer); - goto err_report; - } - } + /* Take care of alignment duties. */ + if (alpha_auto_align_on && alpha_current_align < 2) + alpha_align (2, (char *) NULL, alpha_insn_label, 0); + if (alpha_current_align > 2) + alpha_current_align = 2; + alpha_insn_label = NULL; - tok->X_op = r->op; - reloc_found_p = 1; - ++tok; - break; -#endif /* RELOC_OP_P */ + /* Write out the instruction. */ + f = frag_more (4); + md_number_to_chars (f, insn->insn, 4); - case ',': - ++input_line_pointer; - if (saw_comma || !saw_arg) - goto err; - saw_comma = 1; - break; +#ifdef OBJ_ELF + dwarf2_emit_insn (4); +#endif - case '(': - { - char *hold = input_line_pointer++; + /* Apply the fixups in order. */ + for (i = 0; i < insn->nfixups; ++i) + { + const struct alpha_operand *operand = (const struct alpha_operand *) 0; + struct alpha_fixup *fixup = &insn->fixups[i]; + struct alpha_reloc_tag *info = NULL; + int size, pcrel; + fixS *fixP; - /* First try for parenthesized register ... */ - expression (tok); - if (*input_line_pointer == ')' && tok->X_op == O_register) - { - tok->X_op = (saw_comma ? O_cpregister : O_pregister); - saw_comma = 0; - saw_arg = 1; - ++input_line_pointer; - ++tok; - break; - } + /* Some fixups are only used internally and so have no howto. */ + if ((int) fixup->reloc < 0) + { + operand = &alpha_operands[-(int) fixup->reloc]; + size = 4; + pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0); + } + else if (fixup->reloc > BFD_RELOC_UNUSED + || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16 + || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16) + { + size = 2; + pcrel = 0; + } + else + { + reloc_howto_type *reloc_howto + = bfd_reloc_type_lookup (stdoutput, fixup->reloc); + assert (reloc_howto); - /* ... then fall through to plain expression. */ - input_line_pointer = hold; - } + size = bfd_get_reloc_size (reloc_howto); + assert (size >= 1 && size <= 4); - default: - if (saw_arg && !saw_comma) - goto err; + pcrel = reloc_howto->pc_relative; + } - expression (tok); - if (tok->X_op == O_illegal || tok->X_op == O_absent) - goto err; + fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size, + &fixup->exp, pcrel, fixup->reloc); - saw_comma = 0; - saw_arg = 1; - ++tok; + /* Turn off complaints that the addend is too large for some fixups, + and copy in the sequence number for the explicit relocations. */ + switch (fixup->reloc) + { + case BFD_RELOC_ALPHA_HINT: + case BFD_RELOC_GPREL32: + case BFD_RELOC_GPREL16: + case BFD_RELOC_ALPHA_GPREL_HI16: + case BFD_RELOC_ALPHA_GPREL_LO16: + case BFD_RELOC_ALPHA_GOTDTPREL16: + case BFD_RELOC_ALPHA_DTPREL_HI16: + case BFD_RELOC_ALPHA_DTPREL_LO16: + case BFD_RELOC_ALPHA_DTPREL16: + case BFD_RELOC_ALPHA_GOTTPREL16: + case BFD_RELOC_ALPHA_TPREL_HI16: + case BFD_RELOC_ALPHA_TPREL_LO16: + case BFD_RELOC_ALPHA_TPREL16: + fixP->fx_no_overflow = 1; break; - } - } -fini: - if (saw_comma) - goto err; - input_line_pointer = old_input_line_pointer; + case BFD_RELOC_ALPHA_GPDISP_HI16: + fixP->fx_no_overflow = 1; + fixP->fx_addsy = section_symbol (now_seg); + fixP->fx_offset = 0; -#ifdef DEBUG_ALPHA - debug_exp (orig_tok, ntok - (end_tok - tok)); -#endif -#ifdef RELOC_OP_P - is_end_of_line[(unsigned char) '!'] = 0; -#endif + info = get_alpha_reloc_tag (insn->sequence); + if (++info->n_master > 1) + as_bad (_("too many ldah insns for !gpdisp!%ld"), insn->sequence); + if (info->segment != now_seg) + as_bad (_("both insns for !gpdisp!%ld must be in the same section"), + insn->sequence); + fixP->tc_fix_data.info = info; + break; - return ntok - (end_tok - tok); + case BFD_RELOC_ALPHA_GPDISP_LO16: + fixP->fx_no_overflow = 1; -err: -#ifdef RELOC_OP_P - is_end_of_line[(unsigned char) '!'] = 0; -#endif - input_line_pointer = old_input_line_pointer; - return TOKENIZE_ERROR; + info = get_alpha_reloc_tag (insn->sequence); + if (++info->n_slaves > 1) + as_bad (_("too many lda insns for !gpdisp!%ld"), insn->sequence); + if (info->segment != now_seg) + as_bad (_("both insns for !gpdisp!%ld must be in the same section"), + insn->sequence); + fixP->tc_fix_data.info = info; + info->slaves = fixP; + break; + + case BFD_RELOC_ALPHA_LITERAL: + case BFD_RELOC_ALPHA_ELF_LITERAL: + fixP->fx_no_overflow = 1; + + if (insn->sequence == 0) + break; + info = get_alpha_reloc_tag (insn->sequence); + info->master = fixP; + info->n_master++; + if (info->segment != now_seg) + info->multi_section_p = 1; + fixP->tc_fix_data.info = info; + break; #ifdef RELOC_OP_P -err_report: - is_end_of_line[(unsigned char) '!'] = 0; + case DUMMY_RELOC_LITUSE_ADDR: + fixP->fx_offset = LITUSE_ALPHA_ADDR; + goto do_lituse; + case DUMMY_RELOC_LITUSE_BASE: + fixP->fx_offset = LITUSE_ALPHA_BASE; + goto do_lituse; + case DUMMY_RELOC_LITUSE_BYTOFF: + fixP->fx_offset = LITUSE_ALPHA_BYTOFF; + goto do_lituse; + case DUMMY_RELOC_LITUSE_JSR: + fixP->fx_offset = LITUSE_ALPHA_JSR; + goto do_lituse; + case DUMMY_RELOC_LITUSE_TLSGD: + fixP->fx_offset = LITUSE_ALPHA_TLSGD; + goto do_lituse; + case DUMMY_RELOC_LITUSE_TLSLDM: + fixP->fx_offset = LITUSE_ALPHA_TLSLDM; + goto do_lituse; + do_lituse: + fixP->fx_addsy = section_symbol (now_seg); + fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE; + + info = get_alpha_reloc_tag (insn->sequence); + if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD) + info->saw_lu_tlsgd = 1; + else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM) + info->saw_lu_tlsldm = 1; + if (++info->n_slaves > 1) + { + if (info->saw_lu_tlsgd) + as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"), + insn->sequence); + else if (info->saw_lu_tlsldm) + as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"), + insn->sequence); + } + fixP->tc_fix_data.info = info; + fixP->tc_fix_data.next_reloc = info->slaves; + info->slaves = fixP; + if (info->segment != now_seg) + info->multi_section_p = 1; + break; + + case BFD_RELOC_ALPHA_TLSGD: + fixP->fx_no_overflow = 1; + + if (insn->sequence == 0) + break; + info = get_alpha_reloc_tag (insn->sequence); + if (info->saw_tlsgd) + as_bad (_("duplicate !tlsgd!%ld"), insn->sequence); + else if (info->saw_tlsldm) + as_bad (_("sequence number in use for !tlsldm!%ld"), + insn->sequence); + else + info->saw_tlsgd = 1; + fixP->tc_fix_data.info = info; + break; + + case BFD_RELOC_ALPHA_TLSLDM: + fixP->fx_no_overflow = 1; + + if (insn->sequence == 0) + break; + info = get_alpha_reloc_tag (insn->sequence); + if (info->saw_tlsldm) + as_bad (_("duplicate !tlsldm!%ld"), insn->sequence); + else if (info->saw_tlsgd) + as_bad (_("sequence number in use for !tlsgd!%ld"), + insn->sequence); + else + info->saw_tlsldm = 1; + fixP->tc_fix_data.info = info; + break; #endif - input_line_pointer = old_input_line_pointer; - return TOKENIZE_ERROR_REPORT; + default: + if ((int) fixup->reloc < 0) + { + if (operand->flags & AXP_OPERAND_NOOVERFLOW) + fixP->fx_no_overflow = 1; + } + break; + } + } } -/* Search forward through all variants of an opcode looking for a - syntax match. */ +/* Insert an operand value into an instruction. */ -static const struct alpha_opcode * -find_opcode_match (first_opcode, tok, pntok, pcpumatch) - const struct alpha_opcode *first_opcode; - const expressionS *tok; - int *pntok; - int *pcpumatch; +static unsigned +insert_operand (unsigned insn, + const struct alpha_operand *operand, + offsetT val, + char *file, + unsigned line) { - const struct alpha_opcode *opcode = first_opcode; - int ntok = *pntok; - int got_cpu_match = 0; - - do + if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW)) { - const unsigned char *opidx; - int tokidx = 0; - - /* Don't match opcodes that don't exist on this architecture. */ - if (!(opcode->flags & alpha_target)) - goto match_failed; - - got_cpu_match = 1; + offsetT min, max; - for (opidx = opcode->operands; *opidx; ++opidx) + if (operand->flags & AXP_OPERAND_SIGNED) { - const struct alpha_operand *operand = &alpha_operands[*opidx]; + max = (1 << (operand->bits - 1)) - 1; + min = -(1 << (operand->bits - 1)); + } + else + { + max = (1 << operand->bits) - 1; + min = 0; + } - /* Only take input from real operands. */ - if (operand->flags & AXP_OPERAND_FAKE) - continue; + if (val < min || val > max) + as_warn_value_out_of_range (_("operand"), val, min, max, file, line); + } - /* When we expect input, make sure we have it. */ - if (tokidx >= ntok) - { - if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0) - goto match_failed; - continue; - } - - /* Match operand type with expression type. */ - switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK) - { - case AXP_OPERAND_IR: - if (tok[tokidx].X_op != O_register - || !is_ir_num (tok[tokidx].X_add_number)) - goto match_failed; - break; - case AXP_OPERAND_FPR: - if (tok[tokidx].X_op != O_register - || !is_fpr_num (tok[tokidx].X_add_number)) - goto match_failed; - break; - case AXP_OPERAND_IR | AXP_OPERAND_PARENS: - if (tok[tokidx].X_op != O_pregister - || !is_ir_num (tok[tokidx].X_add_number)) - goto match_failed; - break; - case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA: - if (tok[tokidx].X_op != O_cpregister - || !is_ir_num (tok[tokidx].X_add_number)) - goto match_failed; - break; - - case AXP_OPERAND_RELATIVE: - case AXP_OPERAND_SIGNED: - case AXP_OPERAND_UNSIGNED: - switch (tok[tokidx].X_op) - { - case O_illegal: - case O_absent: - case O_register: - case O_pregister: - case O_cpregister: - goto match_failed; - - default: - break; - } - break; - - default: - /* Everything else should have been fake. */ - abort (); - } - ++tokidx; - } - - /* Possible match -- did we use all of our input? */ - if (tokidx == ntok) - { - *pntok = ntok; - return opcode; - } - - match_failed:; - } - while (++opcode - alpha_opcodes < (int) alpha_num_opcodes - && !strcmp (opcode->name, first_opcode->name)); - - if (*pcpumatch) - *pcpumatch = got_cpu_match; - - return NULL; -} - -/* Search forward through all variants of a macro looking for a syntax - match. */ - -static const struct alpha_macro * -find_macro_match (first_macro, tok, pntok) - const struct alpha_macro *first_macro; - const expressionS *tok; - int *pntok; -{ - const struct alpha_macro *macro = first_macro; - int ntok = *pntok; - - do - { - const enum alpha_macro_arg *arg = macro->argsets; - int tokidx = 0; - - while (*arg) - { - switch (*arg) - { - case MACRO_EOA: - if (tokidx == ntok) - return macro; - else - tokidx = 0; - break; - - /* Index register. */ - case MACRO_IR: - if (tokidx >= ntok || tok[tokidx].X_op != O_register - || !is_ir_num (tok[tokidx].X_add_number)) - goto match_failed; - ++tokidx; - break; - - /* Parenthesized index register. */ - case MACRO_PIR: - if (tokidx >= ntok || tok[tokidx].X_op != O_pregister - || !is_ir_num (tok[tokidx].X_add_number)) - goto match_failed; - ++tokidx; - break; - - /* Optional parenthesized index register. */ - case MACRO_OPIR: - if (tokidx < ntok && tok[tokidx].X_op == O_pregister - && is_ir_num (tok[tokidx].X_add_number)) - ++tokidx; - break; - - /* Leading comma with a parenthesized index register. */ - case MACRO_CPIR: - if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister - || !is_ir_num (tok[tokidx].X_add_number)) - goto match_failed; - ++tokidx; - break; - - /* Floating point register. */ - case MACRO_FPR: - if (tokidx >= ntok || tok[tokidx].X_op != O_register - || !is_fpr_num (tok[tokidx].X_add_number)) - goto match_failed; - ++tokidx; - break; - - /* Normal expression. */ - case MACRO_EXP: - if (tokidx >= ntok) - goto match_failed; - switch (tok[tokidx].X_op) - { - case O_illegal: - case O_absent: - case O_register: - case O_pregister: - case O_cpregister: - case O_literal: - case O_lituse_base: - case O_lituse_bytoff: - case O_lituse_jsr: - case O_gpdisp: - case O_gprelhigh: - case O_gprellow: - case O_gprel: - case O_samegp: - goto match_failed; - - default: - break; - } - ++tokidx; - break; - - match_failed: - while (*arg != MACRO_EOA) - ++arg; - tokidx = 0; - break; - } - ++arg; - } - } - while (++macro - alpha_macros < (int) alpha_num_macros - && !strcmp (macro->name, first_macro->name)); - - return NULL; -} - -/* Insert an operand value into an instruction. */ - -static unsigned -insert_operand (insn, operand, val, file, line) - unsigned insn; - const struct alpha_operand *operand; - offsetT val; - char *file; - unsigned line; -{ - if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW)) - { - offsetT min, max; - - if (operand->flags & AXP_OPERAND_SIGNED) - { - max = (1 << (operand->bits - 1)) - 1; - min = -(1 << (operand->bits - 1)); - } - else - { - max = (1 << operand->bits) - 1; - min = 0; - } - - if (val < min || val > max) - as_warn_value_out_of_range (_("operand"), val, min, max, file, line); - } - - if (operand->insert) - { - const char *errmsg = NULL; + if (operand->insert) + { + const char *errmsg = NULL; insn = (*operand->insert) (insn, val, &errmsg); if (errmsg) @@ -2370,12 +1834,11 @@ insert_operand (insn, operand, val, file, line) an instruction and a fixup. */ static void -assemble_insn (opcode, tok, ntok, insn, reloc) - const struct alpha_opcode *opcode; - const expressionS *tok; - int ntok; - struct alpha_insn *insn; - bfd_reloc_code_real_type reloc; +assemble_insn (const struct alpha_opcode *opcode, + const expressionS *tok, + int ntok, + struct alpha_insn *insn, + bfd_reloc_code_real_type reloc) { const struct alpha_operand *reloc_operand = NULL; const expressionS *reloc_exp = NULL; @@ -2393,7 +1856,7 @@ assemble_insn (opcode, tok, ntok, insn, reloc) if (operand->flags & AXP_OPERAND_FAKE) { - /* fake operands take no value and generate no fixup */ + /* Fake operands take no value and generate no fixup. */ image = insert_operand (image, operand, 0, NULL, 0); continue; } @@ -2516,939 +1979,702 @@ assemble_insn (opcode, tok, ntok, insn, reloc) insn->insn = image; } -/* Actually output an instruction with its fixup. */ +/* Handle all "simple" integer register loads -- ldq, ldq_l, ldq_u, + etc. They differ from the real instructions in that they do simple + expressions like the lda macro. */ static void -emit_insn (insn) - struct alpha_insn *insn; +emit_ir_load (const expressionS *tok, + int ntok, + const void * opname) { - char *f; - int i; + int basereg; + long lituse; + expressionS newtok[3]; + struct alpha_insn insn; - /* Take care of alignment duties. */ - if (alpha_auto_align_on && alpha_current_align < 2) - alpha_align (2, (char *) NULL, alpha_insn_label, 0); - if (alpha_current_align > 2) - alpha_current_align = 2; - alpha_insn_label = NULL; + if (ntok == 2) + basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register); + else + basereg = tok[2].X_add_number; - /* Write out the instruction. */ - f = frag_more (4); - md_number_to_chars (f, insn->insn, 4); + lituse = load_expression (tok[0].X_add_number, &tok[1], &basereg, + &newtok[1]); -#ifdef OBJ_ELF - dwarf2_emit_insn (4); -#endif + newtok[0] = tok[0]; + set_tok_preg (newtok[2], basereg); - /* Apply the fixups in order. */ - for (i = 0; i < insn->nfixups; ++i) + assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); + + if (lituse) { - const struct alpha_operand *operand = (const struct alpha_operand *) 0; - struct alpha_fixup *fixup = &insn->fixups[i]; - struct alpha_reloc_tag *info = NULL; - int size, pcrel; - fixS *fixP; + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; + } - /* Some fixups are only used internally and so have no howto. */ - if ((int) fixup->reloc < 0) - { - operand = &alpha_operands[-(int) fixup->reloc]; - size = 4; - pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0); - } - else if (fixup->reloc > BFD_RELOC_UNUSED - || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16 - || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16) - { - size = 2; - pcrel = 0; - } - else - { - reloc_howto_type *reloc_howto - = bfd_reloc_type_lookup (stdoutput, fixup->reloc); - assert (reloc_howto); + emit_insn (&insn); +} - size = bfd_get_reloc_size (reloc_howto); - assert (size >= 1 && size <= 4); +/* Handle fp register loads, and both integer and fp register stores. + Again, we handle simple expressions. */ - pcrel = reloc_howto->pc_relative; - } +static void +emit_loadstore (const expressionS *tok, + int ntok, + const void * opname) +{ + int basereg; + long lituse; + expressionS newtok[3]; + struct alpha_insn insn; - fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size, - &fixup->exp, pcrel, fixup->reloc); + if (ntok == 2) + basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register); + else + basereg = tok[2].X_add_number; - /* Turn off complaints that the addend is too large for some fixups, - and copy in the sequence number for the explicit relocations. */ - switch (fixup->reloc) - { - case BFD_RELOC_ALPHA_HINT: - case BFD_RELOC_GPREL32: - case BFD_RELOC_GPREL16: - case BFD_RELOC_ALPHA_GPREL_HI16: - case BFD_RELOC_ALPHA_GPREL_LO16: - case BFD_RELOC_ALPHA_GOTDTPREL16: - case BFD_RELOC_ALPHA_DTPREL_HI16: - case BFD_RELOC_ALPHA_DTPREL_LO16: - case BFD_RELOC_ALPHA_DTPREL16: - case BFD_RELOC_ALPHA_GOTTPREL16: - case BFD_RELOC_ALPHA_TPREL_HI16: - case BFD_RELOC_ALPHA_TPREL_LO16: - case BFD_RELOC_ALPHA_TPREL16: - fixP->fx_no_overflow = 1; - break; + if (tok[1].X_op != O_constant || !range_signed_16 (tok[1].X_add_number)) + { + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); - case BFD_RELOC_ALPHA_GPDISP_HI16: - fixP->fx_no_overflow = 1; - fixP->fx_addsy = section_symbol (now_seg); - fixP->fx_offset = 0; + lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]); + } + else + { + newtok[1] = tok[1]; + lituse = 0; + } - info = get_alpha_reloc_tag (insn->sequence); - if (++info->n_master > 1) - as_bad (_("too many ldah insns for !gpdisp!%ld"), insn->sequence); - if (info->segment != now_seg) - as_bad (_("both insns for !gpdisp!%ld must be in the same section"), - insn->sequence); - fixP->tc_fix_data.info = info; - break; + newtok[0] = tok[0]; + set_tok_preg (newtok[2], basereg); - case BFD_RELOC_ALPHA_GPDISP_LO16: - fixP->fx_no_overflow = 1; + assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); - info = get_alpha_reloc_tag (insn->sequence); - if (++info->n_slaves > 1) - as_bad (_("too many lda insns for !gpdisp!%ld"), insn->sequence); - if (info->segment != now_seg) - as_bad (_("both insns for !gpdisp!%ld must be in the same section"), - insn->sequence); - fixP->tc_fix_data.info = info; - info->slaves = fixP; - break; + if (lituse) + { + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; + } - case BFD_RELOC_ALPHA_LITERAL: - case BFD_RELOC_ALPHA_ELF_LITERAL: - fixP->fx_no_overflow = 1; + emit_insn (&insn); +} - if (insn->sequence == 0) - break; - info = get_alpha_reloc_tag (insn->sequence); - info->master = fixP; - info->n_master++; - if (info->segment != now_seg) - info->multi_section_p = 1; - fixP->tc_fix_data.info = info; - break; +/* Load a half-word or byte as an unsigned value. */ -#ifdef RELOC_OP_P - case DUMMY_RELOC_LITUSE_ADDR: - fixP->fx_offset = LITUSE_ALPHA_ADDR; - goto do_lituse; - case DUMMY_RELOC_LITUSE_BASE: - fixP->fx_offset = LITUSE_ALPHA_BASE; - goto do_lituse; - case DUMMY_RELOC_LITUSE_BYTOFF: - fixP->fx_offset = LITUSE_ALPHA_BYTOFF; - goto do_lituse; - case DUMMY_RELOC_LITUSE_JSR: - fixP->fx_offset = LITUSE_ALPHA_JSR; - goto do_lituse; - case DUMMY_RELOC_LITUSE_TLSGD: - fixP->fx_offset = LITUSE_ALPHA_TLSGD; - goto do_lituse; - case DUMMY_RELOC_LITUSE_TLSLDM: - fixP->fx_offset = LITUSE_ALPHA_TLSLDM; - goto do_lituse; - do_lituse: - fixP->fx_addsy = section_symbol (now_seg); - fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE; +static void +emit_ldXu (const expressionS *tok, + int ntok, + const void * vlgsize) +{ + if (alpha_target & AXP_OPCODE_BWX) + emit_ir_load (tok, ntok, ldXu_op[(long) vlgsize]); + else + { + expressionS newtok[3]; + struct alpha_insn insn; + int basereg; + long lituse; - info = get_alpha_reloc_tag (insn->sequence); - if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD) - info->saw_lu_tlsgd = 1; - else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM) - info->saw_lu_tlsldm = 1; - if (++info->n_slaves > 1) - { - if (info->saw_lu_tlsgd) - as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"), - insn->sequence); - else if (info->saw_lu_tlsldm) - as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"), - insn->sequence); - } - fixP->tc_fix_data.info = info; - fixP->tc_fix_data.next_reloc = info->slaves; - info->slaves = fixP; - if (info->segment != now_seg) - info->multi_section_p = 1; - break; + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); - case BFD_RELOC_ALPHA_TLSGD: - fixP->fx_no_overflow = 1; + if (ntok == 2) + basereg = (tok[1].X_op == O_constant + ? AXP_REG_ZERO : alpha_gp_register); + else + basereg = tok[2].X_add_number; - if (insn->sequence == 0) - break; - info = get_alpha_reloc_tag (insn->sequence); - if (info->saw_tlsgd) - as_bad (_("duplicate !tlsgd!%ld"), insn->sequence); - else if (info->saw_tlsldm) - as_bad (_("sequence number in use for !tlsldm!%ld"), - insn->sequence); - else - info->saw_tlsgd = 1; - fixP->tc_fix_data.info = info; - break; + /* Emit "lda $at, exp". */ + lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL); - case BFD_RELOC_ALPHA_TLSLDM: - fixP->fx_no_overflow = 1; + /* Emit "ldq_u targ, 0($at)". */ + newtok[0] = tok[0]; + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], basereg); + assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn); - if (insn->sequence == 0) - break; - info = get_alpha_reloc_tag (insn->sequence); - if (info->saw_tlsldm) - as_bad (_("duplicate !tlsldm!%ld"), insn->sequence); - else if (info->saw_tlsgd) - as_bad (_("sequence number in use for !tlsgd!%ld"), - insn->sequence); - else - info->saw_tlsldm = 1; - fixP->tc_fix_data.info = info; - break; -#endif - default: - if ((int) fixup->reloc < 0) - { - if (operand->flags & AXP_OPERAND_NOOVERFLOW) - fixP->fx_no_overflow = 1; - } - break; + if (lituse) + { + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; } - } -} - -/* Given an opcode name and a pre-tokenized set of arguments, assemble - the insn, but do not emit it. - Note that this implies no macros allowed, since we can't store more - than one insn in an insn structure. */ + emit_insn (&insn); -static void -assemble_tokens_to_insn (opname, tok, ntok, insn) - const char *opname; - const expressionS *tok; - int ntok; - struct alpha_insn *insn; -{ - const struct alpha_opcode *opcode; + /* Emit "extXl targ, $at, targ". */ + set_tok_reg (newtok[1], basereg); + newtok[2] = newtok[0]; + assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn); - /* search opcodes */ - opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname); - if (opcode) - { - int cpumatch; - opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); - if (opcode) + if (lituse) { - assemble_insn (opcode, tok, ntok, insn, BFD_RELOC_UNUSED); - return; + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; } - else if (cpumatch) - as_bad (_("inappropriate arguments for opcode `%s'"), opname); - else - as_bad (_("opcode `%s' not supported for target %s"), opname, - alpha_target_name); + + emit_insn (&insn); } - else - as_bad (_("unknown opcode `%s'"), opname); } -/* Given an opcode name and a pre-tokenized set of arguments, take the - opcode all the way through emission. */ +/* Load a half-word or byte as a signed value. */ static void -assemble_tokens (opname, tok, ntok, local_macros_on) - const char *opname; - const expressionS *tok; - int ntok; - int local_macros_on; +emit_ldX (const expressionS *tok, + int ntok, + const void * vlgsize) { - int found_something = 0; - const struct alpha_opcode *opcode; - const struct alpha_macro *macro; - int cpumatch = 1; - bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED; + emit_ldXu (tok, ntok, vlgsize); + assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); +} -#ifdef RELOC_OP_P - /* If a user-specified relocation is present, this is not a macro. */ - if (ntok && USER_RELOC_P (tok[ntok - 1].X_op)) - { - reloc = ALPHA_RELOC_TABLE (tok[ntok - 1].X_op)->reloc; - ntok--; - } - else -#endif - if (local_macros_on) - { - macro = ((const struct alpha_macro *) - hash_find (alpha_macro_hash, opname)); - if (macro) - { - found_something = 1; - macro = find_macro_match (macro, tok, &ntok); - if (macro) - { - (*macro->emit) (tok, ntok, macro->arg); - return; - } - } - } - - /* Search opcodes. */ - opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname); - if (opcode) - { - found_something = 1; - opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); - if (opcode) - { - struct alpha_insn insn; - assemble_insn (opcode, tok, ntok, &insn, reloc); - - /* Copy the sequence number for the reloc from the reloc token. */ - if (reloc != BFD_RELOC_UNUSED) - insn.sequence = tok[ntok].X_add_number; - - emit_insn (&insn); - return; - } - } - - if (found_something) - { - if (cpumatch) - as_bad (_("inappropriate arguments for opcode `%s'"), opname); - else - as_bad (_("opcode `%s' not supported for target %s"), opname, - alpha_target_name); - } - else - as_bad (_("unknown opcode `%s'"), opname); -} - -/* Some instruction sets indexed by lg(size). */ -static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL }; -static const char * const insXl_op[] = { "insbl", "inswl", "insll", "insql" }; -static const char * const insXh_op[] = { NULL, "inswh", "inslh", "insqh" }; -static const char * const extXl_op[] = { "extbl", "extwl", "extll", "extql" }; -static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" }; -static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" }; -static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" }; -static const char * const stX_op[] = { "stb", "stw", "stl", "stq" }; -static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL }; - -/* Implement the ldgp macro. */ +/* Load an integral value from an unaligned address as an unsigned + value. */ static void -emit_ldgp (tok, ntok, unused) - const expressionS *tok; - int ntok ATTRIBUTE_UNUSED; - const PTR unused ATTRIBUTE_UNUSED; +emit_uldXu (const expressionS *tok, + int ntok, + const void * vlgsize) { -#ifdef OBJ_AOUT -FIXME -#endif -#if defined(OBJ_ECOFF) || defined(OBJ_ELF) - /* from "ldgp r1,n(r2)", generate "ldah r1,X(R2); lda r1,Y(r1)" - with appropriate constants and relocations. */ - struct alpha_insn insn; + long lgsize = (long) vlgsize; expressionS newtok[3]; - expressionS addend; -#ifdef OBJ_ECOFF - if (regno (tok[2].X_add_number) == AXP_REG_PV) - ecoff_set_gp_prolog_size (0); -#endif + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); - newtok[0] = tok[0]; + /* Emit "lda $at, exp". */ + memcpy (newtok, tok, sizeof (expressionS) * ntok); + newtok[0].X_add_number = AXP_REG_AT; + assemble_tokens ("lda", newtok, ntok, 1); + + /* Emit "ldq_u $t9, 0($at)". */ + set_tok_reg (newtok[0], AXP_REG_T9); set_tok_const (newtok[1], 0); - newtok[2] = tok[2]; + set_tok_preg (newtok[2], AXP_REG_AT); + assemble_tokens ("ldq_u", newtok, 3, 1); - assemble_tokens_to_insn ("ldah", newtok, 3, &insn); + /* Emit "ldq_u $t10, size-1($at)". */ + set_tok_reg (newtok[0], AXP_REG_T10); + set_tok_const (newtok[1], (1 << lgsize) - 1); + assemble_tokens ("ldq_u", newtok, 3, 1); - addend = tok[1]; + /* Emit "extXl $t9, $at, $t9". */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_reg (newtok[1], AXP_REG_AT); + set_tok_reg (newtok[2], AXP_REG_T9); + assemble_tokens (extXl_op[lgsize], newtok, 3, 1); -#ifdef OBJ_ECOFF - if (addend.X_op != O_constant) - as_bad (_("can not resolve expression")); - addend.X_op = O_symbol; - addend.X_add_symbol = alpha_gp_symbol; -#endif + /* Emit "extXh $t10, $at, $t10". */ + set_tok_reg (newtok[0], AXP_REG_T10); + set_tok_reg (newtok[2], AXP_REG_T10); + assemble_tokens (extXh_op[lgsize], newtok, 3, 1); - insn.nfixups = 1; - insn.fixups[0].exp = addend; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16; - insn.sequence = next_sequence_num; + /* Emit "or $t9, $t10, targ". */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_reg (newtok[1], AXP_REG_T10); + newtok[2] = tok[0]; + assemble_tokens ("or", newtok, 3, 1); +} - emit_insn (&insn); +/* Load an integral value from an unaligned address as a signed value. + Note that quads should get funneled to the unsigned load since we + don't have to do the sign extension. */ - set_tok_preg (newtok[2], tok[0].X_add_number); +static void +emit_uldX (const expressionS *tok, + int ntok, + const void * vlgsize) +{ + emit_uldXu (tok, ntok, vlgsize); + assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); +} - assemble_tokens_to_insn ("lda", newtok, 3, &insn); +/* Implement the ldil macro. */ -#ifdef OBJ_ECOFF - addend.X_add_number += 4; -#endif +static void +emit_ldil (const expressionS *tok, + int ntok, + const void * unused ATTRIBUTE_UNUSED) +{ + expressionS newtok[2]; - insn.nfixups = 1; - insn.fixups[0].exp = addend; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16; - insn.sequence = next_sequence_num--; + memcpy (newtok, tok, sizeof (newtok)); + newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number); - emit_insn (&insn); -#endif /* OBJ_ECOFF || OBJ_ELF */ + assemble_tokens ("lda", newtok, ntok, 1); } -#ifdef OBJ_EVAX - -/* Add symbol+addend to link pool. - Return offset from basesym to entry in link pool. - - Add new fixup only if offset isn't 16bit. */ +/* Store a half-word or byte. */ -valueT -add_to_link_pool (basesym, sym, addend) - symbolS *basesym; - symbolS *sym; - offsetT addend; +static void +emit_stX (const expressionS *tok, + int ntok, + const void * vlgsize) { - segT current_section = now_seg; - int current_subsec = now_subseg; - valueT offset; - bfd_reloc_code_real_type reloc_type; - char *p; - segment_info_type *seginfo = seg_info (alpha_link_section); - fixS *fixp; - - offset = - *symbol_get_obj (basesym); + int lgsize = (int) (long) vlgsize; - /* @@ This assumes all entries in a given section will be of the same - size... Probably correct, but unwise to rely on. */ - /* This must always be called with the same subsegment. */ + if (alpha_target & AXP_OPCODE_BWX) + emit_loadstore (tok, ntok, stX_op[lgsize]); + else + { + expressionS newtok[3]; + struct alpha_insn insn; + int basereg; + long lituse; - if (seginfo->frchainP) - for (fixp = seginfo->frchainP->fix_root; - fixp != (fixS *) NULL; - fixp = fixp->fx_next, offset += 8) - { - if (fixp->fx_addsy == sym && fixp->fx_offset == addend) - { - if (range_signed_16 (offset)) - { - return offset; - } - } - } + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); - /* Not found in 16bit signed range. */ + if (ntok == 2) + basereg = (tok[1].X_op == O_constant + ? AXP_REG_ZERO : alpha_gp_register); + else + basereg = tok[2].X_add_number; - subseg_set (alpha_link_section, 0); - p = frag_more (8); - memset (p, 0, 8); + /* Emit "lda $at, exp". */ + lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL); - fix_new (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0, - BFD_RELOC_64); + /* Emit "ldq_u $t9, 0($at)". */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], basereg); + assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn); - subseg_set (current_section, current_subsec); - seginfo->literal_pool_size += 8; - return offset; -} + if (lituse) + { + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; + } -#endif /* OBJ_EVAX */ + emit_insn (&insn); -/* Load a (partial) expression into a target register. + /* Emit "insXl src, $at, $t10". */ + newtok[0] = tok[0]; + set_tok_reg (newtok[1], basereg); + set_tok_reg (newtok[2], AXP_REG_T10); + assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn); - If poffset is not null, after the call it will either contain - O_constant 0, or a 16-bit offset appropriate for any MEM format - instruction. In addition, pbasereg will be modified to point to - the base register to use in that MEM format instruction. + if (lituse) + { + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; + } - In any case, *pbasereg should contain a base register to add to the - expression. This will normally be either AXP_REG_ZERO or - alpha_gp_register. Symbol addresses will always be loaded via $gp, - so "foo($0)" is interpreted as adding the address of foo to $0; - i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps, - but this is what OSF/1 does. + emit_insn (&insn); - If explicit relocations of the form !literal! are allowed, - and used, then explicit_reloc with be an expression pointer. + /* Emit "mskXl $t9, $at, $t9". */ + set_tok_reg (newtok[0], AXP_REG_T9); + newtok[2] = newtok[0]; + assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn); - Finally, the return value is nonzero if the calling macro may emit - a LITUSE reloc if otherwise appropriate; the return value is the - sequence number to use. */ - -static long -load_expression (targreg, exp, pbasereg, poffset) - int targreg; - const expressionS *exp; - int *pbasereg; - expressionS *poffset; -{ - long emit_lituse = 0; - offsetT addend = exp->X_add_number; - int basereg = *pbasereg; - struct alpha_insn insn; - expressionS newtok[3]; - - switch (exp->X_op) - { - case O_symbol: - { -#ifdef OBJ_ECOFF - offsetT lit; - - /* Attempt to reduce .lit load by splitting the offset from - its symbol when possible, but don't create a situation in - which we'd fail. */ - if (!range_signed_32 (addend) && - (alpha_noat_on || targreg == AXP_REG_AT)) - { - lit = add_to_literal_pool (exp->X_add_symbol, addend, - alpha_lita_section, 8); - addend = 0; - } - else - { - lit = add_to_literal_pool (exp->X_add_symbol, 0, - alpha_lita_section, 8); - } - - if (lit >= 0x8000) - as_fatal (_("overflow in literal (.lita) table")); + if (lituse) + { + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; + } - /* emit "ldq r, lit(gp)" */ + emit_insn (&insn); - if (basereg != alpha_gp_register && targreg == basereg) - { - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); - if (targreg == AXP_REG_AT) - as_bad (_("macro requires $at while $at in use")); + /* Emit "or $t9, $t10, $t9". */ + set_tok_reg (newtok[1], AXP_REG_T10); + assemble_tokens ("or", newtok, 3, 1); - set_tok_reg (newtok[0], AXP_REG_AT); - } - else - set_tok_reg (newtok[0], targreg); - set_tok_sym (newtok[1], alpha_lita_symbol, lit); - set_tok_preg (newtok[2], alpha_gp_register); + /* Emit "stq_u $t9, 0($at). */ + set_tok_const(newtok[1], 0); + set_tok_preg (newtok[2], AXP_REG_AT); + assemble_tokens_to_insn ("stq_u", newtok, 3, &insn); - assemble_tokens_to_insn ("ldq", newtok, 3, &insn); + if (lituse) + { + assert (insn.nfixups < MAX_INSN_FIXUPS); + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; + insn.fixups[insn.nfixups].exp.X_op = O_absent; + insn.nfixups++; + insn.sequence = lituse; + } - assert (insn.nfixups == 1); - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL; - insn.sequence = emit_lituse = next_sequence_num--; -#endif /* OBJ_ECOFF */ -#ifdef OBJ_ELF - /* emit "ldq r, gotoff(gp)" */ + emit_insn (&insn); + } +} - if (basereg != alpha_gp_register && targreg == basereg) - { - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); - if (targreg == AXP_REG_AT) - as_bad (_("macro requires $at while $at in use")); +/* Store an integer to an unaligned address. */ - set_tok_reg (newtok[0], AXP_REG_AT); - } - else - set_tok_reg (newtok[0], targreg); +static void +emit_ustX (const expressionS *tok, + int ntok, + const void * vlgsize) +{ + int lgsize = (int) (long) vlgsize; + expressionS newtok[3]; - /* XXX: Disable this .got minimizing optimization so that we can get - better instruction offset knowledge in the compiler. This happens - very infrequently anyway. */ - if (1 - || (!range_signed_32 (addend) - && (alpha_noat_on || targreg == AXP_REG_AT))) - { - newtok[1] = *exp; - addend = 0; - } - else - { - set_tok_sym (newtok[1], exp->X_add_symbol, 0); - } + /* Emit "lda $at, exp". */ + memcpy (newtok, tok, sizeof (expressionS) * ntok); + newtok[0].X_add_number = AXP_REG_AT; + assemble_tokens ("lda", newtok, ntok, 1); - set_tok_preg (newtok[2], alpha_gp_register); + /* Emit "ldq_u $9, 0($at)". */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], AXP_REG_AT); + assemble_tokens ("ldq_u", newtok, 3, 1); - assemble_tokens_to_insn ("ldq", newtok, 3, &insn); + /* Emit "ldq_u $10, size-1($at)". */ + set_tok_reg (newtok[0], AXP_REG_T10); + set_tok_const (newtok[1], (1 << lgsize) - 1); + assemble_tokens ("ldq_u", newtok, 3, 1); - assert (insn.nfixups == 1); - insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; - insn.sequence = emit_lituse = next_sequence_num--; -#endif /* OBJ_ELF */ -#ifdef OBJ_EVAX - offsetT link; + /* Emit "insXl src, $at, $t11". */ + newtok[0] = tok[0]; + set_tok_reg (newtok[1], AXP_REG_AT); + set_tok_reg (newtok[2], AXP_REG_T11); + assemble_tokens (insXl_op[lgsize], newtok, 3, 1); - /* Find symbol or symbol pointer in link section. */ + /* Emit "insXh src, $at, $t12". */ + set_tok_reg (newtok[2], AXP_REG_T12); + assemble_tokens (insXh_op[lgsize], newtok, 3, 1); - if (exp->X_add_symbol == alpha_evax_proc.symbol) - { - if (range_signed_16 (addend)) - { - set_tok_reg (newtok[0], targreg); - set_tok_const (newtok[1], addend); - set_tok_preg (newtok[2], basereg); - assemble_tokens_to_insn ("lda", newtok, 3, &insn); - addend = 0; - } - else - { - set_tok_reg (newtok[0], targreg); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], basereg); - assemble_tokens_to_insn ("lda", newtok, 3, &insn); - } - } - else - { - if (!range_signed_32 (addend)) - { - link = add_to_link_pool (alpha_evax_proc.symbol, - exp->X_add_symbol, addend); - addend = 0; - } - else - { - link = add_to_link_pool (alpha_evax_proc.symbol, - exp->X_add_symbol, 0); - } - set_tok_reg (newtok[0], targreg); - set_tok_const (newtok[1], link); - set_tok_preg (newtok[2], basereg); - assemble_tokens_to_insn ("ldq", newtok, 3, &insn); - } -#endif /* OBJ_EVAX */ + /* Emit "mskXl $t9, $at, $t9". */ + set_tok_reg (newtok[0], AXP_REG_T9); + newtok[2] = newtok[0]; + assemble_tokens (mskXl_op[lgsize], newtok, 3, 1); - emit_insn (&insn); + /* Emit "mskXh $t10, $at, $t10". */ + set_tok_reg (newtok[0], AXP_REG_T10); + newtok[2] = newtok[0]; + assemble_tokens (mskXh_op[lgsize], newtok, 3, 1); -#ifndef OBJ_EVAX - if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO) - { - /* emit "addq r, base, r" */ + /* Emit "or $t9, $t11, $t9". */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_reg (newtok[1], AXP_REG_T11); + newtok[2] = newtok[0]; + assemble_tokens ("or", newtok, 3, 1); - set_tok_reg (newtok[1], basereg); - set_tok_reg (newtok[2], targreg); - assemble_tokens ("addq", newtok, 3, 0); - } -#endif + /* Emit "or $t10, $t12, $t10". */ + set_tok_reg (newtok[0], AXP_REG_T10); + set_tok_reg (newtok[1], AXP_REG_T12); + newtok[2] = newtok[0]; + assemble_tokens ("or", newtok, 3, 1); - basereg = targreg; - } - break; + /* Emit "stq_u $t9, 0($at)". */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], AXP_REG_AT); + assemble_tokens ("stq_u", newtok, 3, 1); - case O_constant: - break; + /* Emit "stq_u $t10, size-1($at)". */ + set_tok_reg (newtok[0], AXP_REG_T10); + set_tok_const (newtok[1], (1 << lgsize) - 1); + assemble_tokens ("stq_u", newtok, 3, 1); +} - case O_subtract: - /* Assume that this difference expression will be resolved to an - absolute value and that that value will fit in 16 bits. */ +/* Sign extend a half-word or byte. The 32-bit sign extend is + implemented as "addl $31, $r, $t" in the opcode table. */ - set_tok_reg (newtok[0], targreg); - newtok[1] = *exp; - set_tok_preg (newtok[2], basereg); - assemble_tokens ("lda", newtok, 3, 0); +static void +emit_sextX (const expressionS *tok, + int ntok, + const void * vlgsize) +{ + long lgsize = (long) vlgsize; - if (poffset) - set_tok_const (*poffset, 0); - return 0; + if (alpha_target & AXP_OPCODE_BWX) + assemble_tokens (sextX_op[lgsize], tok, ntok, 0); + else + { + int bitshift = 64 - 8 * (1 << lgsize); + expressionS newtok[3]; - case O_big: - if (exp->X_add_number > 0) - as_bad (_("bignum invalid; zero assumed")); - else - as_bad (_("floating point number invalid; zero assumed")); - addend = 0; - break; + /* Emit "sll src,bits,dst". */ + newtok[0] = tok[0]; + set_tok_const (newtok[1], bitshift); + newtok[2] = tok[ntok - 1]; + assemble_tokens ("sll", newtok, 3, 1); - default: - as_bad (_("can't handle expression")); - addend = 0; - break; + /* Emit "sra dst,bits,dst". */ + newtok[0] = newtok[2]; + assemble_tokens ("sra", newtok, 3, 1); } +} - if (!range_signed_32 (addend)) - { - offsetT lit; - long seq_num = next_sequence_num--; - - /* For 64-bit addends, just put it in the literal pool. */ +/* Implement the division and modulus macros. */ #ifdef OBJ_EVAX - /* emit "ldq targreg, lit(basereg)" */ - lit = add_to_link_pool (alpha_evax_proc.symbol, - section_symbol (absolute_section), addend); - set_tok_reg (newtok[0], targreg); - set_tok_const (newtok[1], lit); - set_tok_preg (newtok[2], alpha_gp_register); - assemble_tokens ("ldq", newtok, 3, 0); -#else - if (alpha_lit8_section == NULL) - { - create_literal_section (".lit8", - &alpha_lit8_section, - &alpha_lit8_symbol); - -#ifdef OBJ_ECOFF - alpha_lit8_literal = add_to_literal_pool (alpha_lit8_symbol, 0x8000, - alpha_lita_section, 8); - if (alpha_lit8_literal >= 0x8000) - as_fatal (_("overflow in literal (.lita) table")); -#endif - } - - lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000; - if (lit >= 0x8000) - as_fatal (_("overflow in literal (.lit8) table")); - - /* emit "lda litreg, .lit8+0x8000" */ - - if (targreg == basereg) - { - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); - if (targreg == AXP_REG_AT) - as_bad (_("macro requires $at while $at in use")); - - set_tok_reg (newtok[0], AXP_REG_AT); - } - else - set_tok_reg (newtok[0], targreg); -#ifdef OBJ_ECOFF - set_tok_sym (newtok[1], alpha_lita_symbol, alpha_lit8_literal); -#endif -#ifdef OBJ_ELF - set_tok_sym (newtok[1], alpha_lit8_symbol, 0x8000); -#endif - set_tok_preg (newtok[2], alpha_gp_register); - - assemble_tokens_to_insn ("ldq", newtok, 3, &insn); +/* Make register usage like in normal procedure call. + Don't clobber PV and RA. */ - assert (insn.nfixups == 1); -#ifdef OBJ_ECOFF - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL; -#endif -#ifdef OBJ_ELF - insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; -#endif - insn.sequence = seq_num; +static void +emit_division (const expressionS *tok, + int ntok, + const void * symname) +{ + /* DIVISION and MODULUS. Yech. - emit_insn (&insn); + Convert + OP x,y,result + to + mov x,R16 # if x != R16 + mov y,R17 # if y != R17 + lda AT,__OP + jsr AT,(AT),0 + mov R0,result - /* emit "ldq litreg, lit(litreg)" */ + with appropriate optimizations if R0,R16,R17 are the registers + specified by the compiler. */ - set_tok_const (newtok[1], lit); - set_tok_preg (newtok[2], newtok[0].X_add_number); + int xr, yr, rr; + symbolS *sym; + expressionS newtok[3]; - assemble_tokens_to_insn ("ldq", newtok, 3, &insn); + xr = regno (tok[0].X_add_number); + yr = regno (tok[1].X_add_number); - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = seq_num; - emit_lituse = 0; + if (ntok < 3) + rr = xr; + else + rr = regno (tok[2].X_add_number); - emit_insn (&insn); + /* Move the operands into the right place. */ + if (yr == AXP_REG_R16 && xr == AXP_REG_R17) + { + /* They are in exactly the wrong order -- swap through AT. */ + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); - /* emit "addq litreg, base, target" */ + set_tok_reg (newtok[0], AXP_REG_R16); + set_tok_reg (newtok[1], AXP_REG_AT); + assemble_tokens ("mov", newtok, 2, 1); - if (basereg != AXP_REG_ZERO) - { - set_tok_reg (newtok[1], basereg); - set_tok_reg (newtok[2], targreg); - assemble_tokens ("addq", newtok, 3, 0); - } -#endif /* !OBJ_EVAX */ + set_tok_reg (newtok[0], AXP_REG_R17); + set_tok_reg (newtok[1], AXP_REG_R16); + assemble_tokens ("mov", newtok, 2, 1); - if (poffset) - set_tok_const (*poffset, 0); - *pbasereg = targreg; + set_tok_reg (newtok[0], AXP_REG_AT); + set_tok_reg (newtok[1], AXP_REG_R17); + assemble_tokens ("mov", newtok, 2, 1); } else { - offsetT low, high, extra, tmp; - - /* for 32-bit operands, break up the addend */ - - low = sign_extend_16 (addend); - tmp = addend - low; - high = sign_extend_16 (tmp >> 16); - - if (tmp - (high << 16)) - { - extra = 0x4000; - tmp -= 0x40000000; - high = sign_extend_16 (tmp >> 16); - } - else - extra = 0; - - set_tok_reg (newtok[0], targreg); - set_tok_preg (newtok[2], basereg); - - if (extra) + if (yr == AXP_REG_R16) { - /* emit "ldah r, extra(r) */ - set_tok_const (newtok[1], extra); - assemble_tokens ("ldah", newtok, 3, 0); - set_tok_preg (newtok[2], basereg = targreg); + set_tok_reg (newtok[0], AXP_REG_R16); + set_tok_reg (newtok[1], AXP_REG_R17); + assemble_tokens ("mov", newtok, 2, 1); } - if (high) + if (xr != AXP_REG_R16) { - /* emit "ldah r, high(r) */ - set_tok_const (newtok[1], high); - assemble_tokens ("ldah", newtok, 3, 0); - basereg = targreg; - set_tok_preg (newtok[2], basereg); + set_tok_reg (newtok[0], xr); + set_tok_reg (newtok[1], AXP_REG_R16); + assemble_tokens ("mov", newtok, 2, 1); } - if ((low && !poffset) || (!poffset && basereg != targreg)) + if (yr != AXP_REG_R16 && yr != AXP_REG_R17) { - /* emit "lda r, low(base)" */ - set_tok_const (newtok[1], low); - assemble_tokens ("lda", newtok, 3, 0); - basereg = targreg; - low = 0; + set_tok_reg (newtok[0], yr); + set_tok_reg (newtok[1], AXP_REG_R17); + assemble_tokens ("mov", newtok, 2, 1); } - - if (poffset) - set_tok_const (*poffset, low); - *pbasereg = basereg; } - return emit_lituse; -} - -/* The lda macro differs from the lda instruction in that it handles - most simple expressions, particularly symbol address loads and - large constants. */ + sym = symbol_find_or_make ((const char *) symname); -static void -emit_lda (tok, ntok, unused) - const expressionS *tok; - int ntok; - const PTR unused ATTRIBUTE_UNUSED; -{ - int basereg; + set_tok_reg (newtok[0], AXP_REG_AT); + set_tok_sym (newtok[1], sym, 0); + assemble_tokens ("lda", newtok, 2, 1); - if (ntok == 2) - basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register); - else - basereg = tok[2].X_add_number; + /* Call the division routine. */ + set_tok_reg (newtok[0], AXP_REG_AT); + set_tok_cpreg (newtok[1], AXP_REG_AT); + set_tok_const (newtok[2], 0); + assemble_tokens ("jsr", newtok, 3, 1); - (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL); + /* Move the result to the right place. */ + if (rr != AXP_REG_R0) + { + set_tok_reg (newtok[0], AXP_REG_R0); + set_tok_reg (newtok[1], rr); + assemble_tokens ("mov", newtok, 2, 1); + } } -/* The ldah macro differs from the ldah instruction in that it has $31 - as an implied base register. */ +#else /* !OBJ_EVAX */ static void -emit_ldah (tok, ntok, unused) - const expressionS *tok; - int ntok ATTRIBUTE_UNUSED; - const PTR unused ATTRIBUTE_UNUSED; +emit_division (const expressionS *tok, + int ntok, + const void * symname) { - expressionS newtok[3]; - - newtok[0] = tok[0]; - newtok[1] = tok[1]; - set_tok_preg (newtok[2], AXP_REG_ZERO); - - assemble_tokens ("ldah", newtok, 3, 0); -} + /* DIVISION and MODULUS. Yech. + Convert + OP x,y,result + to + lda pv,__OP + mov x,t10 + mov y,t11 + jsr t9,(pv),__OP + mov t12,result -/* Handle all "simple" integer register loads -- ldq, ldq_l, ldq_u, - etc. They differ from the real instructions in that they do simple - expressions like the lda macro. */ + with appropriate optimizations if t10,t11,t12 are the registers + specified by the compiler. */ -static void -emit_ir_load (tok, ntok, opname) - const expressionS *tok; - int ntok; - const PTR opname; -{ - int basereg; - long lituse; + int xr, yr, rr; + symbolS *sym; expressionS newtok[3]; - struct alpha_insn insn; - if (ntok == 2) - basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register); - else - basereg = tok[2].X_add_number; - - lituse = load_expression (tok[0].X_add_number, &tok[1], &basereg, - &newtok[1]); + xr = regno (tok[0].X_add_number); + yr = regno (tok[1].X_add_number); - newtok[0] = tok[0]; - set_tok_preg (newtok[2], basereg); + if (ntok < 3) + rr = xr; + else + rr = regno (tok[2].X_add_number); - assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); + sym = symbol_find_or_make ((const char *) symname); - if (lituse) + /* Move the operands into the right place. */ + if (yr == AXP_REG_T10 && xr == AXP_REG_T11) { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; - } + /* They are in exactly the wrong order -- swap through AT. */ + if (alpha_noat_on) + as_bad (_("macro requires $at register while noat in effect")); - emit_insn (&insn); -} + set_tok_reg (newtok[0], AXP_REG_T10); + set_tok_reg (newtok[1], AXP_REG_AT); + assemble_tokens ("mov", newtok, 2, 1); -/* Handle fp register loads, and both integer and fp register stores. - Again, we handle simple expressions. */ + set_tok_reg (newtok[0], AXP_REG_T11); + set_tok_reg (newtok[1], AXP_REG_T10); + assemble_tokens ("mov", newtok, 2, 1); -static void -emit_loadstore (tok, ntok, opname) - const expressionS *tok; - int ntok; - const PTR opname; + set_tok_reg (newtok[0], AXP_REG_AT); + set_tok_reg (newtok[1], AXP_REG_T11); + assemble_tokens ("mov", newtok, 2, 1); + } + else + { + if (yr == AXP_REG_T10) + { + set_tok_reg (newtok[0], AXP_REG_T10); + set_tok_reg (newtok[1], AXP_REG_T11); + assemble_tokens ("mov", newtok, 2, 1); + } + + if (xr != AXP_REG_T10) + { + set_tok_reg (newtok[0], xr); + set_tok_reg (newtok[1], AXP_REG_T10); + assemble_tokens ("mov", newtok, 2, 1); + } + + if (yr != AXP_REG_T10 && yr != AXP_REG_T11) + { + set_tok_reg (newtok[0], yr); + set_tok_reg (newtok[1], AXP_REG_T11); + assemble_tokens ("mov", newtok, 2, 1); + } + } + + /* Call the division routine. */ + set_tok_reg (newtok[0], AXP_REG_T9); + set_tok_sym (newtok[1], sym, 0); + assemble_tokens ("jsr", newtok, 2, 1); + + /* Reload the GP register. */ +#ifdef OBJ_AOUT +FIXME +#endif +#if defined(OBJ_ECOFF) || defined(OBJ_ELF) + set_tok_reg (newtok[0], alpha_gp_register); + set_tok_const (newtok[1], 0); + set_tok_preg (newtok[2], AXP_REG_T9); + assemble_tokens ("ldgp", newtok, 3, 1); +#endif + + /* Move the result to the right place. */ + if (rr != AXP_REG_T12) + { + set_tok_reg (newtok[0], AXP_REG_T12); + set_tok_reg (newtok[1], rr); + assemble_tokens ("mov", newtok, 2, 1); + } +} + +#endif /* !OBJ_EVAX */ + +/* The jsr and jmp macros differ from their instruction counterparts + in that they can load the target address and default most + everything. */ + +static void +emit_jsrjmp (const expressionS *tok, + int ntok, + const void * vopname) { - int basereg; - long lituse; - expressionS newtok[3]; + const char *opname = (const char *) vopname; struct alpha_insn insn; + expressionS newtok[3]; + int r, tokidx = 0; + long lituse = 0; - if (ntok == 2) - basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register); + if (tokidx < ntok && tok[tokidx].X_op == O_register) + r = regno (tok[tokidx++].X_add_number); else - basereg = tok[2].X_add_number; + r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA; - if (tok[1].X_op != O_constant || !range_signed_16 (tok[1].X_add_number)) - { - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); + set_tok_reg (newtok[0], r); - lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]); - } + if (tokidx < ntok && + (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) + r = regno (tok[tokidx++].X_add_number); +#ifdef OBJ_EVAX + /* Keep register if jsr $n.. */ +#else else { - newtok[1] = tok[1]; - lituse = 0; + int basereg = alpha_gp_register; + lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL); } +#endif - newtok[0] = tok[0]; - set_tok_preg (newtok[2], basereg); + set_tok_cpreg (newtok[1], r); - assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn); +#ifdef OBJ_EVAX + /* FIXME: Add hint relocs to BFD for evax. */ +#else + if (tokidx < ntok) + newtok[2] = tok[tokidx]; + else +#endif + set_tok_const (newtok[2], 0); + + assemble_tokens_to_insn (opname, newtok, 3, &insn); if (lituse) { assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; + insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR; insn.fixups[insn.nfixups].exp.X_op = O_absent; insn.nfixups++; insn.sequence = lituse; @@ -3457,1575 +2683,1370 @@ emit_loadstore (tok, ntok, opname) emit_insn (&insn); } -/* Load a half-word or byte as an unsigned value. */ +/* The ret and jcr instructions differ from their instruction + counterparts in that everything can be defaulted. */ static void -emit_ldXu (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; +emit_retjcr (const expressionS *tok, + int ntok, + const void * vopname) { - if (alpha_target & AXP_OPCODE_BWX) - emit_ir_load (tok, ntok, ldXu_op[(long) vlgsize]); - else - { - expressionS newtok[3]; - struct alpha_insn insn; - int basereg; - long lituse; - - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); - - if (ntok == 2) - basereg = (tok[1].X_op == O_constant - ? AXP_REG_ZERO : alpha_gp_register); - else - basereg = tok[2].X_add_number; - - /* emit "lda $at, exp" */ - - lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL); - - /* emit "ldq_u targ, 0($at)" */ - - newtok[0] = tok[0]; - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], basereg); - assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn); - - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; - } - - emit_insn (&insn); + const char *opname = (const char *) vopname; + expressionS newtok[3]; + int r, tokidx = 0; - /* emit "extXl targ, $at, targ" */ + if (tokidx < ntok && tok[tokidx].X_op == O_register) + r = regno (tok[tokidx++].X_add_number); + else + r = AXP_REG_ZERO; - set_tok_reg (newtok[1], basereg); - newtok[2] = newtok[0]; - assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn); + set_tok_reg (newtok[0], r); - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; - } + if (tokidx < ntok && + (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) + r = regno (tok[tokidx++].X_add_number); + else + r = AXP_REG_RA; - emit_insn (&insn); - } -} + set_tok_cpreg (newtok[1], r); -/* Load a half-word or byte as a signed value. */ + if (tokidx < ntok) + newtok[2] = tok[tokidx]; + else + set_tok_const (newtok[2], strcmp (opname, "ret") == 0); -static void -emit_ldX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - emit_ldXu (tok, ntok, vlgsize); - assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); + assemble_tokens (opname, newtok, 3, 0); } -/* Load an integral value from an unaligned address as an unsigned - value. */ +/* Implement the ldgp macro. */ static void -emit_uldXu (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; +emit_ldgp (const expressionS *tok, + int ntok ATTRIBUTE_UNUSED, + const void * unused ATTRIBUTE_UNUSED) { - long lgsize = (long) vlgsize; +#ifdef OBJ_AOUT +FIXME +#endif +#if defined(OBJ_ECOFF) || defined(OBJ_ELF) + /* from "ldgp r1,n(r2)", generate "ldah r1,X(R2); lda r1,Y(r1)" + with appropriate constants and relocations. */ + struct alpha_insn insn; expressionS newtok[3]; + expressionS addend; - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); - - /* emit "lda $at, exp" */ +#ifdef OBJ_ECOFF + if (regno (tok[2].X_add_number) == AXP_REG_PV) + ecoff_set_gp_prolog_size (0); +#endif - memcpy (newtok, tok, sizeof (expressionS) * ntok); - newtok[0].X_add_number = AXP_REG_AT; - assemble_tokens ("lda", newtok, ntok, 1); + newtok[0] = tok[0]; + set_tok_const (newtok[1], 0); + newtok[2] = tok[2]; - /* emit "ldq_u $t9, 0($at)" */ + assemble_tokens_to_insn ("ldah", newtok, 3, &insn); - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("ldq_u", newtok, 3, 1); + addend = tok[1]; - /* emit "ldq_u $t10, size-1($at)" */ +#ifdef OBJ_ECOFF + if (addend.X_op != O_constant) + as_bad (_("can not resolve expression")); + addend.X_op = O_symbol; + addend.X_add_symbol = alpha_gp_symbol; +#endif - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_const (newtok[1], (1 << lgsize) - 1); - assemble_tokens ("ldq_u", newtok, 3, 1); + insn.nfixups = 1; + insn.fixups[0].exp = addend; + insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16; + insn.sequence = next_sequence_num; - /* emit "extXl $t9, $at, $t9" */ + emit_insn (&insn); - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_reg (newtok[1], AXP_REG_AT); - set_tok_reg (newtok[2], AXP_REG_T9); - assemble_tokens (extXl_op[lgsize], newtok, 3, 1); + set_tok_preg (newtok[2], tok[0].X_add_number); - /* emit "extXh $t10, $at, $t10" */ + assemble_tokens_to_insn ("lda", newtok, 3, &insn); - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_reg (newtok[2], AXP_REG_T10); - assemble_tokens (extXh_op[lgsize], newtok, 3, 1); +#ifdef OBJ_ECOFF + addend.X_add_number += 4; +#endif - /* emit "or $t9, $t10, targ" */ + insn.nfixups = 1; + insn.fixups[0].exp = addend; + insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16; + insn.sequence = next_sequence_num--; - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_reg (newtok[1], AXP_REG_T10); - newtok[2] = tok[0]; - assemble_tokens ("or", newtok, 3, 1); + emit_insn (&insn); +#endif /* OBJ_ECOFF || OBJ_ELF */ } -/* Load an integral value from an unaligned address as a signed value. - Note that quads should get funneled to the unsigned load since we - don't have to do the sign extension. */ +/* The macro table. */ -static void -emit_uldX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; +static const struct alpha_macro alpha_macros[] = { - emit_uldXu (tok, ntok, vlgsize); - assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1); -} - -/* Implement the ldil macro. */ +/* Load/Store macros. */ + { "lda", emit_lda, NULL, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldah", emit_ldah, NULL, + { MACRO_IR, MACRO_EXP, MACRO_EOA } }, -static void -emit_ldil (tok, ntok, unused) - const expressionS *tok; - int ntok; - const PTR unused ATTRIBUTE_UNUSED; -{ - expressionS newtok[2]; + { "ldl", emit_ir_load, "ldl", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldl_l", emit_ir_load, "ldl_l", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldq", emit_ir_load, "ldq", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldq_l", emit_ir_load, "ldq_l", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldq_u", emit_ir_load, "ldq_u", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldf", emit_loadstore, "ldf", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldg", emit_loadstore, "ldg", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "lds", emit_loadstore, "lds", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldt", emit_loadstore, "ldt", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - memcpy (newtok, tok, sizeof (newtok)); - newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number); + { "ldb", emit_ldX, (void *) 0, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldbu", emit_ldXu, (void *) 0, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldw", emit_ldX, (void *) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ldwu", emit_ldXu, (void *) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - assemble_tokens ("lda", newtok, ntok, 1); -} + { "uldw", emit_uldX, (void *) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldwu", emit_uldXu, (void *) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldl", emit_uldX, (void *) 2, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldlu", emit_uldXu, (void *) 2, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "uldq", emit_uldXu, (void *) 3, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, -/* Store a half-word or byte. */ + { "ldgp", emit_ldgp, NULL, + { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } }, -static void -emit_stX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - int lgsize = (int) (long) vlgsize; + { "ldi", emit_lda, NULL, + { MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { "ldil", emit_ldil, NULL, + { MACRO_IR, MACRO_EXP, MACRO_EOA } }, + { "ldiq", emit_lda, NULL, + { MACRO_IR, MACRO_EXP, MACRO_EOA } }, - if (alpha_target & AXP_OPCODE_BWX) - emit_loadstore (tok, ntok, stX_op[lgsize]); - else - { - expressionS newtok[3]; - struct alpha_insn insn; - int basereg; - long lituse; + { "stl", emit_loadstore, "stl", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stl_c", emit_loadstore, "stl_c", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stq", emit_loadstore, "stq", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stq_c", emit_loadstore, "stq_c", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stq_u", emit_loadstore, "stq_u", + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stf", emit_loadstore, "stf", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stg", emit_loadstore, "stg", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "sts", emit_loadstore, "sts", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stt", emit_loadstore, "stt", + { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); + { "stb", emit_stX, (void *) 0, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "stw", emit_stX, (void *) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ustw", emit_ustX, (void *) 1, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ustl", emit_ustX, (void *) 2, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, + { "ustq", emit_ustX, (void *) 3, + { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } }, - if (ntok == 2) - basereg = (tok[1].X_op == O_constant - ? AXP_REG_ZERO : alpha_gp_register); - else - basereg = tok[2].X_add_number; +/* Arithmetic macros. */ - /* emit "lda $at, exp" */ + { "sextb", emit_sextX, (void *) 0, + { MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EOA, + /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, + { "sextw", emit_sextX, (void *) 1, + { MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EOA, + /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, - lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL); + { "divl", emit_division, "__divl", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + { "divlu", emit_division, "__divlu", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + { "divq", emit_division, "__divq", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + { "divqu", emit_division, "__divqu", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + { "reml", emit_division, "__reml", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + { "remlu", emit_division, "__remlu", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + { "remq", emit_division, "__remq", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, + { "remqu", emit_division, "__remqu", + { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_IR, MACRO_EOA, + /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, - /* emit "ldq_u $t9, 0($at)" */ + { "jsr", emit_jsrjmp, "jsr", + { MACRO_PIR, MACRO_EXP, MACRO_EOA, + MACRO_PIR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA, + MACRO_EXP, MACRO_EOA } }, + { "jmp", emit_jsrjmp, "jmp", + { MACRO_PIR, MACRO_EXP, MACRO_EOA, + MACRO_PIR, MACRO_EOA, + MACRO_IR, MACRO_EXP, MACRO_EOA, + MACRO_EXP, MACRO_EOA } }, + { "ret", emit_retjcr, "ret", + { MACRO_IR, MACRO_EXP, MACRO_EOA, + MACRO_IR, MACRO_EOA, + MACRO_PIR, MACRO_EXP, MACRO_EOA, + MACRO_PIR, MACRO_EOA, + MACRO_EXP, MACRO_EOA, + MACRO_EOA } }, + { "jcr", emit_retjcr, "jcr", + { MACRO_IR, MACRO_EXP, MACRO_EOA, + MACRO_IR, MACRO_EOA, + MACRO_PIR, MACRO_EXP, MACRO_EOA, + MACRO_PIR, MACRO_EOA, + MACRO_EXP, MACRO_EOA, + MACRO_EOA } }, + { "jsr_coroutine", emit_retjcr, "jcr", + { MACRO_IR, MACRO_EXP, MACRO_EOA, + MACRO_IR, MACRO_EOA, + MACRO_PIR, MACRO_EXP, MACRO_EOA, + MACRO_PIR, MACRO_EOA, + MACRO_EXP, MACRO_EOA, + MACRO_EOA } }, +}; - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], basereg); - assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn); +static const unsigned int alpha_num_macros + = sizeof (alpha_macros) / sizeof (*alpha_macros); - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; - } +/* Search forward through all variants of a macro looking for a syntax + match. */ - emit_insn (&insn); +static const struct alpha_macro * +find_macro_match (const struct alpha_macro *first_macro, + const expressionS *tok, + int *pntok) - /* emit "insXl src, $at, $t10" */ +{ + const struct alpha_macro *macro = first_macro; + int ntok = *pntok; - newtok[0] = tok[0]; - set_tok_reg (newtok[1], basereg); - set_tok_reg (newtok[2], AXP_REG_T10); - assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn); + do + { + const enum alpha_macro_arg *arg = macro->argsets; + int tokidx = 0; - if (lituse) + while (*arg) { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; - } - - emit_insn (&insn); - - /* emit "mskXl $t9, $at, $t9" */ + switch (*arg) + { + case MACRO_EOA: + if (tokidx == ntok) + return macro; + else + tokidx = 0; + break; - set_tok_reg (newtok[0], AXP_REG_T9); - newtok[2] = newtok[0]; - assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn); + /* Index register. */ + case MACRO_IR: + if (tokidx >= ntok || tok[tokidx].X_op != O_register + || !is_ir_num (tok[tokidx].X_add_number)) + goto match_failed; + ++tokidx; + break; - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; - } + /* Parenthesized index register. */ + case MACRO_PIR: + if (tokidx >= ntok || tok[tokidx].X_op != O_pregister + || !is_ir_num (tok[tokidx].X_add_number)) + goto match_failed; + ++tokidx; + break; - emit_insn (&insn); + /* Optional parenthesized index register. */ + case MACRO_OPIR: + if (tokidx < ntok && tok[tokidx].X_op == O_pregister + && is_ir_num (tok[tokidx].X_add_number)) + ++tokidx; + break; - /* emit "or $t9, $t10, $t9" */ + /* Leading comma with a parenthesized index register. */ + case MACRO_CPIR: + if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister + || !is_ir_num (tok[tokidx].X_add_number)) + goto match_failed; + ++tokidx; + break; - set_tok_reg (newtok[1], AXP_REG_T10); - assemble_tokens ("or", newtok, 3, 1); + /* Floating point register. */ + case MACRO_FPR: + if (tokidx >= ntok || tok[tokidx].X_op != O_register + || !is_fpr_num (tok[tokidx].X_add_number)) + goto match_failed; + ++tokidx; + break; - /* emit "stq_u $t9, 0($at) */ + /* Normal expression. */ + case MACRO_EXP: + if (tokidx >= ntok) + goto match_failed; + switch (tok[tokidx].X_op) + { + case O_illegal: + case O_absent: + case O_register: + case O_pregister: + case O_cpregister: + case O_literal: + case O_lituse_base: + case O_lituse_bytoff: + case O_lituse_jsr: + case O_gpdisp: + case O_gprelhigh: + case O_gprellow: + case O_gprel: + case O_samegp: + goto match_failed; - set_tok_const(newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens_to_insn ("stq_u", newtok, 3, &insn); + default: + break; + } + ++tokidx; + break; - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; + match_failed: + while (*arg != MACRO_EOA) + ++arg; + tokidx = 0; + break; + } + ++arg; } - - emit_insn (&insn); } + while (++macro - alpha_macros < (int) alpha_num_macros + && !strcmp (macro->name, first_macro->name)); + + return NULL; } -/* Store an integer to an unaligned address. */ +/* Given an opcode name and a pre-tokenized set of arguments, take the + opcode all the way through emission. */ static void -emit_ustX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; +assemble_tokens (const char *opname, + const expressionS *tok, + int ntok, + int local_macros_on) { - int lgsize = (int) (long) vlgsize; - expressionS newtok[3]; - - /* emit "lda $at, exp" */ - - memcpy (newtok, tok, sizeof (expressionS) * ntok); - newtok[0].X_add_number = AXP_REG_AT; - assemble_tokens ("lda", newtok, ntok, 1); - - /* emit "ldq_u $9, 0($at)" */ + int found_something = 0; + const struct alpha_opcode *opcode; + const struct alpha_macro *macro; + int cpumatch = 1; + bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED; - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("ldq_u", newtok, 3, 1); +#ifdef RELOC_OP_P + /* If a user-specified relocation is present, this is not a macro. */ + if (ntok && USER_RELOC_P (tok[ntok - 1].X_op)) + { + reloc = ALPHA_RELOC_TABLE (tok[ntok - 1].X_op)->reloc; + ntok--; + } + else +#endif + if (local_macros_on) + { + macro = ((const struct alpha_macro *) + hash_find (alpha_macro_hash, opname)); + if (macro) + { + found_something = 1; + macro = find_macro_match (macro, tok, &ntok); + if (macro) + { + (*macro->emit) (tok, ntok, macro->arg); + return; + } + } + } - /* emit "ldq_u $10, size-1($at)" */ + /* Search opcodes. */ + opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname); + if (opcode) + { + found_something = 1; + opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch); + if (opcode) + { + struct alpha_insn insn; + assemble_insn (opcode, tok, ntok, &insn, reloc); - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_const (newtok[1], (1 << lgsize) - 1); - assemble_tokens ("ldq_u", newtok, 3, 1); + /* Copy the sequence number for the reloc from the reloc token. */ + if (reloc != BFD_RELOC_UNUSED) + insn.sequence = tok[ntok].X_add_number; - /* emit "insXl src, $at, $t11" */ + emit_insn (&insn); + return; + } + } - newtok[0] = tok[0]; - set_tok_reg (newtok[1], AXP_REG_AT); - set_tok_reg (newtok[2], AXP_REG_T11); - assemble_tokens (insXl_op[lgsize], newtok, 3, 1); + if (found_something) + { + if (cpumatch) + as_bad (_("inappropriate arguments for opcode `%s'"), opname); + else + as_bad (_("opcode `%s' not supported for target %s"), opname, + alpha_target_name); + } + else + as_bad (_("unknown opcode `%s'"), opname); +} + +#ifdef OBJ_EVAX - /* emit "insXh src, $at, $t12" */ +/* Add symbol+addend to link pool. + Return offset from basesym to entry in link pool. - set_tok_reg (newtok[2], AXP_REG_T12); - assemble_tokens (insXh_op[lgsize], newtok, 3, 1); + Add new fixup only if offset isn't 16bit. */ - /* emit "mskXl $t9, $at, $t9" */ +valueT +add_to_link_pool (symbolS *basesym, + symbolS *sym, + offsetT addend) +{ + segT current_section = now_seg; + int current_subsec = now_subseg; + valueT offset; + bfd_reloc_code_real_type reloc_type; + char *p; + segment_info_type *seginfo = seg_info (alpha_link_section); + fixS *fixp; - set_tok_reg (newtok[0], AXP_REG_T9); - newtok[2] = newtok[0]; - assemble_tokens (mskXl_op[lgsize], newtok, 3, 1); + offset = - *symbol_get_obj (basesym); - /* emit "mskXh $t10, $at, $t10" */ + /* @@ This assumes all entries in a given section will be of the same + size... Probably correct, but unwise to rely on. */ + /* This must always be called with the same subsegment. */ - set_tok_reg (newtok[0], AXP_REG_T10); - newtok[2] = newtok[0]; - assemble_tokens (mskXh_op[lgsize], newtok, 3, 1); + if (seginfo->frchainP) + for (fixp = seginfo->frchainP->fix_root; + fixp != (fixS *) NULL; + fixp = fixp->fx_next, offset += 8) + { + if (fixp->fx_addsy == sym && fixp->fx_offset == addend) + { + if (range_signed_16 (offset)) + { + return offset; + } + } + } - /* emit "or $t9, $t11, $t9" */ + /* Not found in 16bit signed range. */ - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_reg (newtok[1], AXP_REG_T11); - newtok[2] = newtok[0]; - assemble_tokens ("or", newtok, 3, 1); + subseg_set (alpha_link_section, 0); + p = frag_more (8); + memset (p, 0, 8); - /* emit "or $t10, $t12, $t10" */ + fix_new (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0, + BFD_RELOC_64); - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_reg (newtok[1], AXP_REG_T12); - newtok[2] = newtok[0]; - assemble_tokens ("or", newtok, 3, 1); + subseg_set (current_section, current_subsec); + seginfo->literal_pool_size += 8; + return offset; +} - /* emit "stq_u $t9, 0($at)" */ +#endif /* OBJ_EVAX */ + +/* Assembler directives. */ - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("stq_u", newtok, 3, 1); +/* Handle the .text pseudo-op. This is like the usual one, but it + clears alpha_insn_label and restores auto alignment. */ - /* emit "stq_u $t10, size-1($at)" */ +static void +s_alpha_text (int i) - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_const (newtok[1], (1 << lgsize) - 1); - assemble_tokens ("stq_u", newtok, 3, 1); +{ +#ifdef OBJ_ELF + obj_elf_text (i); +#else + s_text (i); +#endif + alpha_insn_label = NULL; + alpha_auto_align_on = 1; + alpha_current_align = 0; } -/* Sign extend a half-word or byte. The 32-bit sign extend is - implemented as "addl $31, $r, $t" in the opcode table. */ +/* Handle the .data pseudo-op. This is like the usual one, but it + clears alpha_insn_label and restores auto alignment. */ static void -emit_sextX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; +s_alpha_data (int i) { - long lgsize = (long) vlgsize; - - if (alpha_target & AXP_OPCODE_BWX) - assemble_tokens (sextX_op[lgsize], tok, ntok, 0); - else - { - int bitshift = 64 - 8 * (1 << lgsize); - expressionS newtok[3]; - - /* emit "sll src,bits,dst" */ - - newtok[0] = tok[0]; - set_tok_const (newtok[1], bitshift); - newtok[2] = tok[ntok - 1]; - assemble_tokens ("sll", newtok, 3, 1); - - /* emit "sra dst,bits,dst" */ - - newtok[0] = newtok[2]; - assemble_tokens ("sra", newtok, 3, 1); - } +#ifdef OBJ_ELF + obj_elf_data (i); +#else + s_data (i); +#endif + alpha_insn_label = NULL; + alpha_auto_align_on = 1; + alpha_current_align = 0; } -/* Implement the division and modulus macros. */ - -#ifdef OBJ_EVAX +#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) -/* Make register usage like in normal procedure call. - Don't clobber PV and RA. */ +/* Handle the OSF/1 and openVMS .comm pseudo quirks. + openVMS constructs a section for every common symbol. */ static void -emit_division (tok, ntok, symname) - const expressionS *tok; - int ntok; - const PTR symname; +s_alpha_comm (int ignore ATTRIBUTE_UNUSED) { - /* DIVISION and MODULUS. Yech. - - Convert - OP x,y,result - to - mov x,R16 # if x != R16 - mov y,R17 # if y != R17 - lda AT,__OP - jsr AT,(AT),0 - mov R0,result - - with appropriate optimizations if R0,R16,R17 are the registers - specified by the compiler. */ + char *name; + char c; + char *p; + offsetT temp; + symbolS *symbolP; +#ifdef OBJ_EVAX + segT current_section = now_seg; + int current_subsec = now_subseg; + segT new_seg; +#endif - int xr, yr, rr; - symbolS *sym; - expressionS newtok[3]; + name = input_line_pointer; + c = get_symbol_end (); - xr = regno (tok[0].X_add_number); - yr = regno (tok[1].X_add_number); + /* Just after name is now '\0'. */ + p = input_line_pointer; + *p = c; - if (ntok < 3) - rr = xr; - else - rr = regno (tok[2].X_add_number); + SKIP_WHITESPACE (); - /* Move the operands into the right place. */ - if (yr == AXP_REG_R16 && xr == AXP_REG_R17) + /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */ + if (*input_line_pointer == ',') { - /* They are in exactly the wrong order -- swap through AT. */ + input_line_pointer++; + SKIP_WHITESPACE (); + } + if ((temp = get_absolute_expression ()) < 0) + { + as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp); + ignore_rest_of_line (); + return; + } - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); + *p = 0; + symbolP = symbol_find_or_make (name); - set_tok_reg (newtok[0], AXP_REG_R16); - set_tok_reg (newtok[1], AXP_REG_AT); - assemble_tokens ("mov", newtok, 2, 1); +#ifdef OBJ_EVAX + /* Make a section for the common symbol. */ + new_seg = subseg_new (xstrdup (name), 0); +#endif - set_tok_reg (newtok[0], AXP_REG_R17); - set_tok_reg (newtok[1], AXP_REG_R16); - assemble_tokens ("mov", newtok, 2, 1); + *p = c; - set_tok_reg (newtok[0], AXP_REG_AT); - set_tok_reg (newtok[1], AXP_REG_R17); - assemble_tokens ("mov", newtok, 2, 1); +#ifdef OBJ_EVAX + /* Alignment might follow. */ + if (*input_line_pointer == ',') + { + offsetT align; + + input_line_pointer++; + align = get_absolute_expression (); + bfd_set_section_alignment (stdoutput, new_seg, align); + } +#endif + + if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) + { + as_bad (_("Ignoring attempt to re-define symbol")); + ignore_rest_of_line (); + return; + } + +#ifdef OBJ_EVAX + if (bfd_section_size (stdoutput, new_seg) > 0) + { + if (bfd_section_size (stdoutput, new_seg) != temp) + as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), + S_GET_NAME (symbolP), + (long) bfd_section_size (stdoutput, new_seg), + (long) temp); + } +#else + if (S_GET_VALUE (symbolP)) + { + if (S_GET_VALUE (symbolP) != (valueT) temp) + as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), + S_GET_NAME (symbolP), + (long) S_GET_VALUE (symbolP), + (long) temp); } +#endif else { - if (yr == AXP_REG_R16) - { - set_tok_reg (newtok[0], AXP_REG_R16); - set_tok_reg (newtok[1], AXP_REG_R17); - assemble_tokens ("mov", newtok, 2, 1); - } +#ifdef OBJ_EVAX + subseg_set (new_seg, 0); + p = frag_more (temp); + new_seg->flags |= SEC_IS_COMMON; + if (! S_IS_DEFINED (symbolP)) + S_SET_SEGMENT (symbolP, new_seg); +#else + S_SET_VALUE (symbolP, (valueT) temp); +#endif + S_SET_EXTERNAL (symbolP); + } - if (xr != AXP_REG_R16) - { - set_tok_reg (newtok[0], xr); - set_tok_reg (newtok[1], AXP_REG_R16); - assemble_tokens ("mov", newtok, 2, 1); - } +#ifdef OBJ_EVAX + subseg_set (current_section, current_subsec); +#endif - if (yr != AXP_REG_R16 && yr != AXP_REG_R17) - { - set_tok_reg (newtok[0], yr); - set_tok_reg (newtok[1], AXP_REG_R17); - assemble_tokens ("mov", newtok, 2, 1); - } - } + know (symbol_get_frag (symbolP) == &zero_address_frag); - sym = symbol_find_or_make ((const char *) symname); + demand_empty_rest_of_line (); +} - set_tok_reg (newtok[0], AXP_REG_AT); - set_tok_sym (newtok[1], sym, 0); - assemble_tokens ("lda", newtok, 2, 1); +#endif /* ! OBJ_ELF */ - /* Call the division routine. */ - set_tok_reg (newtok[0], AXP_REG_AT); - set_tok_cpreg (newtok[1], AXP_REG_AT); - set_tok_const (newtok[2], 0); - assemble_tokens ("jsr", newtok, 3, 1); +#ifdef OBJ_ECOFF - /* Move the result to the right place. */ - if (rr != AXP_REG_R0) - { - set_tok_reg (newtok[0], AXP_REG_R0); - set_tok_reg (newtok[1], rr); - assemble_tokens ("mov", newtok, 2, 1); - } +/* Handle the .rdata pseudo-op. This is like the usual one, but it + clears alpha_insn_label and restores auto alignment. */ + +static void +s_alpha_rdata (int ignore ATTRIBUTE_UNUSED) +{ + int temp; + + temp = get_absolute_expression (); + subseg_new (".rdata", 0); + demand_empty_rest_of_line (); + alpha_insn_label = NULL; + alpha_auto_align_on = 1; + alpha_current_align = 0; } -#else /* !OBJ_EVAX */ +#endif + +#ifdef OBJ_ECOFF + +/* Handle the .sdata pseudo-op. This is like the usual one, but it + clears alpha_insn_label and restores auto alignment. */ static void -emit_division (tok, ntok, symname) - const expressionS *tok; - int ntok; - const PTR symname; +s_alpha_sdata (int ignore ATTRIBUTE_UNUSED) { - /* DIVISION and MODULUS. Yech. - Convert - OP x,y,result - to - lda pv,__OP - mov x,t10 - mov y,t11 - jsr t9,(pv),__OP - mov t12,result - - with appropriate optimizations if t10,t11,t12 are the registers - specified by the compiler. */ + int temp; - int xr, yr, rr; - symbolS *sym; - expressionS newtok[3]; + temp = get_absolute_expression (); + subseg_new (".sdata", 0); + demand_empty_rest_of_line (); + alpha_insn_label = NULL; + alpha_auto_align_on = 1; + alpha_current_align = 0; +} +#endif - xr = regno (tok[0].X_add_number); - yr = regno (tok[1].X_add_number); +#ifdef OBJ_ELF +struct alpha_elf_frame_data +{ + symbolS *func_sym; + symbolS *func_end_sym; + symbolS *prologue_sym; + unsigned int mask; + unsigned int fmask; + int fp_regno; + int ra_regno; + offsetT frame_size; + offsetT mask_offset; + offsetT fmask_offset; - if (ntok < 3) - rr = xr; - else - rr = regno (tok[2].X_add_number); + struct alpha_elf_frame_data *next; +}; - sym = symbol_find_or_make ((const char *) symname); +static struct alpha_elf_frame_data *all_frame_data; +static struct alpha_elf_frame_data **plast_frame_data = &all_frame_data; +static struct alpha_elf_frame_data *cur_frame_data; - /* Move the operands into the right place. */ - if (yr == AXP_REG_T10 && xr == AXP_REG_T11) - { - /* They are in exactly the wrong order -- swap through AT. */ - if (alpha_noat_on) - as_bad (_("macro requires $at register while noat in effect")); +/* Handle the .section pseudo-op. This is like the usual one, but it + clears alpha_insn_label and restores auto alignment. */ - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_reg (newtok[1], AXP_REG_AT); - assemble_tokens ("mov", newtok, 2, 1); +static void +s_alpha_section (int ignore ATTRIBUTE_UNUSED) +{ + obj_elf_section (ignore); - set_tok_reg (newtok[0], AXP_REG_T11); - set_tok_reg (newtok[1], AXP_REG_T10); - assemble_tokens ("mov", newtok, 2, 1); + alpha_insn_label = NULL; + alpha_auto_align_on = 1; + alpha_current_align = 0; +} - set_tok_reg (newtok[0], AXP_REG_AT); - set_tok_reg (newtok[1], AXP_REG_T11); - assemble_tokens ("mov", newtok, 2, 1); - } +static void +s_alpha_ent (int dummy ATTRIBUTE_UNUSED) +{ + if (ECOFF_DEBUGGING) + ecoff_directive_ent (0); else { - if (yr == AXP_REG_T10) - { - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_reg (newtok[1], AXP_REG_T11); - assemble_tokens ("mov", newtok, 2, 1); - } + char *name, name_end; + name = input_line_pointer; + name_end = get_symbol_end (); - if (xr != AXP_REG_T10) + if (! is_name_beginner (*name)) { - set_tok_reg (newtok[0], xr); - set_tok_reg (newtok[1], AXP_REG_T10); - assemble_tokens ("mov", newtok, 2, 1); + as_warn (_(".ent directive has no name")); + *input_line_pointer = name_end; } - - if (yr != AXP_REG_T10 && yr != AXP_REG_T11) + else { - set_tok_reg (newtok[0], yr); - set_tok_reg (newtok[1], AXP_REG_T11); - assemble_tokens ("mov", newtok, 2, 1); - } - } + symbolS *sym; - /* Call the division routine. */ - set_tok_reg (newtok[0], AXP_REG_T9); - set_tok_sym (newtok[1], sym, 0); - assemble_tokens ("jsr", newtok, 2, 1); + if (cur_frame_data) + as_warn (_("nested .ent directives")); - /* Reload the GP register. */ -#ifdef OBJ_AOUT -FIXME -#endif -#if defined(OBJ_ECOFF) || defined(OBJ_ELF) - set_tok_reg (newtok[0], alpha_gp_register); - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_T9); - assemble_tokens ("ldgp", newtok, 3, 1); -#endif + sym = symbol_find_or_make (name); + symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; - /* Move the result to the right place. */ - if (rr != AXP_REG_T12) - { - set_tok_reg (newtok[0], AXP_REG_T12); - set_tok_reg (newtok[1], rr); - assemble_tokens ("mov", newtok, 2, 1); - } -} + cur_frame_data = calloc (1, sizeof (*cur_frame_data)); + cur_frame_data->func_sym = sym; -#endif /* !OBJ_EVAX */ + /* Provide sensible defaults. */ + cur_frame_data->fp_regno = 30; /* sp */ + cur_frame_data->ra_regno = 26; /* ra */ -/* The jsr and jmp macros differ from their instruction counterparts - in that they can load the target address and default most - everything. */ + *plast_frame_data = cur_frame_data; + plast_frame_data = &cur_frame_data->next; + + /* The .ent directive is sometimes followed by a number. Not sure + what it really means, but ignore it. */ + *input_line_pointer = name_end; + SKIP_WHITESPACE (); + if (*input_line_pointer == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + } + if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') + (void) get_absolute_expression (); + } + demand_empty_rest_of_line (); + } +} static void -emit_jsrjmp (tok, ntok, vopname) - const expressionS *tok; - int ntok; - const PTR vopname; +s_alpha_end (int dummy ATTRIBUTE_UNUSED) { - const char *opname = (const char *) vopname; - struct alpha_insn insn; - expressionS newtok[3]; - int r, tokidx = 0; - long lituse = 0; - - if (tokidx < ntok && tok[tokidx].X_op == O_register) - r = regno (tok[tokidx++].X_add_number); + if (ECOFF_DEBUGGING) + ecoff_directive_end (0); else - r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA; + { + char *name, name_end; + name = input_line_pointer; + name_end = get_symbol_end (); - set_tok_reg (newtok[0], r); + if (! is_name_beginner (*name)) + { + as_warn (_(".end directive has no name")); + *input_line_pointer = name_end; + } + else + { + symbolS *sym; - if (tokidx < ntok && - (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) - r = regno (tok[tokidx++].X_add_number); -#ifdef OBJ_EVAX - /* keep register if jsr $n. */ -#else - else - { - int basereg = alpha_gp_register; - lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL); - } -#endif + sym = symbol_find (name); + if (!cur_frame_data) + as_warn (_(".end directive without matching .ent")); + else if (sym != cur_frame_data->func_sym) + as_warn (_(".end directive names different symbol than .ent")); - set_tok_cpreg (newtok[1], r); + /* Create an expression to calculate the size of the function. */ + if (sym && cur_frame_data) + { + OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (sym); + expressionS *exp = xmalloc (sizeof (expressionS)); -#ifdef OBJ_EVAX - /* FIXME: Add hint relocs to BFD for evax. */ -#else - if (tokidx < ntok) - newtok[2] = tok[tokidx]; - else -#endif - set_tok_const (newtok[2], 0); + obj->size = exp; + exp->X_op = O_subtract; + exp->X_add_symbol = symbol_temp_new_now (); + exp->X_op_symbol = sym; + exp->X_add_number = 0; - assemble_tokens_to_insn (opname, newtok, 3, &insn); + cur_frame_data->func_end_sym = exp->X_add_symbol; + } - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR; - insn.fixups[insn.nfixups].exp.X_op = O_absent; - insn.nfixups++; - insn.sequence = lituse; - } + cur_frame_data = NULL; - emit_insn (&insn); + *input_line_pointer = name_end; + } + demand_empty_rest_of_line (); + } } -/* The ret and jcr instructions differ from their instruction - counterparts in that everything can be defaulted. */ - static void -emit_retjcr (tok, ntok, vopname) - const expressionS *tok; - int ntok; - const PTR vopname; +s_alpha_mask (int fp) { - const char *opname = (const char *) vopname; - expressionS newtok[3]; - int r, tokidx = 0; - - if (tokidx < ntok && tok[tokidx].X_op == O_register) - r = regno (tok[tokidx++].X_add_number); + if (ECOFF_DEBUGGING) + { + if (fp) + ecoff_directive_fmask (0); + else + ecoff_directive_mask (0); + } else - r = AXP_REG_ZERO; - - set_tok_reg (newtok[0], r); + { + long val; + offsetT offset; - if (tokidx < ntok && - (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister)) - r = regno (tok[tokidx++].X_add_number); - else - r = AXP_REG_RA; + if (!cur_frame_data) + { + if (fp) + as_warn (_(".fmask outside of .ent")); + else + as_warn (_(".mask outside of .ent")); + discard_rest_of_line (); + return; + } - set_tok_cpreg (newtok[1], r); + if (get_absolute_expression_and_terminator (&val) != ',') + { + if (fp) + as_warn (_("bad .fmask directive")); + else + as_warn (_("bad .mask directive")); + --input_line_pointer; + discard_rest_of_line (); + return; + } - if (tokidx < ntok) - newtok[2] = tok[tokidx]; - else - set_tok_const (newtok[2], strcmp (opname, "ret") == 0); + offset = get_absolute_expression (); + demand_empty_rest_of_line (); - assemble_tokens (opname, newtok, 3, 0); + if (fp) + { + cur_frame_data->fmask = val; + cur_frame_data->fmask_offset = offset; + } + else + { + cur_frame_data->mask = val; + cur_frame_data->mask_offset = offset; + } + } } - -/* Assembler directives. */ - -/* Handle the .text pseudo-op. This is like the usual one, but it - clears alpha_insn_label and restores auto alignment. */ static void -s_alpha_text (i) - int i; - +s_alpha_frame (int dummy ATTRIBUTE_UNUSED) { -#ifdef OBJ_ELF - obj_elf_text (i); -#else - s_text (i); -#endif - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} + if (ECOFF_DEBUGGING) + ecoff_directive_frame (0); + else + { + long val; -/* Handle the .data pseudo-op. This is like the usual one, but it - clears alpha_insn_label and restores auto alignment. */ + if (!cur_frame_data) + { + as_warn (_(".frame outside of .ent")); + discard_rest_of_line (); + return; + } -static void -s_alpha_data (i) - int i; -{ -#ifdef OBJ_ELF - obj_elf_data (i); -#else - s_data (i); -#endif - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} + cur_frame_data->fp_regno = tc_get_register (1); -#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) + SKIP_WHITESPACE (); + if (*input_line_pointer++ != ',' + || get_absolute_expression_and_terminator (&val) != ',') + { + as_warn (_("bad .frame directive")); + --input_line_pointer; + discard_rest_of_line (); + return; + } + cur_frame_data->frame_size = val; -/* Handle the OSF/1 and openVMS .comm pseudo quirks. - openVMS constructs a section for every common symbol. */ + cur_frame_data->ra_regno = tc_get_register (0); + + /* Next comes the "offset of saved $a0 from $sp". In gcc terms + this is current_function_pretend_args_size. There's no place + to put this value, so ignore it. */ + s_ignore (42); + } +} static void -s_alpha_comm (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_prologue (int ignore ATTRIBUTE_UNUSED) { - register char *name; - register char c; - register char *p; - offsetT temp; - register symbolS *symbolP; - -#ifdef OBJ_EVAX - segT current_section = now_seg; - int current_subsec = now_subseg; - segT new_seg; -#endif - - name = input_line_pointer; - c = get_symbol_end (); + symbolS *sym; + int arg; - /* just after name is now '\0' */ - p = input_line_pointer; - *p = c; + arg = get_absolute_expression (); + demand_empty_rest_of_line (); - SKIP_WHITESPACE (); + if (ECOFF_DEBUGGING) + sym = ecoff_get_cur_proc_sym (); + else + sym = cur_frame_data ? cur_frame_data->func_sym : NULL; - /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */ - if (*input_line_pointer == ',') - { - input_line_pointer++; - SKIP_WHITESPACE (); - } - if ((temp = get_absolute_expression ()) < 0) + if (sym == NULL) { - as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp); - ignore_rest_of_line (); + as_bad (_(".prologue directive without a preceding .ent directive")); return; } - *p = 0; - symbolP = symbol_find_or_make (name); - -#ifdef OBJ_EVAX - /* Make a section for the common symbol. */ - new_seg = subseg_new (xstrdup (name), 0); -#endif - - *p = c; - -#ifdef OBJ_EVAX - /* alignment might follow */ - if (*input_line_pointer == ',') - { - offsetT align; - - input_line_pointer++; - align = get_absolute_expression (); - bfd_set_section_alignment (stdoutput, new_seg, align); - } -#endif - - if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) + switch (arg) { - as_bad (_("Ignoring attempt to re-define symbol")); - ignore_rest_of_line (); - return; - } + case 0: /* No PV required. */ + S_SET_OTHER (sym, STO_ALPHA_NOPV + | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); + break; + case 1: /* Std GP load. */ + S_SET_OTHER (sym, STO_ALPHA_STD_GPLOAD + | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); + break; + case 2: /* Non-std use of PV. */ + break; -#ifdef OBJ_EVAX - if (bfd_section_size (stdoutput, new_seg) > 0) - { - if (bfd_section_size (stdoutput, new_seg) != temp) - as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), - S_GET_NAME (symbolP), - (long) bfd_section_size (stdoutput, new_seg), - (long) temp); - } -#else - if (S_GET_VALUE (symbolP)) - { - if (S_GET_VALUE (symbolP) != (valueT) temp) - as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), - S_GET_NAME (symbolP), - (long) S_GET_VALUE (symbolP), - (long) temp); - } -#endif - else - { -#ifdef OBJ_EVAX - subseg_set (new_seg, 0); - p = frag_more (temp); - new_seg->flags |= SEC_IS_COMMON; - if (! S_IS_DEFINED (symbolP)) - S_SET_SEGMENT (symbolP, new_seg); -#else - S_SET_VALUE (symbolP, (valueT) temp); -#endif - S_SET_EXTERNAL (symbolP); + default: + as_bad (_("Invalid argument %d to .prologue."), arg); + break; } -#ifdef OBJ_EVAX - subseg_set (current_section, current_subsec); -#endif - - know (symbol_get_frag (symbolP) == &zero_address_frag); - - demand_empty_rest_of_line (); + if (cur_frame_data) + cur_frame_data->prologue_sym = symbol_temp_new_now (); } -#endif /* ! OBJ_ELF */ - -#ifdef OBJ_ECOFF - -/* Handle the .rdata pseudo-op. This is like the usual one, but it - clears alpha_insn_label and restores auto alignment. */ +static char *first_file_directive; static void -s_alpha_rdata (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_file (int ignore ATTRIBUTE_UNUSED) { - int temp; + /* Save the first .file directive we see, so that we can change our + minds about whether ecoff debugging should or shouldn't be enabled. */ + if (alpha_flag_mdebug < 0 && ! first_file_directive) + { + char *start = input_line_pointer; + size_t len; - temp = get_absolute_expression (); - subseg_new (".rdata", 0); - demand_empty_rest_of_line (); - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} + discard_rest_of_line (); -#endif + len = input_line_pointer - start; + first_file_directive = xmalloc (len + 1); + memcpy (first_file_directive, start, len); + first_file_directive[len] = '\0'; -#ifdef OBJ_ECOFF + input_line_pointer = start; + } -/* Handle the .sdata pseudo-op. This is like the usual one, but it - clears alpha_insn_label and restores auto alignment. */ + if (ECOFF_DEBUGGING) + ecoff_directive_file (0); + else + dwarf2_directive_file (0); +} static void -s_alpha_sdata (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_loc (int ignore ATTRIBUTE_UNUSED) { - int temp; - - temp = get_absolute_expression (); - subseg_new (".sdata", 0); - demand_empty_rest_of_line (); - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; + if (ECOFF_DEBUGGING) + ecoff_directive_loc (0); + else + dwarf2_directive_loc (0); } -#endif -#ifdef OBJ_ELF -struct alpha_elf_frame_data +static void +s_alpha_stab (int n) { - symbolS *func_sym; - symbolS *func_end_sym; - symbolS *prologue_sym; - unsigned int mask; - unsigned int fmask; - int fp_regno; - int ra_regno; - offsetT frame_size; - offsetT mask_offset; - offsetT fmask_offset; + /* If we've been undecided about mdebug, make up our minds in favour. */ + if (alpha_flag_mdebug < 0) + { + segT sec = subseg_new (".mdebug", 0); + bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY); + bfd_set_section_alignment (stdoutput, sec, 3); - struct alpha_elf_frame_data *next; -}; + ecoff_read_begin_hook (); -static struct alpha_elf_frame_data *all_frame_data; -static struct alpha_elf_frame_data **plast_frame_data = &all_frame_data; -static struct alpha_elf_frame_data *cur_frame_data; + if (first_file_directive) + { + char *save_ilp = input_line_pointer; + input_line_pointer = first_file_directive; + ecoff_directive_file (0); + input_line_pointer = save_ilp; + free (first_file_directive); + } -/* Handle the .section pseudo-op. This is like the usual one, but it - clears alpha_insn_label and restores auto alignment. */ + alpha_flag_mdebug = 1; + } + s_stab (n); +} static void -s_alpha_section (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_coff_wrapper (int which) { - obj_elf_section (ignore); + static void (* const fns[]) PARAMS ((int)) = { + ecoff_directive_begin, + ecoff_directive_bend, + ecoff_directive_def, + ecoff_directive_dim, + ecoff_directive_endef, + ecoff_directive_scl, + ecoff_directive_tag, + ecoff_directive_val, + }; - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} + assert (which >= 0 && which < (int) (sizeof (fns)/sizeof (*fns))); -static void -s_alpha_ent (dummy) - int dummy ATTRIBUTE_UNUSED; -{ if (ECOFF_DEBUGGING) - ecoff_directive_ent (0); + (*fns[which]) (0); else { - char *name, name_end; - name = input_line_pointer; - name_end = get_symbol_end (); + as_bad (_("ECOFF debugging is disabled.")); + ignore_rest_of_line (); + } +} - if (! is_name_beginner (*name)) - { - as_warn (_(".ent directive has no name")); - *input_line_pointer = name_end; - } - else - { - symbolS *sym; - - if (cur_frame_data) - as_warn (_("nested .ent directives")); +/* Called at the end of assembly. Here we emit unwind info for frames + unless the compiler has done it for us. */ - sym = symbol_find_or_make (name); - symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; +void +alpha_elf_md_end (void) +{ + struct alpha_elf_frame_data *p; - cur_frame_data = calloc (1, sizeof (*cur_frame_data)); - cur_frame_data->func_sym = sym; + if (cur_frame_data) + as_warn (_(".ent directive without matching .end")); - /* Provide sensible defaults. */ - cur_frame_data->fp_regno = 30; /* sp */ - cur_frame_data->ra_regno = 26; /* ra */ + /* If someone has generated the unwind info themselves, great. */ + if (bfd_get_section_by_name (stdoutput, ".eh_frame") != NULL) + return; - *plast_frame_data = cur_frame_data; - plast_frame_data = &cur_frame_data->next; + /* Generate .eh_frame data for the unwind directives specified. */ + for (p = all_frame_data; p ; p = p->next) + if (p->prologue_sym) + { + /* Create a temporary symbol at the same location as our + function symbol. This prevents problems with globals. */ + cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym), + S_GET_VALUE (p->func_sym), + symbol_get_frag (p->func_sym))); - /* The .ent directive is sometimes followed by a number. Not sure - what it really means, but ignore it. */ - *input_line_pointer = name_end; - SKIP_WHITESPACE (); - if (*input_line_pointer == ',') - { - input_line_pointer++; - SKIP_WHITESPACE (); - } - if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') - (void) get_absolute_expression (); - } - demand_empty_rest_of_line (); - } -} + cfi_set_return_column (p->ra_regno); + cfi_add_CFA_def_cfa_register (30); + if (p->fp_regno != 30 || p->mask || p->fmask || p->frame_size) + { + unsigned int mask; + offsetT offset; -static void -s_alpha_end (dummy) - int dummy ATTRIBUTE_UNUSED; -{ - if (ECOFF_DEBUGGING) - ecoff_directive_end (0); - else - { - char *name, name_end; - name = input_line_pointer; - name_end = get_symbol_end (); + cfi_add_advance_loc (p->prologue_sym); - if (! is_name_beginner (*name)) - { - as_warn (_(".end directive has no name")); - *input_line_pointer = name_end; - } - else - { - symbolS *sym; + if (p->fp_regno != 30) + if (p->frame_size != 0) + cfi_add_CFA_def_cfa (p->fp_regno, p->frame_size); + else + cfi_add_CFA_def_cfa_register (p->fp_regno); + else if (p->frame_size != 0) + cfi_add_CFA_def_cfa_offset (p->frame_size); - sym = symbol_find (name); - if (!cur_frame_data) - as_warn (_(".end directive without matching .ent")); - else if (sym != cur_frame_data->func_sym) - as_warn (_(".end directive names different symbol than .ent")); + mask = p->mask; + offset = p->mask_offset; - /* Create an expression to calculate the size of the function. */ - if (sym && cur_frame_data) - { - OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (sym); - expressionS *exp = xmalloc (sizeof (expressionS)); + /* Recall that $26 is special-cased and stored first. */ + if ((mask >> 26) & 1) + { + cfi_add_CFA_offset (26, offset); + offset += 8; + mask &= ~(1 << 26); + } + while (mask) + { + unsigned int i; + i = mask & -mask; + mask ^= i; + i = ffs (i) - 1; - obj->size = exp; - exp->X_op = O_subtract; - exp->X_add_symbol = symbol_temp_new_now (); - exp->X_op_symbol = sym; - exp->X_add_number = 0; + cfi_add_CFA_offset (i, offset); + offset += 8; + } - cur_frame_data->func_end_sym = exp->X_add_symbol; - } + mask = p->fmask; + offset = p->fmask_offset; + while (mask) + { + unsigned int i; + i = mask & -mask; + mask ^= i; + i = ffs (i) - 1; - cur_frame_data = NULL; + cfi_add_CFA_offset (i + 32, offset); + offset += 8; + } + } - *input_line_pointer = name_end; - } - demand_empty_rest_of_line (); - } + cfi_end_fde (p->func_end_sym); + } } static void -s_alpha_mask (fp) - int fp; +s_alpha_usepv (int unused ATTRIBUTE_UNUSED) { - if (ECOFF_DEBUGGING) - { - if (fp) - ecoff_directive_fmask (0); - else - ecoff_directive_mask (0); - } - else - { - long val; - offsetT offset; + char *name, name_end; + char *which, which_end; + symbolS *sym; + int other; - if (!cur_frame_data) - { - if (fp) - as_warn (_(".fmask outside of .ent")); - else - as_warn (_(".mask outside of .ent")); - discard_rest_of_line (); - return; - } + name = input_line_pointer; + name_end = get_symbol_end (); - if (get_absolute_expression_and_terminator (&val) != ',') - { - if (fp) - as_warn (_("bad .fmask directive")); - else - as_warn (_("bad .mask directive")); - --input_line_pointer; - discard_rest_of_line (); - return; - } + if (! is_name_beginner (*name)) + { + as_bad (_(".usepv directive has no name")); + *input_line_pointer = name_end; + ignore_rest_of_line (); + return; + } - offset = get_absolute_expression (); - demand_empty_rest_of_line (); + sym = symbol_find_or_make (name); + *input_line_pointer++ = name_end; - if (fp) - { - cur_frame_data->fmask = val; - cur_frame_data->fmask_offset = offset; - } - else - { - cur_frame_data->mask = val; - cur_frame_data->mask_offset = offset; - } + if (name_end != ',') + { + as_bad (_(".usepv directive has no type")); + ignore_rest_of_line (); + return; } -} -static void -s_alpha_frame (dummy) - int dummy ATTRIBUTE_UNUSED; -{ - if (ECOFF_DEBUGGING) - ecoff_directive_frame (0); + SKIP_WHITESPACE (); + which = input_line_pointer; + which_end = get_symbol_end (); + + if (strcmp (which, "no") == 0) + other = STO_ALPHA_NOPV; + else if (strcmp (which, "std") == 0) + other = STO_ALPHA_STD_GPLOAD; else { - long val; - - if (!cur_frame_data) - { - as_warn (_(".frame outside of .ent")); - discard_rest_of_line (); - return; - } + as_bad (_("unknown argument for .usepv")); + other = 0; + } - cur_frame_data->fp_regno = tc_get_register (1); + *input_line_pointer = which_end; + demand_empty_rest_of_line (); - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',' - || get_absolute_expression_and_terminator (&val) != ',') - { - as_warn (_("bad .frame directive")); - --input_line_pointer; - discard_rest_of_line (); - return; - } - cur_frame_data->frame_size = val; + S_SET_OTHER (sym, other | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); +} +#endif /* OBJ_ELF */ - cur_frame_data->ra_regno = tc_get_register (0); +/* Standard calling conventions leaves the CFA at $30 on entry. */ - /* Next comes the "offset of saved $a0 from $sp". In gcc terms - this is current_function_pretend_args_size. There's no place - to put this value, so ignore it. */ - s_ignore (42); - } +void +alpha_cfi_frame_initial_instructions (void) +{ + cfi_add_CFA_def_cfa_register (30); } +#ifdef OBJ_EVAX + +/* Handle the section specific pseudo-op. */ + static void -s_alpha_prologue (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_section (int secid) { - symbolS *sym; - int arg; + int temp; +#define EVAX_SECTION_COUNT 5 + static char *section_name[EVAX_SECTION_COUNT + 1] = + { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" }; - arg = get_absolute_expression (); - demand_empty_rest_of_line (); - - if (ECOFF_DEBUGGING) - sym = ecoff_get_cur_proc_sym (); - else - sym = cur_frame_data ? cur_frame_data->func_sym : NULL; - - if (sym == NULL) + if ((secid <= 0) || (secid > EVAX_SECTION_COUNT)) { - as_bad (_(".prologue directive without a preceding .ent directive")); + as_fatal (_("Unknown section directive")); + demand_empty_rest_of_line (); return; } - - switch (arg) - { - case 0: /* No PV required. */ - S_SET_OTHER (sym, STO_ALPHA_NOPV - | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); - break; - case 1: /* Std GP load. */ - S_SET_OTHER (sym, STO_ALPHA_STD_GPLOAD - | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); - break; - case 2: /* Non-std use of PV. */ - break; - - default: - as_bad (_("Invalid argument %d to .prologue."), arg); - break; - } - - if (cur_frame_data) - cur_frame_data->prologue_sym = symbol_temp_new_now (); + temp = get_absolute_expression (); + subseg_new (section_name[secid], 0); + demand_empty_rest_of_line (); + alpha_insn_label = NULL; + alpha_auto_align_on = 1; + alpha_current_align = 0; } -static char *first_file_directive; +/* Parse .ent directives. */ static void -s_alpha_file (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_ent (int ignore ATTRIBUTE_UNUSED) { - /* Save the first .file directive we see, so that we can change our - minds about whether ecoff debugging should or shouldn't be enabled. */ - if (alpha_flag_mdebug < 0 && ! first_file_directive) - { - char *start = input_line_pointer; - size_t len; + symbolS *symbol; + expressionS symexpr; - discard_rest_of_line (); + alpha_evax_proc.pdsckind = 0; + alpha_evax_proc.framereg = -1; + alpha_evax_proc.framesize = 0; + alpha_evax_proc.rsa_offset = 0; + alpha_evax_proc.ra_save = AXP_REG_RA; + alpha_evax_proc.fp_save = -1; + alpha_evax_proc.imask = 0; + alpha_evax_proc.fmask = 0; + alpha_evax_proc.prologue = 0; + alpha_evax_proc.type = 0; - len = input_line_pointer - start; - first_file_directive = xmalloc (len + 1); - memcpy (first_file_directive, start, len); - first_file_directive[len] = '\0'; + expression (&symexpr); - input_line_pointer = start; + if (symexpr.X_op != O_symbol) + { + as_fatal (_(".ent directive has no symbol")); + demand_empty_rest_of_line (); + return; } - if (ECOFF_DEBUGGING) - ecoff_directive_file (0); - else - dwarf2_directive_file (0); -} + symbol = make_expr_symbol (&symexpr); + symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION; + alpha_evax_proc.symbol = symbol; -static void -s_alpha_loc (ignore) - int ignore ATTRIBUTE_UNUSED; -{ - if (ECOFF_DEBUGGING) - ecoff_directive_loc (0); - else - dwarf2_directive_loc (0); + demand_empty_rest_of_line (); } +/* Parse .frame ,,RA, directives. */ + static void -s_alpha_stab (n) - int n; +s_alpha_frame (int ignore ATTRIBUTE_UNUSED) { - /* If we've been undecided about mdebug, make up our minds in favour. */ - if (alpha_flag_mdebug < 0) - { - segT sec = subseg_new (".mdebug", 0); - bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY); - bfd_set_section_alignment (stdoutput, sec, 3); + long val; - ecoff_read_begin_hook (); + alpha_evax_proc.framereg = tc_get_register (1); - if (first_file_directive) - { - char *save_ilp = input_line_pointer; - input_line_pointer = first_file_directive; - ecoff_directive_file (0); - input_line_pointer = save_ilp; - free (first_file_directive); - } + SKIP_WHITESPACE (); + if (*input_line_pointer++ != ',' + || get_absolute_expression_and_terminator (&val) != ',') + { + as_warn (_("Bad .frame directive 1./2. param")); + --input_line_pointer; + demand_empty_rest_of_line (); + return; + } - alpha_flag_mdebug = 1; + alpha_evax_proc.framesize = val; + + (void) tc_get_register (1); + SKIP_WHITESPACE (); + if (*input_line_pointer++ != ',') + { + as_warn (_("Bad .frame directive 3./4. param")); + --input_line_pointer; + demand_empty_rest_of_line (); + return; } - s_stab (n); + alpha_evax_proc.rsa_offset = get_absolute_expression (); } static void -s_alpha_coff_wrapper (which) - int which; +s_alpha_pdesc (int ignore ATTRIBUTE_UNUSED) { - static void (* const fns[]) PARAMS ((int)) = { - ecoff_directive_begin, - ecoff_directive_bend, - ecoff_directive_def, - ecoff_directive_dim, - ecoff_directive_endef, - ecoff_directive_scl, - ecoff_directive_tag, - ecoff_directive_val, - }; + char *name; + char name_end; + long val; + register char *p; + expressionS exp; + symbolS *entry_sym; + fixS *fixp; + segment_info_type *seginfo = seg_info (alpha_link_section); - assert (which >= 0 && which < (int) (sizeof (fns)/sizeof (*fns))); + if (now_seg != alpha_link_section) + { + as_bad (_(".pdesc directive not in link (.link) section")); + demand_empty_rest_of_line (); + return; + } - if (ECOFF_DEBUGGING) - (*fns[which]) (0); - else + if ((alpha_evax_proc.symbol == 0) + || (!S_IS_DEFINED (alpha_evax_proc.symbol))) { - as_bad (_("ECOFF debugging is disabled.")); - ignore_rest_of_line (); + as_fatal (_(".pdesc has no matching .ent")); + demand_empty_rest_of_line (); + return; } -} -/* Called at the end of assembly. Here we emit unwind info for frames - unless the compiler has done it for us. */ + *symbol_get_obj (alpha_evax_proc.symbol) = + (valueT) seginfo->literal_pool_size; -void -alpha_elf_md_end (void) -{ - struct alpha_elf_frame_data *p; + expression (&exp); + if (exp.X_op != O_symbol) + { + as_warn (_(".pdesc directive has no entry symbol")); + demand_empty_rest_of_line (); + return; + } - if (cur_frame_data) - as_warn (_(".ent directive without matching .end")); + entry_sym = make_expr_symbol (&exp); + /* Save bfd symbol of proc desc in function symbol. */ + symbol_get_bfdsym (alpha_evax_proc.symbol)->udata.p + = symbol_get_bfdsym (entry_sym); - /* If someone has generated the unwind info themselves, great. */ - if (bfd_get_section_by_name (stdoutput, ".eh_frame") != NULL) - return; + SKIP_WHITESPACE (); + if (*input_line_pointer++ != ',') + { + as_warn (_("No comma after .pdesc ")); + demand_empty_rest_of_line (); + return; + } - /* Generate .eh_frame data for the unwind directives specified. */ - for (p = all_frame_data; p ; p = p->next) - if (p->prologue_sym) - { - /* Create a temporary symbol at the same location as our - function symbol. This prevents problems with globals. */ - cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym), - S_GET_VALUE (p->func_sym), - symbol_get_frag (p->func_sym))); + SKIP_WHITESPACE (); + name = input_line_pointer; + name_end = get_symbol_end (); - cfi_set_return_column (p->ra_regno); - cfi_add_CFA_def_cfa_register (30); - if (p->fp_regno != 30 || p->mask || p->fmask || p->frame_size) - { - unsigned int mask; - offsetT offset; + if (strncmp (name, "stack", 5) == 0) + alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_STACK; - cfi_add_advance_loc (p->prologue_sym); + else if (strncmp (name, "reg", 3) == 0) + alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_REGISTER; - if (p->fp_regno != 30) - if (p->frame_size != 0) - cfi_add_CFA_def_cfa (p->fp_regno, p->frame_size); - else - cfi_add_CFA_def_cfa_register (p->fp_regno); - else if (p->frame_size != 0) - cfi_add_CFA_def_cfa_offset (p->frame_size); + else if (strncmp (name, "null", 4) == 0) + alpha_evax_proc.pdsckind = PDSC_S_K_KIND_NULL; - mask = p->mask; - offset = p->mask_offset; + else + { + as_fatal (_("unknown procedure kind")); + demand_empty_rest_of_line (); + return; + } - /* Recall that $26 is special-cased and stored first. */ - if ((mask >> 26) & 1) - { - cfi_add_CFA_offset (26, offset); - offset += 8; - mask &= ~(1 << 26); - } - while (mask) - { - unsigned int i; - i = mask & -mask; - mask ^= i; - i = ffs (i) - 1; + *input_line_pointer = name_end; + demand_empty_rest_of_line (); - cfi_add_CFA_offset (i, offset); - offset += 8; - } - - mask = p->fmask; - offset = p->fmask_offset; - while (mask) - { - unsigned int i; - i = mask & -mask; - mask ^= i; - i = ffs (i) - 1; - - cfi_add_CFA_offset (i + 32, offset); - offset += 8; - } - } - - cfi_end_fde (p->func_end_sym); - } -} - -static void -s_alpha_usepv (int unused ATTRIBUTE_UNUSED) -{ - char *name, name_end; - char *which, which_end; - symbolS *sym; - int other; - - name = input_line_pointer; - name_end = get_symbol_end (); - - if (! is_name_beginner (*name)) - { - as_bad (_(".usepv directive has no name")); - *input_line_pointer = name_end; - ignore_rest_of_line (); - return; - } - - sym = symbol_find_or_make (name); - *input_line_pointer++ = name_end; - - if (name_end != ',') - { - as_bad (_(".usepv directive has no type")); - ignore_rest_of_line (); - return; - } - - SKIP_WHITESPACE (); - which = input_line_pointer; - which_end = get_symbol_end (); - - if (strcmp (which, "no") == 0) - other = STO_ALPHA_NOPV; - else if (strcmp (which, "std") == 0) - other = STO_ALPHA_STD_GPLOAD; - else - { - as_bad (_("unknown argument for .usepv")); - other = 0; - } - - *input_line_pointer = which_end; - demand_empty_rest_of_line (); - - S_SET_OTHER (sym, other | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD)); -} -#endif /* OBJ_ELF */ - -/* Standard calling conventions leaves the CFA at $30 on entry. */ - -void -alpha_cfi_frame_initial_instructions () -{ - cfi_add_CFA_def_cfa_register (30); -} - -#ifdef OBJ_EVAX - -/* Handle the section specific pseudo-op. */ - -static void -s_alpha_section (secid) - int secid; -{ - int temp; -#define EVAX_SECTION_COUNT 5 - static char *section_name[EVAX_SECTION_COUNT + 1] = - { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" }; - - if ((secid <= 0) || (secid > EVAX_SECTION_COUNT)) - { - as_fatal (_("Unknown section directive")); - demand_empty_rest_of_line (); - return; - } - temp = get_absolute_expression (); - subseg_new (section_name[secid], 0); - demand_empty_rest_of_line (); - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} - -/* Parse .ent directives. */ - -static void -s_alpha_ent (ignore) - int ignore ATTRIBUTE_UNUSED; -{ - symbolS *symbol; - expressionS symexpr; - - alpha_evax_proc.pdsckind = 0; - alpha_evax_proc.framereg = -1; - alpha_evax_proc.framesize = 0; - alpha_evax_proc.rsa_offset = 0; - alpha_evax_proc.ra_save = AXP_REG_RA; - alpha_evax_proc.fp_save = -1; - alpha_evax_proc.imask = 0; - alpha_evax_proc.fmask = 0; - alpha_evax_proc.prologue = 0; - alpha_evax_proc.type = 0; - - expression (&symexpr); - - if (symexpr.X_op != O_symbol) - { - as_fatal (_(".ent directive has no symbol")); - demand_empty_rest_of_line (); - return; - } - - symbol = make_expr_symbol (&symexpr); - symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION; - alpha_evax_proc.symbol = symbol; - - demand_empty_rest_of_line (); -} - -/* Parse .frame ,,RA, directives. */ - -static void -s_alpha_frame (ignore) - int ignore ATTRIBUTE_UNUSED; -{ - long val; - - alpha_evax_proc.framereg = tc_get_register (1); - - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',' - || get_absolute_expression_and_terminator (&val) != ',') - { - as_warn (_("Bad .frame directive 1./2. param")); - --input_line_pointer; - demand_empty_rest_of_line (); - return; - } - - alpha_evax_proc.framesize = val; - - (void) tc_get_register (1); - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',') - { - as_warn (_("Bad .frame directive 3./4. param")); - --input_line_pointer; - demand_empty_rest_of_line (); - return; - } - alpha_evax_proc.rsa_offset = get_absolute_expression (); -} - -static void -s_alpha_pdesc (ignore) - int ignore ATTRIBUTE_UNUSED; -{ - char *name; - char name_end; - long val; - register char *p; - expressionS exp; - symbolS *entry_sym; - fixS *fixp; - segment_info_type *seginfo = seg_info (alpha_link_section); - - if (now_seg != alpha_link_section) - { - as_bad (_(".pdesc directive not in link (.link) section")); - demand_empty_rest_of_line (); - return; - } - - if ((alpha_evax_proc.symbol == 0) - || (!S_IS_DEFINED (alpha_evax_proc.symbol))) - { - as_fatal (_(".pdesc has no matching .ent")); - demand_empty_rest_of_line (); - return; - } - - *symbol_get_obj (alpha_evax_proc.symbol) = - (valueT) seginfo->literal_pool_size; - - expression (&exp); - if (exp.X_op != O_symbol) - { - as_warn (_(".pdesc directive has no entry symbol")); - demand_empty_rest_of_line (); - return; - } - - entry_sym = make_expr_symbol (&exp); - /* Save bfd symbol of proc desc in function symbol. */ - symbol_get_bfdsym (alpha_evax_proc.symbol)->udata.p - = symbol_get_bfdsym (entry_sym); - - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',') - { - as_warn (_("No comma after .pdesc ")); - demand_empty_rest_of_line (); - return; - } - - SKIP_WHITESPACE (); - name = input_line_pointer; - name_end = get_symbol_end (); - - if (strncmp (name, "stack", 5) == 0) - { - alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_STACK; - } - else if (strncmp (name, "reg", 3) == 0) - { - alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_REGISTER; - } - else if (strncmp (name, "null", 4) == 0) - { - alpha_evax_proc.pdsckind = PDSC_S_K_KIND_NULL; - } - else - { - as_fatal (_("unknown procedure kind")); - demand_empty_rest_of_line (); - return; - } - - *input_line_pointer = name_end; - demand_empty_rest_of_line (); - -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif frag_align (3, 0, 0); p = frag_more (16); @@ -5097,10 +4118,9 @@ s_alpha_pdesc (ignore) /* Support for crash debug on vms. */ static void -s_alpha_name (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_name (int ignore ATTRIBUTE_UNUSED) { - register char *p; + char *p; expressionS exp; segment_info_type *seginfo = seg_info (alpha_link_section); @@ -5133,8 +4153,7 @@ s_alpha_name (ignore) } static void -s_alpha_linkage (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_linkage (int ignore ATTRIBUTE_UNUSED) { expressionS exp; char *p; @@ -5159,8 +4178,7 @@ s_alpha_linkage (ignore) } static void -s_alpha_code_address (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_code_address (int ignore ATTRIBUTE_UNUSED) { expressionS exp; char *p; @@ -5171,9 +4189,7 @@ s_alpha_code_address (ignore) expression (&exp); if (exp.X_op != O_symbol) - { - as_fatal (_("No symbol after .code_address")); - } + as_fatal (_("No symbol after .code_address")); else { p = frag_more (8); @@ -5185,8 +4201,7 @@ s_alpha_code_address (ignore) } static void -s_alpha_fp_save (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_fp_save (int ignore ATTRIBUTE_UNUSED) { alpha_evax_proc.fp_save = tc_get_register (1); @@ -5195,8 +4210,7 @@ s_alpha_fp_save (ignore) } static void -s_alpha_mask (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_mask (int ignore ATTRIBUTE_UNUSED) { long val; @@ -5214,8 +4228,7 @@ s_alpha_mask (ignore) } static void -s_alpha_fmask (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_fmask (int ignore ATTRIBUTE_UNUSED) { long val; @@ -5233,8 +4246,7 @@ s_alpha_fmask (ignore) } static void -s_alpha_end (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_end (int ignore ATTRIBUTE_UNUSED) { char c; @@ -5245,8 +4257,7 @@ s_alpha_end (ignore) } static void -s_alpha_file (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_file (int ignore ATTRIBUTE_UNUSED) { symbolS *s; int length; @@ -5268,8 +4279,7 @@ s_alpha_file (ignore) /* Handle the .gprel32 pseudo op. */ static void -s_alpha_gprel32 (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_gprel32 (int ignore ATTRIBUTE_UNUSED) { expressionS e; char *p; @@ -5323,8 +4333,7 @@ s_alpha_gprel32 (ignore) correctly aligned. */ static void -s_alpha_float_cons (type) - int type; +s_alpha_float_cons (int type) { int log_size; @@ -5363,8 +4372,7 @@ s_alpha_float_cons (type) parse it. */ static void -s_alpha_proc (is_static) - int is_static ATTRIBUTE_UNUSED; +s_alpha_proc (int is_static ATTRIBUTE_UNUSED) { char *name; char c; @@ -5372,7 +4380,7 @@ s_alpha_proc (is_static) symbolS *symbolP; int temp; - /* Takes ".proc name,nargs" */ + /* Takes ".proc name,nargs". */ SKIP_WHITESPACE (); name = input_line_pointer; c = get_symbol_end (); @@ -5402,8 +4410,7 @@ s_alpha_proc (is_static) the assembler features. */ static void -s_alpha_set (x) - int x ATTRIBUTE_UNUSED; +s_alpha_set (int x ATTRIBUTE_UNUSED) { char *name, ch, *s; int yesno = 1; @@ -5439,12 +4446,13 @@ s_alpha_set (x) the $gp register. */ static void -s_alpha_base (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_base (int ignore ATTRIBUTE_UNUSED) { SKIP_WHITESPACE (); + if (*input_line_pointer == '$') - { /* $rNN form */ + { + /* $rNN form. */ input_line_pointer++; if (*input_line_pointer == 'r') input_line_pointer++; @@ -5465,8 +4473,7 @@ s_alpha_base (ignore) way the MIPS port does: .align 0 turns off auto alignment. */ static void -s_alpha_align (ignore) - int ignore ATTRIBUTE_UNUSED; +s_alpha_align (int ignore ATTRIBUTE_UNUSED) { int align; char fill, *pfill; @@ -5509,8 +4516,7 @@ s_alpha_align (ignore) /* Hook the normal string processor to reset known alignment. */ static void -s_alpha_stringer (terminate) - int terminate; +s_alpha_stringer (int terminate) { alpha_current_align = 0; alpha_insn_label = NULL; @@ -5520,8 +4526,7 @@ s_alpha_stringer (terminate) /* Hook the normal space processing to reset known alignment. */ static void -s_alpha_space (ignore) - int ignore; +s_alpha_space (int ignore) { alpha_current_align = 0; alpha_insn_label = NULL; @@ -5531,8 +4536,7 @@ s_alpha_space (ignore) /* Hook into cons for auto-alignment. */ void -alpha_cons_align (size) - int size; +alpha_cons_align (int size) { int log_size; @@ -5551,8 +4555,7 @@ alpha_cons_align (size) pseudos. We just turn off auto-alignment and call down to cons. */ static void -s_alpha_ucons (bytes) - int bytes; +s_alpha_ucons (int bytes) { int hold = alpha_auto_align_on; alpha_auto_align_on = 0; @@ -5563,8 +4566,7 @@ s_alpha_ucons (bytes) /* Switch the working cpu type. */ static void -s_alpha_arch (ignored) - int ignored ATTRIBUTE_UNUSED; +s_alpha_arch (int ignored ATTRIBUTE_UNUSED) { char *name, ch; const struct cpu_type *p; @@ -5590,9 +4592,7 @@ found: /* print token expression with alpha specific extension. */ static void -alpha_print_token (f, exp) - FILE *f; - const expressionS *exp; +alpha_print_token (FILE *f, const expressionS *exp) { switch (exp->X_op) { @@ -5617,9 +4617,10 @@ alpha_print_token (f, exp) /* The target specific pseudo-ops which we support. */ -const pseudo_typeS md_pseudo_table[] = { +const pseudo_typeS md_pseudo_table[] = +{ #ifdef OBJ_ECOFF - {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */ + {"comm", s_alpha_comm, 0}, /* OSF1 compiler does this. */ {"rdata", s_alpha_rdata, 0}, #endif {"text", s_alpha_text, 0}, @@ -5726,184 +4727,975 @@ const pseudo_typeS md_pseudo_table[] = { {NULL, 0, 0}, }; -/* Build a BFD section with its flags set appropriately for the .lita, - .lit8, or .lit4 sections. */ +#ifdef OBJ_ECOFF -static void -create_literal_section (name, secp, symp) - const char *name; - segT *secp; - symbolS **symp; +/* @@@ GP selection voodoo. All of this seems overly complicated and + unnecessary; which is the primary reason it's for ECOFF only. */ +static inline void maybe_set_gp PARAMS ((asection *)); + +static inline void +maybe_set_gp (asection *sec) { - segT current_section = now_seg; - int current_subsec = now_subseg; - segT new_sec; + bfd_vma vma; + + if (!sec) + return; + vma = bfd_get_section_vma (foo, sec); + if (vma && vma < alpha_gp_value) + alpha_gp_value = vma; +} + +static void +select_gp_value (void) +{ + assert (alpha_gp_value == 0); + + /* Get minus-one in whatever width... */ + alpha_gp_value = 0; + alpha_gp_value--; + + /* Select the smallest VMA of these existing sections. */ + maybe_set_gp (alpha_lita_section); + +/* @@ Will a simple 0x8000 work here? If not, why not? */ +#define GP_ADJUSTMENT (0x8000 - 0x10) + + alpha_gp_value += GP_ADJUSTMENT; + + S_SET_VALUE (alpha_gp_symbol, alpha_gp_value); + +#ifdef DEBUG1 + printf (_("Chose GP value of %lx\n"), alpha_gp_value); +#endif +} +#endif /* OBJ_ECOFF */ + +#ifdef OBJ_ELF +/* Map 's' to SHF_ALPHA_GPREL. */ + +int +alpha_elf_section_letter (int letter, char **ptr_msg) +{ + if (letter == 's') + return SHF_ALPHA_GPREL; + + *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string"); + return -1; +} + +/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */ + +flagword +alpha_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED) +{ + if (attr & SHF_ALPHA_GPREL) + flags |= SEC_SMALL_DATA; + return flags; +} +#endif /* OBJ_ELF */ + +/* This is called from HANDLE_ALIGN in write.c. Fill in the contents + of an rs_align_code fragment. */ + +void +alpha_handle_align (fragS *fragp) +{ + static char const unop[4] = { 0x00, 0x00, 0xfe, 0x2f }; + static char const nopunop[8] = + { + 0x1f, 0x04, 0xff, 0x47, + 0x00, 0x00, 0xfe, 0x2f + }; + + int bytes, fix; + char *p; + + if (fragp->fr_type != rs_align_code) + return; + + bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; + p = fragp->fr_literal + fragp->fr_fix; + fix = 0; + + if (bytes & 3) + { + fix = bytes & 3; + memset (p, 0, fix); + p += fix; + bytes -= fix; + } + + if (bytes & 4) + { + memcpy (p, unop, 4); + p += 4; + bytes -= 4; + fix += 4; + } + + memcpy (p, nopunop, 8); + + fragp->fr_fix += fix; + fragp->fr_var = 8; +} + +/* Public interface functions. */ + +/* This function is called once, at assembler startup time. It sets + up all the tables, etc. that the MD part of the assembler will + need, that can be determined before arguments are parsed. */ + +void +md_begin (void) +{ + unsigned int i; + + /* Verify that X_op field is wide enough. */ + { + expressionS e; + + e.X_op = O_max; + assert (e.X_op == O_max); + } + + /* Create the opcode hash table. */ + alpha_opcode_hash = hash_new (); + + for (i = 0; i < alpha_num_opcodes;) + { + const char *name, *retval, *slash; + + name = alpha_opcodes[i].name; + retval = hash_insert (alpha_opcode_hash, name, (void *) &alpha_opcodes[i]); + if (retval) + as_fatal (_("internal error: can't hash opcode `%s': %s"), + name, retval); + + /* Some opcodes include modifiers of various sorts with a "/mod" + syntax, like the architecture manual suggests. However, for + use with gcc at least, we also need access to those same opcodes + without the "/". */ + + if ((slash = strchr (name, '/')) != NULL) + { + char *p = xmalloc (strlen (name)); + + memcpy (p, name, slash - name); + strcpy (p + (slash - name), slash + 1); + + (void) hash_insert (alpha_opcode_hash, p, (void *) &alpha_opcodes[i]); + /* Ignore failures -- the opcode table does duplicate some + variants in different forms, like "hw_stq" and "hw_st/q". */ + } + + while (++i < alpha_num_opcodes + && (alpha_opcodes[i].name == name + || !strcmp (alpha_opcodes[i].name, name))) + continue; + } + + /* Create the macro hash table. */ + alpha_macro_hash = hash_new (); + + for (i = 0; i < alpha_num_macros;) + { + const char *name, *retval; + + name = alpha_macros[i].name; + retval = hash_insert (alpha_macro_hash, name, (void *) &alpha_macros[i]); + if (retval) + as_fatal (_("internal error: can't hash macro `%s': %s"), + name, retval); + + while (++i < alpha_num_macros + && (alpha_macros[i].name == name + || !strcmp (alpha_macros[i].name, name))) + continue; + } + + /* Construct symbols for each of the registers. */ + for (i = 0; i < 32; ++i) + { + char name[4]; + + sprintf (name, "$%d", i); + alpha_register_table[i] = symbol_create (name, reg_section, i, + &zero_address_frag); + } + + for (; i < 64; ++i) + { + char name[5]; + + sprintf (name, "$f%d", i - 32); + alpha_register_table[i] = symbol_create (name, reg_section, i, + &zero_address_frag); + } + + /* Create the special symbols and sections we'll be using. */ + + /* So .sbss will get used for tiny objects. */ + bfd_set_gp_size (stdoutput, g_switch_value); + +#ifdef OBJ_ECOFF + create_literal_section (".lita", &alpha_lita_section, &alpha_lita_symbol); + + /* For handling the GP, create a symbol that won't be output in the + symbol table. We'll edit it out of relocs later. */ + alpha_gp_symbol = symbol_create ("", alpha_lita_section, 0x8000, + &zero_address_frag); +#endif + +#ifdef OBJ_EVAX + create_literal_section (".link", &alpha_link_section, &alpha_link_symbol); +#endif + +#ifdef OBJ_ELF + if (ECOFF_DEBUGGING) + { + segT sec = subseg_new (".mdebug", (subsegT) 0); + bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY); + bfd_set_section_alignment (stdoutput, sec, 3); + } +#endif + + /* Create literal lookup hash table. */ + alpha_literal_hash = hash_new (); + + subseg_set (text_section, 0); +} + +/* The public interface to the instruction assembler. */ + +void +md_assemble (char *str) +{ + /* Current maximum is 13. */ + char opname[32]; + expressionS tok[MAX_INSN_ARGS]; + int ntok, trunclen; + size_t opnamelen; + + /* Split off the opcode. */ + opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/46819"); + trunclen = (opnamelen < sizeof (opname) - 1 + ? opnamelen + : sizeof (opname) - 1); + memcpy (opname, str, trunclen); + opname[trunclen] = '\0'; + + /* Tokenize the rest of the line. */ + if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0) + { + if (ntok != TOKENIZE_ERROR_REPORT) + as_bad (_("syntax error")); + + return; + } + + /* Finish it off. */ + assemble_tokens (opname, tok, ntok, alpha_macros_on); +} + +/* Round up a section's size to the appropriate boundary. */ + +valueT +md_section_align (segT seg, valueT size) +{ + int align = bfd_get_section_alignment (stdoutput, seg); + valueT mask = ((valueT) 1 << align) - 1; + + return (size + mask) & ~mask; +} + +/* Turn a string in input_line_pointer into a floating point constant + of type TYPE, and store the appropriate bytes in *LITP. The number + of LITTLENUMS emitted is stored in *SIZEP. An error message is + returned, or NULL on OK. */ + +/* Equal to MAX_PRECISION in atof-ieee.c. */ +#define MAX_LITTLENUMS 6 + +extern char *vax_md_atof (int, char *, int *); + +char * +md_atof (int type, char *litP, int *sizeP) +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + + switch (type) + { + /* VAX floats. */ + case 'G': + /* VAX md_atof doesn't like "G" for some reason. */ + type = 'g'; + case 'F': + case 'D': + return vax_md_atof (type, litP, sizeP); + + /* IEEE floats. */ + case 'f': + prec = 2; + break; + + case 'd': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return _("Bad call to MD_ATOF()"); + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * sizeof (LITTLENUM_TYPE); + + for (wordP = words + prec - 1; prec--;) + { + md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + + return 0; +} + +/* Take care of the target-specific command-line options. */ + +int +md_parse_option (int c, char *arg) +{ + switch (c) + { + case 'F': + alpha_nofloats_on = 1; + break; + + case OPTION_32ADDR: + alpha_addr32_on = 1; + break; + + case 'g': + alpha_debug = 1; + break; + + case 'G': + g_switch_value = atoi (arg); + break; + + case 'm': + { + const struct cpu_type *p; + + for (p = cpu_types; p->name; ++p) + if (strcmp (arg, p->name) == 0) + { + alpha_target_name = p->name, alpha_target = p->flags; + goto found; + } + as_warn (_("Unknown CPU identifier `%s'"), arg); + found:; + } + break; + +#ifdef OBJ_EVAX + case '+': /* For g++. Hash any name > 63 chars long. */ + alpha_flag_hash_long_names = 1; + break; + + case 'H': /* Show new symbol after hash truncation. */ + alpha_flag_show_after_trunc = 1; + break; + + case 'h': /* For gnu-c/vax compatibility. */ + break; +#endif + + case OPTION_RELAX: + alpha_flag_relax = 1; + break; + +#ifdef OBJ_ELF + case OPTION_MDEBUG: + alpha_flag_mdebug = 1; + break; + case OPTION_NO_MDEBUG: + alpha_flag_mdebug = 0; + break; +#endif + + default: + return 0; + } + + return 1; +} + +/* Print a description of the command-line options that we accept. */ + +void +md_show_usage (FILE *stream) +{ + fputs (_("\ +Alpha options:\n\ +-32addr treat addresses as 32-bit values\n\ +-F lack floating point instructions support\n\ +-mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mev67 | -mev68 | -mall\n\ + specify variant of Alpha architecture\n\ +-m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264 | -m21264a | -m21264b\n\ + these variants include PALcode opcodes\n"), + stream); +#ifdef OBJ_EVAX + fputs (_("\ +VMS options:\n\ +-+ hash encode (don't truncate) names longer than 64 characters\n\ +-H show new symbol after hash truncation\n"), + stream); +#endif +} + +/* Decide from what point a pc-relative relocation is relative to, + relative to the pc-relative fixup. Er, relatively speaking. */ + +long +md_pcrel_from (fixS *fixP) +{ + valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; + + switch (fixP->fx_r_type) + { + case BFD_RELOC_23_PCREL_S2: + case BFD_RELOC_ALPHA_HINT: + case BFD_RELOC_ALPHA_BRSGP: + return addr + 4; + default: + return addr; + } +} + +/* Attempt to simplify or even eliminate a fixup. The return value is + ignored; perhaps it was once meaningful, but now it is historical. + To indicate that a fixup has been eliminated, set fixP->fx_done. + + For ELF, here it is that we transform the GPDISP_HI16 reloc we used + internally into the GPDISP reloc used externally. We had to do + this so that we'd have the GPDISP_LO16 reloc as a tag to compute + the distance to the "lda" instruction for setting the addend to + GPDISP. */ + +void +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg) +{ + char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; + valueT value = * valP; + unsigned image, size; + + switch (fixP->fx_r_type) + { + /* The GPDISP relocations are processed internally with a symbol + referring to the current function's section; we need to drop + in a value which, when added to the address of the start of + the function, gives the desired GP. */ + case BFD_RELOC_ALPHA_GPDISP_HI16: + { + fixS *next = fixP->fx_next; + + /* With user-specified !gpdisp relocations, we can be missing + the matching LO16 reloc. We will have already issued an + error message. */ + if (next) + fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where + - fixP->fx_frag->fr_address - fixP->fx_where); + + value = (value - sign_extend_16 (value)) >> 16; + } +#ifdef OBJ_ELF + fixP->fx_r_type = BFD_RELOC_ALPHA_GPDISP; +#endif + goto do_reloc_gp; + + case BFD_RELOC_ALPHA_GPDISP_LO16: + value = sign_extend_16 (value); + fixP->fx_offset = 0; +#ifdef OBJ_ELF + fixP->fx_done = 1; +#endif + + do_reloc_gp: + fixP->fx_addsy = section_symbol (seg); + md_number_to_chars (fixpos, value, 2); + break; + + case BFD_RELOC_16: + if (fixP->fx_pcrel) + fixP->fx_r_type = BFD_RELOC_16_PCREL; + size = 2; + goto do_reloc_xx; + + case BFD_RELOC_32: + if (fixP->fx_pcrel) + fixP->fx_r_type = BFD_RELOC_32_PCREL; + size = 4; + goto do_reloc_xx; + + case BFD_RELOC_64: + if (fixP->fx_pcrel) + fixP->fx_r_type = BFD_RELOC_64_PCREL; + size = 8; + + do_reloc_xx: + if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) + { + md_number_to_chars (fixpos, value, size); + goto done; + } + return; + +#ifdef OBJ_ECOFF + case BFD_RELOC_GPREL32: + assert (fixP->fx_subsy == alpha_gp_symbol); + fixP->fx_subsy = 0; + /* FIXME: inherited this obliviousness of `value' -- why? */ + md_number_to_chars (fixpos, -alpha_gp_value, 4); + break; +#else + case BFD_RELOC_GPREL32: +#endif + case BFD_RELOC_GPREL16: + case BFD_RELOC_ALPHA_GPREL_HI16: + case BFD_RELOC_ALPHA_GPREL_LO16: + return; + + case BFD_RELOC_23_PCREL_S2: + if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) + { + image = bfd_getl32 (fixpos); + image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF); + goto write_done; + } + return; + + case BFD_RELOC_ALPHA_HINT: + if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0) + { + image = bfd_getl32 (fixpos); + image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF); + goto write_done; + } + return; + +#ifdef OBJ_ELF + case BFD_RELOC_ALPHA_BRSGP: + return; + + case BFD_RELOC_ALPHA_TLSGD: + case BFD_RELOC_ALPHA_TLSLDM: + case BFD_RELOC_ALPHA_GOTDTPREL16: + case BFD_RELOC_ALPHA_DTPREL_HI16: + case BFD_RELOC_ALPHA_DTPREL_LO16: + case BFD_RELOC_ALPHA_DTPREL16: + case BFD_RELOC_ALPHA_GOTTPREL16: + case BFD_RELOC_ALPHA_TPREL_HI16: + case BFD_RELOC_ALPHA_TPREL_LO16: + case BFD_RELOC_ALPHA_TPREL16: + if (fixP->fx_addsy) + S_SET_THREAD_LOCAL (fixP->fx_addsy); + return; +#endif + +#ifdef OBJ_ECOFF + case BFD_RELOC_ALPHA_LITERAL: + md_number_to_chars (fixpos, value, 2); + return; +#endif + case BFD_RELOC_ALPHA_ELF_LITERAL: + case BFD_RELOC_ALPHA_LITUSE: + case BFD_RELOC_ALPHA_LINKAGE: + case BFD_RELOC_ALPHA_CODEADDR: + return; + + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: + return; + + default: + { + const struct alpha_operand *operand; + + if ((int) fixP->fx_r_type >= 0) + as_fatal (_("unhandled relocation type %s"), + bfd_get_reloc_code_name (fixP->fx_r_type)); + + assert (-(int) fixP->fx_r_type < (int) alpha_num_operands); + operand = &alpha_operands[-(int) fixP->fx_r_type]; + + /* The rest of these fixups only exist internally during symbol + resolution and have no representation in the object file. + Therefore they must be completely resolved as constants. */ + + if (fixP->fx_addsy != 0 + && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("non-absolute expression in constant field")); + + image = bfd_getl32 (fixpos); + image = insert_operand (image, operand, (offsetT) value, + fixP->fx_file, fixP->fx_line); + } + goto write_done; + } + + if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0) + return; + else + { + as_warn_where (fixP->fx_file, fixP->fx_line, + _("type %d reloc done?\n"), (int) fixP->fx_r_type); + goto done; + } + +write_done: + md_number_to_chars (fixpos, image, 4); + +done: + fixP->fx_done = 1; +} + +/* Look for a register name in the given symbol. */ + +symbolS * +md_undefined_symbol (char *name) +{ + if (*name == '$') + { + int is_float = 0, num; + + switch (*++name) + { + case 'f': + if (name[1] == 'p' && name[2] == '\0') + return alpha_register_table[AXP_REG_FP]; + is_float = 32; + /* Fall through. */ + + case 'r': + if (!ISDIGIT (*++name)) + break; + /* Fall through. */ + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (name[1] == '\0') + num = name[0] - '0'; + else if (name[0] != '0' && ISDIGIT (name[1]) && name[2] == '\0') + { + num = (name[0] - '0') * 10 + name[1] - '0'; + if (num >= 32) + break; + } + else + break; + + if (!alpha_noat_on && (num + is_float) == AXP_REG_AT) + as_warn (_("Used $at without \".set noat\"")); + return alpha_register_table[num + is_float]; + + case 'a': + if (name[1] == 't' && name[2] == '\0') + { + if (!alpha_noat_on) + as_warn (_("Used $at without \".set noat\"")); + return alpha_register_table[AXP_REG_AT]; + } + break; + + case 'g': + if (name[1] == 'p' && name[2] == '\0') + return alpha_register_table[alpha_gp_register]; + break; + + case 's': + if (name[1] == 'p' && name[2] == '\0') + return alpha_register_table[AXP_REG_SP]; + break; + } + } + return NULL; +} + +#ifdef OBJ_ECOFF +/* @@@ Magic ECOFF bits. */ + +void +alpha_frob_ecoff_data (void) +{ + select_gp_value (); + /* $zero and $f31 are read-only. */ + alpha_gprmask &= ~1; + alpha_fprmask &= ~1; +} +#endif + +/* Hook to remember a recently defined label so that the auto-align + code can adjust the symbol after we know what alignment will be + required. */ + +void +alpha_define_label (symbolS *sym) +{ + alpha_insn_label = sym; +} + +/* Return true if we must always emit a reloc for a type and false if + there is some hope of resolving it at assembly time. */ + +int +alpha_force_relocation (fixS *f) +{ + if (alpha_flag_relax) + return 1; + + switch (f->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + case BFD_RELOC_ALPHA_GPDISP: + case BFD_RELOC_ALPHA_LITERAL: + case BFD_RELOC_ALPHA_ELF_LITERAL: + case BFD_RELOC_ALPHA_LITUSE: + case BFD_RELOC_GPREL16: + case BFD_RELOC_GPREL32: + case BFD_RELOC_ALPHA_GPREL_HI16: + case BFD_RELOC_ALPHA_GPREL_LO16: + case BFD_RELOC_ALPHA_LINKAGE: + case BFD_RELOC_ALPHA_CODEADDR: + case BFD_RELOC_ALPHA_BRSGP: + case BFD_RELOC_ALPHA_TLSGD: + case BFD_RELOC_ALPHA_TLSLDM: + case BFD_RELOC_ALPHA_GOTDTPREL16: + case BFD_RELOC_ALPHA_DTPREL_HI16: + case BFD_RELOC_ALPHA_DTPREL_LO16: + case BFD_RELOC_ALPHA_DTPREL16: + case BFD_RELOC_ALPHA_GOTTPREL16: + case BFD_RELOC_ALPHA_TPREL_HI16: + case BFD_RELOC_ALPHA_TPREL_LO16: + case BFD_RELOC_ALPHA_TPREL16: + return 1; - *secp = new_sec = subseg_new (name, 0); - subseg_set (current_section, current_subsec); - bfd_set_section_alignment (stdoutput, new_sec, 4); - bfd_set_section_flags (stdoutput, new_sec, - SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY - | SEC_DATA); + default: + break; + } - S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec)); + return generic_force_reloc (f); } -#ifdef OBJ_ECOFF - -/* @@@ GP selection voodoo. All of this seems overly complicated and - unnecessary; which is the primary reason it's for ECOFF only. */ -static inline void maybe_set_gp PARAMS ((asection *)); +/* Return true if we can partially resolve a relocation now. */ -static inline void -maybe_set_gp (sec) - asection *sec; +int +alpha_fix_adjustable (fixS *f) { - bfd_vma vma; - if (!sec) - return; - vma = bfd_get_section_vma (foo, sec); - if (vma && vma < alpha_gp_value) - alpha_gp_value = vma; -} + /* Are there any relocation types for which we must generate a + reloc but we can adjust the values contained within it? */ + switch (f->fx_r_type) + { + case BFD_RELOC_ALPHA_GPDISP_HI16: + case BFD_RELOC_ALPHA_GPDISP_LO16: + case BFD_RELOC_ALPHA_GPDISP: + return 0; -static void -select_gp_value () -{ - assert (alpha_gp_value == 0); + case BFD_RELOC_ALPHA_LITERAL: + case BFD_RELOC_ALPHA_ELF_LITERAL: + case BFD_RELOC_ALPHA_LITUSE: + case BFD_RELOC_ALPHA_LINKAGE: + case BFD_RELOC_ALPHA_CODEADDR: + return 1; - /* Get minus-one in whatever width... */ - alpha_gp_value = 0; - alpha_gp_value--; + case BFD_RELOC_VTABLE_ENTRY: + case BFD_RELOC_VTABLE_INHERIT: + return 0; - /* Select the smallest VMA of these existing sections. */ - maybe_set_gp (alpha_lita_section); + case BFD_RELOC_GPREL16: + case BFD_RELOC_GPREL32: + case BFD_RELOC_ALPHA_GPREL_HI16: + case BFD_RELOC_ALPHA_GPREL_LO16: + case BFD_RELOC_23_PCREL_S2: + case BFD_RELOC_32: + case BFD_RELOC_64: + case BFD_RELOC_ALPHA_HINT: + return 1; -/* @@ Will a simple 0x8000 work here? If not, why not? */ -#define GP_ADJUSTMENT (0x8000 - 0x10) + case BFD_RELOC_ALPHA_TLSGD: + case BFD_RELOC_ALPHA_TLSLDM: + case BFD_RELOC_ALPHA_GOTDTPREL16: + case BFD_RELOC_ALPHA_DTPREL_HI16: + case BFD_RELOC_ALPHA_DTPREL_LO16: + case BFD_RELOC_ALPHA_DTPREL16: + case BFD_RELOC_ALPHA_GOTTPREL16: + case BFD_RELOC_ALPHA_TPREL_HI16: + case BFD_RELOC_ALPHA_TPREL_LO16: + case BFD_RELOC_ALPHA_TPREL16: + /* ??? No idea why we can't return a reference to .tbss+10, but + we're preventing this in the other assemblers. Follow for now. */ + return 0; - alpha_gp_value += GP_ADJUSTMENT; +#ifdef OBJ_ELF + case BFD_RELOC_ALPHA_BRSGP: + /* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and + let it get resolved at assembly time. */ + { + symbolS *sym = f->fx_addsy; + const char *name; + int offset = 0; - S_SET_VALUE (alpha_gp_symbol, alpha_gp_value); + if (generic_force_reloc (f)) + return 0; -#ifdef DEBUG1 - printf (_("Chose GP value of %lx\n"), alpha_gp_value); + switch (S_GET_OTHER (sym) & STO_ALPHA_STD_GPLOAD) + { + case STO_ALPHA_NOPV: + break; + case STO_ALPHA_STD_GPLOAD: + offset = 8; + break; + default: + if (S_IS_LOCAL (sym)) + name = ""; + else + name = S_GET_NAME (sym); + as_bad_where (f->fx_file, f->fx_line, + _("!samegp reloc against symbol without .prologue: %s"), + name); + break; + } + f->fx_r_type = BFD_RELOC_23_PCREL_S2; + f->fx_offset += offset; + return 1; + } #endif -} -#endif /* OBJ_ECOFF */ - -#ifdef OBJ_ELF -/* Map 's' to SHF_ALPHA_GPREL. */ - -int -alpha_elf_section_letter (letter, ptr_msg) - int letter; - char **ptr_msg; -{ - if (letter == 's') - return SHF_ALPHA_GPREL; - *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string"); - return -1; + default: + return 1; + } } -/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */ +/* Generate the BFD reloc to be stuck in the object file from the + fixup used internally in the assembler. */ -flagword -alpha_elf_section_flags (flags, attr, type) - flagword flags; - int attr, type ATTRIBUTE_UNUSED; +arelent * +tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, + fixS *fixp) { - if (attr & SHF_ALPHA_GPREL) - flags |= SEC_SMALL_DATA; - return flags; -} -#endif /* OBJ_ELF */ + arelent *reloc; -/* Called internally to handle all alignment needs. This takes care - of eliding calls to frag_align if'n the cached current alignment - says we've already got it, as well as taking care of the auto-align - feature wrt labels. */ + reloc = xmalloc (sizeof (* reloc)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; -static void -alpha_align (n, pfill, label, force) - int n; - char *pfill; - symbolS *label; - int force ATTRIBUTE_UNUSED; -{ - if (alpha_current_align >= n) - return; + /* Make sure none of our internal relocations make it this far. + They'd better have been fully resolved by this point. */ + assert ((int) fixp->fx_r_type > 0); - if (pfill == NULL) + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + if (reloc->howto == NULL) { - if (subseg_text_p (now_seg)) - frag_align_code (n, 0); - else - frag_align (n, 0, 0); + as_bad_where (fixp->fx_file, fixp->fx_line, + _("cannot represent `%s' relocation in object file"), + bfd_get_reloc_code_name (fixp->fx_r_type)); + return NULL; } - else - frag_align (n, *pfill, 0); - alpha_current_align = n; + if (!fixp->fx_pcrel != !reloc->howto->pc_relative) + as_fatal (_("internal error? cannot generate `%s' relocation"), + bfd_get_reloc_code_name (fixp->fx_r_type)); - if (label != NULL && S_GET_SEGMENT (label) == now_seg) + assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); + +#ifdef OBJ_ECOFF + if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL) + /* Fake out bfd_perform_relocation. sigh. */ + reloc->addend = -alpha_gp_value; + else +#endif { - symbol_set_frag (label, frag_now); - S_SET_VALUE (label, (valueT) frag_now_fix ()); + reloc->addend = fixp->fx_offset; +#ifdef OBJ_ELF + /* Ohhh, this is ugly. The problem is that if this is a local global + symbol, the relocation will entirely be performed at link time, not + at assembly time. bfd_perform_reloc doesn't know about this sort + of thing, and as a result we need to fake it out here. */ + if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy) + || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) + || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL)) + && !S_IS_COMMON (fixp->fx_addsy)) + reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value; +#endif } - record_alignment (now_seg, n); - - /* ??? If alpha_flag_relax && force && elf, record the requested alignment - in a reloc for the linker to see. */ + return reloc; } -/* This is called from HANDLE_ALIGN in write.c. Fill in the contents - of an rs_align_code fragment. */ - -void -alpha_handle_align (fragp) - fragS *fragp; -{ - static char const unop[4] = { 0x00, 0x00, 0xfe, 0x2f }; - static char const nopunop[8] = { - 0x1f, 0x04, 0xff, 0x47, - 0x00, 0x00, 0xfe, 0x2f - }; - - int bytes, fix; - char *p; +/* Parse a register name off of the input_line and return a register + number. Gets md_undefined_symbol above to do the register name + matching for us. - if (fragp->fr_type != rs_align_code) - return; + Only called as a part of processing the ECOFF .frame directive. */ - bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; - p = fragp->fr_literal + fragp->fr_fix; - fix = 0; +int +tc_get_register (int frame ATTRIBUTE_UNUSED) +{ + int framereg = AXP_REG_SP; - if (bytes & 3) + SKIP_WHITESPACE (); + if (*input_line_pointer == '$') { - fix = bytes & 3; - memset (p, 0, fix); - p += fix; - bytes -= fix; - } + char *s = input_line_pointer; + char c = get_symbol_end (); + symbolS *sym = md_undefined_symbol (s); - if (bytes & 4) - { - memcpy (p, unop, 4); - p += 4; - bytes -= 4; - fix += 4; + *strchr (s, '\0') = c; + if (sym && (framereg = S_GET_VALUE (sym)) <= 31) + goto found; } + as_warn (_("frame reg expected, using $%d."), framereg); - memcpy (p, nopunop, 8); +found: + note_gpreg (framereg); + return framereg; +} - fragp->fr_fix += fix; - fragp->fr_var = 8; +/* This is called before the symbol table is processed. In order to + work with gcc when using mips-tfile, we must keep all local labels. + However, in other cases, we want to discard them. If we were + called with -g, but we didn't see any debugging information, it may + mean that gcc is smuggling debugging information through to + mips-tfile, in which case we must generate all local labels. */ + +#ifdef OBJ_ECOFF + +void +alpha_frob_file_before_adjust (void) +{ + if (alpha_debug != 0 + && ! ecoff_debugging_seen) + flag_keep_locals = 1; } +#endif /* OBJ_ECOFF */ + /* The Alpha has support for some VAX floating point types, as well as for IEEE floating point. We consider IEEE to be the primary floating point format, and sneak in the VAX floating point support here. */ diff --git a/gas/config/tc-alpha.h b/gas/config/tc-alpha.h index ccb896ca93b..a4acc260b21 100644 --- a/gas/config/tc-alpha.h +++ b/gas/config/tc-alpha.h @@ -1,5 +1,6 @@ /* This file is tc-alpha.h Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 + 2005 Free Software Foundation, Inc. Written by Ken Raeburn . @@ -49,8 +50,8 @@ struct fix; struct alpha_reloc_tag; -extern int alpha_force_relocation PARAMS ((struct fix *)); -extern int alpha_fix_adjustable PARAMS ((struct fix *)); +extern int alpha_force_relocation (struct fix *); +extern int alpha_fix_adjustable (struct fix *); extern unsigned long alpha_gprmask, alpha_fprmask; extern valueT alpha_gp_value; @@ -97,32 +98,32 @@ extern valueT alpha_gp_value; #define md_number_to_chars number_to_chars_littleendian -extern int tc_get_register PARAMS ((int frame)); -extern void alpha_frob_ecoff_data PARAMS ((void)); +extern int tc_get_register (int); +extern void alpha_frob_ecoff_data (void); #define tc_frob_label(sym) alpha_define_label (sym) -extern void alpha_define_label PARAMS ((symbolS *)); +extern void alpha_define_label (symbolS *); #define md_cons_align(nbytes) alpha_cons_align (nbytes) -extern void alpha_cons_align PARAMS ((int)); +extern void alpha_cons_align (int); #define HANDLE_ALIGN(fragp) alpha_handle_align (fragp) -extern void alpha_handle_align PARAMS ((struct frag *)); +extern void alpha_handle_align (struct frag *); #define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4 + 8) #ifdef OBJ_ECOFF #define tc_frob_file_before_adjust() alpha_frob_file_before_adjust () -extern void alpha_frob_file_before_adjust PARAMS ((void)); +extern void alpha_frob_file_before_adjust (void); #endif -#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ +#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs. */ #ifdef OBJ_ELF #define md_elf_section_letter alpha_elf_section_letter -extern int alpha_elf_section_letter PARAMS ((int, char **)); +extern int alpha_elf_section_letter (int, char **); #define md_elf_section_flags alpha_elf_section_flags -extern flagword alpha_elf_section_flags PARAMS ((flagword, int, int)); +extern flagword alpha_elf_section_flags (flagword, int, int); #endif /* Whether to add support for explicit !relocation_op!sequence_number. At the @@ -137,11 +138,11 @@ extern flagword alpha_elf_section_flags PARAMS ((flagword, int, int)); relocations. Also convert the gas-internal relocations to the appropriate linker relocations. */ #define tc_frob_file_before_fix() alpha_before_fix () -extern void alpha_before_fix PARAMS ((void)); +extern void alpha_before_fix (void); #ifdef OBJ_ELF #define md_end alpha_elf_md_end -extern void alpha_elf_md_end PARAMS ((void)); +extern void alpha_elf_md_end (void); #endif /* New fields for supporting explicit relocations (such as !literal to mark @@ -152,15 +153,15 @@ extern void alpha_elf_md_end PARAMS ((void)); struct alpha_fix_tag { - struct fix *next_reloc; /* next !lituse or !gpdisp */ - struct alpha_reloc_tag *info; /* other members with same sequence */ + struct fix *next_reloc; /* Next !lituse or !gpdisp. */ + struct alpha_reloc_tag *info; /* Other members with same sequence. */ }; /* Initialize the TC_FIX_TYPE field. */ #define TC_INIT_FIX_DATA(FIX) \ do { \ - FIX->tc_fix_data.next_reloc = (struct fix *) 0; \ - FIX->tc_fix_data.info = (struct alpha_reloc_tag *) 0; \ + FIX->tc_fix_data.next_reloc = NULL; \ + FIX->tc_fix_data.info = NULL; \ } while (0) /* Work with DEBUG5 to print fields in tc_fix_type. */ @@ -175,7 +176,7 @@ do { \ #define TARGET_USE_CFIPOP 1 #define tc_cfi_frame_initial_instructions alpha_cfi_frame_initial_instructions -extern void alpha_cfi_frame_initial_instructions(void); +extern void alpha_cfi_frame_initial_instructions (void); #define DWARF2_LINE_MIN_INSN_LENGTH 4 #define DWARF2_DEFAULT_RETURN_COLUMN 26 diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c index 3bdb160aab8..17f67391a12 100644 --- a/gas/config/tc-arc.c +++ b/gas/config/tc-arc.c @@ -31,31 +31,12 @@ #include "elf/arc.h" #include "dwarf2dbg.h" -extern int arc_get_mach PARAMS ((char *)); -extern int arc_operand_type PARAMS ((int)); -extern int arc_insn_not_jl PARAMS ((arc_insn)); -extern int arc_limm_fixup_adjust PARAMS ((arc_insn)); -extern int arc_get_noshortcut_flag PARAMS ((void)); -extern int arc_set_ext_seg PARAMS ((void)); -extern void arc_code_symbol PARAMS ((expressionS *)); - -static arc_insn arc_insert_operand PARAMS ((arc_insn, - const struct arc_operand *, int, - const struct arc_operand_value *, - offsetT, char *, unsigned int)); -static void arc_common PARAMS ((int)); -static void arc_extinst PARAMS ((int)); -static void arc_extoper PARAMS ((int)); -static void arc_option PARAMS ((int)); -static int get_arc_exp_reloc_type PARAMS ((int, int, expressionS *, - expressionS *)); - -static void init_opcode_tables PARAMS ((int)); - -const struct suffix_classes { +const struct suffix_classes +{ char *name; int len; -} suffixclass[] = { +} suffixclass[] = +{ { "SUFFIX_COND|SUFFIX_FLAG",23 }, { "SUFFIX_FLAG", 11 }, { "SUFFIX_COND", 11 }, @@ -64,11 +45,13 @@ const struct suffix_classes { #define MAXSUFFIXCLASS (sizeof (suffixclass) / sizeof (struct suffix_classes)) -const struct syntax_classes { +const struct syntax_classes +{ char *name; int len; int class; -} syntaxclass[] = { +} syntaxclass[] = +{ { "SYNTAX_3OP|OP1_MUST_BE_IMM", 26, SYNTAX_3OP|OP1_MUST_BE_IMM|SYNTAX_VALID }, { "OP1_MUST_BE_IMM|SYNTAX_3OP", 26, OP1_MUST_BE_IMM|SYNTAX_3OP|SYNTAX_VALID }, { "SYNTAX_2OP|OP1_IMM_IMPLIED", 26, SYNTAX_2OP|OP1_IMM_IMPLIED|SYNTAX_VALID }, @@ -79,28 +62,6 @@ const struct syntax_classes { #define MAXSYNTAXCLASS (sizeof (syntaxclass) / sizeof (struct syntax_classes)) -const pseudo_typeS md_pseudo_table[] = { - { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */ - { "comm", arc_common, 0 }, - { "common", arc_common, 0 }, - { "lcomm", arc_common, 1 }, - { "lcommon", arc_common, 1 }, - { "2byte", cons, 2 }, - { "half", cons, 2 }, - { "short", cons, 2 }, - { "3byte", cons, 3 }, - { "4byte", cons, 4 }, - { "word", cons, 4 }, - { "option", arc_option, 0 }, - { "cpu", arc_option, 0 }, - { "block", s_space, 0 }, - { "extcondcode", arc_extoper, 0 }, - { "extcoreregister", arc_extoper, 1 }, - { "extauxregister", arc_extoper, 2 }, - { "extinstruction", arc_extinst, 0 }, - { NULL, 0, 0 }, -}; - /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful. */ const char comment_chars[] = "#;"; @@ -144,21 +105,27 @@ static int cpu_tables_init_p = 0; static struct hash_control *arc_suffix_hash = NULL; const char *md_shortopts = ""; -struct option md_longopts[] = { -#define OPTION_EB (OPTION_MD_BASE + 0) + +enum options +{ + OPTION_EB = OPTION_MD_BASE, + OPTION_EL, + OPTION_ARC5, + OPTION_ARC6, + OPTION_ARC7, + OPTION_ARC8, + OPTION_ARC +}; + +struct option md_longopts[] = +{ { "EB", no_argument, NULL, OPTION_EB }, -#define OPTION_EL (OPTION_MD_BASE + 1) { "EL", no_argument, NULL, OPTION_EL }, -#define OPTION_ARC5 (OPTION_MD_BASE + 2) { "marc5", no_argument, NULL, OPTION_ARC5 }, { "pre-v6", no_argument, NULL, OPTION_ARC5 }, -#define OPTION_ARC6 (OPTION_MD_BASE + 3) { "marc6", no_argument, NULL, OPTION_ARC6 }, -#define OPTION_ARC7 (OPTION_MD_BASE + 4) { "marc7", no_argument, NULL, OPTION_ARC7 }, -#define OPTION_ARC8 (OPTION_MD_BASE + 5) { "marc8", no_argument, NULL, OPTION_ARC8 }, -#define OPTION_ARC (OPTION_MD_BASE + 6) { "marc", no_argument, NULL, OPTION_ARC }, { NULL, no_argument, NULL, 0 } }; @@ -173,9 +140,7 @@ struct arc_operand_value *get_ext_suffix (char *s); See if it's a processor-specific option. */ int -md_parse_option (c, arg) - int c; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) { switch (c) { @@ -207,8 +172,7 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, "\ ARC Options:\n\ @@ -223,7 +187,7 @@ ARC Options:\n\ command. */ void -md_begin () +md_begin (void) { /* The endianness can be chosen "at the factory". */ target_big_endian = byte_order == BIG_ENDIAN; @@ -239,9 +203,9 @@ md_begin () /* Initialize the various opcode and operand tables. MACH is one of bfd_mach_arc_xxx. */ + static void -init_opcode_tables (mach) - int mach; +init_opcode_tables (int mach) { int i; char *last; @@ -262,7 +226,7 @@ init_opcode_tables (mach) for (i = 0; i < arc_suffixes_count; i++) { if (strcmp (arc_suffixes[i].name, last) != 0) - hash_insert (arc_suffix_hash, arc_suffixes[i].name, (PTR) (arc_suffixes + i)); + hash_insert (arc_suffix_hash, arc_suffixes[i].name, (void *) (arc_suffixes + i)); last = arc_suffixes[i].name; } @@ -294,14 +258,13 @@ init_opcode_tables (mach) If REG is non-NULL, it is a register number and ignore VAL. */ static arc_insn -arc_insert_operand (insn, operand, mods, reg, val, file, line) - arc_insn insn; - const struct arc_operand *operand; - int mods; - const struct arc_operand_value *reg; - offsetT val; - char *file; - unsigned int line; +arc_insert_operand (arc_insn insn, + const struct arc_operand *operand, + int mods, + const struct arc_operand_value *reg, + offsetT val, + char *file, + unsigned int line) { if (operand->bits != 32) { @@ -351,7 +314,8 @@ arc_insert_operand (insn, operand, mods, reg, val, file, line) we go, because that would require us to first create the frag, and that would screw up references to ``.''. */ -struct arc_fixup { +struct arc_fixup +{ /* index into `arc_operands' */ int opindex; expressionS exp; @@ -361,525 +325,331 @@ struct arc_fixup { #define MAX_SUFFIXES 5 -/* This routine is called for each instruction to be assembled. */ +/* Compute the reloc type of an expression. + The possibly modified expression is stored in EXPNEW. -void -md_assemble (str) - char *str; + This is used to convert the expressions generated by the %-op's into + the appropriate operand type. It is called for both data in instructions + (operands) and data outside instructions (variables, debugging info, etc.). + + Currently supported %-ops: + + %st(symbol): represented as "symbol >> 2" + "st" is short for STatus as in the status register (pc) + + DEFAULT_TYPE is the type to use if no special processing is required. + + DATA_P is non-zero for data or limm values, zero for insn operands. + Remember that the opcode "insertion fns" cannot be used on data, they're + only for inserting operands into insns. They also can't be used for limm + values as the insertion routines don't handle limm values. When called for + insns we return fudged reloc types (real_value - BFD_RELOC_UNUSED). When + called for data or limm values we use real reloc types. */ + +static int +get_arc_exp_reloc_type (int data_p, + int default_type, + expressionS *exp, + expressionS *expnew) { - const struct arc_opcode *opcode; - const struct arc_opcode *std_opcode; - struct arc_opcode *ext_opcode; - char *start; - const char *last_errmsg = 0; - arc_insn insn; - static int init_tables_p = 0; + /* If the expression is "symbol >> 2" we must change it to just "symbol", + as fix_new_exp can't handle it. Similarly for (symbol - symbol) >> 2. + That's ok though. What's really going on here is that we're using + ">> 2" as a special syntax for specifying BFD_RELOC_ARC_B26. */ - /* Opcode table initialization is deferred until here because we have to - wait for a possible .option command. */ - if (!init_tables_p) + if (exp->X_op == O_right_shift + && exp->X_op_symbol != NULL + && exp->X_op_symbol->sy_value.X_op == O_constant + && exp->X_op_symbol->sy_value.X_add_number == 2 + && exp->X_add_number == 0) { - init_opcode_tables (arc_mach_type); - init_tables_p = 1; + if (exp->X_add_symbol != NULL + && (exp->X_add_symbol->sy_value.X_op == O_constant + || exp->X_add_symbol->sy_value.X_op == O_symbol)) + { + *expnew = *exp; + expnew->X_op = O_symbol; + expnew->X_op_symbol = NULL; + return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J']; + } + else if (exp->X_add_symbol != NULL + && exp->X_add_symbol->sy_value.X_op == O_subtract) + { + *expnew = exp->X_add_symbol->sy_value; + return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J']; + } } - /* Skip leading white space. */ - while (ISSPACE (*str)) - str++; + *expnew = *exp; + return default_type; +} + +static int +arc_set_ext_seg (void) +{ + if (!arcext_section) + { + arcext_section = subseg_new (".arcextmap", 0); + bfd_set_section_flags (stdoutput, arcext_section, + SEC_READONLY | SEC_HAS_CONTENTS); + } + else + subseg_set (arcext_section, 0); + return 1; +} - /* The instructions are stored in lists hashed by the first letter (though - we needn't care how they're hashed). Get the first in the list. */ +static void +arc_extoper (int opertype) +{ + char *name; + char *mode; + char c; + char *p; + int imode = 0; + int number; + struct arc_ext_operand_value *ext_oper; + symbolS *symbolP; - ext_opcode = arc_ext_opcodes; - std_opcode = arc_opcode_lookup_asm (str); + segT old_sec; + int old_subsec; - /* Keep looking until we find a match. */ + name = input_line_pointer; + c = get_symbol_end (); + name = xstrdup (name); - start = str; - for (opcode = (ext_opcode ? ext_opcode : std_opcode); - opcode != NULL; - opcode = (ARC_OPCODE_NEXT_ASM (opcode) - ? ARC_OPCODE_NEXT_ASM (opcode) - : (ext_opcode ? ext_opcode = NULL, std_opcode : NULL))) + p = name; + while (*p) { - int past_opcode_p, fc, num_suffixes; - int fix_up_at = 0; - char *syn; - struct arc_fixup fixups[MAX_FIXUPS]; - /* Used as a sanity check. If we need a limm reloc, make sure we ask - for an extra 4 bytes from frag_more. */ - int limm_reloc_p; - int ext_suffix_p; - const struct arc_operand_value *insn_suffixes[MAX_SUFFIXES]; + *p = TOLOWER (*p); + p++; + } - /* Is this opcode supported by the selected cpu? */ - if (! arc_opcode_supported (opcode)) - continue; + /* just after name is now '\0' */ + p = input_line_pointer; + *p = c; + SKIP_WHITESPACE (); - /* Scan the syntax string. If it doesn't match, try the next one. */ + if (*input_line_pointer != ',') + { + as_bad ("expected comma after operand name"); + ignore_rest_of_line (); + free (name); + return; + } - arc_opcode_init_insert (); - insn = opcode->value; - fc = 0; - past_opcode_p = 0; - num_suffixes = 0; - limm_reloc_p = 0; - ext_suffix_p = 0; + input_line_pointer++; /* skip ',' */ + number = get_absolute_expression (); - /* We don't check for (*str != '\0') here because we want to parse - any trailing fake arguments in the syntax string. */ - for (str = start, syn = opcode->syntax; *syn != '\0';) + if (number < 0) + { + as_bad ("negative operand number %d", number); + ignore_rest_of_line (); + free (name); + return; + } + + if (opertype) + { + SKIP_WHITESPACE (); + + if (*input_line_pointer != ',') { - int mods; - const struct arc_operand *operand; + as_bad ("expected comma after register-number"); + ignore_rest_of_line (); + free (name); + return; + } - /* Non operand chars must match exactly. */ - if (*syn != '%' || *++syn == '%') + input_line_pointer++; /* skip ',' */ + mode = input_line_pointer; + + if (!strncmp (mode, "r|w", 3)) + { + imode = 0; + input_line_pointer += 3; + } + else + { + if (!strncmp (mode, "r", 1)) { - if (*str == *syn) + imode = ARC_REGISTER_READONLY; + input_line_pointer += 1; + } + else + { + if (strncmp (mode, "w", 1)) { - if (*syn == ' ') - past_opcode_p = 1; - ++syn; - ++str; + as_bad ("invalid mode"); + ignore_rest_of_line (); + free (name); + return; } else - break; - continue; + { + imode = ARC_REGISTER_WRITEONLY; + input_line_pointer += 1; + } } - - /* We have an operand. Pick out any modifiers. */ - mods = 0; - while (ARC_MOD_P (arc_operands[arc_operand_map[(int) *syn]].flags)) + } + SKIP_WHITESPACE (); + if (1 == opertype) + { + if (*input_line_pointer != ',') { - mods |= arc_operands[arc_operand_map[(int) *syn]].flags & ARC_MOD_BITS; - ++syn; + as_bad ("expected comma after register-mode"); + ignore_rest_of_line (); + free (name); + return; } - operand = arc_operands + arc_operand_map[(int) *syn]; - if (operand->fmt == 0) - as_fatal ("unknown syntax format character `%c'", *syn); - if (operand->flags & ARC_OPERAND_FAKE) + input_line_pointer++; /* skip ',' */ + + if (!strncmp (input_line_pointer, "cannot_shortcut", 15)) { - const char *errmsg = NULL; - if (operand->insert) - { - insn = (*operand->insert) (insn, operand, mods, NULL, 0, &errmsg); - if (errmsg != (const char *) NULL) - { - last_errmsg = errmsg; - if (operand->flags & ARC_OPERAND_ERROR) - { - as_bad (errmsg); - return; - } - else if (operand->flags & ARC_OPERAND_WARN) - as_warn (errmsg); - break; - } - if (limm_reloc_p - && (operand->flags && operand->flags & ARC_OPERAND_LIMM) - && (operand->flags & - (ARC_OPERAND_ABSOLUTE_BRANCH | ARC_OPERAND_ADDRESS))) - { - fixups[fix_up_at].opindex = arc_operand_map[operand->fmt]; - } - } - ++syn; + imode |= arc_get_noshortcut_flag (); + input_line_pointer += 15; } - /* Are we finished with suffixes? */ - else if (!past_opcode_p) + else { - int found; - char c; - char *s, *t; - const struct arc_operand_value *suf, *suffix_end; - const struct arc_operand_value *suffix = NULL; - - if (!(operand->flags & ARC_OPERAND_SUFFIX)) - abort (); - - /* If we're at a space in the input string, we want to skip the - remaining suffixes. There may be some fake ones though, so - just go on to try the next one. */ - if (*str == ' ') - { - ++syn; - continue; - } - - s = str; - if (mods & ARC_MOD_DOT) + if (strncmp (input_line_pointer, "can_shortcut", 12)) { - if (*s != '.') - break; - ++s; + as_bad ("shortcut designator invalid"); + ignore_rest_of_line (); + free (name); + return; } else { - /* This can happen in "b.nd foo" and we're currently looking - for "%q" (ie: a condition code suffix). */ - if (*s == '.') - { - ++syn; - continue; - } + input_line_pointer += 12; } + } + } + } - /* Pick the suffix out and look it up via the hash table. */ - for (t = s; *t && ISALNUM (*t); ++t) - continue; - c = *t; - *t = '\0'; - if ((suf = get_ext_suffix (s))) - ext_suffix_p = 1; - else - suf = hash_find (arc_suffix_hash, s); - if (!suf) - { - /* This can happen in "blle foo" and we're currently using - the template "b%q%.n %j". The "bl" insn occurs later in - the table so "lle" isn't an illegal suffix. */ - *t = c; - break; - } + if ((opertype == 1) && number > 60) + { + as_bad ("core register value (%d) too large", number); + ignore_rest_of_line (); + free (name); + return; + } - /* Is it the right type? Note that the same character is used - several times, so we have to examine all of them. This is - relatively efficient as equivalent entries are kept - together. If it's not the right type, don't increment `str' - so we try the next one in the series. */ - found = 0; - if (ext_suffix_p && arc_operands[suf->type].fmt == *syn) - { - /* Insert the suffix's value into the insn. */ - *t = c; - if (operand->insert) - insn = (*operand->insert) (insn, operand, - mods, NULL, suf->value, - NULL); - else - insn |= suf->value << operand->shift; - suffix = suf; - str = t; - found = 1; - } - else - { - *t = c; - suffix_end = arc_suffixes + arc_suffixes_count; - for (suffix = suf; - suffix < suffix_end && strcmp (suffix->name, suf->name) == 0; - ++suffix) - { - if (arc_operands[suffix->type].fmt == *syn) - { - /* Insert the suffix's value into the insn. */ - if (operand->insert) - insn = (*operand->insert) (insn, operand, - mods, NULL, suffix->value, - NULL); - else - insn |= suffix->value << operand->shift; + if ((opertype == 0) && number > 31) + { + as_bad ("condition code value (%d) too large", number); + ignore_rest_of_line (); + free (name); + return; + } - str = t; - found = 1; - break; - } - } - } - ++syn; - if (!found) - /* Wrong type. Just go on to try next insn entry. */ - ; - else - { - if (num_suffixes == MAX_SUFFIXES) - as_bad ("too many suffixes"); - else - insn_suffixes[num_suffixes++] = suffix; - } - } + ext_oper = xmalloc (sizeof (struct arc_ext_operand_value)); + + if (opertype) + { + /* If the symbol already exists, point it at the new definition. */ + if ((symbolP = symbol_find (name))) + { + if (S_GET_SEGMENT (symbolP) == reg_section) + S_SET_VALUE (symbolP, (int) &ext_oper->operand); else - /* This is either a register or an expression of some kind. */ { - char *hold; - const struct arc_operand_value *reg = NULL; - long value = 0; - expressionS exp; + as_bad ("attempt to override symbol: %s", name); + ignore_rest_of_line (); + free (name); + free (ext_oper); + return; + } + } + else + { + /* If its not there, add it. */ + symbol_table_insert (symbol_create (name, reg_section, + (int) &ext_oper->operand, &zero_address_frag)); + } + } - if (operand->flags & ARC_OPERAND_SUFFIX) - abort (); + ext_oper->operand.name = name; + ext_oper->operand.value = number; + ext_oper->operand.type = arc_operand_type (opertype); + ext_oper->operand.flags = imode; - /* Is there anything left to parse? - We don't check for this at the top because we want to parse - any trailing fake arguments in the syntax string. */ - if (is_end_of_line[(unsigned char) *str]) - break; + ext_oper->next = arc_ext_operands; + arc_ext_operands = ext_oper; - /* Parse the operand. */ - hold = input_line_pointer; - input_line_pointer = str; - expression (&exp); - str = input_line_pointer; - input_line_pointer = hold; + /* OK, now that we know what this operand is, put a description in + the arc extension section of the output file. */ - if (exp.X_op == O_illegal) - as_bad ("illegal operand"); - else if (exp.X_op == O_absent) - as_bad ("missing operand"); - else if (exp.X_op == O_constant) - { - value = exp.X_add_number; - } - else if (exp.X_op == O_register) - { - reg = (struct arc_operand_value *) exp.X_add_number; - } -#define IS_REG_DEST_OPERAND(o) ((o) == 'a') - else if (IS_REG_DEST_OPERAND (*syn)) - as_bad ("symbol as destination register"); - else - { - if (!strncmp (str, "@h30", 4)) - { - arc_code_symbol (&exp); - str += 4; - } - /* We need to generate a fixup for this expression. */ - if (fc >= MAX_FIXUPS) - as_fatal ("too many fixups"); - fixups[fc].exp = exp; - /* We don't support shimm relocs. break here to force - the assembler to output a limm. */ -#define IS_REG_SHIMM_OFFSET(o) ((o) == 'd') - if (IS_REG_SHIMM_OFFSET (*syn)) - break; - /* If this is a register constant (IE: one whose - register value gets stored as 61-63) then this - must be a limm. */ - /* ??? This bit could use some cleaning up. - Referencing the format chars like this goes - against style. */ - if (IS_SYMBOL_OPERAND (*syn)) - { - const char *junk; - limm_reloc_p = 1; - /* Save this, we don't yet know what reloc to use. */ - fix_up_at = fc; - /* Tell insert_reg we need a limm. This is - needed because the value at this point is - zero, a shimm. */ - /* ??? We need a cleaner interface than this. */ - (*arc_operands[arc_operand_map['Q']].insert) - (insn, operand, mods, reg, 0L, &junk); - } - else - fixups[fc].opindex = arc_operand_map[(int) *syn]; - ++fc; - value = 0; - } + old_sec = now_seg; + old_subsec = now_subseg; - /* Insert the register or expression into the instruction. */ - if (operand->insert) - { - const char *errmsg = NULL; - insn = (*operand->insert) (insn, operand, mods, - reg, (long) value, &errmsg); - if (errmsg != (const char *) NULL) - { - last_errmsg = errmsg; - if (operand->flags & ARC_OPERAND_ERROR) - { - as_bad (errmsg); - return; - } - else if (operand->flags & ARC_OPERAND_WARN) - as_warn (errmsg); - break; - } - } - else - insn |= (value & ((1 << operand->bits) - 1)) << operand->shift; - - ++syn; - } - } - - /* If we're at the end of the syntax string, we're done. */ - /* FIXME: try to move this to a separate function. */ - if (*syn == '\0') - { - int i; - char *f; - long limm, limm_p; - - /* For the moment we assume a valid `str' can only contain blanks - now. IE: We needn't try again with a longer version of the - insn and it is assumed that longer versions of insns appear - before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ - - while (ISSPACE (*str)) - ++str; - - if (!is_end_of_line[(unsigned char) *str]) - as_bad ("junk at end of line: `%s'", str); - - /* Is there a limm value? */ - limm_p = arc_opcode_limm_p (&limm); - - /* Perform various error and warning tests. */ - - { - static int in_delay_slot_p = 0; - static int prev_insn_needs_cc_nop_p = 0; - /* delay slot type seen */ - int delay_slot_type = ARC_DELAY_NONE; - /* conditional execution flag seen */ - int conditional = 0; - /* 1 if condition codes are being set */ - int cc_set_p = 0; - /* 1 if conditional branch, including `b' "branch always" */ - int cond_branch_p = opcode->flags & ARC_OPCODE_COND_BRANCH; - - for (i = 0; i < num_suffixes; ++i) - { - switch (arc_operands[insn_suffixes[i]->type].fmt) - { - case 'n': - delay_slot_type = insn_suffixes[i]->value; - break; - case 'q': - conditional = insn_suffixes[i]->value; - break; - case 'f': - cc_set_p = 1; - break; - } - } - - /* Putting an insn with a limm value in a delay slot is supposed to - be legal, but let's warn the user anyway. Ditto for 8 byte - jumps with delay slots. */ - if (in_delay_slot_p && limm_p) - as_warn ("8 byte instruction in delay slot"); - if (delay_slot_type != ARC_DELAY_NONE - && limm_p && arc_insn_not_jl (insn)) /* except for jl addr */ - as_warn ("8 byte jump instruction with delay slot"); - in_delay_slot_p = (delay_slot_type != ARC_DELAY_NONE) && !limm_p; - - /* Warn when a conditional branch immediately follows a set of - the condition codes. Note that this needn't be done if the - insn that sets the condition codes uses a limm. */ - if (cond_branch_p && conditional != 0 /* 0 = "always" */ - && prev_insn_needs_cc_nop_p && arc_mach_type == bfd_mach_arc_5) - as_warn ("conditional branch follows set of flags"); - prev_insn_needs_cc_nop_p = - /* FIXME: ??? not required: - (delay_slot_type != ARC_DELAY_NONE) && */ - cc_set_p && !limm_p; - } - - /* Write out the instruction. - It is important to fetch enough space in one call to `frag_more'. - We use (f - frag_now->fr_literal) to compute where we are and we - don't want frag_now to change between calls. */ - if (limm_p) - { - f = frag_more (8); - md_number_to_chars (f, insn, 4); - md_number_to_chars (f + 4, limm, 4); - dwarf2_emit_insn (8); - } - else if (limm_reloc_p) - { - /* We need a limm reloc, but the tables think we don't. */ - abort (); - } - else - { - f = frag_more (4); - md_number_to_chars (f, insn, 4); - dwarf2_emit_insn (4); - } - - /* Create any fixups. */ - for (i = 0; i < fc; ++i) - { - int op_type, reloc_type; - expressionS exptmp; - const struct arc_operand *operand; - - /* Create a fixup for this operand. - At this point we do not use a bfd_reloc_code_real_type for - operands residing in the insn, but instead just use the - operand index. This lets us easily handle fixups for any - operand type, although that is admittedly not a very exciting - feature. We pick a BFD reloc type in md_apply_fix3. - - Limm values (4 byte immediate "constants") must be treated - normally because they're not part of the actual insn word - and thus the insertion routines don't handle them. */ + arc_set_ext_seg (); - if (arc_operands[fixups[i].opindex].flags & ARC_OPERAND_LIMM) - { - /* Modify the fixup addend as required by the cpu. */ - fixups[i].exp.X_add_number += arc_limm_fixup_adjust (insn); - op_type = fixups[i].opindex; - /* FIXME: can we add this data to the operand table? */ - if (op_type == arc_operand_map['L'] - || op_type == arc_operand_map['s'] - || op_type == arc_operand_map['o'] - || op_type == arc_operand_map['O']) - reloc_type = BFD_RELOC_32; - else if (op_type == arc_operand_map['J']) - reloc_type = BFD_RELOC_ARC_B26; - else - abort (); - reloc_type = get_arc_exp_reloc_type (1, reloc_type, - &fixups[i].exp, - &exptmp); - } - else - { - op_type = get_arc_exp_reloc_type (0, fixups[i].opindex, - &fixups[i].exp, &exptmp); - reloc_type = op_type + (int) BFD_RELOC_UNUSED; - } - operand = &arc_operands[op_type]; - fix_new_exp (frag_now, - ((f - frag_now->fr_literal) - + (operand->flags & ARC_OPERAND_LIMM ? 4 : 0)), 4, - &exptmp, - (operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0, - (bfd_reloc_code_real_type) reloc_type); - } + switch (opertype) + { + case 0: + p = frag_more (1); + *p = 3 + strlen (name) + 1; + p = frag_more (1); + *p = EXT_COND_CODE; + p = frag_more (1); + *p = number; + p = frag_more (strlen (name) + 1); + strcpy (p, name); + break; + case 1: + p = frag_more (1); + *p = 3 + strlen (name) + 1; + p = frag_more (1); + *p = EXT_CORE_REGISTER; + p = frag_more (1); + *p = number; + p = frag_more (strlen (name) + 1); + strcpy (p, name); + break; + case 2: + p = frag_more (1); + *p = 6 + strlen (name) + 1; + p = frag_more (1); + *p = EXT_AUX_REGISTER; + p = frag_more (1); + *p = number >> 24 & 0xff; + p = frag_more (1); + *p = number >> 16 & 0xff; + p = frag_more (1); + *p = number >> 8 & 0xff; + p = frag_more (1); + *p = number & 0xff; + p = frag_more (strlen (name) + 1); + strcpy (p, name); + break; + default: + as_bad ("invalid opertype"); + ignore_rest_of_line (); + free (name); + return; + break; + } - /* All done. */ - return; - } + subseg_set (old_sec, old_subsec); - /* Try the next entry. */ - } + /* Enter all registers into the symbol table. */ - if (NULL == last_errmsg) - as_bad ("bad instruction `%s'", start); - else - as_bad (last_errmsg); + demand_empty_rest_of_line (); } - + static void -arc_extoper (opertype) - int opertype; +arc_extinst (int ignore ATTRIBUTE_UNUSED) { + char syntax[129]; char *name; - char *mode; - char c; char *p; - int imode = 0; - int number; - struct arc_ext_operand_value *ext_oper; - symbolS *symbolP; + char c; + int suffixcode = -1; + int opcode, subopcode; + int i; + int class = 0; + int name_len; + struct arc_opcode *ext_op; segT old_sec; int old_subsec; @@ -887,267 +657,24 @@ arc_extoper (opertype) name = input_line_pointer; c = get_symbol_end (); name = xstrdup (name); - - p = name; - while (*p) - { - *p = TOLOWER (*p); - p++; - } + strcpy (syntax, name); + name_len = strlen (name); /* just after name is now '\0' */ p = input_line_pointer; *p = c; + SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad ("expected comma after operand name"); ignore_rest_of_line (); - free (name); return; } input_line_pointer++; /* skip ',' */ - number = get_absolute_expression (); - - if (number < 0) - { - as_bad ("negative operand number %d", number); - ignore_rest_of_line (); - free (name); - return; - } - - if (opertype) - { - SKIP_WHITESPACE (); - - if (*input_line_pointer != ',') - { - as_bad ("expected comma after register-number"); - ignore_rest_of_line (); - free (name); - return; - } - - input_line_pointer++; /* skip ',' */ - mode = input_line_pointer; - - if (!strncmp (mode, "r|w", 3)) - { - imode = 0; - input_line_pointer += 3; - } - else - { - if (!strncmp (mode, "r", 1)) - { - imode = ARC_REGISTER_READONLY; - input_line_pointer += 1; - } - else - { - if (strncmp (mode, "w", 1)) - { - as_bad ("invalid mode"); - ignore_rest_of_line (); - free (name); - return; - } - else - { - imode = ARC_REGISTER_WRITEONLY; - input_line_pointer += 1; - } - } - } - SKIP_WHITESPACE (); - if (1 == opertype) - { - if (*input_line_pointer != ',') - { - as_bad ("expected comma after register-mode"); - ignore_rest_of_line (); - free (name); - return; - } - - input_line_pointer++; /* skip ',' */ - - if (!strncmp (input_line_pointer, "cannot_shortcut", 15)) - { - imode |= arc_get_noshortcut_flag (); - input_line_pointer += 15; - } - else - { - if (strncmp (input_line_pointer, "can_shortcut", 12)) - { - as_bad ("shortcut designator invalid"); - ignore_rest_of_line (); - free (name); - return; - } - else - { - input_line_pointer += 12; - } - } - } - } - - if ((opertype == 1) && number > 60) - { - as_bad ("core register value (%d) too large", number); - ignore_rest_of_line (); - free (name); - return; - } - - if ((opertype == 0) && number > 31) - { - as_bad ("condition code value (%d) too large", number); - ignore_rest_of_line (); - free (name); - return; - } - - ext_oper = (struct arc_ext_operand_value *) \ - xmalloc (sizeof (struct arc_ext_operand_value)); - - if (opertype) - { - /* If the symbol already exists, point it at the new definition. */ - if ((symbolP = symbol_find (name))) - { - if (S_GET_SEGMENT (symbolP) == reg_section) - S_SET_VALUE (symbolP, (int) &ext_oper->operand); - else - { - as_bad ("attempt to override symbol: %s", name); - ignore_rest_of_line (); - free (name); - free (ext_oper); - return; - } - } - else - { - /* If its not there, add it. */ - symbol_table_insert (symbol_create (name, reg_section, - (int) &ext_oper->operand, &zero_address_frag)); - } - } - - ext_oper->operand.name = name; - ext_oper->operand.value = number; - ext_oper->operand.type = arc_operand_type (opertype); - ext_oper->operand.flags = imode; - - ext_oper->next = arc_ext_operands; - arc_ext_operands = ext_oper; - - /* OK, now that we know what this operand is, put a description in - the arc extension section of the output file. */ - - old_sec = now_seg; - old_subsec = now_subseg; - - arc_set_ext_seg (); - - switch (opertype) - { - case 0: - p = frag_more (1); - *p = 3 + strlen (name) + 1; - p = frag_more (1); - *p = EXT_COND_CODE; - p = frag_more (1); - *p = number; - p = frag_more (strlen (name) + 1); - strcpy (p, name); - break; - case 1: - p = frag_more (1); - *p = 3 + strlen (name) + 1; - p = frag_more (1); - *p = EXT_CORE_REGISTER; - p = frag_more (1); - *p = number; - p = frag_more (strlen (name) + 1); - strcpy (p, name); - break; - case 2: - p = frag_more (1); - *p = 6 + strlen (name) + 1; - p = frag_more (1); - *p = EXT_AUX_REGISTER; - p = frag_more (1); - *p = number >> 24 & 0xff; - p = frag_more (1); - *p = number >> 16 & 0xff; - p = frag_more (1); - *p = number >> 8 & 0xff; - p = frag_more (1); - *p = number & 0xff; - p = frag_more (strlen (name) + 1); - strcpy (p, name); - break; - default: - as_bad ("invalid opertype"); - ignore_rest_of_line (); - free (name); - return; - break; - } - - subseg_set (old_sec, old_subsec); - - /* Enter all registers into the symbol table. */ - - demand_empty_rest_of_line (); -} - -static void -arc_extinst (ignore) - int ignore ATTRIBUTE_UNUSED; -{ - char syntax[129]; - char *name; - char *p; - char c; - int suffixcode = -1; - int opcode, subopcode; - int i; - int class = 0; - int name_len; - struct arc_opcode *ext_op; - - segT old_sec; - int old_subsec; - - name = input_line_pointer; - c = get_symbol_end (); - name = xstrdup (name); - strcpy (syntax, name); - name_len = strlen (name); - - /* just after name is now '\0' */ - p = input_line_pointer; - *p = c; - - SKIP_WHITESPACE (); - - if (*input_line_pointer != ',') - { - as_bad ("expected comma after operand name"); - ignore_rest_of_line (); - return; - } - - input_line_pointer++; /* skip ',' */ - opcode = get_absolute_expression (); + opcode = get_absolute_expression (); SKIP_WHITESPACE (); @@ -1276,7 +803,7 @@ arc_extinst (ignore) strcat (syntax, "%F"); strcat (syntax, "%S%L"); - ext_op = (struct arc_opcode *) xmalloc (sizeof (struct arc_opcode)); + ext_op = xmalloc (sizeof (struct arc_opcode)); ext_op->syntax = xstrdup (syntax); ext_op->mask = I (-1) | ((0x3 == opcode) ? C (-1) : 0); @@ -1314,23 +841,8 @@ arc_extinst (ignore) demand_empty_rest_of_line (); } -int -arc_set_ext_seg () -{ - if (!arcext_section) - { - arcext_section = subseg_new (".arcextmap", 0); - bfd_set_section_flags (stdoutput, arcext_section, - SEC_READONLY | SEC_HAS_CONTENTS); - } - else - subseg_set (arcext_section, 0); - return 1; -} - static void -arc_common (localScope) - int localScope; +arc_common (int localScope) { char *name; char c; @@ -1441,9 +953,9 @@ arc_common (localScope) /* Select the cpu we're assembling for. */ static void -arc_option (ignore) - int ignore ATTRIBUTE_UNUSED; +arc_option (int ignore ATTRIBUTE_UNUSED) { + extern int arc_get_mach (char *); int mach; char c; char *cpu; @@ -1497,10 +1009,7 @@ arc_option (ignore) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -1541,10 +1050,7 @@ md_atof (type, litP, sizeP) endianness. */ void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { if (target_big_endian) number_to_chars_bigendian (buf, val, n); @@ -1555,9 +1061,7 @@ md_number_to_chars (buf, val, n) /* Round up a section size to the appropriate boundary. */ valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); @@ -1567,9 +1071,8 @@ md_section_align (segment, size) /* We don't have any form of relaxing. */ int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp ATTRIBUTE_UNUSED; - asection *seg ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, + asection *seg ATTRIBUTE_UNUSED) { as_fatal (_("md_estimate_size_before_relax\n")); return 1; @@ -1578,21 +1081,20 @@ md_estimate_size_before_relax (fragp, seg) /* Convert a machine dependent frag. We never generate these. */ void -md_convert_frag (abfd, sec, fragp) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - fragS *fragp ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + fragS *fragp ATTRIBUTE_UNUSED) { as_fatal (_("md_convert_frag\n")); } -void -arc_code_symbol (expressionP) - expressionS *expressionP; +static void +arc_code_symbol (expressionS *expressionP) { if (expressionP->X_op == O_symbol && expressionP->X_add_number == 0) { expressionS two; + expressionP->X_op = O_right_shift; expressionP->X_add_symbol->sy_value.X_op = O_constant; two.X_op = O_constant; @@ -1607,6 +1109,7 @@ arc_code_symbol (expressionP) && expressionP->X_add_number == 0) { expressionS two; + expressionP->X_add_symbol = make_expr_symbol (expressionP); expressionP->X_op = O_right_shift; two.X_op = O_constant; @@ -1615,10 +1118,7 @@ arc_code_symbol (expressionP) expressionP->X_op_symbol = make_expr_symbol (&two); } else - { - as_bad ("expression too complex code symbol"); - return; - } + as_bad ("expression too complex code symbol"); } /* Parse an operand that is machine-specific. @@ -1632,8 +1132,7 @@ arc_code_symbol (expressionP) to achieve the same effect. */ void -md_operand (expressionP) - expressionS *expressionP; +md_operand (expressionS *expressionP) { char *p = input_line_pointer; @@ -1690,8 +1189,7 @@ md_operand (expressionP) them all in the symbol table to begin with. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -1704,9 +1202,8 @@ md_undefined_symbol (name) `label' will be right shifted by 2. */ void -arc_parse_cons_expression (exp, nbytes) - expressionS *exp; - unsigned int nbytes ATTRIBUTE_UNUSED; +arc_parse_cons_expression (expressionS *exp, + unsigned int nbytes ATTRIBUTE_UNUSED) { char *p = input_line_pointer; int code_symbol_fix = 0; @@ -1728,11 +1225,10 @@ arc_parse_cons_expression (exp, nbytes) /* Record a fixup for a cons expression. */ void -arc_cons_fix_new (frag, where, nbytes, exp) - fragS *frag; - int where; - int nbytes; - expressionS *exp; +arc_cons_fix_new (fragS *frag, + int where, + int nbytes, + expressionS *exp) { if (nbytes == 4) { @@ -1758,73 +1254,12 @@ arc_cons_fix_new (frag, where, nbytes, exp) given a PC relative reloc. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { /* Return the address of the delay slot. */ return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size; } -/* Compute the reloc type of an expression. - The possibly modified expression is stored in EXPNEW. - - This is used to convert the expressions generated by the %-op's into - the appropriate operand type. It is called for both data in instructions - (operands) and data outside instructions (variables, debugging info, etc.). - - Currently supported %-ops: - - %st(symbol): represented as "symbol >> 2" - "st" is short for STatus as in the status register (pc) - - DEFAULT_TYPE is the type to use if no special processing is required. - - DATA_P is non-zero for data or limm values, zero for insn operands. - Remember that the opcode "insertion fns" cannot be used on data, they're - only for inserting operands into insns. They also can't be used for limm - values as the insertion routines don't handle limm values. When called for - insns we return fudged reloc types (real_value - BFD_RELOC_UNUSED). When - called for data or limm values we use real reloc types. */ - -static int -get_arc_exp_reloc_type (data_p, default_type, exp, expnew) - int data_p; - int default_type; - expressionS *exp; - expressionS *expnew; -{ - /* If the expression is "symbol >> 2" we must change it to just "symbol", - as fix_new_exp can't handle it. Similarly for (symbol - symbol) >> 2. - That's ok though. What's really going on here is that we're using - ">> 2" as a special syntax for specifying BFD_RELOC_ARC_B26. */ - - if (exp->X_op == O_right_shift - && exp->X_op_symbol != NULL - && exp->X_op_symbol->sy_value.X_op == O_constant - && exp->X_op_symbol->sy_value.X_add_number == 2 - && exp->X_add_number == 0) - { - if (exp->X_add_symbol != NULL - && (exp->X_add_symbol->sy_value.X_op == O_constant - || exp->X_add_symbol->sy_value.X_op == O_symbol)) - { - *expnew = *exp; - expnew->X_op = O_symbol; - expnew->X_op_symbol = NULL; - return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J']; - } - else if (exp->X_add_symbol != NULL - && exp->X_add_symbol->sy_value.X_op == O_subtract) - { - *expnew = exp->X_add_symbol->sy_value; - return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J']; - } - } - - *expnew = *exp; - return default_type; -} - /* Apply a fixup to the object code. This is called for all the fixups we generated by the call to fix_new_exp, above. In the call above we used a reloc code which was the largest legal reloc code @@ -1834,10 +1269,7 @@ get_arc_exp_reloc_type (data_p, default_type, exp, expnew) that, we determine the correct reloc code and put it back in the fixup. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg) { valueT value = * valP; @@ -1881,10 +1313,8 @@ md_apply_fix3 (fixP, valP, seg) bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); if (fixP->fx_done) - { - /* Nothing else to do here. */ - return; - } + /* Nothing else to do here. */ + return; /* Determine a BFD reloc value based on the operand information. We are only prepared to turn a few of the operands into relocs. @@ -1956,14 +1386,13 @@ md_apply_fix3 (fixP, valP, seg) format. */ arelent * -tc_gen_reloc (section, fixP) - asection *section ATTRIBUTE_UNUSED; - fixS *fixP; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, + fixS *fixP) { arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc = xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; @@ -1986,3 +1415,520 @@ tc_gen_reloc (section, fixP) return reloc; } + +const pseudo_typeS md_pseudo_table[] = +{ + { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */ + { "comm", arc_common, 0 }, + { "common", arc_common, 0 }, + { "lcomm", arc_common, 1 }, + { "lcommon", arc_common, 1 }, + { "2byte", cons, 2 }, + { "half", cons, 2 }, + { "short", cons, 2 }, + { "3byte", cons, 3 }, + { "4byte", cons, 4 }, + { "word", cons, 4 }, + { "option", arc_option, 0 }, + { "cpu", arc_option, 0 }, + { "block", s_space, 0 }, + { "extcondcode", arc_extoper, 0 }, + { "extcoreregister", arc_extoper, 1 }, + { "extauxregister", arc_extoper, 2 }, + { "extinstruction", arc_extinst, 0 }, + { NULL, 0, 0 }, +}; + +/* This routine is called for each instruction to be assembled. */ + +void +md_assemble (char *str) +{ + const struct arc_opcode *opcode; + const struct arc_opcode *std_opcode; + struct arc_opcode *ext_opcode; + char *start; + const char *last_errmsg = 0; + arc_insn insn; + static int init_tables_p = 0; + + /* Opcode table initialization is deferred until here because we have to + wait for a possible .option command. */ + if (!init_tables_p) + { + init_opcode_tables (arc_mach_type); + init_tables_p = 1; + } + + /* Skip leading white space. */ + while (ISSPACE (*str)) + str++; + + /* The instructions are stored in lists hashed by the first letter (though + we needn't care how they're hashed). Get the first in the list. */ + + ext_opcode = arc_ext_opcodes; + std_opcode = arc_opcode_lookup_asm (str); + + /* Keep looking until we find a match. */ + start = str; + for (opcode = (ext_opcode ? ext_opcode : std_opcode); + opcode != NULL; + opcode = (ARC_OPCODE_NEXT_ASM (opcode) + ? ARC_OPCODE_NEXT_ASM (opcode) + : (ext_opcode ? ext_opcode = NULL, std_opcode : NULL))) + { + int past_opcode_p, fc, num_suffixes; + int fix_up_at = 0; + char *syn; + struct arc_fixup fixups[MAX_FIXUPS]; + /* Used as a sanity check. If we need a limm reloc, make sure we ask + for an extra 4 bytes from frag_more. */ + int limm_reloc_p; + int ext_suffix_p; + const struct arc_operand_value *insn_suffixes[MAX_SUFFIXES]; + + /* Is this opcode supported by the selected cpu? */ + if (! arc_opcode_supported (opcode)) + continue; + + /* Scan the syntax string. If it doesn't match, try the next one. */ + arc_opcode_init_insert (); + insn = opcode->value; + fc = 0; + past_opcode_p = 0; + num_suffixes = 0; + limm_reloc_p = 0; + ext_suffix_p = 0; + + /* We don't check for (*str != '\0') here because we want to parse + any trailing fake arguments in the syntax string. */ + for (str = start, syn = opcode->syntax; *syn != '\0';) + { + int mods; + const struct arc_operand *operand; + + /* Non operand chars must match exactly. */ + if (*syn != '%' || *++syn == '%') + { + if (*str == *syn) + { + if (*syn == ' ') + past_opcode_p = 1; + ++syn; + ++str; + } + else + break; + continue; + } + + /* We have an operand. Pick out any modifiers. */ + mods = 0; + while (ARC_MOD_P (arc_operands[arc_operand_map[(int) *syn]].flags)) + { + mods |= arc_operands[arc_operand_map[(int) *syn]].flags & ARC_MOD_BITS; + ++syn; + } + operand = arc_operands + arc_operand_map[(int) *syn]; + if (operand->fmt == 0) + as_fatal ("unknown syntax format character `%c'", *syn); + + if (operand->flags & ARC_OPERAND_FAKE) + { + const char *errmsg = NULL; + if (operand->insert) + { + insn = (*operand->insert) (insn, operand, mods, NULL, 0, &errmsg); + if (errmsg != (const char *) NULL) + { + last_errmsg = errmsg; + if (operand->flags & ARC_OPERAND_ERROR) + { + as_bad (errmsg); + return; + } + else if (operand->flags & ARC_OPERAND_WARN) + as_warn (errmsg); + break; + } + if (limm_reloc_p + && (operand->flags && operand->flags & ARC_OPERAND_LIMM) + && (operand->flags & + (ARC_OPERAND_ABSOLUTE_BRANCH | ARC_OPERAND_ADDRESS))) + { + fixups[fix_up_at].opindex = arc_operand_map[operand->fmt]; + } + } + ++syn; + } + /* Are we finished with suffixes? */ + else if (!past_opcode_p) + { + int found; + char c; + char *s, *t; + const struct arc_operand_value *suf, *suffix_end; + const struct arc_operand_value *suffix = NULL; + + if (!(operand->flags & ARC_OPERAND_SUFFIX)) + abort (); + + /* If we're at a space in the input string, we want to skip the + remaining suffixes. There may be some fake ones though, so + just go on to try the next one. */ + if (*str == ' ') + { + ++syn; + continue; + } + + s = str; + if (mods & ARC_MOD_DOT) + { + if (*s != '.') + break; + ++s; + } + else + { + /* This can happen in "b.nd foo" and we're currently looking + for "%q" (ie: a condition code suffix). */ + if (*s == '.') + { + ++syn; + continue; + } + } + + /* Pick the suffix out and look it up via the hash table. */ + for (t = s; *t && ISALNUM (*t); ++t) + continue; + c = *t; + *t = '\0'; + if ((suf = get_ext_suffix (s))) + ext_suffix_p = 1; + else + suf = hash_find (arc_suffix_hash, s); + if (!suf) + { + /* This can happen in "blle foo" and we're currently using + the template "b%q%.n %j". The "bl" insn occurs later in + the table so "lle" isn't an illegal suffix. */ + *t = c; + break; + } + + /* Is it the right type? Note that the same character is used + several times, so we have to examine all of them. This is + relatively efficient as equivalent entries are kept + together. If it's not the right type, don't increment `str' + so we try the next one in the series. */ + found = 0; + if (ext_suffix_p && arc_operands[suf->type].fmt == *syn) + { + /* Insert the suffix's value into the insn. */ + *t = c; + if (operand->insert) + insn = (*operand->insert) (insn, operand, + mods, NULL, suf->value, + NULL); + else + insn |= suf->value << operand->shift; + suffix = suf; + str = t; + found = 1; + } + else + { + *t = c; + suffix_end = arc_suffixes + arc_suffixes_count; + for (suffix = suf; + suffix < suffix_end && strcmp (suffix->name, suf->name) == 0; + ++suffix) + { + if (arc_operands[suffix->type].fmt == *syn) + { + /* Insert the suffix's value into the insn. */ + if (operand->insert) + insn = (*operand->insert) (insn, operand, + mods, NULL, suffix->value, + NULL); + else + insn |= suffix->value << operand->shift; + + str = t; + found = 1; + break; + } + } + } + ++syn; + if (!found) + /* Wrong type. Just go on to try next insn entry. */ + ; + else + { + if (num_suffixes == MAX_SUFFIXES) + as_bad ("too many suffixes"); + else + insn_suffixes[num_suffixes++] = suffix; + } + } + else + /* This is either a register or an expression of some kind. */ + { + char *hold; + const struct arc_operand_value *reg = NULL; + long value = 0; + expressionS exp; + + if (operand->flags & ARC_OPERAND_SUFFIX) + abort (); + + /* Is there anything left to parse? + We don't check for this at the top because we want to parse + any trailing fake arguments in the syntax string. */ + if (is_end_of_line[(unsigned char) *str]) + break; + + /* Parse the operand. */ + hold = input_line_pointer; + input_line_pointer = str; + expression (&exp); + str = input_line_pointer; + input_line_pointer = hold; + + if (exp.X_op == O_illegal) + as_bad ("illegal operand"); + else if (exp.X_op == O_absent) + as_bad ("missing operand"); + else if (exp.X_op == O_constant) + value = exp.X_add_number; + else if (exp.X_op == O_register) + reg = (struct arc_operand_value *) exp.X_add_number; +#define IS_REG_DEST_OPERAND(o) ((o) == 'a') + else if (IS_REG_DEST_OPERAND (*syn)) + as_bad ("symbol as destination register"); + else + { + if (!strncmp (str, "@h30", 4)) + { + arc_code_symbol (&exp); + str += 4; + } + /* We need to generate a fixup for this expression. */ + if (fc >= MAX_FIXUPS) + as_fatal ("too many fixups"); + fixups[fc].exp = exp; + /* We don't support shimm relocs. break here to force + the assembler to output a limm. */ +#define IS_REG_SHIMM_OFFSET(o) ((o) == 'd') + if (IS_REG_SHIMM_OFFSET (*syn)) + break; + /* If this is a register constant (IE: one whose + register value gets stored as 61-63) then this + must be a limm. */ + /* ??? This bit could use some cleaning up. + Referencing the format chars like this goes + against style. */ + if (IS_SYMBOL_OPERAND (*syn)) + { + const char *junk; + limm_reloc_p = 1; + /* Save this, we don't yet know what reloc to use. */ + fix_up_at = fc; + /* Tell insert_reg we need a limm. This is + needed because the value at this point is + zero, a shimm. */ + /* ??? We need a cleaner interface than this. */ + (*arc_operands[arc_operand_map['Q']].insert) + (insn, operand, mods, reg, 0L, &junk); + } + else + fixups[fc].opindex = arc_operand_map[(int) *syn]; + ++fc; + value = 0; + } + + /* Insert the register or expression into the instruction. */ + if (operand->insert) + { + const char *errmsg = NULL; + insn = (*operand->insert) (insn, operand, mods, + reg, (long) value, &errmsg); + if (errmsg != (const char *) NULL) + { + last_errmsg = errmsg; + if (operand->flags & ARC_OPERAND_ERROR) + { + as_bad (errmsg); + return; + } + else if (operand->flags & ARC_OPERAND_WARN) + as_warn (errmsg); + break; + } + } + else + insn |= (value & ((1 << operand->bits) - 1)) << operand->shift; + + ++syn; + } + } + + /* If we're at the end of the syntax string, we're done. */ + /* FIXME: try to move this to a separate function. */ + if (*syn == '\0') + { + int i; + char *f; + long limm, limm_p; + + /* For the moment we assume a valid `str' can only contain blanks + now. IE: We needn't try again with a longer version of the + insn and it is assumed that longer versions of insns appear + before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */ + + while (ISSPACE (*str)) + ++str; + + if (!is_end_of_line[(unsigned char) *str]) + as_bad ("junk at end of line: `%s'", str); + + /* Is there a limm value? */ + limm_p = arc_opcode_limm_p (&limm); + + /* Perform various error and warning tests. */ + + { + static int in_delay_slot_p = 0; + static int prev_insn_needs_cc_nop_p = 0; + /* delay slot type seen */ + int delay_slot_type = ARC_DELAY_NONE; + /* conditional execution flag seen */ + int conditional = 0; + /* 1 if condition codes are being set */ + int cc_set_p = 0; + /* 1 if conditional branch, including `b' "branch always" */ + int cond_branch_p = opcode->flags & ARC_OPCODE_COND_BRANCH; + + for (i = 0; i < num_suffixes; ++i) + { + switch (arc_operands[insn_suffixes[i]->type].fmt) + { + case 'n': + delay_slot_type = insn_suffixes[i]->value; + break; + case 'q': + conditional = insn_suffixes[i]->value; + break; + case 'f': + cc_set_p = 1; + break; + } + } + + /* Putting an insn with a limm value in a delay slot is supposed to + be legal, but let's warn the user anyway. Ditto for 8 byte + jumps with delay slots. */ + if (in_delay_slot_p && limm_p) + as_warn ("8 byte instruction in delay slot"); + if (delay_slot_type != ARC_DELAY_NONE + && limm_p && arc_insn_not_jl (insn)) /* except for jl addr */ + as_warn ("8 byte jump instruction with delay slot"); + in_delay_slot_p = (delay_slot_type != ARC_DELAY_NONE) && !limm_p; + + /* Warn when a conditional branch immediately follows a set of + the condition codes. Note that this needn't be done if the + insn that sets the condition codes uses a limm. */ + if (cond_branch_p && conditional != 0 /* 0 = "always" */ + && prev_insn_needs_cc_nop_p && arc_mach_type == bfd_mach_arc_5) + as_warn ("conditional branch follows set of flags"); + prev_insn_needs_cc_nop_p = + /* FIXME: ??? not required: + (delay_slot_type != ARC_DELAY_NONE) && */ + cc_set_p && !limm_p; + } + + /* Write out the instruction. + It is important to fetch enough space in one call to `frag_more'. + We use (f - frag_now->fr_literal) to compute where we are and we + don't want frag_now to change between calls. */ + if (limm_p) + { + f = frag_more (8); + md_number_to_chars (f, insn, 4); + md_number_to_chars (f + 4, limm, 4); + dwarf2_emit_insn (8); + } + else if (limm_reloc_p) + /* We need a limm reloc, but the tables think we don't. */ + abort (); + else + { + f = frag_more (4); + md_number_to_chars (f, insn, 4); + dwarf2_emit_insn (4); + } + + /* Create any fixups. */ + for (i = 0; i < fc; ++i) + { + int op_type, reloc_type; + expressionS exptmp; + const struct arc_operand *operand; + + /* Create a fixup for this operand. + At this point we do not use a bfd_reloc_code_real_type for + operands residing in the insn, but instead just use the + operand index. This lets us easily handle fixups for any + operand type, although that is admittedly not a very exciting + feature. We pick a BFD reloc type in md_apply_fix3. + + Limm values (4 byte immediate "constants") must be treated + normally because they're not part of the actual insn word + and thus the insertion routines don't handle them. */ + + if (arc_operands[fixups[i].opindex].flags & ARC_OPERAND_LIMM) + { + /* Modify the fixup addend as required by the cpu. */ + fixups[i].exp.X_add_number += arc_limm_fixup_adjust (insn); + op_type = fixups[i].opindex; + /* FIXME: can we add this data to the operand table? */ + if (op_type == arc_operand_map['L'] + || op_type == arc_operand_map['s'] + || op_type == arc_operand_map['o'] + || op_type == arc_operand_map['O']) + reloc_type = BFD_RELOC_32; + else if (op_type == arc_operand_map['J']) + reloc_type = BFD_RELOC_ARC_B26; + else + abort (); + reloc_type = get_arc_exp_reloc_type (1, reloc_type, + &fixups[i].exp, + &exptmp); + } + else + { + op_type = get_arc_exp_reloc_type (0, fixups[i].opindex, + &fixups[i].exp, &exptmp); + reloc_type = op_type + (int) BFD_RELOC_UNUSED; + } + operand = &arc_operands[op_type]; + fix_new_exp (frag_now, + ((f - frag_now->fr_literal) + + (operand->flags & ARC_OPERAND_LIMM ? 4 : 0)), 4, + &exptmp, + (operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0, + (bfd_reloc_code_real_type) reloc_type); + } + return; + } + } + + if (NULL == last_errmsg) + as_bad ("bad instruction `%s'", start); + else + as_bad (last_errmsg); +} diff --git a/gas/config/tc-arc.h b/gas/config/tc-arc.h index 884d375546a..03d1554ee7b 100644 --- a/gas/config/tc-arc.h +++ b/gas/config/tc-arc.h @@ -1,5 +1,5 @@ /* tc-arc.h - Macros and type defines for the ARC. - Copyright 1994, 1995, 1997, 2000, 2001, 2002 + Copyright 1994, 1995, 1997, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. Contributed by Doug Evans (dje@cygnus.com). @@ -45,24 +45,23 @@ /* The endianness of the target format may change based on command line arguments. */ -extern const char *arc_target_format; -#define DEFAULT_TARGET_FORMAT "elf32-littlearc" -#define TARGET_FORMAT arc_target_format -#define DEFAULT_BYTE_ORDER LITTLE_ENDIAN +extern const char * arc_target_format; +#define DEFAULT_TARGET_FORMAT "elf32-littlearc" +#define TARGET_FORMAT arc_target_format +#define DEFAULT_BYTE_ORDER LITTLE_ENDIAN #define WORKING_DOT_WORD - -#define LISTING_HEADER "ARC GAS " +#define LISTING_HEADER "ARC GAS " /* The ARC needs to parse reloc specifiers in .word. */ -extern void arc_parse_cons_expression PARAMS ((struct expressionS *, unsigned)); +extern void arc_parse_cons_expression (struct expressionS *, unsigned); #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ -arc_parse_cons_expression (EXP, NBYTES) + arc_parse_cons_expression (EXP, NBYTES) -extern void arc_cons_fix_new PARAMS ((struct frag *, int, int, struct expressionS *)); +extern void arc_cons_fix_new (struct frag *, int, int, struct expressionS *); #define TC_CONS_FIX_NEW(FRAG, WHERE, NBYTES, EXP) \ -arc_cons_fix_new (FRAG, WHERE, NBYTES, EXP) + arc_cons_fix_new (FRAG, WHERE, NBYTES, EXP) #define DWARF2_LINE_MIN_INSN_LENGTH 4 diff --git a/gas/config/tc-d10v.c b/gas/config/tc-d10v.c index a5360a940c8..eb00fbb0605 100644 --- a/gas/config/tc-d10v.c +++ b/gas/config/tc-d10v.c @@ -26,12 +26,12 @@ #include "opcode/d10v.h" #include "elf/ppc.h" -const char comment_chars[] = ";"; -const char line_comment_chars[] = "#"; +const char comment_chars[] = ";"; +const char line_comment_chars[] = "#"; const char line_separator_chars[] = ""; -const char *md_shortopts = "O"; -const char EXP_CHARS[] = "eE"; -const char FLT_CHARS[] = "dD"; +const char *md_shortopts = "O"; +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "dD"; int Optimizing = 0; @@ -42,7 +42,8 @@ int Optimizing = 0; #define AT_WORD_RIGHT_SHIFT 2 /* Fixups. */ -#define MAX_INSN_FIXUPS (5) +#define MAX_INSN_FIXUPS 5 + struct d10v_fixup { expressionS exp; @@ -80,40 +81,19 @@ static bfd_boolean flag_warn_suppress_instructionswap; static bfd_boolean flag_allow_gstabs_packing = 1; /* Local functions. */ -static int reg_name_search PARAMS ((char *name)); -static int register_name PARAMS ((expressionS *expressionP)); -static int check_range PARAMS ((unsigned long num, int bits, int flags)); -static int postfix PARAMS ((char *p)); -static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op)); -static int get_operands PARAMS ((expressionS exp[])); -static struct d10v_opcode *find_opcode PARAMS ((struct d10v_opcode *opcode, expressionS ops[])); -static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers, unsigned long insn)); -static void write_long PARAMS ((unsigned long insn, Fixups *fx)); -static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx)); -static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1, - struct d10v_opcode *opcode2, unsigned long insn2, packing_type exec_type, Fixups *fx)); -static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode)); -static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_type, - offsetT value, int left, fixS *fix)); -static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1, - struct d10v_opcode *opcode2, unsigned long insn2, - packing_type exec_type)); - -static void check_resource_conflict PARAMS ((struct d10v_opcode *opcode1, - unsigned long insn1, - struct d10v_opcode *opcode2, - unsigned long insn2)); - -static symbolS * find_symbol_matching_register PARAMS ((expressionS *)); + +enum options +{ + OPTION_NOWARNSWAP = OPTION_MD_BASE, + OPTION_GSTABSPACKING, + OPTION_NOGSTABSPACKING +}; struct option md_longopts[] = { -#define OPTION_NOWARNSWAP (OPTION_MD_BASE) {"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP}, -#define OPTION_GSTABSPACKING (OPTION_MD_BASE + 1) {"gstabspacking", no_argument, NULL, OPTION_GSTABSPACKING}, {"gstabs-packing", no_argument, NULL, OPTION_GSTABSPACKING}, -#define OPTION_NOGSTABSPACKING (OPTION_MD_BASE + 2) {"nogstabspacking", no_argument, NULL, OPTION_NOGSTABSPACKING}, {"no-gstabs-packing", no_argument, NULL, OPTION_NOGSTABSPACKING}, {NULL, no_argument, NULL, 0} @@ -121,15 +101,6 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); -static void d10v_dot_word PARAMS ((int)); - -/* The target specific pseudo-ops which we support. */ -const pseudo_typeS md_pseudo_table[] = -{ - { "word", d10v_dot_word, 2 }, - { NULL, NULL, 0 } -}; - /* Opcode hash table. */ static struct hash_control *d10v_hash; @@ -138,8 +109,7 @@ static struct hash_control *d10v_hash; array on success, or -1 on failure. */ static int -reg_name_search (name) - char *name; +reg_name_search (char *name) { int middle, low, high; int cmp; @@ -166,8 +136,7 @@ reg_name_search (name) to see if it is a valid register name. */ static int -register_name (expressionP) - expressionS *expressionP; +register_name (expressionS *expressionP) { int reg_number; char c, *p = input_line_pointer; @@ -197,10 +166,7 @@ register_name (expressionP) } static int -check_range (num, bits, flags) - unsigned long num; - int bits; - int flags; +check_range (unsigned long num, int bits, int flags) { long min, max; int retval = 0; @@ -246,8 +212,7 @@ check_range (num, bits, flags) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("D10V options:\n\ -O Optimize. Will do some operations in parallel.\n\ @@ -258,9 +223,7 @@ md_show_usage (stream) } int -md_parse_option (c, arg) - int c; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) { switch (c) { @@ -284,8 +247,7 @@ md_parse_option (c, arg) } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -296,10 +258,7 @@ md_undefined_symbol (name) returned, or NULL on OK. */ char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[4]; @@ -334,25 +293,22 @@ md_atof (type, litP, sizeP) } void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) { abort (); } valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg, valueT addr) { int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align)); } void -md_begin () +md_begin (void) { char *prev_name = ""; struct d10v_opcode *opcode; @@ -381,8 +337,7 @@ md_begin () from an expression. */ static int -postfix (p) - char *p; +postfix (char *p) { while (*p != '-' && *p != '+') { @@ -394,42 +349,40 @@ postfix (p) if (*p == '-') { *p = ' '; - return (-1); + return -1; } if (*p == '+') { *p = ' '; - return (1); + return 1; } - return (0); + return 0; } static bfd_reloc_code_real_type -get_reloc (op) - struct d10v_operand *op; +get_reloc (struct d10v_operand *op) { int bits = op->bits; if (bits <= 4) - return (0); + return 0; if (op->flags & OPERAND_ADDR) { if (bits == 8) - return (BFD_RELOC_D10V_10_PCREL_R); + return BFD_RELOC_D10V_10_PCREL_R; else - return (BFD_RELOC_D10V_18_PCREL); + return BFD_RELOC_D10V_18_PCREL; } - return (BFD_RELOC_16); + return BFD_RELOC_16; } /* Parse a string of operands. Return an array of expressions. */ static int -get_operands (exp) - expressionS exp[]; +get_operands (expressionS exp[]) { char *p = input_line_pointer; int numops = 0; @@ -561,16 +514,15 @@ get_operands (exp) } exp[numops].X_op = 0; - return (numops); + return numops; } static unsigned long -d10v_insert_operand (insn, op_type, value, left, fix) - unsigned long insn; - int op_type; - offsetT value; - int left; - fixS *fix; +d10v_insert_operand (unsigned long insn, + int op_type, + offsetT value, + int left, + fixS *fix) { int shift, bits; @@ -595,10 +547,9 @@ d10v_insert_operand (insn, op_type, value, left, fix) array of operand expressions. Return the instruction. */ static unsigned long -build_insn (opcode, opers, insn) - struct d10v_opcode *opcode; - expressionS *opers; - unsigned long insn; +build_insn (struct d10v_opcode *opcode, + expressionS *opers, + unsigned long insn) { int i, bits, shift, flags, format; unsigned long number; @@ -689,9 +640,7 @@ build_insn (opcode, opers, insn) /* Write out a long form instruction. */ static void -write_long (insn, fx) - unsigned long insn; - Fixups *fx; +write_long (unsigned long insn, Fixups *fx) { int i, where; char *f = frag_more (4); @@ -724,10 +673,9 @@ write_long (insn, fx) /* Write out a short form instruction by itself. */ static void -write_1_short (opcode, insn, fx) - struct d10v_opcode *opcode; - unsigned long insn; - Fixups *fx; +write_1_short (struct d10v_opcode *opcode, + unsigned long insn, + Fixups *fx) { char *f = frag_more (4); int i, where; @@ -771,171 +719,151 @@ write_1_short (opcode, insn, fx) fx->fc = 0; } -/* Expects two short instructions. - If possible, writes out both as a single packed instruction. - Otherwise, writes out the first one, packed with a NOP. - Returns number of instructions not written out. */ +/* Determine if there are any resource conflicts among two manually + parallelized instructions. Some of this was lifted from parallel_ok. */ -static int -write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx) - struct d10v_opcode *opcode1, *opcode2; - unsigned long insn1, insn2; - packing_type exec_type; - Fixups *fx; +static void +check_resource_conflict (struct d10v_opcode *op1, + unsigned long insn1, + struct d10v_opcode *op2, + unsigned long insn2) { - unsigned long insn; - char *f; - int i, j, where; + int i, j, flags, mask, shift, regno; + unsigned long ins, mod[2]; + struct d10v_opcode *op; - if ((exec_type != PACK_PARALLEL) - && ((opcode1->exec_type & PARONLY) || (opcode2->exec_type & PARONLY))) - as_fatal (_("Instruction must be executed in parallel")); + if ((op1->exec_type & SEQ) + || ! ((op1->exec_type & PAR) || (op1->exec_type & PARONLY))) + { + as_warn (_("packing conflict: %s must dispatch sequentially"), + op1->name); + return; + } - if ((opcode1->format & LONG_OPCODE) || (opcode2->format & LONG_OPCODE)) - as_fatal (_("Long instructions may not be combined.")); + if ((op2->exec_type & SEQ) + || ! ((op2->exec_type & PAR) || (op2->exec_type & PARONLY))) + { + as_warn (_("packing conflict: %s must dispatch sequentially"), + op2->name); + return; + } - switch (exec_type) + /* See if both instructions write to the same resource. + + The idea here is to create two sets of bitmasks (mod and used) which + indicate which registers are modified or used by each instruction. + The operation can only be done in parallel if neither instruction + modifies the same register. Accesses to control registers and memory + are treated as accesses to a single register. So if both instructions + write memory or if the first instruction writes memory and the second + reads, then they cannot be done in parallel. We treat reads to the PSW + (which includes C, F0, and F1) in isolation. So simultaneously writing + C and F0 in two different sub-instructions is permitted. */ + + /* The bitmasks (mod and used) look like this (bit 31 = MSB). + r0-r15 0-15 + a0-a1 16-17 + cr (not psw) 18 + psw(other) 19 + mem 20 + psw(C flag) 21 + psw(F0 flag) 22 */ + + for (j = 0; j < 2; j++) { - case PACK_UNSPEC: /* Order not specified. */ - if (opcode1->exec_type & ALONE) - { - /* Case of a short branch on a separate GAS line. Pack with NOP. */ - write_1_short (opcode1, insn1, fx->next); - return 1; - } - if (Optimizing - && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type)) + if (j == 0) { - /* Parallel. */ - if (opcode1->unit == IU) - insn = FM00 | (insn2 << 15) | insn1; - else if (opcode2->unit == MU) - insn = FM00 | (insn2 << 15) | insn1; - else - insn = FM00 | (insn1 << 15) | insn2; + op = op1; + ins = insn1; } - else if (opcode1->unit == IU) - /* Reverse sequential with IU opcode1 on right and done first. */ - insn = FM10 | (insn2 << 15) | insn1; else - /* Sequential with non-IU opcode1 on left and done first. */ - insn = FM01 | (insn1 << 15) | insn2; - break; - - case PACK_PARALLEL: - if (opcode1->exec_type & SEQ || opcode2->exec_type & SEQ) - as_fatal - (_("One of these instructions may not be executed in parallel.")); - if (opcode1->unit == IU) - { - if (opcode2->unit == IU) - as_fatal (_("Two IU instructions may not be executed in parallel")); - if (!flag_warn_suppress_instructionswap) - as_warn (_("Swapping instruction order")); - insn = FM00 | (insn2 << 15) | insn1; - } - else if (opcode2->unit == MU) { - if (opcode1->unit == MU) - as_fatal (_("Two MU instructions may not be executed in parallel")); - if (!flag_warn_suppress_instructionswap) - as_warn (_("Swapping instruction order")); - insn = FM00 | (insn2 << 15) | insn1; + op = op2; + ins = insn2; } - else - insn = FM00 | (insn1 << 15) | insn2; - check_resource_conflict (opcode1, insn1, opcode2, insn2); - break; + mod[j] = 0; + if (op->exec_type & BRANCH_LINK) + mod[j] |= 1 << 13; - case PACK_LEFT_RIGHT: - if (opcode1->unit != IU) - insn = FM01 | (insn1 << 15) | insn2; - else if (opcode2->unit == MU || opcode2->unit == EITHER) + for (i = 0; op->operands[i]; i++) { - if (!flag_warn_suppress_instructionswap) - as_warn (_("Swapping instruction order")); - insn = FM10 | (insn2 << 15) | insn1; - } - else - as_fatal (_("IU instruction may not be in the left container")); - if (opcode1->exec_type & ALONE) - as_warn (_("Instruction in R container is squashed by flow control instruction in L container.")); - break; + flags = d10v_operands[op->operands[i]].flags; + shift = d10v_operands[op->operands[i]].shift; + mask = 0x7FFFFFFF >> (31 - d10v_operands[op->operands[i]].bits); + if (flags & OPERAND_REG) + { + regno = (ins >> shift) & mask; + if (flags & (OPERAND_ACC0 | OPERAND_ACC1)) + regno += 16; + else if (flags & OPERAND_CONTROL) /* mvtc or mvfc */ + { + if (regno == 0) + regno = 19; + else + regno = 18; + } + else if (flags & OPERAND_FFLAG) + regno = 22; + else if (flags & OPERAND_CFLAG) + regno = 21; - case PACK_RIGHT_LEFT: - if (opcode2->unit != MU) - insn = FM10 | (insn1 << 15) | insn2; - else if (opcode1->unit == IU || opcode1->unit == EITHER) - { - if (!flag_warn_suppress_instructionswap) - as_warn (_("Swapping instruction order")); - insn = FM01 | (insn2 << 15) | insn1; + if (flags & OPERAND_DEST + /* Auto inc/dec also modifies the register. */ + || (op->operands[i + 1] != 0 + && (d10v_operands[op->operands[i + 1]].flags + & (OPERAND_PLUS | OPERAND_MINUS)) != 0)) + { + mod[j] |= 1 << regno; + if (flags & OPERAND_EVEN) + mod[j] |= 1 << (regno + 1); + } + } + else if (flags & OPERAND_ATMINUS) + { + /* SP implicitly used/modified. */ + mod[j] |= 1 << 15; + } } - else - as_fatal (_("MU instruction may not be in the right container")); - if (opcode2->exec_type & ALONE) - as_warn (_("Instruction in R container is squashed by flow control instruction in L container.")); - break; - default: - as_fatal (_("unknown execution type passed to write_2_short()")); + if (op->exec_type & WMEM) + mod[j] |= 1 << 20; + else if (op->exec_type & WF0) + mod[j] |= 1 << 22; + else if (op->exec_type & WCAR) + mod[j] |= 1 << 21; } - f = frag_more (4); - number_to_chars_bigendian (f, insn, 4); - - /* Process fixup chains. fx refers to insn2 when j == 0, and to - insn1 when j == 1. Yes, it's reversed. */ - - for (j = 0; j < 2; j++) + if ((mod[0] & mod[1]) == 0) + return; + else { - for (i = 0; i < fx->fc; i++) - { - if (fx->fix[i].reloc) - { - where = f - frag_now->fr_literal; - if (fx->fix[i].size == 2) - where += 2; - - if (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R - /* A BFD_RELOC_D10V_10_PCREL_R relocation applied to - the instruction in the L container has to be - adjusted to BDF_RELOC_D10V_10_PCREL_L. When - j==0, we're processing insn2's operands, so we - want to mark the operand if insn2 is *not* in the - R container. When j==1, we're processing insn1's - operands, so we want to mark the operand if insn2 - *is* in the R container. Note that, if two - instructions are identical, we're never going to - swap them, so the test is safe. */ - && j == ((insn & 0x7fff) == insn2)) - fx->fix[i].operand |= 1024; - - if (fx->fix[i].reloc == BFD_RELOC_D10V_18) - fx->fix[i].operand |= 4096; + unsigned long x; + x = mod[0] & mod[1]; - fix_new_exp (frag_now, - where, - fx->fix[i].size, - &(fx->fix[i].exp), - fx->fix[i].pcrel, - fx->fix[i].operand|2048); - } - } - fx->fc = 0; - fx = fx->next; + for (j = 0; j <= 15; j++) + if (x & (1 << j)) + as_warn (_("resource conflict (R%d)"), j); + for (j = 16; j <= 17; j++) + if (x & (1 << j)) + as_warn (_("resource conflict (A%d)"), j - 16); + if (x & (1 << 19)) + as_warn (_("resource conflict (PSW)")); + if (x & (1 << 21)) + as_warn (_("resource conflict (C flag)")); + if (x & (1 << 22)) + as_warn (_("resource conflict (F flag)")); } - return (0); } /* Check 2 instructions and determine if they can be safely executed in parallel. Return 1 if they can be. */ static int -parallel_ok (op1, insn1, op2, insn2, exec_type) - struct d10v_opcode *op1, *op2; - unsigned long insn1, insn2; - packing_type exec_type; +parallel_ok (struct d10v_opcode *op1, + unsigned long insn1, + struct d10v_opcode *op2, + unsigned long insn2, + packing_type exec_type) { int i, j, flags, mask, shift, regno; unsigned long ins, mod[2], used[2]; @@ -1054,310 +982,179 @@ parallel_ok (op1, insn1, op2, insn2, exec_type) return 0; } -/* Determine if there are any resource conflicts among two manually - parallelized instructions. Some of this was lifted from parallel_ok. */ - -static void -check_resource_conflict (op1, insn1, op2, insn2) - struct d10v_opcode *op1, *op2; - unsigned long insn1, insn2; -{ - int i, j, flags, mask, shift, regno; - unsigned long ins, mod[2]; - struct d10v_opcode *op; - - if ((op1->exec_type & SEQ) - || ! ((op1->exec_type & PAR) || (op1->exec_type & PARONLY))) - { - as_warn (_("packing conflict: %s must dispatch sequentially"), - op1->name); - return; - } - - if ((op2->exec_type & SEQ) - || ! ((op2->exec_type & PAR) || (op2->exec_type & PARONLY))) - { - as_warn (_("packing conflict: %s must dispatch sequentially"), - op2->name); - return; - } +/* Expects two short instructions. + If possible, writes out both as a single packed instruction. + Otherwise, writes out the first one, packed with a NOP. + Returns number of instructions not written out. */ - /* See if both instructions write to the same resource. +static int +write_2_short (struct d10v_opcode *opcode1, + unsigned long insn1, + struct d10v_opcode *opcode2, + unsigned long insn2, + packing_type exec_type, + Fixups *fx) +{ + unsigned long insn; + char *f; + int i, j, where; - The idea here is to create two sets of bitmasks (mod and used) which - indicate which registers are modified or used by each instruction. - The operation can only be done in parallel if neither instruction - modifies the same register. Accesses to control registers and memory - are treated as accesses to a single register. So if both instructions - write memory or if the first instruction writes memory and the second - reads, then they cannot be done in parallel. We treat reads to the PSW - (which includes C, F0, and F1) in isolation. So simultaneously writing - C and F0 in two different sub-instructions is permitted. */ + if ((exec_type != PACK_PARALLEL) + && ((opcode1->exec_type & PARONLY) || (opcode2->exec_type & PARONLY))) + as_fatal (_("Instruction must be executed in parallel")); - /* The bitmasks (mod and used) look like this (bit 31 = MSB). - r0-r15 0-15 - a0-a1 16-17 - cr (not psw) 18 - psw(other) 19 - mem 20 - psw(C flag) 21 - psw(F0 flag) 22 */ + if ((opcode1->format & LONG_OPCODE) || (opcode2->format & LONG_OPCODE)) + as_fatal (_("Long instructions may not be combined.")); - for (j = 0; j < 2; j++) + switch (exec_type) { - if (j == 0) - { - op = op1; - ins = insn1; - } - else + case PACK_UNSPEC: /* Order not specified. */ + if (opcode1->exec_type & ALONE) { - op = op2; - ins = insn2; + /* Case of a short branch on a separate GAS line. Pack with NOP. */ + write_1_short (opcode1, insn1, fx->next); + return 1; } - mod[j] = 0; - if (op->exec_type & BRANCH_LINK) - mod[j] |= 1 << 13; - - for (i = 0; op->operands[i]; i++) + if (Optimizing + && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type)) { - flags = d10v_operands[op->operands[i]].flags; - shift = d10v_operands[op->operands[i]].shift; - mask = 0x7FFFFFFF >> (31 - d10v_operands[op->operands[i]].bits); - if (flags & OPERAND_REG) - { - regno = (ins >> shift) & mask; - if (flags & (OPERAND_ACC0 | OPERAND_ACC1)) - regno += 16; - else if (flags & OPERAND_CONTROL) /* mvtc or mvfc */ - { - if (regno == 0) - regno = 19; - else - regno = 18; - } - else if (flags & OPERAND_FFLAG) - regno = 22; - else if (flags & OPERAND_CFLAG) - regno = 21; - - if (flags & OPERAND_DEST - /* Auto inc/dec also modifies the register. */ - || (op->operands[i + 1] != 0 - && (d10v_operands[op->operands[i + 1]].flags - & (OPERAND_PLUS | OPERAND_MINUS)) != 0)) - { - mod[j] |= 1 << regno; - if (flags & OPERAND_EVEN) - mod[j] |= 1 << (regno + 1); - } - } - else if (flags & OPERAND_ATMINUS) - { - /* SP implicitly used/modified. */ - mod[j] |= 1 << 15; - } + /* Parallel. */ + if (opcode1->unit == IU) + insn = FM00 | (insn2 << 15) | insn1; + else if (opcode2->unit == MU) + insn = FM00 | (insn2 << 15) | insn1; + else + insn = FM00 | (insn1 << 15) | insn2; } - - if (op->exec_type & WMEM) - mod[j] |= 1 << 20; - else if (op->exec_type & WF0) - mod[j] |= 1 << 22; - else if (op->exec_type & WCAR) - mod[j] |= 1 << 21; - } - - if ((mod[0] & mod[1]) == 0) - return; - else - { - unsigned long x; - x = mod[0] & mod[1]; - - for (j = 0; j <= 15; j++) - if (x & (1 << j)) - as_warn (_("resource conflict (R%d)"), j); - for (j = 16; j <= 17; j++) - if (x & (1 << j)) - as_warn (_("resource conflict (A%d)"), j - 16); - if (x & (1 << 19)) - as_warn (_("resource conflict (PSW)")); - if (x & (1 << 21)) - as_warn (_("resource conflict (C flag)")); - if (x & (1 << 22)) - as_warn (_("resource conflict (F flag)")); - } -} - -/* This is the main entry point for the machine-dependent assembler. - str points to a machine-dependent instruction. This function is - supposed to emit the frags/bytes it assembles to. For the D10V, it - mostly handles the special VLIW parsing and packing and leaves the - difficult stuff to do_assemble(). */ - -static unsigned long prev_insn; -static struct d10v_opcode *prev_opcode = 0; -static subsegT prev_subseg; -static segT prev_seg = 0;; - -void -md_assemble (str) - char *str; -{ - /* etype is saved extype. For multi-line instructions. */ - - packing_type extype = PACK_UNSPEC; /* Parallel, etc. */ - - struct d10v_opcode *opcode; - unsigned long insn; - char *str2; - - if (etype == PACK_UNSPEC) - { - /* Look for the special multiple instruction separators. */ - str2 = strstr (str, "||"); - if (str2) - extype = PACK_PARALLEL; + else if (opcode1->unit == IU) + /* Reverse sequential with IU opcode1 on right and done first. */ + insn = FM10 | (insn2 << 15) | insn1; else + /* Sequential with non-IU opcode1 on left and done first. */ + insn = FM01 | (insn1 << 15) | insn2; + break; + + case PACK_PARALLEL: + if (opcode1->exec_type & SEQ || opcode2->exec_type & SEQ) + as_fatal + (_("One of these instructions may not be executed in parallel.")); + if (opcode1->unit == IU) { - str2 = strstr (str, "->"); - if (str2) - extype = PACK_LEFT_RIGHT; - else - { - str2 = strstr (str, "<-"); - if (str2) - extype = PACK_RIGHT_LEFT; - } + if (opcode2->unit == IU) + as_fatal (_("Two IU instructions may not be executed in parallel")); + if (!flag_warn_suppress_instructionswap) + as_warn (_("Swapping instruction order")); + insn = FM00 | (insn2 << 15) | insn1; } - - /* str2 points to the separator, if there is one. */ - if (str2) + else if (opcode2->unit == MU) { - *str2 = 0; - - /* If two instructions are present and we already have one saved, - then first write out the saved one. */ - d10v_cleanup (); - - /* Assemble first instruction and save it. */ - prev_insn = do_assemble (str, &prev_opcode); - prev_seg = now_seg; - prev_subseg = now_subseg; - if (prev_insn == (unsigned long) -1) - as_fatal (_("can't find opcode ")); - fixups = fixups->next; - str = str2 + 2; + if (opcode1->unit == MU) + as_fatal (_("Two MU instructions may not be executed in parallel")); + if (!flag_warn_suppress_instructionswap) + as_warn (_("Swapping instruction order")); + insn = FM00 | (insn2 << 15) | insn1; } - } + else + insn = FM00 | (insn1 << 15) | insn2; + check_resource_conflict (opcode1, insn1, opcode2, insn2); + break; - insn = do_assemble (str, &opcode); - if (insn == (unsigned long) -1) - { - if (extype != PACK_UNSPEC) + case PACK_LEFT_RIGHT: + if (opcode1->unit != IU) + insn = FM01 | (insn1 << 15) | insn2; + else if (opcode2->unit == MU || opcode2->unit == EITHER) { - etype = extype; - return; + if (!flag_warn_suppress_instructionswap) + as_warn (_("Swapping instruction order")); + insn = FM10 | (insn2 << 15) | insn1; } - as_fatal (_("can't find opcode ")); - } - - if (etype != PACK_UNSPEC) - { - extype = etype; - etype = PACK_UNSPEC; - } - - /* If this is a long instruction, write it and any previous short - instruction. */ - if (opcode->format & LONG_OPCODE) - { - if (extype != PACK_UNSPEC) - as_fatal (_("Unable to mix instructions as specified")); - d10v_cleanup (); - write_long (insn, fixups); - prev_opcode = NULL; - return; - } - - if (prev_opcode - && prev_seg - && ((prev_seg != now_seg) || (prev_subseg != now_subseg))) - d10v_cleanup (); + else + as_fatal (_("IU instruction may not be in the left container")); + if (opcode1->exec_type & ALONE) + as_warn (_("Instruction in R container is squashed by flow control instruction in L container.")); + break; - if (prev_opcode - && (0 == write_2_short (prev_opcode, prev_insn, opcode, insn, extype, - fixups))) - { - /* No instructions saved. */ - prev_opcode = NULL; - } - else - { - if (extype != PACK_UNSPEC) - as_fatal (_("Unable to mix instructions as specified")); - /* Save last instruction so it may be packed on next pass. */ - prev_opcode = opcode; - prev_insn = insn; - prev_seg = now_seg; - prev_subseg = now_subseg; - fixups = fixups->next; - } -} + case PACK_RIGHT_LEFT: + if (opcode2->unit != MU) + insn = FM10 | (insn1 << 15) | insn2; + else if (opcode1->unit == IU || opcode1->unit == EITHER) + { + if (!flag_warn_suppress_instructionswap) + as_warn (_("Swapping instruction order")); + insn = FM01 | (insn2 << 15) | insn1; + } + else + as_fatal (_("MU instruction may not be in the right container")); + if (opcode2->exec_type & ALONE) + as_warn (_("Instruction in R container is squashed by flow control instruction in L container.")); + break; -/* Assemble a single instruction. - Return an opcode, or -1 (an invalid opcode) on error. */ + default: + as_fatal (_("unknown execution type passed to write_2_short()")); + } -static unsigned long -do_assemble (str, opcode) - char *str; - struct d10v_opcode **opcode; -{ - unsigned char *op_start, *op_end; - char *save; - char name[20]; - int nlen = 0; - expressionS myops[6]; - unsigned long insn; + f = frag_more (4); + number_to_chars_bigendian (f, insn, 4); - /* Drop leading whitespace. */ - while (*str == ' ') - str++; + /* Process fixup chains. fx refers to insn2 when j == 0, and to + insn1 when j == 1. Yes, it's reversed. */ - /* Find the opcode end. */ - for (op_start = op_end = (unsigned char *) str; - *op_end && nlen < 20 && !is_end_of_line[*op_end] && *op_end != ' '; - op_end++) + for (j = 0; j < 2; j++) { - name[nlen] = TOLOWER (op_start[nlen]); - nlen++; - } - name[nlen] = 0; - - if (nlen == 0) - return -1; + for (i = 0; i < fx->fc; i++) + { + if (fx->fix[i].reloc) + { + where = f - frag_now->fr_literal; + if (fx->fix[i].size == 2) + where += 2; - /* Find the first opcode with the proper name. */ - *opcode = (struct d10v_opcode *) hash_find (d10v_hash, name); - if (*opcode == NULL) - as_fatal (_("unknown opcode: %s"), name); + if (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R + /* A BFD_RELOC_D10V_10_PCREL_R relocation applied to + the instruction in the L container has to be + adjusted to BDF_RELOC_D10V_10_PCREL_L. When + j==0, we're processing insn2's operands, so we + want to mark the operand if insn2 is *not* in the + R container. When j==1, we're processing insn1's + operands, so we want to mark the operand if insn2 + *is* in the R container. Note that, if two + instructions are identical, we're never going to + swap them, so the test is safe. */ + && j == ((insn & 0x7fff) == insn2)) + fx->fix[i].operand |= 1024; - save = input_line_pointer; - input_line_pointer = (char *) op_end; - *opcode = find_opcode (*opcode, myops); - if (*opcode == 0) - return -1; - input_line_pointer = save; + if (fx->fix[i].reloc == BFD_RELOC_D10V_18) + fx->fix[i].operand |= 4096; - insn = build_insn ((*opcode), myops, 0); - return (insn); + fix_new_exp (frag_now, + where, + fx->fix[i].size, + &(fx->fix[i].exp), + fx->fix[i].pcrel, + fx->fix[i].operand|2048); + } + } + fx->fc = 0; + fx = fx->next; + } + return 0; } +/* This is the main entry point for the machine-dependent assembler. + str points to a machine-dependent instruction. This function is + supposed to emit the frags/bytes it assembles to. For the D10V, it + mostly handles the special VLIW parsing and packing and leaves the + difficult stuff to do_assemble(). */ + +static unsigned long prev_insn; +static struct d10v_opcode *prev_opcode = 0; +static subsegT prev_subseg; +static segT prev_seg = 0;; + /* Find the symbol which has the same name as the register in exp. */ static symbolS * -find_symbol_matching_register (exp) - expressionS *exp; +find_symbol_matching_register (expressionS *exp) { int i; @@ -1381,9 +1178,7 @@ find_symbol_matching_register (exp) the operands to choose the correct opcode. */ static struct d10v_opcode * -find_opcode (opcode, myops) - struct d10v_opcode *opcode; - expressionS myops[]; +find_opcode (struct d10v_opcode *opcode, expressionS myops[]) { int i, match; struct d10v_opcode *next_opcode; @@ -1503,10 +1298,8 @@ find_opcode (opcode, myops) opcode = next_opcode; } else - { - /* Not a constant, so use a long instruction. */ - opcode += 2; - } + /* Not a constant, so use a long instruction. */ + opcode += 2; } match = 0; @@ -1599,7 +1392,7 @@ find_opcode (opcode, myops) if (!match) { as_bad (_("bad opcode or operands")); - return (0); + return 0; } /* Check that all registers that are required to be even are. @@ -1637,17 +1430,61 @@ find_opcode (opcode, myops) return opcode; } +/* Assemble a single instruction. + Return an opcode, or -1 (an invalid opcode) on error. */ + +static unsigned long +do_assemble (char *str, struct d10v_opcode **opcode) +{ + unsigned char *op_start, *op_end; + char *save; + char name[20]; + int nlen = 0; + expressionS myops[6]; + unsigned long insn; + + /* Drop leading whitespace. */ + while (*str == ' ') + str++; + + /* Find the opcode end. */ + for (op_start = op_end = (unsigned char *) str; + *op_end && nlen < 20 && !is_end_of_line[*op_end] && *op_end != ' '; + op_end++) + { + name[nlen] = TOLOWER (op_start[nlen]); + nlen++; + } + name[nlen] = 0; + + if (nlen == 0) + return -1; + + /* Find the first opcode with the proper name. */ + *opcode = (struct d10v_opcode *) hash_find (d10v_hash, name); + if (*opcode == NULL) + as_fatal (_("unknown opcode: %s"), name); + + save = input_line_pointer; + input_line_pointer = (char *) op_end; + *opcode = find_opcode (*opcode, myops); + if (*opcode == 0) + return -1; + input_line_pointer = save; + + insn = build_insn ((*opcode), myops, 0); + return insn; +} + /* If while processing a fixup, a reloc really needs to be created. Then it is done here. */ arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc = xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); @@ -1668,18 +1505,15 @@ tc_gen_reloc (seg, fixp) } int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp ATTRIBUTE_UNUSED; - asection *seg ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, + asection *seg ATTRIBUTE_UNUSED) { abort (); return 0; } long -md_pcrel_from_section (fixp, sec) - fixS *fixp; - segT sec; +md_pcrel_from_section (fixS *fixp, segT sec) { if (fixp->fx_addsy != (symbolS *) NULL && (!S_IS_DEFINED (fixp->fx_addsy) @@ -1689,10 +1523,7 @@ md_pcrel_from_section (fixp, sec) } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { char *where; unsigned long insn; @@ -1804,7 +1635,7 @@ md_apply_fix3 (fixP, valP, seg) NOTE: invoked by various macros such as md_cleanup: see. */ int -d10v_cleanup () +d10v_cleanup (void) { segT seg; subsegT subseg; @@ -1836,8 +1667,7 @@ d10v_cleanup () Clobbers input_line_pointer, checks end-of-line. */ static void -d10v_dot_word (dummy) - int dummy ATTRIBUTE_UNUSED; +d10v_dot_word (int dummy ATTRIBUTE_UNUSED) { expressionS exp; char *p; @@ -1880,8 +1710,7 @@ d10v_dot_word (dummy) From expr.c. */ void -md_operand (expressionP) - expressionS *expressionP; +md_operand (expressionS *expressionP) { if (*input_line_pointer == '#' && ! do_not_ignore_hash) { @@ -1891,8 +1720,7 @@ md_operand (expressionP) } bfd_boolean -d10v_fix_adjustable (fixP) - fixS *fixP; +d10v_fix_adjustable (fixS *fixP) { /* We need the symbol name for the VTABLE entries. */ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT @@ -1901,3 +1729,113 @@ d10v_fix_adjustable (fixP) return 1; } + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "word", d10v_dot_word, 2 }, + { NULL, NULL, 0 } +}; + +void +md_assemble (char *str) +{ + /* etype is saved extype. For multi-line instructions. */ + packing_type extype = PACK_UNSPEC; /* Parallel, etc. */ + struct d10v_opcode *opcode; + unsigned long insn; + char *str2; + + if (etype == PACK_UNSPEC) + { + /* Look for the special multiple instruction separators. */ + str2 = strstr (str, "||"); + if (str2) + extype = PACK_PARALLEL; + else + { + str2 = strstr (str, "->"); + if (str2) + extype = PACK_LEFT_RIGHT; + else + { + str2 = strstr (str, "<-"); + if (str2) + extype = PACK_RIGHT_LEFT; + } + } + + /* str2 points to the separator, if there is one. */ + if (str2) + { + *str2 = 0; + + /* If two instructions are present and we already have one saved, + then first write out the saved one. */ + d10v_cleanup (); + + /* Assemble first instruction and save it. */ + prev_insn = do_assemble (str, &prev_opcode); + prev_seg = now_seg; + prev_subseg = now_subseg; + if (prev_insn == (unsigned long) -1) + as_fatal (_("can't find opcode ")); + fixups = fixups->next; + str = str2 + 2; + } + } + + insn = do_assemble (str, &opcode); + if (insn == (unsigned long) -1) + { + if (extype != PACK_UNSPEC) + { + etype = extype; + return; + } + as_fatal (_("can't find opcode ")); + } + + if (etype != PACK_UNSPEC) + { + extype = etype; + etype = PACK_UNSPEC; + } + + /* If this is a long instruction, write it and any previous short + instruction. */ + if (opcode->format & LONG_OPCODE) + { + if (extype != PACK_UNSPEC) + as_fatal (_("Unable to mix instructions as specified")); + d10v_cleanup (); + write_long (insn, fixups); + prev_opcode = NULL; + return; + } + + if (prev_opcode + && prev_seg + && ((prev_seg != now_seg) || (prev_subseg != now_subseg))) + d10v_cleanup (); + + if (prev_opcode + && (0 == write_2_short (prev_opcode, prev_insn, opcode, insn, extype, + fixups))) + { + /* No instructions saved. */ + prev_opcode = NULL; + } + else + { + if (extype != PACK_UNSPEC) + as_fatal (_("Unable to mix instructions as specified")); + /* Save last instruction so it may be packed on next pass. */ + prev_opcode = opcode; + prev_insn = insn; + prev_seg = now_seg; + prev_subseg = now_subseg; + fixups = fixups->next; + } +} + diff --git a/gas/config/tc-d10v.h b/gas/config/tc-d10v.h index debb799b95c..261da041c95 100644 --- a/gas/config/tc-d10v.h +++ b/gas/config/tc-d10v.h @@ -1,5 +1,5 @@ /* tc-d10v.h -- Header file for tc-d10v.c. - Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003 + Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. Written by Martin Hunt, Cygnus Support. @@ -34,32 +34,36 @@ #define TARGET_FORMAT "elf32-d10v" /* Call md_pcrel_from_section, not md_pcrel_from. */ -#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC) +#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC) struct fix; -long md_pcrel_from_section PARAMS ((struct fix *, segT)); +long md_pcrel_from_section (struct fix *, segT); /* Permit temporary numeric labels. */ #define LOCAL_LABELS_FB 1 -#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ +/* .-foo gets turned into PC relative relocs. */ +#define DIFF_EXPR_OK /* We don't need to handle .word strangely. */ #define WORKING_DOT_WORD #define md_number_to_chars number_to_chars_bigendian -int d10v_cleanup PARAMS ((void)); +int d10v_cleanup (void); #define md_after_pass_hook() d10v_cleanup () #define md_cleanup() d10v_cleanup () #define md_do_align(a,b,c,d,e) d10v_cleanup () -#define tc_frob_label(sym) do {\ - d10v_cleanup (); \ - symbol_set_frag (sym, frag_now); \ - S_SET_VALUE (sym, (valueT) frag_now_fix ()); \ -} while (0) +#define tc_frob_label(sym) \ + do \ + { \ + d10v_cleanup (); \ + symbol_set_frag (sym, frag_now); \ + S_SET_VALUE (sym, (valueT) frag_now_fix ()); \ + } \ + while (0) #define tc_fix_adjustable(FIX) d10v_fix_adjustable(FIX) -bfd_boolean d10v_fix_adjustable PARAMS ((struct fix *)); +bfd_boolean d10v_fix_adjustable (struct fix *); /* Values passed to md_apply_fix3 don't include the symbol value. */ #define MD_APPLY_SYM_VALUE(FIX) 0 diff --git a/gas/config/tc-d30v.c b/gas/config/tc-d30v.c index d24c9e45d25..5c6b4232e89 100644 --- a/gas/config/tc-d30v.c +++ b/gas/config/tc-d30v.c @@ -25,12 +25,12 @@ #include "subsegs.h" #include "opcode/d30v.h" -const char comment_chars[] = ";"; -const char line_comment_chars[] = "#"; +const char comment_chars[] = ";"; +const char line_comment_chars[] = "#"; const char line_separator_chars[] = ""; -const char *md_shortopts = "OnNcC"; -const char EXP_CHARS[] = "eE"; -const char FLT_CHARS[] = "dD"; +const char *md_shortopts = "OnNcC"; +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "dD"; #if HAVE_LIMITS_H #include @@ -52,14 +52,15 @@ static int warn_register_name_conflicts = 1; /* EXEC types. */ typedef enum _exec_type { - EXEC_UNKNOWN, /* no order specified */ - EXEC_PARALLEL, /* done in parallel (FM=00) */ - EXEC_SEQ, /* sequential (FM=01) */ - EXEC_REVSEQ /* reverse sequential (FM=10) */ + EXEC_UNKNOWN, /* No order specified. */ + EXEC_PARALLEL, /* Done in parallel (FM=00). */ + EXEC_SEQ, /* Sequential (FM=01). */ + EXEC_REVSEQ /* Reverse sequential (FM=10). */ } exec_type_enum; /* Fixups. */ -#define MAX_INSN_FIXUPS (5) +#define MAX_INSN_FIXUPS 5 + struct d30v_fixup { expressionS exp; @@ -110,34 +111,6 @@ static symbolS *d30v_last_label; #define NOP_RIGHT ((long long) NOP) #define NOP2 (FM00 | NOP_LEFT | NOP_RIGHT) -/* Local functions. */ -static int reg_name_search PARAMS ((char *name)); -static int register_name PARAMS ((expressionS *expressionP)); -static int check_range PARAMS ((unsigned long num, int bits, int flags)); -static int postfix PARAMS ((char *p)); -static bfd_reloc_code_real_type get_reloc PARAMS ((struct d30v_operand *op, int rel_flag)); -static int get_operands PARAMS ((expressionS exp[], int cmp_hack)); -static struct d30v_format *find_format PARAMS ((struct d30v_opcode *opcode, - expressionS ops[],int fsize, int cmp_hack)); -static long long build_insn PARAMS ((struct d30v_insn *opcode, expressionS *opers)); -static void write_long PARAMS ((struct d30v_insn *opcode, long long insn, Fixups *fx)); -static void write_1_short PARAMS ((struct d30v_insn *opcode, long long insn, - Fixups *fx, int use_sequential)); -static int write_2_short PARAMS ((struct d30v_insn *opcode1, long long insn1, - struct d30v_insn *opcode2, long long insn2, exec_type_enum exec_type, Fixups *fx)); -static long long do_assemble PARAMS ((char *str, struct d30v_insn *opcode, - int shortp, int is_parallel)); -static int parallel_ok PARAMS ((struct d30v_insn *opcode1, unsigned long insn1, - struct d30v_insn *opcode2, unsigned long insn2, - exec_type_enum exec_type)); -static void d30v_number_to_chars PARAMS ((char *buf, long long value, int nbytes)); -static void check_size PARAMS ((long value, int bits, char *file, int line)); -static void d30v_align PARAMS ((int, char *, symbolS *)); -static void s_d30v_align PARAMS ((int)); -static void s_d30v_text PARAMS ((int)); -static void s_d30v_data PARAMS ((int)); -static void s_d30v_section PARAMS ((int)); - struct option md_longopts[] = { {NULL, no_argument, NULL, 0} @@ -145,21 +118,6 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); -/* The target specific pseudo-ops which we support. */ -const pseudo_typeS md_pseudo_table[] = -{ - { "word", cons, 4 }, - { "hword", cons, 2 }, - { "align", s_d30v_align, 0 }, - { "text", s_d30v_text, 0 }, - { "data", s_d30v_data, 0 }, - { "section", s_d30v_section, 0 }, - { "section.s", s_d30v_section, 0 }, - { "sect", s_d30v_section, 0 }, - { "sect.s", s_d30v_section, 0 }, - { NULL, NULL, 0 } -}; - /* Opcode hash table. */ static struct hash_control *d30v_hash; @@ -168,8 +126,7 @@ static struct hash_control *d30v_hash; array on success, or -1 on failure. */ static int -reg_name_search (name) - char *name; +reg_name_search (char *name) { int middle, low, high; int cmp; @@ -206,8 +163,7 @@ reg_name_search (name) register name. */ static int -register_name (expressionP) - expressionS *expressionP; +register_name (expressionS *expressionP) { int reg_number; char c, *p = input_line_pointer; @@ -236,10 +192,7 @@ register_name (expressionP) } static int -check_range (num, bits, flags) - unsigned long num; - int bits; - int flags; +check_range (unsigned long num, int bits, int flags) { long min, max; @@ -282,8 +235,7 @@ check_range (num, bits, flags) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("\nD30V options:\n\ -O Make adjacent short instructions parallel if possible.\n\ @@ -294,9 +246,7 @@ md_show_usage (stream) } int -md_parse_option (c, arg) - int c; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) { switch (c) { @@ -331,8 +281,7 @@ md_parse_option (c, arg) } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -343,10 +292,7 @@ md_undefined_symbol (name) returned, or NULL on OK. */ char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[4]; @@ -381,25 +327,22 @@ md_atof (type, litP, sizeP) } void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) { abort (); } valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg, valueT addr) { int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align)); } void -md_begin () +md_begin (void) { struct d30v_opcode *opcode; d30v_hash = hash_new (); @@ -419,8 +362,7 @@ md_begin () from an expression. */ static int -postfix (p) - char *p; +postfix (char *p) { while (*p != '-' && *p != '+') { @@ -445,9 +387,7 @@ postfix (p) } static bfd_reloc_code_real_type -get_reloc (op, rel_flag) - struct d30v_operand *op; - int rel_flag; +get_reloc (struct d30v_operand *op, int rel_flag) { switch (op->bits) { @@ -484,9 +424,7 @@ get_reloc (op, rel_flag) /* Parse a string of operands and return an array of expressions. */ static int -get_operands (exp, cmp_hack) - expressionS exp[]; - int cmp_hack; +get_operands (expressionS exp[], int cmp_hack) { char *p = input_line_pointer; int numops = 0; @@ -579,9 +517,7 @@ get_operands (exp, cmp_hack) It does everything but write the FM bits. */ static long long -build_insn (opcode, opers) - struct d30v_insn *opcode; - expressionS *opers; +build_insn (struct d30v_insn *opcode, expressionS *opers) { int i, length, bits, shift, flags; unsigned long number, id = 0; @@ -621,16 +557,13 @@ build_insn (opcode, opers) number = 0; } else if (number & OPERAND_FLAG) - { - /* NUMBER is a flag register. */ - id = 3; - } + /* NUMBER is a flag register. */ + id = 3; + number &= 0x7F; } else if (flags & OPERAND_SPECIAL) - { - number = id; - } + number = id; if (opers[i].X_op != O_register && opers[i].X_op != O_constant && !(flags & OPERAND_NAME)) @@ -661,10 +594,10 @@ build_insn (opcode, opers) if (bits == 32) { /* It's a LONG instruction. */ - insn |= ((number & 0xffffffff) >> 26); /* top 6 bits */ - insn <<= 32; /* shift the first word over */ - insn |= ((number & 0x03FC0000) << 2); /* next 8 bits */ - insn |= number & 0x0003FFFF; /* bottom 18 bits */ + insn |= ((number & 0xffffffff) >> 26); /* Top 6 bits. */ + insn <<= 32; /* Shift the first word over. */ + insn |= ((number & 0x03FC0000) << 2); /* Next 8 bits. */ + insn |= number & 0x0003FFFF; /* Bottom 18 bits. */ } else insn |= number << shift; @@ -673,13 +606,24 @@ build_insn (opcode, opers) return insn; } +static void +d30v_number_to_chars (char *buf, /* Return 'nbytes' of chars here. */ + long long value, /* The value of the bits. */ + int n) /* Number of bytes in the output. */ +{ + while (n--) + { + buf[n] = value & 0xff; + value >>= 8; + } +} + /* Write out a long form instruction. */ static void -write_long (opcode, insn, fx) - struct d30v_insn *opcode ATTRIBUTE_UNUSED; - long long insn; - Fixups *fx; +write_long (struct d30v_insn *opcode ATTRIBUTE_UNUSED, + long long insn, + Fixups *fx) { int i, where; char *f = frag_more (8); @@ -692,12 +636,8 @@ write_long (opcode, insn, fx) if (fx->fix[i].reloc) { where = f - frag_now->fr_literal; - fix_new_exp (frag_now, - where, - fx->fix[i].size, - &(fx->fix[i].exp), - fx->fix[i].pcrel, - fx->fix[i].reloc); + fix_new_exp (frag_now, where, fx->fix[i].size, &(fx->fix[i].exp), + fx->fix[i].pcrel, fx->fix[i].reloc); } } @@ -707,11 +647,10 @@ write_long (opcode, insn, fx) /* Write out a short form instruction by itself. */ static void -write_1_short (opcode, insn, fx, use_sequential) - struct d30v_insn *opcode; - long long insn; - Fixups *fx; - int use_sequential; +write_1_short (struct d30v_insn *opcode, + long long insn, + Fixups *fx, + int use_sequential) { char *f = frag_more (8); int i, where; @@ -729,7 +668,6 @@ write_1_short (opcode, insn, fx, use_sequential) /* According to 4.3.1: for FM=01, sub-instructions performed only by IU cannot be encoded in L-container. */ - if (opcode->op->unit == IU) /* Right then left. */ insn |= FM10 | NOP_LEFT; @@ -741,7 +679,6 @@ write_1_short (opcode, insn, fx, use_sequential) { /* According to 4.3.1: for FM=00, sub-instructions performed only by IU cannot be encoded in L-container. */ - if (opcode->op->unit == IU) /* Right container. */ insn |= FM00 | NOP_LEFT; @@ -769,205 +706,15 @@ write_1_short (opcode, insn, fx, use_sequential) fx->fc = 0; } -/* Write out a short form instruction if possible. - Return number of instructions not written out. */ - -static int -write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx) - struct d30v_insn *opcode1, *opcode2; - long long insn1, insn2; - exec_type_enum exec_type; - Fixups *fx; -{ - long long insn = NOP2; - char *f; - int i, j, where; - - if (exec_type == EXEC_SEQ - && (opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR)) - && ((opcode1->op->flags_used & FLAG_DELAY) == 0) - && ((opcode1->ecc == ECC_AL) || ! Optimizing)) - { - /* Unconditional, non-delayed branches kill instructions in - the right bin. Conditional branches don't always but if - we are not optimizing, then we have been asked to produce - an error about such constructs. For the purposes of this - test, subroutine calls are considered to be branches. */ - write_1_short (opcode1, insn1, fx->next, FALSE); - return 1; - } - - /* Note: we do not have to worry about subroutine calls occurring - in the right hand container. The return address is always - aligned to the next 64 bit boundary, be that 64 or 32 bit away. */ - switch (exec_type) - { - case EXEC_UNKNOWN: /* Order not specified. */ - if (Optimizing - && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type) - && ! ( (opcode1->op->unit == EITHER_BUT_PREFER_MU - || opcode1->op->unit == MU) - && - ( opcode2->op->unit == EITHER_BUT_PREFER_MU - || opcode2->op->unit == MU))) - { - /* Parallel. */ - exec_type = EXEC_PARALLEL; - - if (opcode1->op->unit == IU - || opcode2->op->unit == MU - || opcode2->op->unit == EITHER_BUT_PREFER_MU) - insn = FM00 | (insn2 << 32) | insn1; - else - { - insn = FM00 | (insn1 << 32) | insn2; - fx = fx->next; - } - } - else if ((opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR) - && ((opcode1->op->flags_used & FLAG_DELAY) == 0)) - || opcode1->op->flags_used & FLAG_RP) - { - /* We must emit (non-delayed) branch type instructions - on their own with nothing in the right container. */ - /* We must treat repeat instructions likewise, since the - following instruction has to be separate from the repeat - in order to be repeated. */ - write_1_short (opcode1, insn1, fx->next, FALSE); - return 1; - } - else if (prev_left_kills_right_p) - { - /* The left instruction kils the right slot, so we - must leave it empty. */ - write_1_short (opcode1, insn1, fx->next, FALSE); - return 1; - } - else if (opcode1->op->unit == IU) - { - if (opcode2->op->unit == EITHER_BUT_PREFER_MU) - { - /* Case 103810 is a request from Mitsubishi that opcodes - with EITHER_BUT_PREFER_MU should not be executed in - reverse sequential order. */ - write_1_short (opcode1, insn1, fx->next, FALSE); - return 1; - } - - /* Reverse sequential. */ - insn = FM10 | (insn2 << 32) | insn1; - exec_type = EXEC_REVSEQ; - } - else - { - /* Sequential. */ - insn = FM01 | (insn1 << 32) | insn2; - fx = fx->next; - exec_type = EXEC_SEQ; - } - break; - - case EXEC_PARALLEL: /* Parallel. */ - flag_explicitly_parallel = flag_xp_state; - if (! parallel_ok (opcode1, insn1, opcode2, insn2, exec_type)) - as_bad (_("Instructions may not be executed in parallel")); - else if (opcode1->op->unit == IU) - { - if (opcode2->op->unit == IU) - as_bad (_("Two IU instructions may not be executed in parallel")); - as_warn (_("Swapping instruction order")); - insn = FM00 | (insn2 << 32) | insn1; - } - else if (opcode2->op->unit == MU) - { - if (opcode1->op->unit == MU) - as_bad (_("Two MU instructions may not be executed in parallel")); - else if (opcode1->op->unit == EITHER_BUT_PREFER_MU) - as_warn (_("Executing %s in IU may not work"), opcode1->op->name); - as_warn (_("Swapping instruction order")); - insn = FM00 | (insn2 << 32) | insn1; - } - else - { - if (opcode2->op->unit == EITHER_BUT_PREFER_MU) - as_warn (_("Executing %s in IU may not work in parallel execution"), - opcode2->op->name); - - insn = FM00 | (insn1 << 32) | insn2; - fx = fx->next; - } - flag_explicitly_parallel = 0; - break; - - case EXEC_SEQ: /* Sequential. */ - if (opcode1->op->unit == IU) - as_bad (_("IU instruction may not be in the left container")); - if (prev_left_kills_right_p) - as_bad (_("special left instruction `%s' kills instruction " - "`%s' in right container"), - opcode1->op->name, opcode2->op->name); - insn = FM01 | (insn1 << 32) | insn2; - fx = fx->next; - break; - - case EXEC_REVSEQ: /* Reverse sequential. */ - if (opcode2->op->unit == MU) - as_bad (_("MU instruction may not be in the right container")); - if (opcode1->op->unit == EITHER_BUT_PREFER_MU) - as_warn (_("Executing %s in reverse serial with %s may not work"), - opcode1->op->name, opcode2->op->name); - else if (opcode2->op->unit == EITHER_BUT_PREFER_MU) - as_warn (_("Executing %s in IU in reverse serial may not work"), - opcode2->op->name); - insn = FM10 | (insn1 << 32) | insn2; - fx = fx->next; - break; - - default: - as_fatal (_("unknown execution type passed to write_2_short()")); - } - - f = frag_more (8); - d30v_number_to_chars (f, insn, 8); - - /* If the previous instruction was a 32-bit multiply but it is put into a - parallel container, mark the current instruction as being a 32-bit - multiply. */ - if (prev_mul32_p && exec_type == EXEC_PARALLEL) - cur_mul32_p = 1; - - for (j = 0; j < 2; j++) - { - for (i = 0; i < fx->fc; i++) - { - if (fx->fix[i].reloc) - { - where = (f - frag_now->fr_literal) + 4 * j; - - fix_new_exp (frag_now, - where, - fx->fix[i].size, - &(fx->fix[i].exp), - fx->fix[i].pcrel, - fx->fix[i].reloc); - } - } - - fx->fc = 0; - fx = fx->next; - } - - return 0; -} - /* Check 2 instructions and determine if they can be safely executed in parallel. Return 1 if they can be. */ static int -parallel_ok (op1, insn1, op2, insn2, exec_type) - struct d30v_insn *op1, *op2; - unsigned long insn1, insn2; - exec_type_enum exec_type; +parallel_ok (struct d30v_insn *op1, + unsigned long insn1, + struct d30v_insn *op2, + unsigned long insn2, + exec_type_enum exec_type) { int i, j, shift, regno, bits, ecc; unsigned long flags, mask, flags_set1, flags_set2, flags_used1, flags_used2; @@ -1215,206 +962,352 @@ parallel_ok (op1, insn1, op2, insn2, exec_type) return 1; } -/* This is the main entry point for the machine-dependent assembler. - STR points to a machine-dependent instruction. This function is - supposed to emit the frags/bytes it assembles to. For the D30V, it - mostly handles the special VLIW parsing and packing and leaves the - difficult stuff to do_assemble (). */ - -static long long prev_insn = -1; -static struct d30v_insn prev_opcode; -static subsegT prev_subseg; -static segT prev_seg = 0; +/* Write out a short form instruction if possible. + Return number of instructions not written out. */ -void -md_assemble (str) - char *str; +static int +write_2_short (struct d30v_insn *opcode1, + long long insn1, + struct d30v_insn *opcode2, + long long insn2, + exec_type_enum exec_type, + Fixups *fx) { - struct d30v_insn opcode; - long long insn; - /* Execution type; parallel, etc. */ - exec_type_enum extype = EXEC_UNKNOWN; - /* Saved extype. Used for multiline instructions. */ - static exec_type_enum etype = EXEC_UNKNOWN; - char *str2; - - if ((prev_insn != -1) && prev_seg - && ((prev_seg != now_seg) || (prev_subseg != now_subseg))) - d30v_cleanup (FALSE); + long long insn = NOP2; + char *f; + int i, j, where; - if (d30v_current_align < 3) - d30v_align (3, NULL, d30v_last_label); - else if (d30v_current_align > 3) - d30v_current_align = 3; - d30v_last_label = NULL; + if (exec_type == EXEC_SEQ + && (opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR)) + && ((opcode1->op->flags_used & FLAG_DELAY) == 0) + && ((opcode1->ecc == ECC_AL) || ! Optimizing)) + { + /* Unconditional, non-delayed branches kill instructions in + the right bin. Conditional branches don't always but if + we are not optimizing, then we have been asked to produce + an error about such constructs. For the purposes of this + test, subroutine calls are considered to be branches. */ + write_1_short (opcode1, insn1, fx->next, FALSE); + return 1; + } - flag_explicitly_parallel = 0; - flag_xp_state = 0; - if (etype == EXEC_UNKNOWN) + /* Note: we do not have to worry about subroutine calls occurring + in the right hand container. The return address is always + aligned to the next 64 bit boundary, be that 64 or 32 bit away. */ + switch (exec_type) { - /* Look for the special multiple instruction separators. */ - str2 = strstr (str, "||"); - if (str2) - { - extype = EXEC_PARALLEL; - flag_xp_state = 1; - } - else + case EXEC_UNKNOWN: /* Order not specified. */ + if (Optimizing + && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type) + && ! ( (opcode1->op->unit == EITHER_BUT_PREFER_MU + || opcode1->op->unit == MU) + && + ( opcode2->op->unit == EITHER_BUT_PREFER_MU + || opcode2->op->unit == MU))) { - str2 = strstr (str, "->"); - if (str2) - extype = EXEC_SEQ; + /* Parallel. */ + exec_type = EXEC_PARALLEL; + + if (opcode1->op->unit == IU + || opcode2->op->unit == MU + || opcode2->op->unit == EITHER_BUT_PREFER_MU) + insn = FM00 | (insn2 << 32) | insn1; else { - str2 = strstr (str, "<-"); - if (str2) - extype = EXEC_REVSEQ; + insn = FM00 | (insn1 << 32) | insn2; + fx = fx->next; } } + else if ((opcode1->op->flags_used & (FLAG_JMP | FLAG_JSR) + && ((opcode1->op->flags_used & FLAG_DELAY) == 0)) + || opcode1->op->flags_used & FLAG_RP) + { + /* We must emit (non-delayed) branch type instructions + on their own with nothing in the right container. */ + /* We must treat repeat instructions likewise, since the + following instruction has to be separate from the repeat + in order to be repeated. */ + write_1_short (opcode1, insn1, fx->next, FALSE); + return 1; + } + else if (prev_left_kills_right_p) + { + /* The left instruction kils the right slot, so we + must leave it empty. */ + write_1_short (opcode1, insn1, fx->next, FALSE); + return 1; + } + else if (opcode1->op->unit == IU) + { + if (opcode2->op->unit == EITHER_BUT_PREFER_MU) + { + /* Case 103810 is a request from Mitsubishi that opcodes + with EITHER_BUT_PREFER_MU should not be executed in + reverse sequential order. */ + write_1_short (opcode1, insn1, fx->next, FALSE); + return 1; + } - /* STR2 points to the separator, if one. */ - if (str2) + /* Reverse sequential. */ + insn = FM10 | (insn2 << 32) | insn1; + exec_type = EXEC_REVSEQ; + } + else { - *str2 = 0; + /* Sequential. */ + insn = FM01 | (insn1 << 32) | insn2; + fx = fx->next; + exec_type = EXEC_SEQ; + } + break; - /* If two instructions are present and we already have one saved, - then first write it out. */ - d30v_cleanup (FALSE); + case EXEC_PARALLEL: /* Parallel. */ + flag_explicitly_parallel = flag_xp_state; + if (! parallel_ok (opcode1, insn1, opcode2, insn2, exec_type)) + as_bad (_("Instructions may not be executed in parallel")); + else if (opcode1->op->unit == IU) + { + if (opcode2->op->unit == IU) + as_bad (_("Two IU instructions may not be executed in parallel")); + as_warn (_("Swapping instruction order")); + insn = FM00 | (insn2 << 32) | insn1; + } + else if (opcode2->op->unit == MU) + { + if (opcode1->op->unit == MU) + as_bad (_("Two MU instructions may not be executed in parallel")); + else if (opcode1->op->unit == EITHER_BUT_PREFER_MU) + as_warn (_("Executing %s in IU may not work"), opcode1->op->name); + as_warn (_("Swapping instruction order")); + insn = FM00 | (insn2 << 32) | insn1; + } + else + { + if (opcode2->op->unit == EITHER_BUT_PREFER_MU) + as_warn (_("Executing %s in IU may not work in parallel execution"), + opcode2->op->name); - /* Assemble first instruction and save it. */ - prev_insn = do_assemble (str, &prev_opcode, 1, 0); - if (prev_insn == -1) - as_bad (_("Cannot assemble instruction")); - if (prev_opcode.form != NULL && prev_opcode.form->form >= LONG) - as_bad (_("First opcode is long. Unable to mix instructions as specified.")); - fixups = fixups->next; - str = str2 + 2; - prev_seg = now_seg; - prev_subseg = now_subseg; + insn = FM00 | (insn1 << 32) | insn2; + fx = fx->next; } - } + flag_explicitly_parallel = 0; + break; - insn = do_assemble (str, &opcode, - (extype != EXEC_UNKNOWN || etype != EXEC_UNKNOWN), - extype == EXEC_PARALLEL); - if (insn == -1) - { - if (extype != EXEC_UNKNOWN) - etype = extype; - as_bad (_("Cannot assemble instruction")); - return; - } + case EXEC_SEQ: /* Sequential. */ + if (opcode1->op->unit == IU) + as_bad (_("IU instruction may not be in the left container")); + if (prev_left_kills_right_p) + as_bad (_("special left instruction `%s' kills instruction " + "`%s' in right container"), + opcode1->op->name, opcode2->op->name); + insn = FM01 | (insn1 << 32) | insn2; + fx = fx->next; + break; - if (etype != EXEC_UNKNOWN) - { - extype = etype; - etype = EXEC_UNKNOWN; + case EXEC_REVSEQ: /* Reverse sequential. */ + if (opcode2->op->unit == MU) + as_bad (_("MU instruction may not be in the right container")); + if (opcode1->op->unit == EITHER_BUT_PREFER_MU) + as_warn (_("Executing %s in reverse serial with %s may not work"), + opcode1->op->name, opcode2->op->name); + else if (opcode2->op->unit == EITHER_BUT_PREFER_MU) + as_warn (_("Executing %s in IU in reverse serial may not work"), + opcode2->op->name); + insn = FM10 | (insn1 << 32) | insn2; + fx = fx->next; + break; + + default: + as_fatal (_("unknown execution type passed to write_2_short()")); } - /* Word multiply instructions must not be followed by either a load or a - 16-bit multiply instruction in the next cycle. */ - if ( (extype != EXEC_REVSEQ) - && prev_mul32_p - && (opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16))) + f = frag_more (8); + d30v_number_to_chars (f, insn, 8); + + /* If the previous instruction was a 32-bit multiply but it is put into a + parallel container, mark the current instruction as being a 32-bit + multiply. */ + if (prev_mul32_p && exec_type == EXEC_PARALLEL) + cur_mul32_p = 1; + + for (j = 0; j < 2; j++) { - /* However, load and multiply should able to be combined in a parallel - operation, so check for that first. */ - if (prev_insn != -1 - && (opcode.op->flags_used & FLAG_MEM) - && opcode.form->form < LONG - && (extype == EXEC_PARALLEL || (Optimizing && extype == EXEC_UNKNOWN)) - && parallel_ok (&prev_opcode, (long) prev_insn, - &opcode, (long) insn, extype) - && write_2_short (&prev_opcode, (long) prev_insn, - &opcode, (long) insn, extype, fixups) == 0) - { - /* No instructions saved. */ - prev_insn = -1; - return; - } - else + for (i = 0; i < fx->fc; i++) { - /* Can't parallelize, flush previous instruction and emit a - word of NOPS, unless the previous instruction is a NOP, - in which case just flush it, as this will generate a word - of NOPs for us. */ - - if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0)) - d30v_cleanup (FALSE); - else + if (fx->fix[i].reloc) { - char *f; - - if (prev_insn != -1) - d30v_cleanup (TRUE); - else - { - f = frag_more (8); - d30v_number_to_chars (f, NOP2, 8); + where = (f - frag_now->fr_literal) + 4 * j; - if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY) - { - if (opcode.op->flags_used & FLAG_MEM) - as_warn (_("word of NOPs added between word multiply and load")); - else - as_warn (_("word of NOPs added between word multiply and 16-bit multiply")); - } - } + fix_new_exp (frag_now, + where, + fx->fix[i].size, + &(fx->fix[i].exp), + fx->fix[i].pcrel, + fx->fix[i].reloc); } - - extype = EXEC_UNKNOWN; } + + fx->fc = 0; + fx = fx->next; } - else if ( (extype == EXEC_REVSEQ) - && cur_mul32_p - && (prev_opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16))) - { - /* Can't parallelize, flush current instruction and add a - sequential NOP. */ - write_1_short (&opcode, (long) insn, fixups->next->next, TRUE); - /* Make the previous instruction the current one. */ - extype = EXEC_UNKNOWN; - insn = prev_insn; - now_seg = prev_seg; - now_subseg = prev_subseg; - prev_insn = -1; - cur_mul32_p = prev_mul32_p; - prev_mul32_p = 0; - memcpy (&opcode, &prev_opcode, sizeof (prev_opcode)); - } + return 0; +} - /* If this is a long instruction, write it and any previous short - instruction. */ - if (opcode.form->form >= LONG) - { - if (extype != EXEC_UNKNOWN) - as_bad (_("Instruction uses long version, so it cannot be mixed as specified")); - d30v_cleanup (FALSE); - write_long (&opcode, insn, fixups); - prev_insn = -1; - } - else if ((prev_insn != -1) - && (write_2_short - (&prev_opcode, (long) prev_insn, &opcode, - (long) insn, extype, fixups) == 0)) - { - /* No instructions saved. */ - prev_insn = -1; - } - else +/* Get a pointer to an entry in the format table. + It must look at all formats for an opcode and use the operands + to choose the correct one. Return NULL on error. */ + +static struct d30v_format * +find_format (struct d30v_opcode *opcode, + expressionS myops[], + int fsize, + int cmp_hack) +{ + int numops, match, index, i = 0, j, k; + struct d30v_format *fm; + + if (opcode == NULL) + return NULL; + + /* Get all the operands and save them as expressions. */ + numops = get_operands (myops, cmp_hack); + + while ((index = opcode->format[i++]) != 0) { - if (extype != EXEC_UNKNOWN) - as_bad (_("Unable to mix instructions as specified")); + if (fsize == FORCE_SHORT && index >= LONG) + continue; - /* Save off last instruction so it may be packed on next pass. */ - memcpy (&prev_opcode, &opcode, sizeof (prev_opcode)); - prev_insn = insn; - prev_seg = now_seg; - prev_subseg = now_subseg; - fixups = fixups->next; - prev_mul32_p = cur_mul32_p; + if (fsize == FORCE_LONG && index < LONG) + continue; + + fm = (struct d30v_format *) &d30v_format_table[index]; + k = index; + while (fm->form == index) + { + match = 1; + /* Now check the operands for compatibility. */ + for (j = 0; match && fm->operands[j]; j++) + { + int flags = d30v_operand_table[fm->operands[j]].flags; + int bits = d30v_operand_table[fm->operands[j]].bits; + int X_op = myops[j].X_op; + int num = myops[j].X_add_number; + + if (flags & OPERAND_SPECIAL) + break; + else if (X_op == O_illegal) + match = 0; + else if (flags & OPERAND_REG) + { + if (X_op != O_register + || ((flags & OPERAND_ACC) && !(num & OPERAND_ACC)) + || (!(flags & OPERAND_ACC) && (num & OPERAND_ACC)) + || ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG)) + || (!(flags & (OPERAND_FLAG | OPERAND_CONTROL)) && (num & OPERAND_FLAG)) + || ((flags & OPERAND_CONTROL) + && !(num & (OPERAND_CONTROL | OPERAND_FLAG)))) + match = 0; + } + else if (((flags & OPERAND_MINUS) + && (X_op != O_absent || num != OPERAND_MINUS)) + || ((flags & OPERAND_PLUS) + && (X_op != O_absent || num != OPERAND_PLUS)) + || ((flags & OPERAND_ATMINUS) + && (X_op != O_absent || num != OPERAND_ATMINUS)) + || ((flags & OPERAND_ATPAR) + && (X_op != O_absent || num != OPERAND_ATPAR)) + || ((flags & OPERAND_ATSIGN) + && (X_op != O_absent || num != OPERAND_ATSIGN))) + match = 0; + else if (flags & OPERAND_NUM) + { + /* A number can be a constant or symbol expression. */ + + /* If we have found a register name, but that name + also matches a symbol, then re-parse the name as + an expression. */ + if (X_op == O_register + && symbol_find ((char *) myops[j].X_op_symbol)) + { + input_line_pointer = (char *) myops[j].X_op_symbol; + expression (&myops[j]); + } + + /* Turn an expression into a symbol for later resolution. */ + if (X_op != O_absent && X_op != O_constant + && X_op != O_symbol && X_op != O_register + && X_op != O_big) + { + symbolS *sym = make_expr_symbol (&myops[j]); + myops[j].X_op = X_op = O_symbol; + myops[j].X_add_symbol = sym; + myops[j].X_add_number = num = 0; + } + + if (fm->form >= LONG) + { + /* If we're testing for a LONG format, either fits. */ + if (X_op != O_constant && X_op != O_symbol) + match = 0; + } + else if (fm->form < LONG + && ((fsize == FORCE_SHORT && X_op == O_symbol) + || (fm->form == SHORT_D2 && j == 0))) + match = 1; + + /* This is the tricky part. Will the constant or symbol + fit into the space in the current format? */ + else if (X_op == O_constant) + { + if (check_range (num, bits, flags)) + match = 0; + } + else if (X_op == O_symbol + && S_IS_DEFINED (myops[j].X_add_symbol) + && S_GET_SEGMENT (myops[j].X_add_symbol) == now_seg + && opcode->reloc_flag == RELOC_PCREL) + { + /* If the symbol is defined, see if the value will fit + into the form we're considering. */ + fragS *f; + long value; + + /* Calculate the current address by running through the + previous frags and adding our current offset. */ + value = 0; + for (f = frchain_now->frch_root; f; f = f->fr_next) + value += f->fr_fix + f->fr_offset; + value = (S_GET_VALUE (myops[j].X_add_symbol) - value + - (obstack_next_free (&frchain_now->frch_obstack) + - frag_now->fr_literal)); + if (check_range (value, bits, flags)) + match = 0; + } + else + match = 0; + } + } + /* We're only done if the operands matched so far AND there + are no more to check. */ + if (match && myops[j].X_op == 0) + { + /* Final check - issue a warning if an odd numbered register + is used as the first register in an instruction that reads + or writes 2 registers. */ + + for (j = 0; fm->operands[j]; j++) + if (myops[j].X_op == O_register + && (myops[j].X_add_number & 1) + && (d30v_operand_table[fm->operands[j]].flags & OPERAND_2REG)) + as_warn (_("Odd numbered register used as target of multi-register instruction")); + + return fm; + } + fm = (struct d30v_format *) &d30v_format_table[++k]; + } } + return NULL; } /* Assemble a single instruction and return an opcode. @@ -1423,11 +1316,10 @@ md_assemble (str) #define NAME_BUF_LEN 20 static long long -do_assemble (str, opcode, shortp, is_parallel) - char *str; - struct d30v_insn *opcode; - int shortp; - int is_parallel; +do_assemble (char *str, + struct d30v_insn *opcode, + int shortp, + int is_parallel) { char *op_start; char *save; @@ -1610,219 +1502,429 @@ do_assemble (str, opcode, shortp, is_parallel) return insn; } -/* Get a pointer to an entry in the format table. - It must look at all formats for an opcode and use the operands - to choose the correct one. Return NULL on error. */ +/* Called internally to handle all alignment needs. This takes care + of eliding calls to frag_align if'n the cached current alignment + says we've already got it, as well as taking care of the auto-aligning + labels wrt code. */ -static struct d30v_format * -find_format (opcode, myops, fsize, cmp_hack) - struct d30v_opcode *opcode; - expressionS myops[]; - int fsize; - int cmp_hack; +static void +d30v_align (int n, char *pfill, symbolS *label) { - int numops, match, index, i = 0, j, k; - struct d30v_format *fm; - - if (opcode == NULL) - return NULL; + /* The front end is prone to changing segments out from under us + temporarily when -g is in effect. */ + int switched_seg_p = (d30v_current_align_seg != now_seg); - /* Get all the operands and save them as expressions. */ - numops = get_operands (myops, cmp_hack); + /* Do not assume that if 'd30v_current_align >= n' and + '! switched_seg_p' that it is safe to avoid performing + this alignment request. The alignment of the current frag + can be changed under our feet, for example by a .ascii + directive in the source code. cf testsuite/gas/d30v/reloc.s */ + d30v_cleanup (FALSE); - while ((index = opcode->format[i++]) != 0) + if (pfill == NULL) { - if (fsize == FORCE_SHORT && index >= LONG) - continue; + if (n > 2 + && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + { + static char const nop[4] = { 0x00, 0xf0, 0x00, 0x00 }; - if (fsize == FORCE_LONG && index < LONG) - continue; + /* First, make sure we're on a four-byte boundary, in case + someone has been putting .byte values the text section. */ + if (d30v_current_align < 2 || switched_seg_p) + frag_align (2, 0, 0); + frag_align_pattern (n, nop, sizeof nop, 0); + } + else + frag_align (n, 0, 0); + } + else + frag_align (n, *pfill, 0); - fm = (struct d30v_format *) &d30v_format_table[index]; - k = index; - while (fm->form == index) - { - match = 1; - /* Now check the operands for compatibility. */ - for (j = 0; match && fm->operands[j]; j++) - { - int flags = d30v_operand_table[fm->operands[j]].flags; - int bits = d30v_operand_table[fm->operands[j]].bits; - int X_op = myops[j].X_op; - int num = myops[j].X_add_number; + if (!switched_seg_p) + d30v_current_align = n; - if (flags & OPERAND_SPECIAL) - break; - else if (X_op == O_illegal) - match = 0; - else if (flags & OPERAND_REG) - { - if (X_op != O_register - || ((flags & OPERAND_ACC) && !(num & OPERAND_ACC)) - || (!(flags & OPERAND_ACC) && (num & OPERAND_ACC)) - || ((flags & OPERAND_FLAG) && !(num & OPERAND_FLAG)) - || (!(flags & (OPERAND_FLAG | OPERAND_CONTROL)) && (num & OPERAND_FLAG)) - || ((flags & OPERAND_CONTROL) - && !(num & (OPERAND_CONTROL | OPERAND_FLAG)))) - { - match = 0; - } - } - else if (((flags & OPERAND_MINUS) - && (X_op != O_absent || num != OPERAND_MINUS)) - || ((flags & OPERAND_PLUS) - && (X_op != O_absent || num != OPERAND_PLUS)) - || ((flags & OPERAND_ATMINUS) - && (X_op != O_absent || num != OPERAND_ATMINUS)) - || ((flags & OPERAND_ATPAR) - && (X_op != O_absent || num != OPERAND_ATPAR)) - || ((flags & OPERAND_ATSIGN) - && (X_op != O_absent || num != OPERAND_ATSIGN))) - { - match = 0; - } - else if (flags & OPERAND_NUM) - { - /* A number can be a constant or symbol expression. */ + if (label != NULL) + { + symbolS *sym; + int label_seen = FALSE; + struct frag *old_frag; + valueT old_value; + valueT new_value; - /* If we have found a register name, but that name - also matches a symbol, then re-parse the name as - an expression. */ - if (X_op == O_register - && symbol_find ((char *) myops[j].X_op_symbol)) - { - input_line_pointer = (char *) myops[j].X_op_symbol; - expression (&myops[j]); - } + assert (S_GET_SEGMENT (label) == now_seg); - /* Turn an expression into a symbol for later resolution. */ - if (X_op != O_absent && X_op != O_constant - && X_op != O_symbol && X_op != O_register - && X_op != O_big) - { - symbolS *sym = make_expr_symbol (&myops[j]); - myops[j].X_op = X_op = O_symbol; - myops[j].X_add_symbol = sym; - myops[j].X_add_number = num = 0; - } + old_frag = symbol_get_frag (label); + old_value = S_GET_VALUE (label); + new_value = (valueT) frag_now_fix (); - if (fm->form >= LONG) - { - /* If we're testing for a LONG format, either fits. */ - if (X_op != O_constant && X_op != O_symbol) - match = 0; - } - else if (fm->form < LONG - && ((fsize == FORCE_SHORT && X_op == O_symbol) - || (fm->form == SHORT_D2 && j == 0))) - match = 1; + /* It is possible to have more than one label at a particular + address, especially if debugging is enabled, so we must + take care to adjust all the labels at this address in this + fragment. To save time we search from the end of the symbol + list, backwards, since the symbols we are interested in are + almost certainly the ones that were most recently added. + Also to save time we stop searching once we have seen at least + one matching label, and we encounter a label that is no longer + in the target fragment. Note, this search is guaranteed to + find at least one match when sym == label, so no special case + code is necessary. */ + for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym)) + { + if (symbol_get_frag (sym) == old_frag + && S_GET_VALUE (sym) == old_value) + { + label_seen = TRUE; + symbol_set_frag (sym, frag_now); + S_SET_VALUE (sym, new_value); + } + else if (label_seen && symbol_get_frag (sym) != old_frag) + break; + } + } - /* This is the tricky part. Will the constant or symbol - fit into the space in the current format? */ - else if (X_op == O_constant) - { - if (check_range (num, bits, flags)) - match = 0; - } - else if (X_op == O_symbol - && S_IS_DEFINED (myops[j].X_add_symbol) - && S_GET_SEGMENT (myops[j].X_add_symbol) == now_seg - && opcode->reloc_flag == RELOC_PCREL) - { - /* If the symbol is defined, see if the value will fit - into the form we're considering. */ - fragS *f; - long value; + record_alignment (now_seg, n); +} - /* Calculate the current address by running through the - previous frags and adding our current offset. */ - value = 0; - for (f = frchain_now->frch_root; f; f = f->fr_next) - value += f->fr_fix + f->fr_offset; - value = (S_GET_VALUE (myops[j].X_add_symbol) - value - - (obstack_next_free (&frchain_now->frch_obstack) - - frag_now->fr_literal)); - if (check_range (value, bits, flags)) - match = 0; +/* This is the main entry point for the machine-dependent assembler. + STR points to a machine-dependent instruction. This function is + supposed to emit the frags/bytes it assembles to. For the D30V, it + mostly handles the special VLIW parsing and packing and leaves the + difficult stuff to do_assemble (). */ + +static long long prev_insn = -1; +static struct d30v_insn prev_opcode; +static subsegT prev_subseg; +static segT prev_seg = 0; + +void +md_assemble (char *str) +{ + struct d30v_insn opcode; + long long insn; + /* Execution type; parallel, etc. */ + exec_type_enum extype = EXEC_UNKNOWN; + /* Saved extype. Used for multiline instructions. */ + static exec_type_enum etype = EXEC_UNKNOWN; + char *str2; + + if ((prev_insn != -1) && prev_seg + && ((prev_seg != now_seg) || (prev_subseg != now_subseg))) + d30v_cleanup (FALSE); + + if (d30v_current_align < 3) + d30v_align (3, NULL, d30v_last_label); + else if (d30v_current_align > 3) + d30v_current_align = 3; + d30v_last_label = NULL; + + flag_explicitly_parallel = 0; + flag_xp_state = 0; + if (etype == EXEC_UNKNOWN) + { + /* Look for the special multiple instruction separators. */ + str2 = strstr (str, "||"); + if (str2) + { + extype = EXEC_PARALLEL; + flag_xp_state = 1; + } + else + { + str2 = strstr (str, "->"); + if (str2) + extype = EXEC_SEQ; + else + { + str2 = strstr (str, "<-"); + if (str2) + extype = EXEC_REVSEQ; + } + } + + /* STR2 points to the separator, if one. */ + if (str2) + { + *str2 = 0; + + /* If two instructions are present and we already have one saved, + then first write it out. */ + d30v_cleanup (FALSE); + + /* Assemble first instruction and save it. */ + prev_insn = do_assemble (str, &prev_opcode, 1, 0); + if (prev_insn == -1) + as_bad (_("Cannot assemble instruction")); + if (prev_opcode.form != NULL && prev_opcode.form->form >= LONG) + as_bad (_("First opcode is long. Unable to mix instructions as specified.")); + fixups = fixups->next; + str = str2 + 2; + prev_seg = now_seg; + prev_subseg = now_subseg; + } + } + + insn = do_assemble (str, &opcode, + (extype != EXEC_UNKNOWN || etype != EXEC_UNKNOWN), + extype == EXEC_PARALLEL); + if (insn == -1) + { + if (extype != EXEC_UNKNOWN) + etype = extype; + as_bad (_("Cannot assemble instruction")); + return; + } + + if (etype != EXEC_UNKNOWN) + { + extype = etype; + etype = EXEC_UNKNOWN; + } + + /* Word multiply instructions must not be followed by either a load or a + 16-bit multiply instruction in the next cycle. */ + if ( (extype != EXEC_REVSEQ) + && prev_mul32_p + && (opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16))) + { + /* However, load and multiply should able to be combined in a parallel + operation, so check for that first. */ + if (prev_insn != -1 + && (opcode.op->flags_used & FLAG_MEM) + && opcode.form->form < LONG + && (extype == EXEC_PARALLEL || (Optimizing && extype == EXEC_UNKNOWN)) + && parallel_ok (&prev_opcode, (long) prev_insn, + &opcode, (long) insn, extype) + && write_2_short (&prev_opcode, (long) prev_insn, + &opcode, (long) insn, extype, fixups) == 0) + { + /* No instructions saved. */ + prev_insn = -1; + return; + } + else + { + /* Can't parallelize, flush previous instruction and emit a + word of NOPS, unless the previous instruction is a NOP, + in which case just flush it, as this will generate a word + of NOPs for us. */ + + if (prev_insn != -1 && (strcmp (prev_opcode.op->name, "nop") == 0)) + d30v_cleanup (FALSE); + else + { + char *f; + + if (prev_insn != -1) + d30v_cleanup (TRUE); + else + { + f = frag_more (8); + d30v_number_to_chars (f, NOP2, 8); + + if (warn_nops == NOP_ALL || warn_nops == NOP_MULTIPLY) + { + if (opcode.op->flags_used & FLAG_MEM) + as_warn (_("word of NOPs added between word multiply and load")); + else + as_warn (_("word of NOPs added between word multiply and 16-bit multiply")); } - else - match = 0; } } - /* We're only done if the operands matched so far AND there - are no more to check. */ - if (match && myops[j].X_op == 0) - { - /* Final check - issue a warning if an odd numbered register - is used as the first register in an instruction that reads - or writes 2 registers. */ - for (j = 0; fm->operands[j]; j++) - if (myops[j].X_op == O_register - && (myops[j].X_add_number & 1) - && (d30v_operand_table[fm->operands[j]].flags & OPERAND_2REG)) - as_warn (_("Odd numbered register used as target of multi-register instruction")); + extype = EXEC_UNKNOWN; + } + } + else if ( (extype == EXEC_REVSEQ) + && cur_mul32_p + && (prev_opcode.op->flags_used & (FLAG_MEM | FLAG_MUL16))) + { + /* Can't parallelize, flush current instruction and add a + sequential NOP. */ + write_1_short (&opcode, (long) insn, fixups->next->next, TRUE); + + /* Make the previous instruction the current one. */ + extype = EXEC_UNKNOWN; + insn = prev_insn; + now_seg = prev_seg; + now_subseg = prev_subseg; + prev_insn = -1; + cur_mul32_p = prev_mul32_p; + prev_mul32_p = 0; + memcpy (&opcode, &prev_opcode, sizeof (prev_opcode)); + } + + /* If this is a long instruction, write it and any previous short + instruction. */ + if (opcode.form->form >= LONG) + { + if (extype != EXEC_UNKNOWN) + as_bad (_("Instruction uses long version, so it cannot be mixed as specified")); + d30v_cleanup (FALSE); + write_long (&opcode, insn, fixups); + prev_insn = -1; + } + else if ((prev_insn != -1) + && (write_2_short + (&prev_opcode, (long) prev_insn, &opcode, + (long) insn, extype, fixups) == 0)) + { + /* No instructions saved. */ + prev_insn = -1; + } + else + { + if (extype != EXEC_UNKNOWN) + as_bad (_("Unable to mix instructions as specified")); + + /* Save off last instruction so it may be packed on next pass. */ + memcpy (&prev_opcode, &opcode, sizeof (prev_opcode)); + prev_insn = insn; + prev_seg = now_seg; + prev_subseg = now_subseg; + fixups = fixups->next; + prev_mul32_p = cur_mul32_p; + } +} + +/* If while processing a fixup, a reloc really needs to be created, + then it is done here. */ + +arelent * +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) +{ + arelent *reloc; + reloc = xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + if (reloc->howto == NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("reloc %d not supported by object file format"), + (int) fixp->fx_r_type); + return NULL; + } + + reloc->addend = 0; + return reloc; +} + +int +md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, + asection *seg ATTRIBUTE_UNUSED) +{ + abort (); + return 0; +} + +long +md_pcrel_from_section (fixS *fixp, segT sec) +{ + if (fixp->fx_addsy != (symbolS *) NULL + && (!S_IS_DEFINED (fixp->fx_addsy) + || (S_GET_SEGMENT (fixp->fx_addsy) != sec))) + return 0; + return fixp->fx_frag->fr_address + fixp->fx_where; +} + +/* Called after the assembler has finished parsing the input file or + after a label is defined. Because the D30V assembler sometimes + saves short instructions to see if it can package them with the + next instruction, there may be a short instruction that still needs + written. */ + +int +d30v_cleanup (int use_sequential) +{ + segT seg; + subsegT subseg; + + if (prev_insn != -1) + { + seg = now_seg; + subseg = now_subseg; + subseg_set (prev_seg, prev_subseg); + write_1_short (&prev_opcode, (long) prev_insn, fixups->next, + use_sequential); + subseg_set (seg, subseg); + prev_insn = -1; + if (use_sequential) + prev_mul32_p = FALSE; + } + + return 1; +} + +/* This function is called at the start of every line. It checks to + see if the first character is a '.', which indicates the start of a + pseudo-op. If it is, then write out any unwritten instructions. */ + +void +d30v_start_line (void) +{ + char *c = input_line_pointer; + + while (ISSPACE (*c)) + c++; + + if (*c == '.') + d30v_cleanup (FALSE); +} + +static void +check_size (long value, int bits, char *file, int line) +{ + int tmp, max; + + if (value < 0) + tmp = ~value; + else + tmp = value; + + max = (1 << (bits - 1)) - 1; - return fm; - } - fm = (struct d30v_format *) &d30v_format_table[++k]; - } - } - return NULL; + if (tmp > max) + as_bad_where (file, line, _("value too large to fit in %d bits"), bits); } -/* If while processing a fixup, a reloc really needs to be created, - then it is done here. */ +/* d30v_frob_label() is called when after a label is recognized. */ -arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; +void +d30v_frob_label (symbolS *lab) { - arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); - *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); - reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); - if (reloc->howto == (reloc_howto_type *) NULL) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - _("reloc %d not supported by object file format"), - (int) fixp->fx_r_type); - return NULL; - } + /* Emit any pending instructions. */ + d30v_cleanup (FALSE); - reloc->addend = 0; - return reloc; -} + /* Update the label's address with the current output pointer. */ + symbol_set_frag (lab, frag_now); + S_SET_VALUE (lab, (valueT) frag_now_fix ()); -int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp ATTRIBUTE_UNUSED; - asection *seg ATTRIBUTE_UNUSED; -{ - abort (); - return 0; + /* Record this label for future adjustment after we find out what + kind of data it references, and the required alignment therewith. */ + d30v_last_label = lab; } -long -md_pcrel_from_section (fixp, sec) - fixS *fixp; - segT sec; +/* Hook into cons for capturing alignment changes. */ + +void +d30v_cons_align (int size) { - if (fixp->fx_addsy != (symbolS *) NULL - && (!S_IS_DEFINED (fixp->fx_addsy) - || (S_GET_SEGMENT (fixp->fx_addsy) != sec))) - return 0; - return fixp->fx_frag->fr_address + fixp->fx_where; + int log_size; + + log_size = 0; + while ((size >>= 1) != 0) + ++log_size; + + if (d30v_current_align < log_size) + d30v_align (log_size, (char *) NULL, NULL); + else if (d30v_current_align > log_size) + d30v_current_align = log_size; + d30v_last_label = NULL; } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { char *where; unsigned long insn, insn2; @@ -1960,213 +2062,11 @@ md_apply_fix3 (fixP, valP, seg) } } -/* Called after the assembler has finished parsing the input file or - after a label is defined. Because the D30V assembler sometimes - saves short instructions to see if it can package them with the - next instruction, there may be a short instruction that still needs - written. */ - -int -d30v_cleanup (use_sequential) - int use_sequential; -{ - segT seg; - subsegT subseg; - - if (prev_insn != -1) - { - seg = now_seg; - subseg = now_subseg; - subseg_set (prev_seg, prev_subseg); - write_1_short (&prev_opcode, (long) prev_insn, fixups->next, - use_sequential); - subseg_set (seg, subseg); - prev_insn = -1; - if (use_sequential) - prev_mul32_p = FALSE; - } - - return 1; -} - -static void -d30v_number_to_chars (buf, value, n) - char *buf; /* Return 'nbytes' of chars here. */ - long long value; /* The value of the bits. */ - int n; /* Number of bytes in the output. */ -{ - while (n--) - { - buf[n] = value & 0xff; - value >>= 8; - } -} - -/* This function is called at the start of every line. It checks to - see if the first character is a '.', which indicates the start of a - pseudo-op. If it is, then write out any unwritten instructions. */ - -void -d30v_start_line () -{ - char *c = input_line_pointer; - - while (ISSPACE (*c)) - c++; - - if (*c == '.') - d30v_cleanup (FALSE); -} - -static void -check_size (value, bits, file, line) - long value; - int bits; - char *file; - int line; -{ - int tmp, max; - - if (value < 0) - tmp = ~value; - else - tmp = value; - - max = (1 << (bits - 1)) - 1; - - if (tmp > max) - as_bad_where (file, line, _("value too large to fit in %d bits"), bits); -} - -/* d30v_frob_label() is called when after a label is recognized. */ - -void -d30v_frob_label (lab) - symbolS *lab; -{ - /* Emit any pending instructions. */ - d30v_cleanup (FALSE); - - /* Update the label's address with the current output pointer. */ - symbol_set_frag (lab, frag_now); - S_SET_VALUE (lab, (valueT) frag_now_fix ()); - - /* Record this label for future adjustment after we find out what - kind of data it references, and the required alignment therewith. */ - d30v_last_label = lab; -} - -/* Hook into cons for capturing alignment changes. */ - -void -d30v_cons_align (size) - int size; -{ - int log_size; - - log_size = 0; - while ((size >>= 1) != 0) - ++log_size; - - if (d30v_current_align < log_size) - d30v_align (log_size, (char *) NULL, NULL); - else if (d30v_current_align > log_size) - d30v_current_align = log_size; - d30v_last_label = NULL; -} - -/* Called internally to handle all alignment needs. This takes care - of eliding calls to frag_align if'n the cached current alignment - says we've already got it, as well as taking care of the auto-aligning - labels wrt code. */ - -static void -d30v_align (n, pfill, label) - int n; - char *pfill; - symbolS *label; -{ - /* The front end is prone to changing segments out from under us - temporarily when -g is in effect. */ - int switched_seg_p = (d30v_current_align_seg != now_seg); - - /* Do not assume that if 'd30v_current_align >= n' and - '! switched_seg_p' that it is safe to avoid performing - this alignment request. The alignment of the current frag - can be changed under our feet, for example by a .ascii - directive in the source code. cf testsuite/gas/d30v/reloc.s */ - d30v_cleanup (FALSE); - - if (pfill == NULL) - { - if (n > 2 - && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) - { - static char const nop[4] = { 0x00, 0xf0, 0x00, 0x00 }; - - /* First, make sure we're on a four-byte boundary, in case - someone has been putting .byte values the text section. */ - if (d30v_current_align < 2 || switched_seg_p) - frag_align (2, 0, 0); - frag_align_pattern (n, nop, sizeof nop, 0); - } - else - frag_align (n, 0, 0); - } - else - frag_align (n, *pfill, 0); - - if (!switched_seg_p) - d30v_current_align = n; - - if (label != NULL) - { - symbolS *sym; - int label_seen = FALSE; - struct frag *old_frag; - valueT old_value; - valueT new_value; - - assert (S_GET_SEGMENT (label) == now_seg); - - old_frag = symbol_get_frag (label); - old_value = S_GET_VALUE (label); - new_value = (valueT) frag_now_fix (); - - /* It is possible to have more than one label at a particular - address, especially if debugging is enabled, so we must - take care to adjust all the labels at this address in this - fragment. To save time we search from the end of the symbol - list, backwards, since the symbols we are interested in are - almost certainly the ones that were most recently added. - Also to save time we stop searching once we have seen at least - one matching label, and we encounter a label that is no longer - in the target fragment. Note, this search is guaranteed to - find at least one match when sym == label, so no special case - code is necessary. */ - for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym)) - { - if (symbol_get_frag (sym) == old_frag - && S_GET_VALUE (sym) == old_value) - { - label_seen = TRUE; - symbol_set_frag (sym, frag_now); - S_SET_VALUE (sym, new_value); - } - else if (label_seen && symbol_get_frag (sym) != old_frag) - break; - } - } - - record_alignment (now_seg, n); -} - /* Handle the .align pseudo-op. This aligns to a power of two. We hook here to latch the current alignment. */ static void -s_d30v_align (ignore) - int ignore ATTRIBUTE_UNUSED; +s_d30v_align (int ignore ATTRIBUTE_UNUSED) { int align; char fill, *pfill = NULL; @@ -2201,8 +2101,7 @@ s_d30v_align (ignore) clears the saved last label and resets known alignment. */ static void -s_d30v_text (i) - int i; +s_d30v_text (int i) { s_text (i); @@ -2215,8 +2114,7 @@ s_d30v_text (i) clears the saved last label and resets known alignment. */ static void -s_d30v_data (i) - int i; +s_d30v_data (int i) { s_data (i); d30v_last_label = NULL; @@ -2228,11 +2126,26 @@ s_d30v_data (i) clears the saved last label and resets known alignment. */ static void -s_d30v_section (ignore) - int ignore; +s_d30v_section (int ignore) { obj_elf_section (ignore); d30v_last_label = NULL; d30v_current_align = 0; d30v_current_align_seg = now_seg; } + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "word", cons, 4 }, + { "hword", cons, 2 }, + { "align", s_d30v_align, 0 }, + { "text", s_d30v_text, 0 }, + { "data", s_d30v_data, 0 }, + { "section", s_d30v_section, 0 }, + { "section.s", s_d30v_section, 0 }, + { "sect", s_d30v_section, 0 }, + { "sect.s", s_d30v_section, 0 }, + { NULL, NULL, 0 } +}; + diff --git a/gas/config/tc-d30v.h b/gas/config/tc-d30v.h index 7306817c10a..6d0853c57c1 100644 --- a/gas/config/tc-d30v.h +++ b/gas/config/tc-d30v.h @@ -1,5 +1,6 @@ /* tc-310v.h -- Header file for tc-d30v.c. - Copyright 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1997, 1998, 2000, 2001, 2002, 2005 + Free Software Foundation, Inc. Written by Martin Hunt, Cygnus Support. This file is part of GAS, the GNU Assembler. @@ -26,39 +27,40 @@ #endif /* The target BFD architecture. */ -#define TARGET_ARCH bfd_arch_d30v -#define TARGET_FORMAT "elf32-d30v" -#define TARGET_BYTES_BIG_ENDIAN 1 +#define TARGET_ARCH bfd_arch_d30v +#define TARGET_FORMAT "elf32-d30v" +#define TARGET_BYTES_BIG_ENDIAN 1 #define md_operand(x) /* Call md_pcrel_from_section, not md_pcrel_from. */ struct fix; -extern long md_pcrel_from_section PARAMS ((struct fix *, segT)); -#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC) +extern long md_pcrel_from_section (struct fix *, segT); +#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC) /* Permit temporary numeric labels. */ #define LOCAL_LABELS_FB 1 -#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ +/* .-foo gets turned into PC relative relocs. */ +#define DIFF_EXPR_OK /* We don't need to handle .word strangely. */ #define WORKING_DOT_WORD #define md_number_to_chars number_to_chars_bigendian -int d30v_cleanup PARAMS ((int)); +int d30v_cleanup (int); #define md_after_pass_hook() d30v_cleanup (FALSE) #define md_cleanup() d30v_cleanup (FALSE) #define TC_START_LABEL(ch, ptr) (ch == ':' && d30v_cleanup (FALSE)) -void d30v_start_line PARAMS ((void)); +void d30v_start_line (void); #define md_start_line_hook() d30v_start_line () -void d30v_frob_label PARAMS ((symbolS *)); -#define tc_frob_label(sym) d30v_frob_label(sym) +void d30v_frob_label (symbolS *); +#define tc_frob_label(sym) d30v_frob_label (sym) -void d30v_cons_align PARAMS ((int)); -#define md_cons_align(nbytes) d30v_cons_align(nbytes) +void d30v_cons_align (int); +#define md_cons_align(nbytes) d30v_cons_align (nbytes) /* Values passed to md_apply_fix3 don't include the symbol value. */ #define MD_APPLY_SYM_VALUE(FIX) 0 diff --git a/gas/config/tc-dlx.c b/gas/config/tc-dlx.c index 2e254252247..12a0b239a47 100644 --- a/gas/config/tc-dlx.c +++ b/gas/config/tc-dlx.c @@ -58,35 +58,6 @@ struct machine_it } the_insn; -/* static void print_insn PARAMS ((struct machine_it *)); */ -char * parse_operand PARAMS ((char *, expressionS *)); -int md_chars_to_number PARAMS ((unsigned char *, int)); - -static void machine_ip PARAMS ((char *)); -static void s_proc PARAMS ((int)); -static void insert_sreg PARAMS ((char *, int)); -static int hilo_modifier_ok PARAMS ((char *)); -static int is_ldst_registers PARAMS ((char *)); -static int match_sft_register PARAMS ((char *)); -static void define_some_regs PARAMS ((void)); -static char * dlx_parse_loadop PARAMS ((char *)); -static char * dlx_parse_storeop PARAMS ((char *)); -static char * fix_ld_st_operand PARAMS ((unsigned long, char *)); - -const pseudo_typeS - -dlx_pseudo_table[] = - { - /* Some additional ops that are used by gcc-dlx. */ - {"asciiz", stringer, 1}, - {"half", cons, 2}, - {"dword", cons, 8}, - {"word", cons, 4}, - {"proc", s_proc, 0}, - {"endproc", s_proc, 1}, - {NULL, 0, 0}, - }; - /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful. */ const char comment_chars[] = ";"; @@ -113,9 +84,7 @@ const char EXP_CHARS[] = "eE"; const char FLT_CHARS[] = "rRsSfFdDxXpP"; static void -insert_sreg (regname, regnum) - char *regname; - int regnum; +insert_sreg (char *regname, int regnum) { /* Must be large enough to hold the names of the special registers. */ char buf[80]; @@ -135,7 +104,7 @@ insert_sreg (regname, regnum) See MIPS Assembly Language Programmer's Guide page 1-4 */ static void -define_some_regs () +define_some_regs (void) { /* Software representation. */ insert_sreg ("zero", 0); @@ -176,11 +145,10 @@ define_some_regs () insert_sreg ("iad", 2); } -/* Subroutine check the string to match an register, */ +/* Subroutine check the string to match an register. */ static int -match_sft_register (name) - char *name; +match_sft_register (char *name) { #define MAX_REG_NO 35 /* Currently we have 35 software registers defined - @@ -211,8 +179,7 @@ match_sft_register (name) /* Subroutine check the string to match an register. */ static int -is_ldst_registers (name) - char *name; +is_ldst_registers (char *name) { char *ptr = name; @@ -229,8 +196,7 @@ is_ldst_registers (name) If DEFAULT_PREFIX is NULL, use the target's "leading char". */ static void -s_proc (end_p) - int end_p; +s_proc (int end_p) { /* Record the current function so that we can issue an error message for misplaced .func,.endfunc, and also so that .endfunc needs no @@ -303,7 +269,7 @@ s_proc (end_p) need. */ void -md_begin () +md_begin (void) { const char *retval = NULL; int lose = 0; @@ -317,7 +283,7 @@ md_begin () { const char *name = machine_opcodes[i].name; - retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]); + retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]); if (retval != NULL) { @@ -333,170 +299,6 @@ md_begin () define_some_regs (); } -/* Assemble a single instruction. Its label has already been handled - by the generic front end. We just parse opcode and operands, and - produce the bytes of data and relocation. */ - -void -md_assemble (str) - char *str; -{ - char *toP; - fixS *fixP; - bit_fixS *bitP; - - know (str); - machine_ip (str); - toP = frag_more (4); - /* Put out the opcode. */ - md_number_to_chars (toP, the_insn.opcode, 4); - - /* Put out the symbol-dependent stuff. */ - if (the_insn.reloc != NO_RELOC) - { - fixP = fix_new_exp (frag_now, - (toP - frag_now->fr_literal + the_insn.reloc_offset), - the_insn.size, & the_insn.exp, the_insn.pcrel, - the_insn.reloc); - - /* Turn off complaints that the addend is - too large for things like foo+100000@ha. */ - switch (the_insn.reloc) - { - case RELOC_DLX_HI16: - case RELOC_DLX_LO16: - fixP->fx_no_overflow = 1; - break; - default: - break; - } - - switch (fixP->fx_r_type) - { - case RELOC_DLX_REL26: - bitP = malloc (sizeof (bit_fixS)); - bitP->fx_bit_size = 26; - bitP->fx_bit_offset = 25; - bitP->fx_bit_base = the_insn.opcode & 0xFC000000; - bitP->fx_bit_base_adj = 0; - bitP->fx_bit_max = 0; - bitP->fx_bit_min = 0; - bitP->fx_bit_add = 0x03FFFFFF; - fixP->fx_bit_fixP = bitP; - break; - case RELOC_DLX_LO16: - case RELOC_DLX_REL16: - bitP = malloc (sizeof (bit_fixS)); - bitP->fx_bit_size = 16; - bitP->fx_bit_offset = 15; - bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; - bitP->fx_bit_base_adj = 0; - bitP->fx_bit_max = 0; - bitP->fx_bit_min = 0; - bitP->fx_bit_add = 0x0000FFFF; - fixP->fx_bit_fixP = bitP; - break; - case RELOC_DLX_HI16: - bitP = malloc (sizeof (bit_fixS)); - bitP->fx_bit_size = 16; - bitP->fx_bit_offset = 15; - bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; - bitP->fx_bit_base_adj = 0; - bitP->fx_bit_max = 0; - bitP->fx_bit_min = 0; - bitP->fx_bit_add = 0x0000FFFF; - fixP->fx_bit_fixP = bitP; - break; - default: - fixP->fx_bit_fixP = (bit_fixS *)NULL; - break; - } - } -} - -static int -hilo_modifier_ok (s) - char *s; -{ - char *ptr = s; - int idx, count = 1; - - if (*ptr != '(') - return 1; - - for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1) - { - if (count == 0) - return count; - - if (ptr[idx] == '(') - count += 1; - - if (ptr[idx] == ')') - count -= 1; - } - - return (count == 0) ? 1:0; -} - -char * -parse_operand (s, operandp) - char *s; - expressionS *operandp; -{ - char *save = input_line_pointer; - char *new; - - the_insn.HI = the_insn.LO = 0; - - /* Search for %hi and %lo, make a mark and skip it. */ - if (strncmp (s, "%hi", 3) == 0) - { - s += 3; - the_insn.HI = 1; - } - else - { - if (strncmp (s, "%lo", 3) == 0) - { - s += 3; - the_insn.LO = 1; - } - else - the_insn.LO = 0; - } - - if (the_insn.HI || the_insn.LO) - { - if (!hilo_modifier_ok (s)) - as_bad (_("Expression Error for operand modifier %%hi/%%lo\n")); - } - - /* Check for the % and $ register representation */ - if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R') - && ISDIGIT ((unsigned char) s[1])) - { - /* We have a numeric register expression. No biggy. */ - s += 1; - input_line_pointer = s; - (void) expression (operandp); - if (operandp->X_op != O_constant - || operandp->X_add_number > 31) - as_bad (_("Invalid expression after %%%%\n")); - operandp->X_op = O_register; - } - else - { - /* Normal operand parsing. */ - input_line_pointer = s; - (void) expression (operandp); - } - - new = input_line_pointer; - input_line_pointer = save; - return new; -} - /* This function will check the opcode and return 1 if the opcode is one of the load/store instruction, and it will fix the operand string to the standard form so we can use the standard parse_operand routine. */ @@ -506,8 +308,7 @@ parse_operand (s, operandp) static char iBuf[81]; static char * -dlx_parse_loadop (str) - char * str; +dlx_parse_loadop (char * str) { char *ptr = str; int idx = 0; @@ -625,8 +426,7 @@ dlx_parse_loadop (str) } static char * -dlx_parse_storeop (str) - char * str; +dlx_parse_storeop (char * str) { char *ptr = str; int idx = 0; @@ -743,9 +543,7 @@ dlx_parse_storeop (str) } static char * -fix_ld_st_operand (opcode, str) - unsigned long opcode; - char* str; +fix_ld_st_operand (unsigned long opcode, char* str) { /* Check the opcode. */ switch ((int) opcode) @@ -768,13 +566,92 @@ fix_ld_st_operand (opcode, str) } } +static int +hilo_modifier_ok (char *s) +{ + char *ptr = s; + int idx, count = 1; + + if (*ptr != '(') + return 1; + + for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1) + { + if (count == 0) + return count; + + if (ptr[idx] == '(') + count += 1; + + if (ptr[idx] == ')') + count -= 1; + } + + return (count == 0) ? 1:0; +} + +static char * +parse_operand (char *s, expressionS *operandp) +{ + char *save = input_line_pointer; + char *new; + + the_insn.HI = the_insn.LO = 0; + + /* Search for %hi and %lo, make a mark and skip it. */ + if (strncmp (s, "%hi", 3) == 0) + { + s += 3; + the_insn.HI = 1; + } + else + { + if (strncmp (s, "%lo", 3) == 0) + { + s += 3; + the_insn.LO = 1; + } + else + the_insn.LO = 0; + } + + if (the_insn.HI || the_insn.LO) + { + if (!hilo_modifier_ok (s)) + as_bad (_("Expression Error for operand modifier %%hi/%%lo\n")); + } + + /* Check for the % and $ register representation */ + if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R') + && ISDIGIT ((unsigned char) s[1])) + { + /* We have a numeric register expression. No biggy. */ + s += 1; + input_line_pointer = s; + (void) expression (operandp); + if (operandp->X_op != O_constant + || operandp->X_add_number > 31) + as_bad (_("Invalid expression after %%%%\n")); + operandp->X_op = O_register; + } + else + { + /* Normal operand parsing. */ + input_line_pointer = s; + (void) expression (operandp); + } + + new = input_line_pointer; + input_line_pointer = save; + return new; +} + /* Instruction parsing. Takes a string containing the opcode. Operands are at input_line_pointer. Output is in the_insn. Warnings or errors are generated. */ static void -machine_ip (str) - char *str; +machine_ip (char *str) { char *s; const char *args; @@ -1017,6 +894,86 @@ machine_ip (str) } } +/* Assemble a single instruction. Its label has already been handled + by the generic front end. We just parse opcode and operands, and + produce the bytes of data and relocation. */ + +void +md_assemble (char *str) +{ + char *toP; + fixS *fixP; + bit_fixS *bitP; + + know (str); + machine_ip (str); + toP = frag_more (4); + /* Put out the opcode. */ + md_number_to_chars (toP, the_insn.opcode, 4); + + /* Put out the symbol-dependent stuff. */ + if (the_insn.reloc != NO_RELOC) + { + fixP = fix_new_exp (frag_now, + (toP - frag_now->fr_literal + the_insn.reloc_offset), + the_insn.size, & the_insn.exp, the_insn.pcrel, + the_insn.reloc); + + /* Turn off complaints that the addend is + too large for things like foo+100000@ha. */ + switch (the_insn.reloc) + { + case RELOC_DLX_HI16: + case RELOC_DLX_LO16: + fixP->fx_no_overflow = 1; + break; + default: + break; + } + + switch (fixP->fx_r_type) + { + case RELOC_DLX_REL26: + bitP = malloc (sizeof (bit_fixS)); + bitP->fx_bit_size = 26; + bitP->fx_bit_offset = 25; + bitP->fx_bit_base = the_insn.opcode & 0xFC000000; + bitP->fx_bit_base_adj = 0; + bitP->fx_bit_max = 0; + bitP->fx_bit_min = 0; + bitP->fx_bit_add = 0x03FFFFFF; + fixP->fx_bit_fixP = bitP; + break; + case RELOC_DLX_LO16: + case RELOC_DLX_REL16: + bitP = malloc (sizeof (bit_fixS)); + bitP->fx_bit_size = 16; + bitP->fx_bit_offset = 15; + bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; + bitP->fx_bit_base_adj = 0; + bitP->fx_bit_max = 0; + bitP->fx_bit_min = 0; + bitP->fx_bit_add = 0x0000FFFF; + fixP->fx_bit_fixP = bitP; + break; + case RELOC_DLX_HI16: + bitP = malloc (sizeof (bit_fixS)); + bitP->fx_bit_size = 16; + bitP->fx_bit_offset = 15; + bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; + bitP->fx_bit_base_adj = 0; + bitP->fx_bit_max = 0; + bitP->fx_bit_min = 0; + bitP->fx_bit_add = 0x0000FFFF; + fixP->fx_bit_fixP = bitP; + break; + default: + fixP->fx_bit_fixP = NULL; + break; + } + } +} + /* This is identical to the md_atof in m68k.c. I think this is right, but I'm not sure. @@ -1030,10 +987,7 @@ machine_ip (str) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -1088,35 +1042,13 @@ md_atof (type, litP, sizeP) /* Write out big-endian. */ void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { number_to_chars_bigendian (buf, val, n); } -/* md_chars_to_number: convert from target byte order to host byte order. */ - -int -md_chars_to_number (val, n) - unsigned char *val; /* Value in target byte order. */ - int n; /* Number of bytes in the input. */ -{ - int retval; - - for (retval = 0; n--;) - { - retval <<= 8; - retval |= val[n]; - } - - return retval; -} - bfd_boolean -md_dlx_fix_adjustable (fixP) - fixS *fixP; +md_dlx_fix_adjustable (fixS *fixP) { /* We need the symbol name for the VTABLE entries. */ return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT @@ -1124,10 +1056,7 @@ md_dlx_fix_adjustable (fixP) } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { long val = *valP; char *place = fixP->fx_where + fixP->fx_frag->fr_literal; @@ -1136,41 +1065,41 @@ md_apply_fix3 (fixP, valP, seg) { case RELOC_DLX_LO16: case RELOC_DLX_REL16: - if (fixP->fx_bit_fixP != (bit_fixS *) NULL) + if (fixP->fx_bit_fixP != NULL) { val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base; free (fixP->fx_bit_fixP); - fixP->fx_bit_fixP = (bit_fixS *) NULL; + fixP->fx_bit_fixP = NULL; } #ifdef DEBUG else - know ((fixP->fx_bit_fixP != (bit_fixS *) NULL)); + know ((fixP->fx_bit_fixP != NULL)); #endif break; case RELOC_DLX_HI16: - if (fixP->fx_bit_fixP != (bit_fixS *) NULL) + if (fixP->fx_bit_fixP != NULL) { val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base; free (fixP->fx_bit_fixP); - fixP->fx_bit_fixP = (bit_fixS *)NULL; + fixP->fx_bit_fixP = NULL; } #ifdef DEBUG else - know ((fixP->fx_bit_fixP != (bit_fixS *) NULL)); + know ((fixP->fx_bit_fixP != NULL)); #endif break; case RELOC_DLX_REL26: - if (fixP->fx_bit_fixP != (bit_fixS *) NULL) + if (fixP->fx_bit_fixP != NULL) { val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base; free (fixP->fx_bit_fixP); - fixP->fx_bit_fixP = (bit_fixS *) NULL; + fixP->fx_bit_fixP = NULL; } #ifdef DEBUG else - know ((fixP->fx_bit_fixP != (bit_fixS *) NULL)); + know ((fixP->fx_bit_fixP != NULL)); #endif break; @@ -1206,24 +1135,21 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, + char *arg ATTRIBUTE_UNUSED) { return 0; } void -md_show_usage (stream) - FILE *stream ATTRIBUTE_UNUSED; +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) { } /* This is called when a line is unrecognized. */ int -dlx_unrecognized_line (c) - int c; +dlx_unrecognized_line (int c) { int lab; char *s; @@ -1241,10 +1167,8 @@ dlx_unrecognized_line (c) } if (*s != ':') - { - /* Not a label definition. */ - return 0; - } + /* Not a label definition. */ + return 0; if (dollar_label_defined (lab)) { @@ -1264,20 +1188,17 @@ dlx_unrecognized_line (c) are a lot of them. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return NULL; } - /* Parse an operand that is machine-specific, the function was called in expr.c by operand() function, when everything failed before it call a quit. */ void -md_operand (expressionP) - expressionS* expressionP; +md_operand (expressionS* expressionP) { /* Check for the #number representation */ if (input_line_pointer[0] == '#' && @@ -1298,9 +1219,8 @@ md_operand (expressionP) /* Round up a section size to the appropriate boundary. */ valueT -md_section_align (segment, size) - segT segment ATTRIBUTE_UNUSED; - valueT size; +md_section_align (segT segment ATTRIBUTE_UNUSED, + valueT size) { /* Byte alignment is fine. */ return size; @@ -1311,8 +1231,7 @@ md_section_align (segment, size) which we have set up as the address of the fixup too. */ long -md_pcrel_from (fixP) - fixS* fixP; +md_pcrel_from (fixS* fixP) { return 4 + fixP->fx_where + fixP->fx_frag->fr_address; } @@ -1323,16 +1242,15 @@ md_pcrel_from (fixP) The above FIXME is from a29k, but I think it is also needed here. */ arelent * -tc_gen_reloc (section, fixP) - asection *section ATTRIBUTE_UNUSED; - fixS *fixP; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, + fixS *fixP) { arelent * reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc = xmalloc (sizeof (arelent)); reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); - if (reloc->howto == (reloc_howto_type *) NULL) + if (reloc->howto == NULL) { as_bad_where (fixP->fx_file, fixP->fx_line, "internal error: can't export reloc type %d (`%s')", @@ -1343,7 +1261,7 @@ tc_gen_reloc (section, fixP) assert (!fixP->fx_pcrel == !reloc->howto->pc_relative); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; @@ -1354,11 +1272,23 @@ tc_gen_reloc (section, fixP) return reloc; } -extern void pop_insert PARAMS ((const pseudo_typeS *)); +const pseudo_typeS +dlx_pseudo_table[] = +{ + /* Some additional ops that are used by gcc-dlx. */ + {"asciiz", stringer, 1}, + {"half", cons, 2}, + {"dword", cons, 8}, + {"word", cons, 4}, + {"proc", s_proc, 0}, + {"endproc", s_proc, 1}, + {NULL, NULL, 0} +}; void -dlx_pop_insert () +dlx_pop_insert (void) { pop_insert (dlx_pseudo_table); return ; } + diff --git a/gas/config/tc-dlx.h b/gas/config/tc-dlx.h index 9aab0d2d4f1..709ae88151b 100644 --- a/gas/config/tc-dlx.h +++ b/gas/config/tc-dlx.h @@ -1,5 +1,5 @@ /* tc-dlx.h -- Assemble for the DLX - Copyright 2002, 2003 Free Software Foundation, Inc. + Copyright 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -31,17 +31,18 @@ #endif /* The target BFD architecture. */ -#define TARGET_ARCH bfd_arch_dlx -#define TARGET_FORMAT "elf32-dlx" -#define TARGET_BYTES_BIG_ENDIAN 1 +#define TARGET_ARCH bfd_arch_dlx +#define TARGET_FORMAT "elf32-dlx" +#define TARGET_BYTES_BIG_ENDIAN 1 #define WORKING_DOT_WORD #define LEX_DOLLAR 1 -/* #define md_operand(x) */ -extern void dlx_pop_insert PARAMS ((void)); -extern int set_dlx_skip_hi16_flag PARAMS ((int)); +extern void dlx_pop_insert (void); +extern int set_dlx_skip_hi16_flag (int); +extern int dlx_unrecognized_line (int); +extern bfd_boolean md_dlx_fix_adjustable (struct fix *); #define md_pop_insert() dlx_pop_insert () @@ -51,12 +52,10 @@ extern int set_dlx_skip_hi16_flag PARAMS ((int)); #define tc_unrecognized_line(c) dlx_unrecognized_line (c) -extern int dlx_unrecognized_line PARAMS ((int)); - -#define tc_headers_hook(a) ; /* not used */ -#define tc_headers_hook(a) ; /* not used */ -#define tc_crawl_symbol_chain(a) ; /* not used */ -#define tc_coff_symbol_emit_hook(a) ; /* not used */ +#define tc_headers_hook(a) ; /* Not used. */ +#define tc_headers_hook(a) ; /* Not used. */ +#define tc_crawl_symbol_chain(a) ; /* Not used. */ +#define tc_coff_symbol_emit_hook(a) ; /* Not used. */ #define AOUT_MACHTYPE 101 #define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype (fix_ptr) @@ -65,8 +64,7 @@ extern int dlx_unrecognized_line PARAMS ((int)); /* Should the reloc be output ? on the 29k, this is true only if there is a symbol attached. on the h8, this is always true, since no fixup is done - on dlx, I have no idea!! but lets keep it here just for fun. -*/ + on dlx, I have no idea!! but lets keep it here just for fun. */ #define TC_COUNT_RELOC(x) (x->fx_addsy) #define TC_CONS_RELOC BFD_RELOC_32_PCREL @@ -75,7 +73,6 @@ extern int dlx_unrecognized_line PARAMS ((int)); #define EXTERN_FORCE_RELOC 0 #define tc_fix_adjustable(FIX) md_dlx_fix_adjustable (FIX) -extern bfd_boolean md_dlx_fix_adjustable PARAMS ((struct fix *)); /* Values passed to md_apply_fix3 don't include the symbol value. */ #define MD_APPLY_SYM_VALUE(FIX) 0 @@ -91,4 +88,5 @@ extern bfd_boolean md_dlx_fix_adjustable PARAMS ((struct fix *)); #undef LOCAL_LABELS_DOLLAR #define LOCAL_LABELS_DOLLAR 0 -#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ +/* .-foo gets turned into PC relative relocs. */ +#define DIFF_EXPR_OK diff --git a/gas/config/tc-fr30.c b/gas/config/tc-fr30.c index 34c9f42e4bb..cf62dd18c69 100644 --- a/gas/config/tc-fr30.c +++ b/gas/config/tc-fr30.c @@ -66,9 +66,8 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, + char *arg ATTRIBUTE_UNUSED) { switch (c) { @@ -79,8 +78,7 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE * stream; +md_show_usage (FILE * stream) { fprintf (stream, _(" FR30 specific command line options:\n")); } @@ -94,7 +92,7 @@ const pseudo_typeS md_pseudo_table[] = void -md_begin () +md_begin (void) { /* Initialize the `cgen' interface. */ @@ -110,8 +108,7 @@ md_begin () } void -md_assemble (str) - char *str; +md_assemble (char *str) { static int last_insn_had_delay_slot = 0; fr30_insn insn; @@ -147,8 +144,7 @@ md_assemble (str) We just ignore it. */ void -md_operand (expressionP) - expressionS * expressionP; +md_operand (expressionS * expressionP) { if (* input_line_pointer == '#') { @@ -158,19 +154,17 @@ md_operand (expressionP) } valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); + return ((size + (1 << align) - 1) & (-1 << align)); } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { - return 0; + return NULL; } /* Interface to relax_segment. */ @@ -215,9 +209,7 @@ const relax_typeS md_relax_table[] = 0 value. */ int -md_estimate_size_before_relax (fragP, segment) - fragS * fragP; - segT segment; +md_estimate_size_before_relax (fragS * fragP, segT segment) { /* The only thing we have to handle here are symbols outside of the current segment. They may be undefined or in a different segment in @@ -268,10 +260,9 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_subtype is the subtype of what the address relaxed to. */ void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) { } @@ -281,18 +272,14 @@ md_convert_frag (abfd, sec, fragP) given a PC relative reloc. */ long -md_pcrel_from_section (fixP, sec) - fixS * fixP; - segT sec; +md_pcrel_from_section (fixS * fixP, segT sec) { if (fixP->fx_addsy != (symbolS *) NULL && (! S_IS_DEFINED (fixP->fx_addsy) || S_GET_SEGMENT (fixP->fx_addsy) != sec)) - { - /* The symbol is undefined (or is defined but not in this section). - Let the linker figure it out. */ - return 0; - } + /* The symbol is undefined (or is defined but not in this section). + Let the linker figure it out. */ + return 0; return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1; } @@ -302,10 +289,9 @@ md_pcrel_from_section (fixP, sec) *FIXP may be modified if desired. */ bfd_reloc_code_real_type -md_cgen_lookup_reloc (insn, operand, fixP) - const CGEN_INSN *insn ATTRIBUTE_UNUSED; - const CGEN_OPERAND *operand; - fixS *fixP; +md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED, + const CGEN_OPERAND *operand, + fixS *fixP) { switch (operand->type) { @@ -318,7 +304,7 @@ md_cgen_lookup_reloc (insn, operand, fixP) case FR30_OPERAND_I8: return BFD_RELOC_8; case FR30_OPERAND_I32: return BFD_RELOC_FR30_48; case FR30_OPERAND_I20: return BFD_RELOC_FR30_20; - default : /* avoid -Wall warning */ + default : /* Avoid -Wall warning. */ break; } @@ -328,10 +314,7 @@ md_cgen_lookup_reloc (insn, operand, fixP) /* Write a value out to the object file, using the appropriate endianness. */ void -md_number_to_chars (buf, val, n) - char * buf; - valueT val; - int n; +md_number_to_chars (char * buf, valueT val, int n) { number_to_chars_bigendian (buf, val, n); } @@ -341,14 +324,11 @@ md_number_to_chars (buf, val, n) emitted is stored in *sizeP . An error message is returned, or NULL on OK. */ -/* Equal to MAX_PRECISION in atof-ieee.c */ +/* Equal to MAX_PRECISION in atof-ieee.c. */ #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char * litP; - int * sizeP; +md_atof (int type, char * litP, int * sizeP) { int i; int prec; @@ -394,11 +374,8 @@ md_atof (type, litP, sizeP) } /* Worker function for fr30_is_colon_insn(). */ -static char restore_colon PARAMS ((int)); - static char -restore_colon (advance_i_l_p_by) - int advance_i_l_p_by; +restore_colon (int advance_i_l_p_by) { char c; @@ -420,12 +397,11 @@ restore_colon (advance_i_l_p_by) to the real end of the instruction/symbol, and returns the character that really terminated the symbol. Otherwise it returns 0. */ char -fr30_is_colon_insn (start) - char * start; +fr30_is_colon_insn (char * start) { char * i_l_p = input_line_pointer; - /* Check to see if the symbol parsed so far is 'ldi' */ + /* Check to see if the symbol parsed so far is 'ldi'. */ if ( (start[0] != 'l' && start[0] != 'L') || (start[1] != 'd' && start[1] != 'D') || (start[2] != 'i' && start[2] != 'I') @@ -466,15 +442,15 @@ fr30_is_colon_insn (start) return 0; } - /* Check to see if the text following the colon is '8' */ + /* Check to see if the text following the colon is '8'. */ if (i_l_p[1] == '8' && (i_l_p[2] == ' ' || i_l_p[2] == '\t')) return restore_colon (2); - /* Check to see if the text following the colon is '20' */ + /* Check to see if the text following the colon is '20'. */ else if (i_l_p[1] == '2' && i_l_p[2] =='0' && (i_l_p[3] == ' ' || i_l_p[3] == '\t')) return restore_colon (3); - /* Check to see if the text following the colon is '32' */ + /* Check to see if the text following the colon is '32'. */ else if (i_l_p[1] == '3' && i_l_p[2] =='2' && (i_l_p[3] == ' ' || i_l_p[3] == '\t')) return restore_colon (3); @@ -482,10 +458,9 @@ fr30_is_colon_insn (start) } bfd_boolean -fr30_fix_adjustable (fixP) - fixS * fixP; +fr30_fix_adjustable (fixS * fixP) { - /* We need the symbol name for the VTABLE entries */ + /* We need the symbol name for the VTABLE entries. */ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) return 0; diff --git a/gas/config/tc-fr30.h b/gas/config/tc-fr30.h index 8c1166b9051..4119bd929c1 100644 --- a/gas/config/tc-fr30.h +++ b/gas/config/tc-fr30.h @@ -1,5 +1,5 @@ /* tc-fr30.h -- Header file for tc-fr30.c. - Copyright 1998, 1999, 2000, 2001, 2002, 2003 + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -22,7 +22,7 @@ #define TC_FR30 #ifndef BFD_ASSEMBLER -/* leading space so will compile with cc */ +/* Leading space so will compile with cc. */ #error FR30 support requires BFD_ASSEMBLER #endif @@ -38,7 +38,7 @@ /* Permit temporary numeric labels. */ #define LOCAL_LABELS_FB 1 -#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ +#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs. */ /* We don't need to handle .word strangely. */ #define WORKING_DOT_WORD @@ -50,13 +50,13 @@ #define tc_fix_adjustable(FIX) fr30_fix_adjustable (FIX) struct fix; -extern bfd_boolean fr30_fix_adjustable PARAMS ((struct fix *)); +extern bfd_boolean fr30_fix_adjustable (struct fix *); #define tc_gen_reloc gas_cgen_tc_gen_reloc /* Call md_pcrel_from_section(), not md_pcrel_from(). */ #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC) -extern long md_pcrel_from_section PARAMS ((struct fix *, segT)); +extern long md_pcrel_from_section (struct fix *, segT); /* For 8 vs 16 vs 32 bit branch selection. */ #define TC_GENERIC_RELAX_TABLE md_relax_table @@ -72,4 +72,4 @@ extern const struct relax_type md_relax_table[]; the local variable 'c' which is passed to this macro as 'character'. */ #define TC_START_LABEL(character, i_l_p) \ ((character) != ':' ? 0 : (character = fr30_is_colon_insn (s)) ? 0 : ((character = ':'), 1)) -extern char fr30_is_colon_insn PARAMS ((char *)); +extern char fr30_is_colon_insn (char *); diff --git a/gas/config/tc-h8500.c b/gas/config/tc-h8500.c index bdbaa2d6a29..a2e7f73115e 100644 --- a/gas/config/tc-h8500.c +++ b/gas/config/tc-h8500.c @@ -30,16 +30,15 @@ #include "opcodes/h8500-opc.h" #include "safe-ctype.h" -const char comment_chars[] = "!"; +const char comment_chars[] = "!"; const char line_separator_chars[] = ";"; -const char line_comment_chars[] = "!#"; +const char line_comment_chars[] = "!#"; /* This table describes all the machine specific pseudo-ops the assembler has to support. The fields are: pseudo-op name without dot function to call to execute this pseudo-op - Integer arg to pass to the function - */ + Integer arg to pass to the function. */ const pseudo_typeS md_pseudo_table[] = { @@ -59,32 +58,33 @@ const int md_reloc_size; const char EXP_CHARS[] = "eE"; -/* Chars that mean this number is a floating point constant */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ +/* Chars that mean this number is a floating point constant. + As in 0f12.456 + or 0d1.2345e12. */ const char FLT_CHARS[] = "rRsSfFdDxXpP"; -#define C(a,b) ENCODE_RELAX(a,b) -#define ENCODE_RELAX(what,length) (((what) << 2) + (length)) +#define C(a,b) ENCODE_RELAX(a, b) +#define ENCODE_RELAX(what, length) (((what) << 2) + (length)) -#define GET_WHAT(x) ((x>>2)) +#define GET_WHAT(x) ((x >> 2)) -#define BYTE_DISP 1 -#define WORD_DISP 2 +#define BYTE_DISP 1 +#define WORD_DISP 2 #define UNDEF_BYTE_DISP 0 #define UNDEF_WORD_DISP 3 -#define BRANCH 1 -#define SCB_F 2 -#define SCB_TST 3 -#define END 4 +#define BRANCH 1 +#define SCB_F 2 +#define SCB_TST 3 +#define END 4 -#define BYTE_F 127 -#define BYTE_B -126 -#define WORD_F 32767 -#define WORD_B 32768 +#define BYTE_F 127 +#define BYTE_B -126 +#define WORD_F 32767 +#define WORD_B 32768 -relax_typeS md_relax_table[C (END, 0)] = { +relax_typeS md_relax_table[C (END, 0)] = +{ { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, @@ -110,15 +110,13 @@ relax_typeS md_relax_table[C (END, 0)] = { }; -static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ +static struct hash_control *opcode_hash_control; /* Opcode mnemonics. */ -/* - This function is called once, at assembler startup time. This should - set up all the tables, etc. that the MD part of the assembler needs - */ +/* This function is called once, at assembler startup time. This should + set up all the tables, etc. that the MD part of the assembler needs. */ void -md_begin () +md_begin (void) { const h8500_opcode_info *opcode; char prev_buffer[100]; @@ -127,7 +125,7 @@ md_begin () opcode_hash_control = hash_new (); prev_buffer[0] = 0; - /* Insert unique names into hash table */ + /* Insert unique names into hash table. */ for (opcode = h8500_table; opcode->name; opcode++) { if (idx != opcode->idx) @@ -138,19 +136,17 @@ md_begin () } } -static int rn; /* register number used by RN */ -static int rs; /* register number used by RS */ -static int rd; /* register number used by RD */ -static int crb; /* byte size cr */ -static int crw; /* word sized cr */ -static int cr; /* unknown size cr */ - -static expressionS displacement;/* displacement expression */ +static int rn; /* Register number used by RN. */ +static int rs; /* Register number used by RS. */ +static int rd; /* Register number used by RD. */ +static int crb; /* Byte size cr. */ +static int crw; /* Word sized cr. */ +static int cr; /* Unknown size cr. */ +static expressionS displacement;/* Displacement expression. */ static int immediate_inpage; -static expressionS immediate; /* immediate expression */ - -static expressionS absolute; /* absolute expression */ +static expressionS immediate; /* Immediate expression. */ +static expressionS absolute; /* Absolute expression. */ typedef struct { @@ -164,13 +160,10 @@ h8500_operand_info; /* Try to parse a reg name. Return the number of chars consumed. */ -static int parse_reg PARAMS ((char *, int *, unsigned int *)); +static int parse_reg (char *, int *, unsigned int *); static int -parse_reg (src, mode, reg) - char *src; - int *mode; - unsigned int *reg; +parse_reg (char *src, int *mode, unsigned int *reg) { char *end; int len; @@ -243,13 +236,8 @@ parse_reg (src, mode, reg) return 0; } -static char *parse_exp PARAMS ((char *, expressionS *, int *)); - static char * -parse_exp (s, op, page) - char *s; - expressionS *op; - int *page; +parse_exp (char *s, expressionS *op, int *page) { char *save; char *new; @@ -287,22 +275,18 @@ parse_exp (s, op, page) } typedef enum - { - exp_signed, exp_unsigned, exp_sandu - } sign_type; - -static char *skip_colonthing - PARAMS ((sign_type, char *, h8500_operand_info *, int, int, int, int)); +{ + exp_signed, exp_unsigned, exp_sandu +} sign_type; static char * -skip_colonthing (sign, ptr, exp, def, size8, size16, size24) - sign_type sign; - char *ptr; - h8500_operand_info *exp; - int def; - int size8; - int size16; - int size24; +skip_colonthing (sign_type sign, + char *ptr, + h8500_operand_info *exp, + int def, + int size8, + int size16, + int size24) { ptr = parse_exp (ptr, &exp->exp, &exp->page); if (*ptr == ':') @@ -336,47 +320,37 @@ skip_colonthing (sign, ptr, exp, def, size8, size16, size24) else { if (exp->page == 'p') - { - exp->type = IMM8; - } + exp->type = IMM8; else if (exp->page == 'h') - { - exp->type = IMM16; - } + exp->type = IMM16; else { - /* Let's work out the size from the context */ + /* Let's work out the size from the context. */ int n = exp->exp.X_add_number; + if (size8 && 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))))) - { - exp->type = size8; - } + exp->type = size8; else - { - exp->type = def; - } + exp->type = def; } } return ptr; } -static int parse_reglist PARAMS ((char *, h8500_operand_info *)); - static int -parse_reglist (src, op) - char *src; - h8500_operand_info *op; +parse_reglist (char *src, h8500_operand_info *op) { int mode; unsigned int rn; int mask = 0; unsigned int rm; - int idx = 1; /* skip ( */ + int idx = 1; + /* Skip (. */ while (src[idx] && src[idx] != ')') { int done = parse_reg (src + idx, &mode, &rn); @@ -391,6 +365,7 @@ parse_reglist (src, op) as_bad (_("syntax error in reg list")); return 0; } + if (src[idx] == '-') { idx++; @@ -405,10 +380,9 @@ parse_reglist (src, op) } } else - { - as_bad (_("missing final register in range")); - } + as_bad (_("missing final register in range")); } + if (src[idx] == ',') idx++; } @@ -420,7 +394,6 @@ parse_reglist (src, op) op->exp.X_unsigned = 1; op->type = IMM8; return idx; - } /* The many forms of operand: @@ -431,22 +404,18 @@ parse_reglist (src, op) @Rn+ @-Rn @aa[:size] absolute - #xx[:size] immediate data - - */ - -static void get_operand PARAMS ((char **, h8500_operand_info *, char)); + #xx[:size] immediate data. */ static void -get_operand (ptr, op, ispage) - char **ptr; - h8500_operand_info *op; - char ispage; +get_operand (char **ptr, + h8500_operand_info *op, + char ispage) { char *src = *ptr; int mode; unsigned int num; unsigned int len; + op->page = 0; if (src[0] == '(' && src[1] == 'r') { @@ -559,20 +528,14 @@ get_operand (ptr, op, ispage) return; } else - { - *ptr = skip_colonthing (exp_signed, src, op, - ispage ? ABS24 : PCREL8, PCREL8, PCREL16, ABS24); - } + *ptr = skip_colonthing (exp_signed, src, op, + ispage ? ABS24 : PCREL8, PCREL8, PCREL16, ABS24); } -static char *get_operands - PARAMS ((h8500_opcode_info *, char *, h8500_operand_info *)); - static char * -get_operands (info, args, operand) - h8500_opcode_info *info; - char *args; - h8500_operand_info *operand; +get_operands (h8500_opcode_info *info, + char *args, + h8500_operand_info *operand) { char *ptr = args; @@ -608,15 +571,11 @@ get_operands (info, args, operand) addressing modes, return the opcode which matches the opcodes provided. */ -int pcrel8; /* Set when we've seen a pcrel operand */ - -static h8500_opcode_info *get_specific - PARAMS ((h8500_opcode_info *, h8500_operand_info *)); +int pcrel8; /* Set when we've seen a pcrel operand. */ static h8500_opcode_info * -get_specific (opcode, operands) - h8500_opcode_info *opcode; - h8500_operand_info *operands; +get_specific (h8500_opcode_info *opcode, + h8500_operand_info *operands) { h8500_opcode_info *this_try = opcode; int found = 0; @@ -629,8 +588,8 @@ get_specific (opcode, operands) this_try = opcode++; - /* look at both operands needed by the opcodes and provided by - the user*/ + /* Look at both operands needed by the opcodes and provided by + the user. */ for (i = 0; i < noperands; i++) { h8500_operand_info *user = operands + i; @@ -638,7 +597,7 @@ get_specific (opcode, operands) switch (this_try->arg_type[i]) { case FPIND_D8: - /* Opcode needs (disp:8,fp) */ + /* Opcode needs (disp:8,fp). */ if (user->type == RNIND_D8 && user->reg == 6) { displacement = user->exp; @@ -673,16 +632,14 @@ get_specific (opcode, operands) case SPDEC: if (user->type == RNDEC && user->reg == 7) - { - continue; - } + continue; break; + case SPINC: if (user->type == RNINC && user->reg == 7) - { - continue; - } + continue; break; + case ABS16: if (user->type == ABS16) { @@ -735,10 +692,9 @@ get_specific (opcode, operands) break; case FP: if (user->type == RN && user->reg == 6) - { - continue; - } + continue; break; + case PCREL16: if (user->type == PCREL16) { @@ -784,8 +740,7 @@ get_specific (opcode, operands) case QIM: if (user->type == IMM8 && user->exp.X_op == O_constant - && - (user->exp.X_add_number == -2 + && (user->exp.X_add_number == -2 || user->exp.X_add_number == -1 || user->exp.X_add_number == 1 || user->exp.X_add_number == 2)) @@ -821,7 +776,6 @@ get_specific (opcode, operands) case RNIND: case RNDEC: case RN: - if (user->type == this_try->arg_type[i]) { rn = user->reg; @@ -830,16 +784,14 @@ get_specific (opcode, operands) break; case SP: if (user->type == RN && user->reg == 7) - { - continue; - } + continue; break; default: printf (_("unhandled %d\n"), this_try->arg_type[i]); break; } - /* If we get here this didn't work out */ + /* If we get here this didn't work out. */ goto fail; } found = 1; @@ -853,48 +805,31 @@ get_specific (opcode, operands) return 0; } -static int check PARAMS ((expressionS *, int, int)); - static int -check (operand, low, high) - expressionS *operand; - int low; - int high; +check (expressionS *operand, + int low, + int high) { if (operand->X_op != O_constant || operand->X_add_number < low || operand->X_add_number > high) - { - as_bad (_("operand must be absolute in range %d..%d"), low, high); - } + as_bad (_("operand must be absolute in range %d..%d"), low, high); + return operand->X_add_number; } - -static void insert PARAMS ((char *, int, expressionS *, int, int)); - + static void -insert (output, index, exp, reloc, pcrel) - char *output; - int index; - expressionS *exp; - int reloc; - int pcrel; +insert (char *output, int index, expressionS *exp, int reloc, int pcrel) { fix_new_exp (frag_now, output - frag_now->fr_literal + index, - 4, /* always say size is 4, but we know better */ - exp, - pcrel, - reloc); + 4, /* Always say size is 4, but we know better. */ + exp, pcrel, reloc); } -static void build_relaxable_instruction - PARAMS ((h8500_opcode_info *, h8500_operand_info *)); - static void -build_relaxable_instruction (opcode, operand) - h8500_opcode_info *opcode; - h8500_operand_info *operand ATTRIBUTE_UNUSED; +build_relaxable_instruction (h8500_opcode_info *opcode, + h8500_operand_info *operand ATTRIBUTE_UNUSED) { /* All relaxable instructions start life as two bytes but can become three bytes long if a lonely branch and up to 9 bytes if long @@ -904,18 +839,12 @@ build_relaxable_instruction (opcode, operand) int type; if (opcode->bytes[0].contents == 0x01) - { - type = SCB_F; - } + type = SCB_F; else if (opcode->bytes[0].contents == 0x06 || opcode->bytes[0].contents == 0x07) - { - type = SCB_TST; - } + type = SCB_TST; else - { - type = BRANCH; - } + type = BRANCH; p = frag_var (rs_machine_dependent, md_relax_table[C (type, WORD_DISP)].rlx_length, @@ -927,19 +856,13 @@ build_relaxable_instruction (opcode, operand) p[0] = opcode->bytes[0].contents; if (type != BRANCH) - { - p[1] = opcode->bytes[1].contents | rs; - } + p[1] = opcode->bytes[1].contents | rs; } /* Now we know what sort of opcodes it is, let's build the bytes. */ -static void build_bytes PARAMS ((h8500_opcode_info *, h8500_operand_info *)); - static void -build_bytes (opcode, operand) - h8500_opcode_info *opcode; - h8500_operand_info *operand; +build_bytes (h8500_opcode_info *opcode, h8500_operand_info *operand) { int index; @@ -1072,8 +995,7 @@ build_bytes (opcode, operand) the frags/bytes it assembles to. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { char *op_start; char *op_end; @@ -1092,14 +1014,9 @@ md_assemble (str) for (op_start = op_end = str; !is_end_of_line[(unsigned char) *op_end] && *op_end != ' '; op_end++) - { - if ( /**op_end != '.' - && *op_end != ':' - && */ nlen < 10) - { - name[nlen++] = *op_end; - } - } + if (nlen < 10) + name[nlen++] = *op_end; + name[nlen] = 0; if (op_end == op_start) @@ -1120,7 +1037,7 @@ md_assemble (str) if (opcode == 0) { - /* Couldn't find an opcode which matched the operands */ + /* Couldn't find an opcode which matched the operands. */ char *where = frag_more (2); where[0] = 0x0; @@ -1133,22 +1050,19 @@ md_assemble (str) } void -tc_crawl_symbol_chain (headers) - object_headers *headers ATTRIBUTE_UNUSED; +tc_crawl_symbol_chain (object_headers *headers ATTRIBUTE_UNUSED) { printf (_("call to tc_crawl_symbol_chain \n")); } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { - return 0; + return NULL; } void -tc_headers_hook (headers) - object_headers *headers ATTRIBUTE_UNUSED; +tc_headers_hook (object_headers *headers ATTRIBUTE_UNUSED) { printf (_("call to tc_headers_hook \n")); } @@ -1163,10 +1077,7 @@ tc_headers_hook (headers) returned, or NULL on OK. */ char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -1217,32 +1128,25 @@ md_atof (type, litP, sizeP) } const char *md_shortopts = ""; -struct option md_longopts[] = { +struct option md_longopts[] = +{ {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED) { return 0; } void -md_show_usage (stream) - FILE *stream ATTRIBUTE_UNUSED; +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) { } -static void wordify_scb PARAMS ((char *, int *, int *)); - static void -wordify_scb (buffer, disp_size, inst_size) - char *buffer; - int *disp_size; - int *inst_size; +wordify_scb (char *buffer, int *disp_size, int *inst_size) { int rn = buffer[1] & 0x7; @@ -1307,10 +1211,9 @@ wordify_scb (buffer, disp_size, inst_size) are. */ void -md_convert_frag (headers, seg, fragP) - object_headers *headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - fragS *fragP; +md_convert_frag (object_headers *headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + fragS *fragP) { int disp_size = 0; int inst_size = 0; @@ -1362,7 +1265,7 @@ md_convert_frag (headers, seg, fragP) } if (inst_size) { - /* Get the address of the end of the instruction */ + /* Get the address of the end of the instruction. */ int next_inst = fragP->fr_fix + fragP->fr_address + disp_size + inst_size; int targ_addr = (S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset); @@ -1374,20 +1277,14 @@ md_convert_frag (headers, seg, fragP) } valueT -md_section_align (seg, size) - segT seg ; - valueT size; +md_section_align (segT seg, valueT size) { return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); - } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED) { long val = * (long *) valP; char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; @@ -1437,9 +1334,7 @@ md_apply_fix3 (fixP, valP, seg) by which a fragment must grow to reach it's destination. */ int -md_estimate_size_before_relax (fragP, segment_type) - register fragS *fragP; - register segT segment_type; +md_estimate_size_before_relax (fragS *fragP, segT segment_type) { int what; @@ -1452,7 +1347,7 @@ md_estimate_size_before_relax (fragP, segment_type) case C (SCB_F, UNDEF_BYTE_DISP): case C (SCB_TST, UNDEF_BYTE_DISP): what = GET_WHAT (fragP->fr_subtype); - /* used to be a branch to somewhere which was unknown */ + /* Used to be a branch to somewhere which was unknown. */ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) { /* Got a symbol and it's defined in this segment, become byte @@ -1460,11 +1355,9 @@ md_estimate_size_before_relax (fragP, segment_type) fragP->fr_subtype = C (what, BYTE_DISP); } else - { - /* Its got a segment, but its not ours, so it will always be - long. */ - fragP->fr_subtype = C (what, UNDEF_WORD_DISP); - } + /* Its got a segment, but its not ours, so it will always be + long. */ + fragP->fr_subtype = C (what, UNDEF_WORD_DISP); break; case C (BRANCH, BYTE_DISP): @@ -1487,35 +1380,28 @@ md_estimate_size_before_relax (fragP, segment_type) /* Put number into target byte order. */ void -md_number_to_chars (ptr, use, nbytes) - char *ptr; - valueT use; - int nbytes; +md_number_to_chars (char *ptr, valueT use, int nbytes) { number_to_chars_bigendian (ptr, use, nbytes); } long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; } void -tc_coff_symbol_emit_hook (ignore) - symbolS *ignore ATTRIBUTE_UNUSED; +tc_coff_symbol_emit_hook (symbolS *ignore ATTRIBUTE_UNUSED) { } short -tc_coff_fix2rtype (fix_ptr) - fixS *fix_ptr; +tc_coff_fix2rtype (fixS *fix_ptr) { if (fix_ptr->fx_r_type == RELOC_32) { - /* cons likes to create reloc32's whatever the size of the reloc.. - */ + /* Cons likes to create reloc32's whatever the size of the reloc. */ switch (fix_ptr->fx_size) { case 2: @@ -1532,11 +1418,9 @@ tc_coff_fix2rtype (fix_ptr) } void -tc_reloc_mangle (fix_ptr, intr, base) - fixS *fix_ptr; - struct internal_reloc *intr; - bfd_vma base; - +tc_reloc_mangle (fixS *fix_ptr, + struct internal_reloc *intr, + bfd_vma base) { symbolS *symbol_ptr; @@ -1546,8 +1430,7 @@ tc_reloc_mangle (fix_ptr, intr, base) to output it */ if (fix_ptr->fx_r_type == RELOC_32) { - /* cons likes to create reloc32's whatever the size of the reloc.. - */ + /* Cons likes to create reloc32's whatever the size of the reloc. */ switch (fix_ptr->fx_size) { case 2: @@ -1561,9 +1444,7 @@ tc_reloc_mangle (fix_ptr, intr, base) } } else - { - intr->r_type = fix_ptr->fx_r_type; - } + intr->r_type = fix_ptr->fx_r_type; intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base; intr->r_offset = fix_ptr->fx_offset; @@ -1580,21 +1461,14 @@ tc_reloc_mangle (fix_ptr, intr, base) intr->r_symndx = dot->sy_number; } else - { - intr->r_symndx = symbol_ptr->sy_number; - } - + intr->r_symndx = symbol_ptr->sy_number; } else - { - intr->r_symndx = -1; - } - + intr->r_symndx = -1; } int -start_label (ptr) - char *ptr; +start_label (char *ptr) { /* Check for :s.w */ if (ISALPHA (ptr[1]) && ptr[2] == '.') @@ -1606,8 +1480,7 @@ start_label (ptr) } int -tc_coff_sizemachdep (frag) - fragS *frag; +tc_coff_sizemachdep (fragS *frag) { return md_relax_table[frag->fr_subtype].rlx_length; } diff --git a/gas/config/tc-h8500.h b/gas/config/tc-h8500.h index 5902524d4f1..e305bd689c9 100644 --- a/gas/config/tc-h8500.h +++ b/gas/config/tc-h8500.h @@ -1,5 +1,6 @@ /* This file is tc-h8500.h - Copyright 1993, 1995, 1997, 1998, 2000, 2003 Free Software Foundation, Inc. + Copyright 1993, 1995, 1997, 1998, 2000, 2003, 2005 + Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -29,27 +30,27 @@ struct internal_reloc; #define WORKING_DOT_WORD /* This macro translates between an internal fix and a coff reloc type. */ -#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP) +#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype (fixP) #define BFD_ARCH bfd_arch_h8500 #define COFF_MAGIC 0x8500 -#define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy) +#define TC_COUNT_RELOC(x) ((x)->fx_addsy || (x)->fx_subsy) #define IGNORE_NONSTANDARD_ESCAPES -#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c) +#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a, b, c) extern void tc_reloc_mangle - PARAMS ((struct fix *, struct internal_reloc *, bfd_vma)); + (struct fix *, struct internal_reloc *, bfd_vma); #define DO_NOT_STRIP 0 #define LISTING_HEADER "Renesas H8/500 GAS " #define NEED_FX_R_TYPE 1 #define RELOC_32 1234 -#define TC_START_LABEL(ch, ptr) (ch == ':' && start_label(ptr)) -int start_label PARAMS ((char *)); +#define TC_START_LABEL(ch, ptr) (ch == ':' && start_label (ptr)) +int start_label (char *); -#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag) -int tc_coff_sizemachdep PARAMS ((struct frag *)); +#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep (frag) +int tc_coff_sizemachdep (struct frag *); #define md_operand(x) diff --git a/gas/config/tc-i370.c b/gas/config/tc-i370.c index c11d75d8b2e..08a665fdf99 100644 --- a/gas/config/tc-i370.c +++ b/gas/config/tc-i370.c @@ -22,11 +22,10 @@ 02111-1307, USA. */ /* This assembler implements a very hacked version of an elf-like thing - * that gcc emits (when gcc is suitably hacked). To make it behave more - * HLASM-like, try turning on the -M or --mri flag (as there are various - * similarities between HLASM and the MRI assemblers, such as section - * names, lack of leading . in pseudo-ops, DC and DS, etc ... - */ + that gcc emits (when gcc is suitably hacked). To make it behave more + HLASM-like, try turning on the -M or --mri flag (as there are various + similarities between HLASM and the MRI assemblers, such as section + names, lack of leading . in pseudo-ops, DC and DS, etc. */ #include #include "as.h" @@ -40,7 +39,7 @@ #include "elf/i370.h" #endif -/* This is the assembler for the System/390 Architecture */ +/* This is the assembler for the System/390 Architecture. */ /* Tell the main code what the endianness is. */ extern int target_big_endian; @@ -77,8 +76,7 @@ const char EXP_CHARS[] = "eE"; const char FLT_CHARS[] = "dD"; void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, "\ S/370 options: (these have not yet been tested and may not work) \n\ @@ -93,84 +91,15 @@ S/370 options: (these have not yet been tested and may not work) \n\ #endif } - -static void i370_byte PARAMS ((int)); -static void i370_tc PARAMS ((int)); -static void i370_ebcdic PARAMS ((int)); - -static void i370_dc PARAMS ((int)); -static void i370_ds PARAMS ((int)); -static void i370_rmode PARAMS ((int)); -static void i370_csect PARAMS ((int)); -static void i370_dsect PARAMS ((int)); -static void i370_ltorg PARAMS ((int)); -static void i370_using PARAMS ((int)); -static void i370_drop PARAMS ((int)); -static void i370_make_relative PARAMS ((expressionS *exp, expressionS *baseaddr)); - -#ifdef OBJ_ELF -static bfd_reloc_code_real_type i370_elf_suffix PARAMS ((char **, expressionS *)); -static void i370_elf_cons PARAMS ((int)); -static void i370_elf_rdata PARAMS ((int)); -static void i370_elf_lcomm PARAMS ((int)); -static void i370_elf_validate_fix PARAMS ((fixS *, segT)); -#endif - - -/* The target specific pseudo-ops which we support. */ - -const pseudo_typeS md_pseudo_table[] = -{ - /* Pseudo-ops which must be overridden. */ - { "byte", i370_byte, 0 }, - - { "dc", i370_dc, 0 }, - { "ds", i370_ds, 0 }, - { "rmode", i370_rmode, 0 }, - { "csect", i370_csect, 0 }, - { "dsect", i370_dsect, 0 }, - - /* enable ebcdic strings e.g. for 3270 support */ - { "ebcdic", i370_ebcdic, 0 }, - -#ifdef OBJ_ELF - { "long", i370_elf_cons, 4 }, - { "word", i370_elf_cons, 4 }, - { "short", i370_elf_cons, 2 }, - { "rdata", i370_elf_rdata, 0 }, - { "rodata", i370_elf_rdata, 0 }, - { "lcomm", i370_elf_lcomm, 0 }, -#endif - - /* This pseudo-op is used even when not generating XCOFF output. */ - { "tc", i370_tc, 0 }, - - /* dump the literal pool */ - { "ltorg", i370_ltorg, 0 }, - - /* support the hlasm-style USING directive */ - { "using", i370_using, 0 }, - { "drop", i370_drop, 0 }, - - { NULL, NULL, 0 } -}; - -/* ***************************************************************** */ - /* Whether to use user friendly register names. */ #define TARGET_REG_NAMES_P TRUE static bfd_boolean reg_names_p = TARGET_REG_NAMES_P; -static bfd_boolean register_name PARAMS ((expressionS *)); -static void i370_set_cpu PARAMS ((void)); -static i370_insn_t i370_insert_operand - PARAMS ((i370_insn_t insn, const struct i370_operand *operand, offsetT val)); -static void i370_macro PARAMS ((char *str, const struct i370_macro *macro)); -/* Predefined register names if -mregnames */ -/* In general, there are lots of them, in an attempt to be compatible */ -/* with a number of assemblers. */ +/* Predefined register names if -mregnames + In general, there are lots of them, in an attempt to be compatible + with a number of assemblers. */ /* Structure to hold information about predefined registers. */ struct pd_reg @@ -206,10 +135,10 @@ struct pd_reg static const struct pd_reg pre_defined_registers[] = { - { "arg", 11 }, /* Argument Pointer */ - { "base", 3 }, /* Base Reg */ + { "arg", 11 }, /* Argument Pointer. */ + { "base", 3 }, /* Base Reg. */ - { "f.0", 0 }, /* Floating point registers */ + { "f.0", 0 }, /* Floating point registers. */ { "f.2", 2 }, { "f.4", 4 }, { "f.6", 6 }, @@ -219,11 +148,11 @@ static const struct pd_reg pre_defined_registers[] = { "f4", 4 }, { "f6", 6 }, - { "dsa",13 }, /* stack pointer */ - { "lr", 14 }, /* Link Register */ - { "pgt", 4 }, /* Page Origin Table Pointer */ + { "dsa",13 }, /* Stack pointer. */ + { "lr", 14 }, /* Link Register. */ + { "pgt", 4 }, /* Page Origin Table Pointer. */ - { "r.0", 0 }, /* General Purpose Registers */ + { "r.0", 0 }, /* General Purpose Registers. */ { "r.1", 1 }, { "r.10", 10 }, { "r.11", 11 }, @@ -240,16 +169,16 @@ static const struct pd_reg pre_defined_registers[] = { "r.8", 8 }, { "r.9", 9 }, - { "r.arg", 11 }, /* Argument Pointer */ - { "r.base", 3 }, /* Base Reg */ - { "r.dsa", 13 }, /* Stack Pointer */ - { "r.pgt", 4 }, /* Page Origin Table Pointer */ - { "r.sp", 13 }, /* Stack Pointer */ + { "r.arg", 11 }, /* Argument Pointer. */ + { "r.base", 3 }, /* Base Reg. */ + { "r.dsa", 13 }, /* Stack Pointer. */ + { "r.pgt", 4 }, /* Page Origin Table Pointer. */ + { "r.sp", 13 }, /* Stack Pointer. */ - { "r.tca", 12 }, /* Pointer to the table of contents */ - { "r.toc", 12 }, /* Pointer to the table of contents */ + { "r.tca", 12 }, /* Pointer to the table of contents. */ + { "r.toc", 12 }, /* Pointer to the table of contents. */ - { "r0", 0 }, /* More general purpose registers */ + { "r0", 0 }, /* More general purpose registers. */ { "r1", 1 }, { "r10", 10 }, { "r11", 11 }, @@ -266,12 +195,12 @@ static const struct pd_reg pre_defined_registers[] = { "r8", 8 }, { "r9", 9 }, - { "rbase", 3 }, /* Base Reg */ + { "rbase", 3 }, /* Base Reg. */ - { "rtca", 12 }, /* Pointer to the table of contents */ - { "rtoc", 12 }, /* Pointer to the table of contents */ + { "rtca", 12 }, /* Pointer to the table of contents. */ + { "rtoc", 12 }, /* Pointer to the table of contents. */ - { "sp", 13 }, /* Stack Pointer */ + { "sp", 13 }, /* Stack Pointer. */ }; @@ -280,14 +209,10 @@ static const struct pd_reg pre_defined_registers[] = /* Given NAME, find the register number associated with that name, return the integer value associated with the given name or -1 on failure. */ -static int reg_name_search - PARAMS ((const struct pd_reg *, int, const char * name)); - static int -reg_name_search (regs, regcount, name) - const struct pd_reg *regs; - int regcount; - const char *name; +reg_name_search (const struct pd_reg *regs, + int regcount, + const char *name) { int middle, low, high; int cmp; @@ -311,21 +236,18 @@ reg_name_search (regs, regcount, name) return -1; } -/* - * Summary of register_name(). - * - * in: Input_line_pointer points to 1st char of operand. - * - * out: An expressionS. - * The operand may have been a register: in this case, X_op == O_register, - * X_add_number is set to the register number, and truth is returned. - * Input_line_pointer->(next non-blank) char after operand, or is in its - * original state. - */ +/* Summary of register_name(). + + in: Input_line_pointer points to 1st char of operand. + + out: An expressionS. + The operand may have been a register: in this case, X_op == O_register, + X_add_number is set to the register number, and truth is returned. + Input_line_pointer->(next non-blank) char after operand, or is in its + original state. */ static bfd_boolean -register_name (expressionP) - expressionS *expressionP; +register_name (expressionS *expressionP) { int reg_number; char *name; @@ -346,9 +268,7 @@ register_name (expressionP) /* If it's a number, treat it as a number. If it's alpha, look to see if it's in the register table. */ if (!ISALPHA (name[0])) - { - reg_number = get_single_number (); - } + reg_number = get_single_number (); else { c = get_symbol_end (); @@ -382,32 +302,31 @@ register_name (expressionP) static int i370_cpu = 0; /* The base register to use for opcode with optional operands. - * We define two of these: "text" and "other". Normally, "text" - * would get used in the .text section for branches, while "other" - * gets used in the .data section for address constants. - * - * The idea of a second base register in a different section - * is foreign to the usual HLASM-style semantics; however, it - * allows us to provide support for dynamically loaded libraries, - * by allowing us to place address constants in a section other - * than the text section. The "other" section need not be the - * .data section, it can be any section that isn't the .text section. - * - * Note that HLASM defines a multiple, concurrent .using semantic - * that we do not: in calculating offsets, it uses either the most - * recent .using directive, or the one with the smallest displacement. - * This allows HLASM to support a quasi-block-scope-like behaviour. - * Handy for people writing assembly by hand ... but not supported - * by us. - */ + We define two of these: "text" and "other". Normally, "text" + would get used in the .text section for branches, while "other" + gets used in the .data section for address constants. + + The idea of a second base register in a different section + is foreign to the usual HLASM-style semantics; however, it + allows us to provide support for dynamically loaded libraries, + by allowing us to place address constants in a section other + than the text section. The "other" section need not be the + .data section, it can be any section that isn't the .text section. + + Note that HLASM defines a multiple, concurrent .using semantic + that we do not: in calculating offsets, it uses either the most + recent .using directive, or the one with the smallest displacement. + This allows HLASM to support a quasi-block-scope-like behaviour. + Handy for people writing assembly by hand ... but not supported + by us. */ static int i370_using_text_regno = -1; static int i370_using_other_regno = -1; -/* The base address for address literals */ +/* The base address for address literals. */ static expressionS i370_using_text_baseaddr; static expressionS i370_using_other_baseaddr; -/* the "other" section, used only for syntax error detection */ +/* the "other" section, used only for syntax error detection. */ static segT i370_other_section = undefined_section; /* Opcode hash table. */ @@ -417,11 +336,11 @@ static struct hash_control *i370_hash; static struct hash_control *i370_macro_hash; #ifdef OBJ_ELF -/* What type of shared library support to use */ +/* What type of shared library support to use. */ static enum { SHLIB_NONE, SHLIB_PIC, SHILB_MRELOCATABLE } shlib = SHLIB_NONE; #endif -/* Flags to set in the elf header */ +/* Flags to set in the elf header. */ static flagword i370_flags = 0; #ifndef WORKING_DOT_WORD @@ -441,9 +360,7 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { switch (c) { @@ -468,10 +385,10 @@ md_parse_option (c, arg) case 'm': - /* -m360 mean to assemble for the ancient 360 architecture */ + /* -m360 mean to assemble for the ancient 360 architecture. */ if (strcmp (arg, "360") == 0 || strcmp (arg, "i360") == 0) i370_cpu = I370_OPCODE_360; - /* -mxa means to assemble for the IBM 370 XA */ + /* -mxa means to assemble for the IBM 370 XA. */ else if (strcmp (arg, "xa") == 0) i370_cpu = I370_OPCODE_370_XA; /* -many means to assemble for any architecture (370/XA). */ @@ -485,19 +402,18 @@ md_parse_option (c, arg) reg_names_p = FALSE; #ifdef OBJ_ELF - /* -mrelocatable/-mrelocatable-lib -- warn about initializations that require relocation */ + /* -mrelocatable/-mrelocatable-lib -- warn about + initializations that require relocation. */ else if (strcmp (arg, "relocatable") == 0) { shlib = SHILB_MRELOCATABLE; i370_flags |= EF_I370_RELOCATABLE; } - else if (strcmp (arg, "relocatable-lib") == 0) { shlib = SHILB_MRELOCATABLE; i370_flags |= EF_I370_RELOCATABLE_LIB; } - #endif else { @@ -532,12 +448,12 @@ md_parse_option (c, arg) but can be made more fine grained if desred. */ static void -i370_set_cpu () +i370_set_cpu (void) { const char *default_os = TARGET_OS; const char *default_cpu = TARGET_CPU; - /* override with the superset for the moment. */ + /* Override with the superset for the moment. */ i370_cpu = I370_OPCODE_ESA390_SUPERSET; if (i370_cpu == 0) { @@ -552,11 +468,11 @@ i370_set_cpu () } } -/* Figure out the BFD architecture to use. */ -/* hack alert -- specify the different 370 architectures */ +/* Figure out the BFD architecture to use. + FIXME: specify the different 370 architectures. */ enum bfd_architecture -i370_arch () +i370_arch (void) { return bfd_arch_i370; } @@ -566,9 +482,9 @@ i370_arch () opened. */ void -md_begin () +md_begin (void) { - register const struct i370_opcode *op; + const struct i370_opcode *op; const struct i370_opcode *op_end; const struct i370_macro *macro; const struct i370_macro *macro_end; @@ -595,7 +511,7 @@ md_begin () { const char *retval; - retval = hash_insert (i370_hash, op->name, (PTR) op); + retval = hash_insert (i370_hash, op->name, (void *) op); if (retval != (const char *) NULL) { as_bad ("Internal assembler error for instruction %s", op->name); @@ -614,7 +530,7 @@ md_begin () { const char *retval; - retval = hash_insert (i370_macro_hash, macro->name, (PTR) macro); + retval = hash_insert (i370_macro_hash, macro->name, (void *) macro); if (retval != (const char *) NULL) { as_bad ("Internal assembler error for macro %s", macro->name); @@ -630,27 +546,24 @@ md_begin () /* Insert an operand value into an instruction. */ static i370_insn_t -i370_insert_operand (insn, operand, val) - i370_insn_t insn; - const struct i370_operand *operand; - offsetT val; +i370_insert_operand (i370_insn_t insn, + const struct i370_operand *operand, + offsetT val) { if (operand->insert) { const char *errmsg; - /* used for 48-bit insn's */ + /* Used for 48-bit insn's. */ errmsg = NULL; insn = (*operand->insert) (insn, (long) val, &errmsg); if (errmsg) as_bad ("%s", errmsg); } else - { - /* this is used only for 16, 32 bit insn's */ - insn.i[0] |= (((long) val & ((1 << operand->bits) - 1)) - << operand->shift); - } + /* This is used only for 16, 32 bit insn's. */ + insn.i[0] |= (((long) val & ((1 << operand->bits) - 1)) + << operand->shift); return insn; } @@ -665,10 +578,9 @@ i370_insert_operand (insn, operand, val) BFD_RELOC_UNUSED in all circumstances. However, I'll leave in for now in case someone ambitious finds a good use for this stuff ... this routine was pretty much just copied from the powerpc code ... */ + static bfd_reloc_code_real_type -i370_elf_suffix (str_p, exp_p) - char **str_p; - expressionS *exp_p; +i370_elf_suffix (char **str_p, expressionS *exp_p) { struct map_bfd { @@ -684,7 +596,7 @@ i370_elf_suffix (str_p, exp_p) int len; struct map_bfd *ptr; -#define MAP(str,reloc) { str, sizeof (str)-1, reloc } +#define MAP(str,reloc) { str, sizeof (str) - 1, reloc } static struct map_bfd mapping[] = { @@ -700,9 +612,7 @@ i370_elf_suffix (str_p, exp_p) (str2 < ident + sizeof (ident) - 1 && (ISALNUM (ch) || ch == '@')); ch = *++str) - { - *str2++ = TOLOWER (ch); - } + *str2++ = TOLOWER (ch); *str2 = '\0'; len = str2 - ident; @@ -745,11 +655,11 @@ i370_elf_suffix (str_p, exp_p) return BFD_RELOC_UNUSED; } -/* Like normal .long/.short/.word, except support @got, etc. */ -/* clobbers input_line_pointer, checks end-of-line. */ +/* Like normal .long/.short/.word, except support @got, etc. + Clobbers input_line_pointer, checks end-of-line. */ + static void -i370_elf_cons (nbytes) - register int nbytes; /* 1=.byte, 2=.word, 4=.long */ +i370_elf_cons (int nbytes) /* 1=.byte, 2=.word, 4=.long. */ { expressionS exp; bfd_reloc_code_real_type reloc; @@ -763,6 +673,7 @@ i370_elf_cons (nbytes) do { expression (&exp); + if (exp.X_op == O_symbol && *input_line_pointer == '@' && (reloc = i370_elf_suffix (&input_line_pointer, &exp)) != BFD_RELOC_UNUSED) @@ -772,10 +683,9 @@ i370_elf_cons (nbytes) if (size > nbytes) as_bad ("%s relocations do not fit in %d bytes\n", reloc_howto->name, nbytes); - else { - register char *p = frag_more ((int) nbytes); + char *p = frag_more ((int) nbytes); int offset = nbytes - size; fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size, &exp, 0, reloc); @@ -913,10 +823,10 @@ unsigned char ebcasc[256] = 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }; -/* ebcdic translation tables needed for 3270 support */ +/* EBCDIC translation tables needed for 3270 support. */ + static void -i370_ebcdic (unused) - int unused ATTRIBUTE_UNUSED; +i370_ebcdic (int unused ATTRIBUTE_UNUSED) { char *p, *end; char delim = 0; @@ -928,10 +838,11 @@ i370_ebcdic (unused) while ('\n' == *end) end --; delim = *input_line_pointer; - if (('\'' == delim) || ('\"' == delim)) { - input_line_pointer ++; - end = rindex (input_line_pointer, delim); - } + if (('\'' == delim) || ('\"' == delim)) + { + input_line_pointer ++; + end = rindex (input_line_pointer, delim); + } if (end > input_line_pointer) { @@ -948,22 +859,21 @@ i370_ebcdic (unused) } -/* stub out a couple of routines */ +/* Stub out a couple of routines. */ + static void -i370_rmode (unused) - int unused ATTRIBUTE_UNUSED; +i370_rmode (int unused ATTRIBUTE_UNUSED) { as_tsktsk ("rmode ignored"); } static void -i370_dsect (sect) - int sect; +i370_dsect (int sect) { char *save_line = input_line_pointer; static char section[] = ".data\n"; - /* Just pretend this is .section .data */ + /* Just pretend this is .section .data. */ input_line_pointer = section; obj_elf_section (sect); @@ -971,22 +881,20 @@ i370_dsect (sect) } static void -i370_csect (unused) - int unused ATTRIBUTE_UNUSED; +i370_csect (int unused ATTRIBUTE_UNUSED) { as_tsktsk ("csect not supported"); } /* DC Define Const is only partially supported. - * For samplecode on what to do, look at i370_elf_cons() above. - * This code handles pseudoops of the style - * DC D'3.141592653' # in sysv4, .double 3.14159265 - * DC F'1' # in sysv4, .long 1 - */ + For samplecode on what to do, look at i370_elf_cons() above. + This code handles pseudoops of the style + DC D'3.141592653' # in sysv4, .double 3.14159265 + DC F'1' # in sysv4, .long 1. */ + static void -i370_dc (unused) - int unused ATTRIBUTE_UNUSED; +i370_dc (int unused ATTRIBUTE_UNUSED) { char * p, tmp[50]; int nbytes=0; @@ -999,7 +907,7 @@ i370_dc (unused) return; } - /* figure out the size */ + /* Figure out the size. */ type = *input_line_pointer++; switch (type) { @@ -1018,10 +926,11 @@ i370_dc (unused) return; } - /* get rid of pesky quotes */ + /* Get rid of pesky quotes. */ if ('\'' == *input_line_pointer) { char * close; + ++input_line_pointer; close = strchr (input_line_pointer, '\''); if (close) @@ -1029,9 +938,11 @@ i370_dc (unused) else as_bad ("missing end-quote"); } + if ('\"' == *input_line_pointer) { char * close; + ++input_line_pointer; close = strchr (input_line_pointer, '\"'); if (close) @@ -1062,15 +973,15 @@ i370_dc (unused) } -/* provide minimal support for DS Define Storage */ +/* Provide minimal support for DS Define Storage. */ + static void -i370_ds (unused) - int unused ATTRIBUTE_UNUSED; +i370_ds (int unused ATTRIBUTE_UNUSED) { - /* DS 0H or DS 0F or DS 0D */ + /* DS 0H or DS 0F or DS 0D. */ if ('0' == *input_line_pointer) { - int alignment = 0; /* left shift 1<>= 1, ++align2) ; if (align != 1) @@ -1223,10 +1133,9 @@ i370_elf_lcomm (unused) /* Validate any relocations emitted for -mrelocatable, possibly adding fixups for word relocations in writable segments, so we can adjust them at runtime. */ + static void -i370_elf_validate_fix (fixp, seg) - fixS *fixp; - segT seg; +i370_elf_validate_fix (fixS *fixp, segT seg) { if (fixp->fx_done || fixp->fx_pcrel) return; @@ -1257,12 +1166,12 @@ i370_elf_validate_fix (fixp, seg) { if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0 || fixp->fx_r_type != BFD_RELOC_CTOR) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - "Relocation cannot be done when using -mrelocatable"); - } + as_bad_where (fixp->fx_file, fixp->fx_line, + "Relocation cannot be done when using -mrelocatable"); } return; + default: + break; } } #endif /* OBJ_ELF */ @@ -1270,20 +1179,18 @@ i370_elf_validate_fix (fixp, seg) #define LITERAL_POOL_SUPPORT #ifdef LITERAL_POOL_SUPPORT -/* Provide support for literal pools within the text section. */ -/* Loosely based on similar code from tc-arm.c */ -/* - * We will use four symbols to locate four parts of the literal pool. - * These four sections contain 64,32,16 and 8-bit constants; we use - * four sections so that all memory access can be appropriately aligned. - * That is, we want to avoid mixing these together so that we don't - * waste space padding out to alignments. The four pointers - * longlong_poolP, word_poolP, etc. point to a symbol labeling the - * start of each pool part. - * - * lit_pool_num increments from zero to infinity and uniquely id's - * -- its used to generate the *_poolP symbol name. - */ +/* Provide support for literal pools within the text section. + Loosely based on similar code from tc-arm.c. + We will use four symbols to locate four parts of the literal pool. + These four sections contain 64,32,16 and 8-bit constants; we use + four sections so that all memory access can be appropriately aligned. + That is, we want to avoid mixing these together so that we don't + waste space padding out to alignments. The four pointers + longlong_poolP, word_poolP, etc. point to a symbol labeling the + start of each pool part. + + lit_pool_num increments from zero to infinity and uniquely id's + -- its used to generate the *_poolP symbol name. */ #define MAX_LITERAL_POOL_SIZE 1024 @@ -1296,16 +1203,16 @@ typedef struct literalS } literalT; literalT literals[MAX_LITERAL_POOL_SIZE]; -int next_literal_pool_place = 0; /* Next free entry in the pool */ +int next_literal_pool_place = 0; /* Next free entry in the pool. */ -static symbolS *longlong_poolP = NULL; /* 64-bit pool entries */ -static symbolS *word_poolP = NULL; /* 32-bit pool entries */ -static symbolS *short_poolP = NULL; /* 16-bit pool entries */ -static symbolS *byte_poolP = NULL; /* 8-bit pool entries */ +static symbolS *longlong_poolP = NULL; /* 64-bit pool entries. */ +static symbolS *word_poolP = NULL; /* 32-bit pool entries. */ +static symbolS *short_poolP = NULL; /* 16-bit pool entries. */ +static symbolS *byte_poolP = NULL; /* 8-bit pool entries. */ static int lit_pool_num = 1; -/* create a new, empty symbol */ +/* Create a new, empty symbol. */ static symbolS * symbol_make_empty (void) { @@ -1313,14 +1220,41 @@ symbol_make_empty (void) (valueT) 0, &zero_address_frag); } -/* add an expression to the literal pool */ +/* Make the first argument an address-relative expression + by subtracting the second argument. */ + +static void +i370_make_relative (expressionS *exx, expressionS *baseaddr) +{ + if (O_constant == baseaddr->X_op) + { + exx->X_op = O_symbol; + exx->X_add_number -= baseaddr->X_add_number; + } + else if (O_symbol == baseaddr->X_op) + { + exx->X_op = O_subtract; + exx->X_op_symbol = baseaddr->X_add_symbol; + exx->X_add_number -= baseaddr->X_add_number; + } + else if (O_uminus == baseaddr->X_op) + { + exx->X_op = O_add; + exx->X_op_symbol = baseaddr->X_add_symbol; + exx->X_add_number += baseaddr->X_add_number; + } + else + as_bad ("Missing or bad .using directive"); +} +/* Add an expression to the literal pool. */ + static void add_to_lit_pool (expressionS *exx, char *name, int sz) { int lit_count = 0; int offset_in_pool = 0; - /* start a new pool, if necessary */ + /* Start a new pool, if necessary. */ if (8 == sz && NULL == longlong_poolP) longlong_poolP = symbol_make_empty (); else if (4 == sz && NULL == word_poolP) @@ -1330,12 +1264,11 @@ add_to_lit_pool (expressionS *exx, char *name, int sz) else if (1 == sz && NULL == byte_poolP) byte_poolP = symbol_make_empty (); - /* Check if this literal value is already in the pool: */ - /* hack alert -- we should probably be checking expressions - * of type O_symbol as well ... */ - /* hack alert XXX this is probably(certainly?) broken for O_big, - * which includes 64-bit long-longs ... - */ + /* Check if this literal value is already in the pool. + FIXME: We should probably be checking expressions + of type O_symbol as well. + FIXME: This is probably(certainly?) broken for O_big, + which includes 64-bit long-longs. */ while (lit_count < next_literal_pool_place) { if (exx->X_op == O_constant @@ -1356,30 +1289,23 @@ add_to_lit_pool (expressionS *exx, char *name, int sz) if (lit_count == next_literal_pool_place) /* new entry */ { if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE) - { - as_bad ("Literal Pool Overflow"); - } + as_bad ("Literal Pool Overflow"); literals[next_literal_pool_place].exp = *exx; literals[next_literal_pool_place].size = sz; literals[next_literal_pool_place].offset = offset_in_pool; if (name) - { - literals[next_literal_pool_place].sym_name = strdup (name); - } + literals[next_literal_pool_place].sym_name = strdup (name); else - { - literals[next_literal_pool_place].sym_name = NULL; - } + literals[next_literal_pool_place].sym_name = NULL; next_literal_pool_place++; } /* ???_poolP points to the beginning of the literal pool. - * X_add_number is the offset from the beginning of the - * literal pool to this expr minus the location of the most - * recent .using directive. Thus, the grand total value of the - * expression is the distance from .using to the literal. - */ + X_add_number is the offset from the beginning of the + literal pool to this expr minus the location of the most + recent .using directive. Thus, the grand total value of the + expression is the distance from .using to the literal. */ if (8 == sz) exx->X_add_symbol = longlong_poolP; else if (4 == sz) @@ -1392,36 +1318,28 @@ add_to_lit_pool (expressionS *exx, char *name, int sz) exx->X_op_symbol = NULL; /* If the user has set up a base reg in another section, - * use that; otherwise use the text section. */ + use that; otherwise use the text section. */ if (0 < i370_using_other_regno) - { - i370_make_relative (exx, &i370_using_other_baseaddr); - } + i370_make_relative (exx, &i370_using_other_baseaddr); else - { - i370_make_relative (exx, &i370_using_text_baseaddr); - } + i370_make_relative (exx, &i370_using_text_baseaddr); } /* The symbol setup for the literal pool is done in two steps. First, - * a symbol that represents the start of the literal pool is created, - * above, in the add_to_pool() routine. This sym ???_poolP. - * However, we don't know what fragment its in until a bit later. - * So we defer the frag_now thing, and the symbol name, until .ltorg time - */ + a symbol that represents the start of the literal pool is created, + above, in the add_to_pool() routine. This sym ???_poolP. + However, we don't know what fragment its in until a bit later. + So we defer the frag_now thing, and the symbol name, until .ltorg time. */ /* Can't use symbol_new here, so have to create a symbol and then at - a later date assign it a value. Thats what these functions do */ -static void symbol_locate - PARAMS ((symbolS *, const char *, segT, valueT, fragS *)); + a later date assign it a value. Thats what these functions do. */ static void -symbol_locate (symbolP, name, segment, valu, frag) - symbolS *symbolP; - const char *name; /* It is copied, the caller can modify */ - segT segment; /* Segment identifier (SEG_) */ - valueT valu; /* Symbol value */ - fragS *frag; /* Associated fragment */ +symbol_locate (symbolS *symbolP, + const char *name, /* It is copied, the caller can modify. */ + segT segment, /* Segment identifier (SEG_). */ + valueT valu, /* Symbol value. */ + fragS *frag) /* Associated fragment. */ { size_t name_length; char *preserved_copy_of_name; @@ -1438,11 +1356,10 @@ symbol_locate (symbolP, name, segment, valu, frag) symbol_set_frag (symbolP, frag); - /* - * Link to end of symbol chain. - */ + /* Link to end of symbol chain. */ { extern int symbol_table_frozen; + if (symbol_table_frozen) abort (); } @@ -1462,20 +1379,20 @@ symbol_locate (symbolP, name, segment, valu, frag) } /* i370_addr_offset() will convert operand expressions - * that appear to be absolute into thier base-register - * relative form. These expressions come in two types: - * - * (1) of the form "* + const" * where "*" means - * relative offset since the last using - * i.e. "*" means ".-using_baseaddr" - * - * (2) labels, which are never absolute, but are always - * relative to the last "using". Anything with an alpha - * character is considered to be a label (since symbols - * can never be operands), and since we've already handled - * register operands. For example, "BL .L33" branch low - * to .L33 RX form insn frequently terminates for-loops, - */ + that appear to be absolute into thier base-register + relative form. These expressions come in two types: + + (1) of the form "* + const" * where "*" means + relative offset since the last using + i.e. "*" means ".-using_baseaddr" + + (2) labels, which are never absolute, but are always + relative to the last "using". Anything with an alpha + character is considered to be a label (since symbols + can never be operands), and since we've already handled + register operands. For example, "BL .L33" branch low + to .L33 RX form insn frequently terminates for-loops. */ + static bfd_boolean i370_addr_offset (expressionS *exx) { @@ -1483,15 +1400,13 @@ i370_addr_offset (expressionS *exx) int islabel = 0; int all_digits = 0; - /* search for a label; anything with an alpha char will do */ - /* local labels consist of N digits followed by either b or f */ + /* Search for a label; anything with an alpha char will do. + Local labels consist of N digits followed by either b or f. */ lab = input_line_pointer; while (*lab && (',' != *lab) && ('(' != *lab)) { if (ISDIGIT (*lab)) - { - all_digits = 1; - } + all_digits = 1; else if (ISALPHA (*lab)) { if (!all_digits) @@ -1512,75 +1427,65 @@ i370_addr_offset (expressionS *exx) ++lab; } - /* See if operand has a * in it */ + /* See if operand has a * in it. */ dot = strchr (input_line_pointer, '*'); if (!dot && !islabel) return FALSE; - /* replace * with . and let expr munch on it. */ + /* Replace * with . and let expr munch on it. */ if (dot) *dot = '.'; expression (exx); - /* OK, now we have to subtract the "using" location */ - /* normally branches appear in the text section only... */ + /* OK, now we have to subtract the "using" location. + Normally branches appear in the text section only. */ if (0 == strncmp (now_seg->name, ".text", 5) || 0 > i370_using_other_regno) - { - i370_make_relative (exx, &i370_using_text_baseaddr); - } + i370_make_relative (exx, &i370_using_text_baseaddr); else - { - i370_make_relative (exx, &i370_using_other_baseaddr); - } + i370_make_relative (exx, &i370_using_other_baseaddr); - /* put the * back */ + /* Put the * back. */ if (dot) *dot = '*'; return TRUE; } -/* handle address constants of various sorts */ +/* Handle address constants of various sorts. */ /* The currently supported types are - * =A(some_symb) - * =V(some_extern) - * =X'deadbeef' hexadecimal - * =F'1234' 32-bit const int - * =H'1234' 16-bit const int - */ + =A(some_symb) + =V(some_extern) + =X'deadbeef' hexadecimal + =F'1234' 32-bit const int + =H'1234' 16-bit const int. */ + static bfd_boolean i370_addr_cons (expressionS *exp) { char *name; char *sym_name, delim; int name_len; - int hex_len=0; - int cons_len=0; + int hex_len = 0; + int cons_len = 0; name = input_line_pointer; sym_name = input_line_pointer; - /* Find the spelling of the operand */ + /* Find the spelling of the operand. */ if (name[0] == '=' && ISALPHA (name[1])) - { - name = ++input_line_pointer; - } + name = ++input_line_pointer; else - { - return FALSE; - } + return FALSE; + switch (name[0]) { - case 'A': - case 'V': - /* A == address-of */ - /* V == extern */ + case 'A': /* A == address-of. */ + case 'V': /* V == extern. */ ++input_line_pointer; expression (exp); - /* we use a simple string name to collapse together - * multiple refrences to the same address literal - */ + /* We use a simple string name to collapse together + multiple refrences to the same address literal. */ name_len = strcspn (sym_name, ", "); delim = *(sym_name + name_len); *(sym_name + name_len) = 0x0; @@ -1591,29 +1496,30 @@ i370_addr_cons (expressionS *exp) case 'H': case 'F': case 'X': - case 'E': /* single-precision float point */ - case 'D': /* double-precision float point */ + case 'E': /* Single-precision float point. */ + case 'D': /* Double-precision float point. */ - /* H == 16-bit fixed-point const; expression must be const */ - /* F == fixed-point const; expression must be const */ - /* X == fixed-point const; expression must be const */ + /* H == 16-bit fixed-point const; expression must be const. */ + /* F == fixed-point const; expression must be const. */ + /* X == fixed-point const; expression must be const. */ if ('H' == name[0]) cons_len = 2; else if ('F' == name[0]) cons_len = 4; else if ('X' == name[0]) cons_len = -1; else if ('E' == name[0]) cons_len = 4; else if ('D' == name[0]) cons_len = 8; - /* extract length, if it is present; hack alert -- assume single-digit - * length */ + /* Extract length, if it is present; + FIXME: assume single-digit length. */ if ('L' == name[1]) { - cons_len = name[2] - '0'; /* should work for ascii and ebcdic */ + /* Should work for ASCII and EBCDIC. */ + cons_len = name[2] - '0'; input_line_pointer += 2; } ++input_line_pointer; - /* get rid of pesky quotes */ + /* Get rid of pesky quotes. */ if ('\'' == *input_line_pointer) { char * close; @@ -1640,12 +1546,11 @@ i370_addr_cons (expressionS *exp) char *save; /* The length of hex constants is specified directly with L, - * or implied through the number of hex digits. For example: - * =X'AB' one byte - * =X'abcd' two bytes - * =X'000000AB' four bytes - * =XL4'AB' four bytes, left-padded withn zero - */ + or implied through the number of hex digits. For example: + =X'AB' one byte + =X'abcd' two bytes + =X'000000AB' four bytes + =XL4'AB' four bytes, left-padded withn zero. */ if (('X' == name[0]) && (0 > cons_len)) { save = input_line_pointer; @@ -1658,10 +1563,9 @@ i370_addr_cons (expressionS *exp) cons_len = (hex_len+1) /2; } /* I believe this works even for =XL8'dada0000beeebaaa' - * which should parse out to X_op == O_big - * Note that floats and doubles get represented as - * 0d3.14159265358979 or 0f 2.7 - */ + which should parse out to X_op == O_big + Note that floats and doubles get represented as + 0d3.14159265358979 or 0f 2.7. */ tmp[0] = '0'; tmp[1] = name[0]; tmp[2] = 0; @@ -1671,17 +1575,14 @@ i370_addr_cons (expressionS *exp) expression (exp); input_line_pointer = save + (input_line_pointer-tmp-2); - /* fix up lengths for floats and doubles */ + /* Fix up lengths for floats and doubles. */ if (O_big == exp->X_op) - { - exp->X_add_number = cons_len / CHARS_PER_LITTLENUM; - } + exp->X_add_number = cons_len / CHARS_PER_LITTLENUM; } else - { - expression (exp); - } - /* O_big occurs when more than 4 bytes worth gets parsed */ + expression (exp); + + /* O_big occurs when more than 4 bytes worth gets parsed. */ if ((exp->X_op != O_constant) && (exp->X_op != O_big)) { as_bad ("expression not a constant"); @@ -1700,12 +1601,10 @@ i370_addr_cons (expressionS *exp) /* Dump the contents of the literal pool that we've accumulated so far. - * This aligns the pool to the size of the largest literal in the pool. - */ + This aligns the pool to the size of the largest literal in the pool. */ static void -i370_ltorg (ignore) - int ignore ATTRIBUTE_UNUSED; +i370_ltorg (int ignore ATTRIBUTE_UNUSED) { int litsize; int lit_count = 0; @@ -1716,27 +1615,22 @@ i370_ltorg (ignore) if (strncmp (now_seg->name, ".text", 5)) { if (i370_other_section == undefined_section) - { - as_bad (".ltorg without prior .using in section %s", - now_seg->name); - } + as_bad (".ltorg without prior .using in section %s", + now_seg->name); + if (i370_other_section != now_seg) - { - as_bad (".ltorg in section %s paired to .using in section %s", - now_seg->name, i370_other_section->name); - } + as_bad (".ltorg in section %s paired to .using in section %s", + now_seg->name, i370_other_section->name); } + if (! longlong_poolP && ! word_poolP && ! short_poolP && ! byte_poolP) - { - /* Nothing to do */ - /* as_tsktsk ("Nothing to put in the pool\n"); */ - return; - } + /* Nothing to do. */ + return; - /* find largest literal .. 2 4 or 8 */ + /* Find largest literal .. 2 4 or 8. */ lit_count = 0; while (lit_count < next_literal_pool_place) { @@ -1751,14 +1645,13 @@ i370_ltorg (ignore) else as_bad ("bad alignment of %d bytes in literal pool", biggest_literal_size); if (0 == biggest_align) biggest_align = 1; - /* Align pool for short, word, double word accesses */ + /* Align pool for short, word, double word accesses. */ frag_align (biggest_align, 0, 0); record_alignment (now_seg, biggest_align); /* Note that the gas listing will print only the first five - * entries in the pool .... wonder how to make it print more ... - */ - /* output largest literals first, then the smaller ones. */ + entries in the pool .... wonder how to make it print more. */ + /* Output largest literals first, then the smaller ones. */ for (litsize=8; litsize; litsize /=2) { symbolS *current_poolP = NULL; @@ -1789,11 +1682,10 @@ i370_ltorg (ignore) { #define EMIT_ADDR_CONS_SYMBOLS #ifdef EMIT_ADDR_CONS_SYMBOLS - /* create a bogus symbol, add it to the pool ... - * For the most part, I think this is a useless exercise, - * except that having these symbol names in the objects - * is vaguely useful for debugging ... - */ + /* Create a bogus symbol, add it to the pool ... + For the most part, I think this is a useless exercise, + except that having these symbol names in the objects + is vaguely useful for debugging. */ if (literals[lit_count].sym_name) { symbolS * symP = symbol_make_empty (); @@ -1820,42 +1712,39 @@ i370_ltorg (ignore) #endif /* LITERAL_POOL_SUPPORT */ -/* add support for the HLASM-like USING directive to indicate - * the base register to use ... we don't support the full - * hlasm semantics for this ... we merely pluck a base address - * and a register number out. We print a warning if using is - * called multiple times. I suppose we should check to see - * if the regno is valid ... - */ +/* Add support for the HLASM-like USING directive to indicate + the base register to use ... we don't support the full + hlasm semantics for this ... we merely pluck a base address + and a register number out. We print a warning if using is + called multiple times. I suppose we should check to see + if the regno is valid. */ + static void -i370_using (ignore) - int ignore ATTRIBUTE_UNUSED; +i370_using (int ignore ATTRIBUTE_UNUSED) { expressionS ex, baseaddr; int iregno; char *star; - /* if "*" appears in a using, it means "." */ - /* replace it with "." so that expr doesn't get confused. */ + /* If "*" appears in a using, it means "." + replace it with "." so that expr doesn't get confused. */ star = strchr (input_line_pointer, '*'); if (star) *star = '.'; - /* the first arg to using will usually be ".", but it can - * be a more complex expression too ... */ + /* The first arg to using will usually be ".", but it can + be a more complex expression too. */ expression (&baseaddr); if (star) *star = '*'; if (O_constant != baseaddr.X_op && O_symbol != baseaddr.X_op && O_uminus != baseaddr.X_op) - { as_bad (".using: base address expression illegal or too complex"); - } if (*input_line_pointer != '\0') ++input_line_pointer; - /* the second arg to using had better be a register */ + /* The second arg to using had better be a register. */ register_name (&ex); demand_empty_rest_of_line (); iregno = ex.X_add_number; @@ -1874,8 +1763,7 @@ i370_using (ignore) } static void -i370_drop (ignore) - int ignore ATTRIBUTE_UNUSED; +i370_drop (int ignore ATTRIBUTE_UNUSED) { expressionS ex; int iregno; @@ -1887,60 +1775,28 @@ i370_drop (ignore) if (0 == strncmp (now_seg->name, ".text", 5)) { if (iregno != i370_using_text_regno) - { - as_bad ("droping register %d in section %s does not match using register %d", - iregno, now_seg->name, i370_using_text_regno); - } + as_bad ("droping register %d in section %s does not match using register %d", + iregno, now_seg->name, i370_using_text_regno); + i370_using_text_regno = -1; i370_using_text_baseaddr.X_op = O_absent; } else { if (iregno != i370_using_other_regno) - { - as_bad ("droping register %d in section %s does not match using register %d", - iregno, now_seg->name, i370_using_other_regno); - } + as_bad ("droping register %d in section %s does not match using register %d", + iregno, now_seg->name, i370_using_other_regno); + if (i370_other_section != now_seg) - { - as_bad ("droping register %d in section %s previously used in section %s", - iregno, now_seg->name, i370_other_section->name); - } + as_bad ("droping register %d in section %s previously used in section %s", + iregno, now_seg->name, i370_other_section->name); + i370_using_other_regno = -1; i370_using_other_baseaddr.X_op = O_absent; i370_other_section = undefined_section; } } -/* Make the first argument an address-relative expression - * by subtracting the second argument. - */ -static void -i370_make_relative (expressionS *exx, expressionS *baseaddr) -{ - - if (O_constant == baseaddr->X_op) - { - exx->X_op = O_symbol; - exx->X_add_number -= baseaddr->X_add_number; - } - else if (O_symbol == baseaddr->X_op) - { - exx->X_op = O_subtract; - exx->X_op_symbol = baseaddr->X_add_symbol; - exx->X_add_number -= baseaddr->X_add_number; - } - else if (O_uminus == baseaddr->X_op) - { - exx->X_op = O_add; - exx->X_op_symbol = baseaddr->X_add_symbol; - exx->X_add_number += baseaddr->X_add_number; - } - else - { - as_bad ("Missing or bad .using directive"); - } -} /* We need to keep a list of fixups. We can't simply generate them as we go, because that would require us to first create the frag, and @@ -1953,13 +1809,90 @@ struct i370_fixup bfd_reloc_code_real_type reloc; }; -#define MAX_INSN_FIXUPS (5) +#define MAX_INSN_FIXUPS 5 + +/* Handle a macro. Gather all the operands, transform them as + described by the macro, and call md_assemble recursively. All the + operands are separated by commas; we don't accept parentheses + around operands here. */ + +static void +i370_macro (char *str, const struct i370_macro *macro) +{ + char *operands[10]; + unsigned int count; + char *s; + unsigned int len; + const char *format; + int arg; + char *send; + char *complete; + + /* Gather the users operands into the operands array. */ + count = 0; + s = str; + while (1) + { + if (count >= sizeof operands / sizeof operands[0]) + break; + operands[count++] = s; + s = strchr (s, ','); + if (s == (char *) NULL) + break; + *s++ = '\0'; + } + + if (count != macro->operands) + { + as_bad ("wrong number of operands"); + return; + } + + /* Work out how large the string must be (the size is unbounded + because it includes user input). */ + len = 0; + format = macro->format; + while (*format != '\0') + { + if (*format != '%') + { + ++len; + ++format; + } + else + { + arg = strtol (format + 1, &send, 10); + know (send != format && arg >= 0 && (unsigned) arg < count); + len += strlen (operands[arg]); + format = send; + } + } + + /* Put the string together. */ + complete = s = alloca (len + 1); + format = macro->format; + while (*format != '\0') + { + if (*format != '%') + *s++ = *format++; + else + { + arg = strtol (format + 1, &send, 10); + strcpy (s, operands[arg]); + s += strlen (s); + format = send; + } + } + *s = '\0'; + + /* Assemble the constructed instruction. */ + md_assemble (complete); +} /* This routine is called for each instruction to be assembled. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { char *s, *opcode_str; const struct i370_opcode *opcode; @@ -2022,6 +1955,7 @@ md_assemble (str) for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++) { const struct i370_operand *operand; + operand = &i370_operands[*opindex_ptr]; if ((operand->flags & I370_OPERAND_INDEX) != 0) have_optional_index = 1; @@ -2076,12 +2010,11 @@ md_assemble (str) } /* Perform some off-by-one hacks on the length field of certain instructions. - * Its such a shame to have to do this, but the problem is that HLASM got - * defined so that the lengths differ by one from the actual machine instructions. - * this code should probably be moved to a special inster-operand routine. - * Sigh. Affected instructions are Compare Logical, Move and Exclusive OR - * hack alert -- aren't *all* SS instructions affected ?? - */ + Its such a shame to have to do this, but the problem is that HLASM got + defined so that the lengths differ by one from the actual machine instructions. + this code should probably be moved to a special inster-operand routine. + Sigh. Affected instructions are Compare Logical, Move and Exclusive OR + hack alert -- aren't *all* SS instructions affected ?? */ off_by_one = 0; if (0 == strcasecmp ("CLC", opcode->name) || 0 == strcasecmp ("ED", opcode->name) @@ -2126,29 +2059,20 @@ md_assemble (str) { if (0 == strncmp (now_seg->name, ".text", 5) || 0 > i370_using_other_regno) - { - basereg = i370_using_text_regno; - } + basereg = i370_using_text_regno; else - { - basereg = i370_using_other_regno; - } + basereg = i370_using_other_regno; } else if (use_other) { if (0 > i370_using_other_regno) - { - basereg = i370_using_text_regno; - } + basereg = i370_using_text_regno; else - { - basereg = i370_using_other_regno; - } + basereg = i370_using_other_regno; } if (0 > basereg) - { - as_bad ("not using any base register"); - } + as_bad ("not using any base register"); + insn = i370_insert_operand (insn, operand, basereg); continue; } @@ -2166,60 +2090,53 @@ md_assemble (str) hold = input_line_pointer; input_line_pointer = str; - /* register names are only allowed where there are registers ... */ + /* Register names are only allowed where there are registers. */ if ((operand->flags & I370_OPERAND_GPR) != 0) { - /* quickie hack to get past things like (,r13) */ + /* Quickie hack to get past things like (,r13). */ if (skip_optional_index && (',' == *input_line_pointer)) { *input_line_pointer = ' '; input_line_pointer ++; } + if (! register_name (&ex)) - { - as_bad ("expecting a register for operand %d", - opindex_ptr - opcode->operands + 1); - } + as_bad ("expecting a register for operand %d", + opindex_ptr - opcode->operands + 1); } /* Check for an address constant expression. */ /* We will put PSW-relative addresses in the text section, - * and address literals in the .data (or other) section. */ + and address literals in the .data (or other) section. */ else if (i370_addr_cons (&ex)) - use_other=1; + use_other = 1; else if (i370_addr_offset (&ex)) - use_text=1; + use_text = 1; else expression (&ex); str = input_line_pointer; input_line_pointer = hold; - /* perform some off-by-one hacks on the length field of certain instructions. - * Its such a shame to have to do this, but the problem is that HLASM got - * defined so that the programmer specifies a length that is one greater - * than what the machine instruction wants. - * Sigh. - */ + /* Perform some off-by-one hacks on the length field of certain instructions. + Its such a shame to have to do this, but the problem is that HLASM got + defined so that the programmer specifies a length that is one greater + than what the machine instruction wants. Sigh. */ if (off_by_one && (0 == strcasecmp ("SS L", operand->name))) - { - ex.X_add_number --; - } + ex.X_add_number --; if (ex.X_op == O_illegal) as_bad ("illegal operand"); else if (ex.X_op == O_absent) as_bad ("missing operand"); else if (ex.X_op == O_register) - { - insn = i370_insert_operand (insn, operand, ex.X_add_number); - } + insn = i370_insert_operand (insn, operand, ex.X_add_number); else if (ex.X_op == O_constant) { #ifdef OBJ_ELF /* Allow @HA, @L, @H on constants. - * Well actually, no we don't; there really don't make sense - * (at least not to me) for the i370. However, this code is - * left here for any dubious future expansion reasons ... */ + Well actually, no we don't; there really don't make sense + (at least not to me) for the i370. However, this code is + left here for any dubious future expansion reasons. */ char *orig_str = str; if ((reloc = i370_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED) @@ -2264,14 +2181,12 @@ md_assemble (str) ++fc; } #endif /* OBJ_ELF */ - else { /* We need to generate a fixup for this expression. */ /* Typically, the expression will just be a symbol ... - * printf ("insn %s needs fixup for %s \n", - * opcode->name, ex.X_add_symbol->bsym->name); - */ + printf ("insn %s needs fixup for %s \n", + opcode->name, ex.X_add_symbol->bsym->name); */ if (fc >= MAX_INSN_FIXUPS) as_fatal ("too many fixups"); @@ -2281,7 +2196,7 @@ md_assemble (str) ++fc; } - /* skip over delimiter (close paren, or comma) */ + /* Skip over delimiter (close paren, or comma). */ if ((')' == *str) && (',' == *(str+1))) ++str; if (*str != '\0') @@ -2297,21 +2212,18 @@ md_assemble (str) /* Write out the instruction. */ f = frag_more (opcode->len); if (4 >= opcode->len) - { - md_number_to_chars (f, insn.i[0], opcode->len); - } + md_number_to_chars (f, insn.i[0], opcode->len); else { md_number_to_chars (f, insn.i[0], 4); + if (6 == opcode->len) - { - md_number_to_chars ((f+4), ((insn.i[1])>>16), 2); - } + md_number_to_chars ((f + 4), ((insn.i[1])>>16), 2); else { - /* not used --- don't have any 8 byte instructions */ + /* Not used --- don't have any 8 byte instructions. */ as_bad ("Internal Error: bad instruction length"); - md_number_to_chars ((f+4), insn.i[1], opcode->len -4); + md_number_to_chars ((f + 4), insn.i[1], opcode->len -4); } } @@ -2370,85 +2282,6 @@ md_assemble (str) } } -/* Handle a macro. Gather all the operands, transform them as - described by the macro, and call md_assemble recursively. All the - operands are separated by commas; we don't accept parentheses - around operands here. */ - -static void -i370_macro (str, macro) - char *str; - const struct i370_macro *macro; -{ - char *operands[10]; - unsigned int count; - char *s; - unsigned int len; - const char *format; - int arg; - char *send; - char *complete; - - /* Gather the users operands into the operands array. */ - count = 0; - s = str; - while (1) - { - if (count >= sizeof operands / sizeof operands[0]) - break; - operands[count++] = s; - s = strchr (s, ','); - if (s == (char *) NULL) - break; - *s++ = '\0'; - } - - if (count != macro->operands) - { - as_bad ("wrong number of operands"); - return; - } - - /* Work out how large the string must be (the size is unbounded - because it includes user input). */ - len = 0; - format = macro->format; - while (*format != '\0') - { - if (*format != '%') - { - ++len; - ++format; - } - else - { - arg = strtol (format + 1, &send, 10); - know (send != format && arg >= 0 && (unsigned) arg < count); - len += strlen (operands[arg]); - format = send; - } - } - - /* Put the string together. */ - complete = s = (char *) alloca (len + 1); - format = macro->format; - while (*format != '\0') - { - if (*format != '%') - *s++ = *format++; - else - { - arg = strtol (format + 1, &send, 10); - strcpy (s, operands[arg]); - s += strlen (s); - format = send; - } - } - *s = '\0'; - - /* Assemble the constructed instruction. */ - md_assemble (complete); -} /* Pseudo-op handling. */ @@ -2456,8 +2289,7 @@ i370_macro (str, macro) pseudo-op, but it can also take a single ASCII string. */ static void -i370_byte (ignore) - int ignore ATTRIBUTE_UNUSED; +i370_byte (int ignore ATTRIBUTE_UNUSED) { if (*input_line_pointer != '\"') { @@ -2500,8 +2332,7 @@ i370_byte (ignore) the first argument is simply ignored. */ static void -i370_tc (ignore) - int ignore ATTRIBUTE_UNUSED; +i370_tc (int ignore ATTRIBUTE_UNUSED) { /* Skip the TOC symbol name. */ @@ -2531,10 +2362,7 @@ i370_tc (ignore) returned, or NULL on OK. */ char * -md_atof (type, litp, sizep) - int type; - char *litp; - int *sizep; +md_atof (int type, char *litp, int *sizep) { int prec; LITTLENUM_TYPE words[4]; @@ -2581,20 +2409,15 @@ md_atof (type, litp, sizep) endianness. */ void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { - number_to_chars_bigendian (buf, val, n); + number_to_chars_bigendian (buf, val, n); } /* Align a section (I don't know why this is machine dependent). */ valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg, valueT addr) { int align = bfd_get_section_alignment (stdoutput, seg); @@ -2604,9 +2427,8 @@ md_section_align (seg, addr) /* We don't have any form of relaxing. */ int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp ATTRIBUTE_UNUSED; - asection *seg ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, + asection *seg ATTRIBUTE_UNUSED) { abort (); return 0; @@ -2615,10 +2437,9 @@ md_estimate_size_before_relax (fragp, seg) /* Convert a machine dependent frag. We never generate these. */ void -md_convert_frag (abfd, sec, fragp) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - fragS *fragp ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + fragS *fragp ATTRIBUTE_UNUSED) { abort (); } @@ -2626,8 +2447,7 @@ md_convert_frag (abfd, sec, fragp) /* We have no need to default values of symbols. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -2638,9 +2458,7 @@ md_undefined_symbol (name) given a PC relative reloc. */ long -md_pcrel_from_section (fixp, sec) - fixS *fixp; - segT sec ATTRIBUTE_UNUSED; +md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED) { return fixp->fx_frag->fr_address + fixp->fx_where; } @@ -2655,14 +2473,10 @@ md_pcrel_from_section (fixp, sec) fixup. See gas/cgen.c for more sample code and explanations of what's - going on here ... -*/ + going on here. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg) { valueT value = * valP; @@ -2830,15 +2644,13 @@ md_apply_fix3 (fixP, valP, seg) /* Generate a reloc for a fixup. */ arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc = xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); @@ -2859,3 +2671,42 @@ tc_gen_reloc (seg, fixp) return reloc; } + +/* The target specific pseudo-ops which we support. */ + +const pseudo_typeS md_pseudo_table[] = +{ + /* Pseudo-ops which must be overridden. */ + { "byte", i370_byte, 0 }, + + { "dc", i370_dc, 0 }, + { "ds", i370_ds, 0 }, + { "rmode", i370_rmode, 0 }, + { "csect", i370_csect, 0 }, + { "dsect", i370_dsect, 0 }, + + /* enable ebcdic strings e.g. for 3270 support */ + { "ebcdic", i370_ebcdic, 0 }, + +#ifdef OBJ_ELF + { "long", i370_elf_cons, 4 }, + { "word", i370_elf_cons, 4 }, + { "short", i370_elf_cons, 2 }, + { "rdata", i370_elf_rdata, 0 }, + { "rodata", i370_elf_rdata, 0 }, + { "lcomm", i370_elf_lcomm, 0 }, +#endif + + /* This pseudo-op is used even when not generating XCOFF output. */ + { "tc", i370_tc, 0 }, + + /* dump the literal pool */ + { "ltorg", i370_ltorg, 0 }, + + /* support the hlasm-style USING directive */ + { "using", i370_using, 0 }, + { "drop", i370_drop, 0 }, + + { NULL, NULL, 0 } +}; + diff --git a/gas/config/tc-i370.h b/gas/config/tc-i370.h index 81007ac97da..24c83b6236e 100644 --- a/gas/config/tc-i370.h +++ b/gas/config/tc-i370.h @@ -1,5 +1,5 @@ /* tc-i370.h -- Header file for tc-i370.c. - Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002 + Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. @@ -37,9 +37,9 @@ struct fix; /* The target BFD architecture. */ #define TARGET_ARCH (i370_arch ()) -extern enum bfd_architecture i370_arch PARAMS ((void)); +extern enum bfd_architecture i370_arch (void); -/* Whether or not the target is big endian */ +/* Whether or not the target is big endian. */ extern int target_big_endian; /* The target BFD format. */ @@ -51,7 +51,8 @@ extern int target_big_endian; /* $ is used to refer to the current location. */ /* #define DOLLAR_DOT */ -#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ +/* foo-. gets turned into PC relative relocs. */ +#define DIFF_EXPR_OK /* Values passed to md_apply_fix3 don't include the symbol value. */ #define MD_APPLY_SYM_VALUE(FIX) 0 @@ -60,8 +61,8 @@ extern int target_big_endian; #define WORKING_DOT_WORD /* Call md_pcrel_from_section, not md_pcrel_from. */ -#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC) -extern long md_pcrel_from_section PARAMS ((struct fix *, segT)); +#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC) +extern long md_pcrel_from_section (struct fix *, segT); #define md_operand(x) diff --git a/gas/config/tc-i960.c b/gas/config/tc-i960.c index 1786afe2920..8d4c30339fb 100644 --- a/gas/config/tc-i960.c +++ b/gas/config/tc-i960.c @@ -74,32 +74,32 @@ #if defined (OBJ_AOUT) || defined (OBJ_BOUT) -#define TC_S_IS_SYSPROC(s) ((1<=S_GET_OTHER(s)) && (S_GET_OTHER(s)<=32)) -#define TC_S_IS_BALNAME(s) (S_GET_OTHER(s) == N_BALNAME) -#define TC_S_IS_CALLNAME(s) (S_GET_OTHER(s) == N_CALLNAME) -#define TC_S_IS_BADPROC(s) ((S_GET_OTHER(s) != 0) && !TC_S_IS_CALLNAME(s) && !TC_S_IS_BALNAME(s) && !TC_S_IS_SYSPROC(s)) +#define TC_S_IS_SYSPROC(s) ((1 <= S_GET_OTHER (s)) && (S_GET_OTHER (s) <= 32)) +#define TC_S_IS_BALNAME(s) (S_GET_OTHER (s) == N_BALNAME) +#define TC_S_IS_CALLNAME(s) (S_GET_OTHER (s) == N_CALLNAME) +#define TC_S_IS_BADPROC(s) ((S_GET_OTHER (s) != 0) && !TC_S_IS_CALLNAME (s) && !TC_S_IS_BALNAME (s) && !TC_S_IS_SYSPROC (s)) -#define TC_S_SET_SYSPROC(s, p) (S_SET_OTHER((s), (p)+1)) -#define TC_S_GET_SYSPROC(s) (S_GET_OTHER(s)-1) +#define TC_S_SET_SYSPROC(s, p) (S_SET_OTHER ((s), (p) + 1)) +#define TC_S_GET_SYSPROC(s) (S_GET_OTHER (s) - 1) -#define TC_S_FORCE_TO_BALNAME(s) (S_SET_OTHER((s), N_BALNAME)) -#define TC_S_FORCE_TO_CALLNAME(s) (S_SET_OTHER((s), N_CALLNAME)) +#define TC_S_FORCE_TO_BALNAME(s) (S_SET_OTHER ((s), N_BALNAME)) +#define TC_S_FORCE_TO_CALLNAME(s) (S_SET_OTHER ((s), N_CALLNAME)) #define TC_S_FORCE_TO_SYSPROC(s) {;} #else /* ! OBJ_A/BOUT */ #ifdef OBJ_COFF -#define TC_S_IS_SYSPROC(s) (S_GET_STORAGE_CLASS(s) == C_SCALL) -#define TC_S_IS_BALNAME(s) (SF_GET_BALNAME(s)) -#define TC_S_IS_CALLNAME(s) (SF_GET_CALLNAME(s)) -#define TC_S_IS_BADPROC(s) (TC_S_IS_SYSPROC(s) && TC_S_GET_SYSPROC(s) < 0 && 31 < TC_S_GET_SYSPROC(s)) +#define TC_S_IS_SYSPROC(s) (S_GET_STORAGE_CLASS (s) == C_SCALL) +#define TC_S_IS_BALNAME(s) (SF_GET_BALNAME (s)) +#define TC_S_IS_CALLNAME(s) (SF_GET_CALLNAME (s)) +#define TC_S_IS_BADPROC(s) (TC_S_IS_SYSPROC (s) && TC_S_GET_SYSPROC (s) < 0 && 31 < TC_S_GET_SYSPROC (s)) #define TC_S_SET_SYSPROC(s, p) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx = (p)) #define TC_S_GET_SYSPROC(s) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx) -#define TC_S_FORCE_TO_BALNAME(s) (SF_SET_BALNAME(s)) -#define TC_S_FORCE_TO_CALLNAME(s) (SF_SET_CALLNAME(s)) -#define TC_S_FORCE_TO_SYSPROC(s) (S_SET_STORAGE_CLASS((s), C_SCALL)) +#define TC_S_FORCE_TO_BALNAME(s) (SF_SET_BALNAME (s)) +#define TC_S_FORCE_TO_CALLNAME(s) (SF_SET_CALLNAME (s)) +#define TC_S_FORCE_TO_SYSPROC(s) (S_SET_STORAGE_CLASS ((s), C_SCALL)) #else /* ! OBJ_COFF */ #ifdef OBJ_ELF @@ -110,7 +110,7 @@ #define TC_S_IS_BADPROC(s) 0 #define TC_S_SET_SYSPROC(s, p) -#define TC_S_GET_SYSPROC(s) 0 +#define TC_S_GET_SYSPROC(s) 0 #define TC_S_FORCE_TO_BALNAME(s) #define TC_S_FORCE_TO_CALLNAME(s) @@ -135,64 +135,12 @@ const int md_reloc_size = sizeof (struct relocation_info); struct memS; struct regop; -/* Emit branch-prediction instrumentation code */ -static void brcnt_emit PARAMS ((void)); -/* Return next branch local label */ -static char *brlab_next PARAMS ((void)); -/* Generate COBR instruction */ -static void cobr_fmt PARAMS ((char *[], long, struct i960_opcode *)); -/* Generate CTRL instruction */ -static void ctrl_fmt PARAMS ((char *, long, int)); -/* Emit (internally) binary */ -static char *emit PARAMS ((long)); -/* Break arguments out of comma-separated list */ -static int get_args PARAMS ((char *, char *[])); -/* Handle COBR or CTRL displacement */ -static void get_cdisp PARAMS ((char *, char *, long, int, int, int)); -/* Find index specification string */ -static char *get_ispec PARAMS ((char *)); -/* Translate text to register number */ -static int get_regnum PARAMS ((char *)); -/* Lexical scan of instruction source */ -static int i_scan PARAMS ((char *, char *[])); -/* Generate MEMA or MEMB instruction */ -static void mem_fmt PARAMS ((char *[], struct i960_opcode *, int)); -/* Convert MEMA instruction to MEMB format */ -static void mema_to_memb PARAMS ((char *)); -/* Parse an expression */ -static void parse_expr PARAMS ((char *, expressionS *)); -/* Parse and replace a 'ldconst' pseudo-op */ -static int parse_ldconst PARAMS ((char *[])); -/* Parse a memory operand */ -static void parse_memop PARAMS ((struct memS *, char *, int)); -/* Parse machine-dependent pseudo-op */ -static void parse_po PARAMS ((int)); -/* Parse a register operand */ -static void parse_regop PARAMS ((struct regop *, char *, char)); -/* Generate a REG format instruction */ -static void reg_fmt PARAMS ((char *[], struct i960_opcode *)); -/* "De-optimize" cobr into compare/branch */ -static void relax_cobr PARAMS ((fragS *)); -/* Process '.leafproc' pseudo-op */ -static void s_leafproc PARAMS ((int, char *[])); -/* Process '.sysproc' pseudo-op */ -static void s_sysproc PARAMS ((int, char *[])); -/* Will a 'shlo' substitute for a 'ldconst'? */ -static int shift_ok PARAMS ((int)); -/* Give syntax error */ -static void syntax PARAMS ((void)); -/* Target chip supports spec-func register? */ -static int targ_has_sfr PARAMS ((int)); -/* Target chip supports instruction set? */ -static int targ_has_iclass PARAMS ((int)); - -/* See md_parse_option() for meanings of these options */ -static char norelax; /* True if -norelax switch seen */ -static char instrument_branches; /* True if -b switch seen */ +/* See md_parse_option() for meanings of these options. */ +static char norelax; /* True if -norelax switch seen. */ +static char instrument_branches; /* True if -b switch seen. */ /* Characters that always start a comment. - If the pre-processor is disabled, these aren't very useful. - */ + If the pre-processor is disabled, these aren't very useful. */ const char comment_chars[] = "#"; /* Characters that only start a comment at the beginning of @@ -201,21 +149,18 @@ const char comment_chars[] = "#"; Note that input_file.c hand checks for '#' at the beginning of the first line of the input file. This is because the compiler outputs - #NO_APP at the beginning of its output. - */ + #NO_APP at the beginning of its output. */ /* Also note that comments started like this one will always work. */ -const char line_comment_chars[] = "#"; - +const char line_comment_chars[] = "#"; const char line_separator_chars[] = ";"; -/* Chars that can be used to separate mant from exp in floating point nums */ +/* Chars that can be used to separate mant from exp in floating point nums. */ const char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant, - as in 0f12.456 or 0d1.2345e12 - */ + as in 0f12.456 or 0d1.2345e12. */ const char FLT_CHARS[] = "fFdDtT"; /* Table used by base assembler to relax addresses based on varying length @@ -227,52 +172,34 @@ const char FLT_CHARS[] = "fFdDtT"; For i80960, the only application is the (de-)optimization of cobr instructions into separate compare and branch instructions when a 13-bit - displacement won't hack it. - */ + displacement won't hack it. */ const relax_typeS md_relax_table[] = { - {0, 0, 0, 0}, /* State 0 => no more relaxation possible */ - {4088, -4096, 0, 2}, /* State 1: conditional branch (cobr) */ - {0x800000 - 8, -0x800000, 4, 0}, /* State 2: compare (reg) & branch (ctrl) */ + {0, 0, 0, 0}, /* State 0 => no more relaxation possible. */ + {4088, -4096, 0, 2}, /* State 1: conditional branch (cobr). */ + {0x800000 - 8, -0x800000, 4, 0}, /* State 2: compare (reg) & branch (ctrl). */ }; -static void s_endian PARAMS ((int)); - /* These are the machine dependent pseudo-ops. This table describes all the machine specific pseudo-ops the assembler has to support. The fields are: pseudo-op name without dot function to call to execute this pseudo-op - integer arg to pass to the function - */ + integer arg to pass to the function. */ #define S_LEAFPROC 1 #define S_SYSPROC 2 -const pseudo_typeS md_pseudo_table[] = -{ - {"bss", s_lcomm, 1}, - {"endian", s_endian, 0}, - {"extended", float_cons, 't'}, - {"leafproc", parse_po, S_LEAFPROC}, - {"sysproc", parse_po, S_SYSPROC}, - - {"word", cons, 4}, - {"quad", cons, 16}, - - {0, 0, 0} -}; - -/* Macros to extract info from an 'expressionS' structure 'e' */ +/* Macros to extract info from an 'expressionS' structure 'e'. */ #define adds(e) e.X_add_symbol #define offs(e) e.X_add_number -/* Branch-prediction bits for CTRL/COBR format opcodes */ -#define BP_MASK 0x00000002 /* Mask for branch-prediction bit */ -#define BP_TAKEN 0x00000000 /* Value to OR in to predict branch */ -#define BP_NOT_TAKEN 0x00000002 /* Value to OR in to predict no branch */ +/* Branch-prediction bits for CTRL/COBR format opcodes. */ +#define BP_MASK 0x00000002 /* Mask for branch-prediction bit. */ +#define BP_TAKEN 0x00000000 /* Value to OR in to predict branch. */ +#define BP_NOT_TAKEN 0x00000002 /* Value to OR in to predict no branch. */ -/* Some instruction opcodes that we need explicitly */ +/* Some instruction opcodes that we need explicitly. */ #define BE 0x12000000 #define BG 0x11000000 #define BGE 0x13000000 @@ -301,12 +228,12 @@ const pseudo_typeS md_pseudo_table[] = used). */ #define MEMA_ABASE 0x2000 -/* Info from which a MEMA or MEMB format instruction can be generated */ +/* Info from which a MEMA or MEMB format instruction can be generated. */ typedef struct memS { - /* (First) 32 bits of instruction */ + /* (First) 32 bits of instruction. */ long opcode; - /* 0-(none), 12- or, 32-bit displacement needed */ + /* 0-(none), 12- or, 32-bit displacement needed. */ int disp; /* The expression in the source instruction from which the displacement should be determined. */ @@ -314,12 +241,12 @@ typedef struct memS } memS; -/* The two pieces of info we need to generate a register operand */ +/* The two pieces of info we need to generate a register operand. */ struct regop { - int mode; /* 0 =>local/global/spec reg; 1=> literal or fp reg */ - int special; /* 0 =>not a sfr; 1=> is a sfr (not valid w/mode=0) */ - int n; /* Register number or literal value */ + int mode; /* 0 =>local/global/spec reg; 1=> literal or fp reg. */ + int special; /* 0 =>not a sfr; 1=> is a sfr (not valid w/mode=0). */ + int n; /* Register number or literal value. */ }; /* Number and assembler mnemonic for all registers that can appear in @@ -420,10 +347,10 @@ regnames[] = /* Number and assembler mnemonic for all registers that can appear as 'abase' (indirect addressing) registers. */ static const struct - { - char *areg_name; - int areg_num; - } +{ + char *areg_name; + int areg_num; +} aregs[] = { { "(pfp)", 0 }, @@ -467,24 +394,23 @@ aregs[] = { NULL, 0 }, /* END OF LIST */ }; -/* Hash tables */ -static struct hash_control *op_hash; /* Opcode mnemonics */ -static struct hash_control *reg_hash; /* Register name hash table */ -static struct hash_control *areg_hash; /* Abase register hash table */ +/* Hash tables. */ +static struct hash_control *op_hash; /* Opcode mnemonics. */ +static struct hash_control *reg_hash; /* Register name hash table. */ +static struct hash_control *areg_hash; /* Abase register hash table. */ -/* Architecture for which we are assembling */ -#define ARCH_ANY 0 /* Default: no architecture checking done */ +/* Architecture for which we are assembling. */ +#define ARCH_ANY 0 /* Default: no architecture checking done. */ #define ARCH_KA 1 #define ARCH_KB 2 #define ARCH_MC 3 #define ARCH_CA 4 #define ARCH_JX 5 #define ARCH_HX 6 -int architecture = ARCH_ANY; /* Architecture requested on invocation line */ +int architecture = ARCH_ANY; /* Architecture requested on invocation line. */ int iclasses_seen; /* OR of instruction classes (I_* constants) - * for which we've actually assembled - * instructions. - */ + for which we've actually assembled + instructions. */ /* BRANCH-PREDICTION INSTRUMENTATION @@ -519,8 +445,7 @@ int iclasses_seen; /* OR of instruction classes (I_* constants) Note that input source code is expected to already contain calls an external routine that will link the branch local table into a - list of such tables. - */ + list of such tables. */ /* Number of branches instrumented so far. Also used to generate unique local labels for each instrumented branch. */ @@ -537,19 +462,16 @@ static int br_cnt; #define BR_TAB_NAME "__BRANCH_TABLE__" /* Name of the table of pointers to branches. A local (i.e., non-external) symbol. */ - -/***************************************************************************** - md_begin: One-time initialization. - Set up hash tables. +static void ctrl_fmt (char *, long, int); - *************************************************************************** */ + void -md_begin () +md_begin (void) { - int i; /* Loop counter */ - const struct i960_opcode *oP; /* Pointer into opcode table */ - const char *retval; /* Value returned by hash functions */ + int i; /* Loop counter. */ + const struct i960_opcode *oP; /* Pointer into opcode table. */ + const char *retval; /* Value returned by hash functions. */ op_hash = hash_new (); reg_hash = hash_new (); @@ -560,7 +482,7 @@ md_begin () retval = 0; for (oP = i960_opcodes; oP->name && !retval; oP++) - retval = hash_insert (op_hash, oP->name, (PTR) oP); + retval = hash_insert (op_hash, oP->name, (void *) oP); for (i = 0; regnames[i].reg_name && !retval; i++) retval = hash_insert (reg_hash, regnames[i].reg_name, @@ -574,170 +496,147 @@ md_begin () as_fatal (_("Hashing returned \"%s\"."), retval); } -/***************************************************************************** - md_assemble: Assemble an instruction +/* parse_expr: parse an expression - Assumptions about the passed-in text: - - all comments, labels removed - - text is an instruction - - all white space compressed to single blanks - - all character constants have been replaced with decimal + Use base assembler's expression parser to parse an expression. + It, unfortunately, runs off a global which we have to save/restore + in order to make it work for us. - *************************************************************************** */ -void -md_assemble (textP) - char *textP; /* Source text of instruction */ -{ - /* Parsed instruction text, containing NO whitespace: arg[0]->opcode - mnemonic arg[1-3]->operands, with char constants replaced by - decimal numbers. */ - char *args[4]; + An empty expression string is treated as an absolute 0. - int n_ops; /* Number of instruction operands */ - /* Pointer to instruction description */ - struct i960_opcode *oP; - /* TRUE iff opcode mnemonic included branch-prediction suffix (".f" - or ".t"). */ - int branch_predict; - /* Setting of branch-prediction bit(s) to be OR'd into instruction - opcode of CTRL/COBR format instructions. */ - long bp_bits; + Sets O_illegal regardless of expression evaluation if entire input + string is not consumed in the evaluation -- tolerate no dangling junk! */ - int n; /* Offset of last character in opcode mnemonic */ +static void +parse_expr (char *textP, /* Text of expression to be parsed. */ + expressionS *expP) /* Where to put the results of parsing. */ +{ + char *save_in; /* Save global here. */ + symbolS *symP; - const char *bp_error_msg = _("branch prediction invalid on this opcode"); + know (textP); - /* Parse instruction into opcode and operands */ - memset (args, '\0', sizeof (args)); - n_ops = i_scan (textP, args); - if (n_ops == -1) + if (*textP == '\0') { - return; /* Error message already issued */ + /* Treat empty string as absolute 0. */ + expP->X_add_symbol = expP->X_op_symbol = NULL; + expP->X_add_number = 0; + expP->X_op = O_constant; } - - /* Do "macro substitution" (sort of) on 'ldconst' pseudo-instruction */ - if (!strcmp (args[0], "ldconst")) + else { - n_ops = parse_ldconst (args); - if (n_ops == -1) - { - return; - } - } + save_in = input_line_pointer; /* Save global. */ + input_line_pointer = textP; /* Make parser work for us. */ - /* Check for branch-prediction suffix on opcode mnemonic, strip it off */ - n = strlen (args[0]) - 1; - branch_predict = 0; - bp_bits = 0; - if (args[0][n - 1] == '.' && (args[0][n] == 't' || args[0][n] == 'f')) - { - /* We could check here to see if the target architecture - supports branch prediction, but why bother? The bit will - just be ignored by processors that don't use it. */ - branch_predict = 1; - bp_bits = (args[0][n] == 't') ? BP_TAKEN : BP_NOT_TAKEN; - args[0][n - 1] = '\0'; /* Strip suffix from opcode mnemonic */ - } + (void) expression (expP); + if ((size_t) (input_line_pointer - textP) != strlen (textP)) + /* Did not consume all of the input. */ + expP->X_op = O_illegal; - /* Look up opcode mnemonic in table and check number of operands. - Check that opcode is legal for the target architecture. If all - looks good, assemble instruction. */ - oP = (struct i960_opcode *) hash_find (op_hash, args[0]); - if (!oP || !targ_has_iclass (oP->iclass)) - { - as_bad (_("invalid opcode, \"%s\"."), args[0]); + symP = expP->X_add_symbol; + if (symP && (hash_find (reg_hash, S_GET_NAME (symP)))) + /* Register name in an expression. */ + /* FIXME: this isn't much of a check any more. */ + expP->X_op = O_illegal; + input_line_pointer = save_in; /* Restore global. */ } - else if (n_ops != oP->num_ops) - { - as_bad (_("improper number of operands. expecting %d, got %d"), - oP->num_ops, n_ops); - } - else +} + +/* emit: output instruction binary + + Output instruction binary, in target byte order, 4 bytes at a time. + Return pointer to where it was placed. */ + +static char * +emit (long instr) /* Word to be output, host byte order. */ +{ + char *toP; /* Where to output it. */ + + toP = frag_more (4); /* Allocate storage. */ + md_number_to_chars (toP, instr, 4); /* Convert to target byte order. */ + return toP; +} + +/* get_cdisp: handle displacement for a COBR or CTRL instruction. + + Parse displacement for a COBR or CTRL instruction. + + If successful, output the instruction opcode and set up for it, + depending on the arg 'var_frag', either: + o an address fixup to be done when all symbol values are known, or + o a varying length code fragment, with address fixup info. This + will be done for cobr instructions that may have to be relaxed + in to compare/branch instructions (8 bytes) if the final + address displacement is greater than 13 bits. */ + +static void +get_cdisp (char *dispP, /* Displacement as specified in source instruction. */ + char *ifmtP, /* "COBR" or "CTRL" (for use in error message). */ + long instr, /* Instruction needing the displacement. */ + int numbits, /* # bits of displacement (13 for COBR, 24 for CTRL). */ + int var_frag,/* 1 if varying length code fragment should be emitted; + 0 if an address fix should be emitted. */ + int callj) /* 1 if callj relocation should be done; else 0. */ +{ + expressionS e; /* Parsed expression. */ + fixS *fixP; /* Structure describing needed address fix. */ + char *outP; /* Where instruction binary is output to. */ + + fixP = NULL; + + parse_expr (dispP, &e); + switch (e.X_op) { - switch (oP->format) + case O_illegal: + as_bad (_("expression syntax error")); + + case O_symbol: + if (S_GET_SEGMENT (e.X_add_symbol) == now_seg + || S_GET_SEGMENT (e.X_add_symbol) == undefined_section) { - case FBRA: - case CTRL: - ctrl_fmt (args[1], oP->opcode | bp_bits, oP->num_ops); - if (oP->format == FBRA) - { - /* Now generate a 'bno' to same arg */ - ctrl_fmt (args[1], BNO | bp_bits, 1); - } - break; - case COBR: - case COJ: - cobr_fmt (args, oP->opcode | bp_bits, oP); - break; - case REG: - if (branch_predict) - { - as_warn (bp_error_msg); - } - reg_fmt (args, oP); - break; - case MEM1: - if (args[0][0] == 'c' && args[0][1] == 'a') - { - if (branch_predict) - { - as_warn (bp_error_msg); - } - mem_fmt (args, oP, 1); - break; - } - case MEM2: - case MEM4: - case MEM8: - case MEM12: - case MEM16: - if (branch_predict) + if (var_frag) { - as_warn (bp_error_msg); + 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); } - mem_fmt (args, oP, 0); - break; - case CALLJ: - if (branch_predict) + else { - as_warn (bp_error_msg); + /* 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_tcbit = 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 *) (size_t) numbits; } - /* Output opcode & set up "fixup" (relocation); flag - relocation as 'callj' type. */ - know (oP->num_ops == 1); - get_cdisp (args[1], "CTRL", oP->opcode, 24, 0, 1); - break; - default: - BAD_CASE (oP->format); - break; } - } -} /* md_assemble() */ - -/***************************************************************************** - md_number_to_chars: convert a number to target byte order + else + as_bad (_("attempt to branch into different segment")); + break; - *************************************************************************** */ -void -md_number_to_chars (buf, value, n) - char *buf; - valueT value; - int n; -{ - number_to_chars_littleendian (buf, value, n); + default: + as_bad (_("target of %s instruction must be a label"), ifmtP); + break; + } } -/***************************************************************************** - md_chars_to_number: convert from target byte order to host byte order. - - *************************************************************************** */ -static int md_chars_to_number PARAMS ((char *, int)); - static int -md_chars_to_number (val, n) - char *val; /* Value in target byte order */ - int n; /* Number of bytes in the input */ +md_chars_to_number (char * val, /* Value in target byte order. */ + int n) /* Number of bytes in the input. */ { int retval; @@ -749,618 +648,741 @@ md_chars_to_number (val, n) return retval; } -#define MAX_LITTLENUMS 6 -#define LNUM_SIZE sizeof (LITTLENUM_TYPE) - -/***************************************************************************** - md_atof: convert ascii to floating point +/* mema_to_memb: convert a MEMA-format opcode to a MEMB-format opcode. - Turn a string at input_line_pointer into a floating point constant of type - 'type', and store the appropriate bytes at *litP. The number of LITTLENUMS - emitted is returned at 'sizeP'. An error message is returned, or a pointer - to an empty message if OK. + There are 2 possible MEMA formats: + - displacement only + - displacement + abase - Note we call the i386 floating point routine, rather than complicating - things with more files or symbolic links. + They are distinguished by the setting of the MEMA_ABASE bit. */ - *************************************************************************** */ -char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +static void +mema_to_memb (char * opcodeP) /* Where to find the opcode, in target byte order. */ { - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - int prec; - char *t; - - switch (type) - { - case 'f': - case 'F': - prec = 2; - break; - - case 'd': - case 'D': - prec = 4; - break; - - case 't': - case 'T': - prec = 5; - type = 'x'; /* That's what atof_ieee() understands */ - break; - - default: - *sizeP = 0; - return _("Bad call to md_atof()"); - } - - t = atof_ieee (input_line_pointer, type, words); - if (t) - { - input_line_pointer = t; - } + long opcode; /* Opcode in host byte order. */ + long mode; /* Mode bits for MEMB instruction. */ - *sizeP = prec * LNUM_SIZE; + opcode = md_chars_to_number (opcodeP, 4); + know (!(opcode & MEMB_BIT)); - /* Output the LITTLENUMs in REVERSE order in accord with i80960 - word-order. (Dunno why atof_ieee doesn't do it in the right - order in the first place -- probably because it's a hack of - atof_m68k.) */ + mode = MEMB_BIT | D_BIT; + if (opcode & MEMA_ABASE) + mode |= A_BIT; - for (wordP = words + prec - 1; prec--;) - { - md_number_to_chars (litP, (long) (*wordP--), LNUM_SIZE); - litP += sizeof (LITTLENUM_TYPE); - } + opcode &= 0xffffc000; /* Clear MEMA offset and mode bits. */ + opcode |= mode; /* Set MEMB mode bits. */ - return 0; + md_number_to_chars (opcodeP, opcode, 4); } -/***************************************************************************** - md_number_to_imm +/* targ_has_sfr: - *************************************************************************** */ -static void md_number_to_imm PARAMS ((char *, long, int)); + Return TRUE iff the target architecture supports the specified + special-function register (sfr). */ -static void -md_number_to_imm (buf, val, n) - char *buf; - long val; - int n; +static int +targ_has_sfr (int n) /* Number (0-31) of sfr. */ { - md_number_to_chars (buf, val, n); + switch (architecture) + { + case ARCH_KA: + case ARCH_KB: + case ARCH_MC: + case ARCH_JX: + return 0; + case ARCH_HX: + return ((0 <= n) && (n <= 4)); + case ARCH_CA: + default: + return ((0 <= n) && (n <= 2)); + } } -/***************************************************************************** - md_number_to_field: +/* Look up a (suspected) register name in the register table and return the + associated register number (or -1 if not found). */ + +static int +get_regnum (char *regname) /* Suspected register name. */ +{ + int *rP; - Stick a value (an address fixup) into a bit field of - previously-generated instruction. + rP = (int *) hash_find (reg_hash, regname); + return (rP == NULL) ? -1 : *rP; +} - *************************************************************************** */ -static void md_number_to_field PARAMS ((char *, long, bit_fixS *)); +/* syntax: Issue a syntax error. */ static void -md_number_to_field (instrP, val, bfixP) - char *instrP; /* Pointer to instruction to be fixed */ - long val; /* Address fixup value */ - bit_fixS *bfixP; /* Description of bit field to be fixed up */ +syntax (void) { - int numbits; /* Length of bit field to be fixed */ - long instr; /* 32-bit instruction to be fixed-up */ - long sign; /* 0 or -1, according to sign bit of 'val' */ + as_bad (_("syntax error")); +} - /* Convert instruction back to host byte order. */ - instr = md_chars_to_number (instrP, 4); +/* parse_regop: parse a register operand. - /* Surprise! -- we stored the number of bits to be modified rather - than a pointer to a structure. */ - numbits = (int) (size_t) bfixP; - if (numbits == 1) - { - /* This is a no-op, stuck here by reloc_callj() */ - return; - } + In case of illegal operand, issue a message and return some valid + information so instruction processing can continue. */ - know ((numbits == 13) || (numbits == 24)); +static void +parse_regop (struct regop *regopP, /* Where to put description of register operand. */ + char *optext, /* Text of operand. */ + char opdesc) /* Descriptor byte: what's legal for this operand. */ +{ + int n; /* Register number. */ + expressionS e; /* Parsed expression. */ - /* Propagate sign bit of 'val' for the given number of bits. Result - should be all 0 or all 1. */ - sign = val >> ((int) numbits - 1); - if (((val < 0) && (sign != -1)) - || ((val > 0) && (sign != 0))) - { - as_bad (_("Fixup of %ld too large for field width of %d"), - val, numbits); - } - else + /* See if operand is a register. */ + n = get_regnum (optext); + if (n >= 0) { - /* Put bit field into instruction and write back in target - * byte order. - */ - val &= ~(-1 << (int) numbits); /* Clear unused sign bits */ - instr |= val; - md_number_to_chars (instrP, instr, 4); - } -} /* md_number_to_field() */ - + if (IS_RG_REG (n)) + { + /* Global or local register. */ + if (!REG_ALIGN (opdesc, n)) + as_bad (_("unaligned register")); -/***************************************************************************** - md_parse_option - Invocation line includes a switch not recognized by the base assembler. - See if it's a processor-specific option. For the 960, these are: + regopP->n = n; + regopP->mode = 0; + regopP->special = 0; + return; + } + else if (IS_FP_REG (n) && FP_OK (opdesc)) + { + /* Floating point register, and it's allowed. */ + regopP->n = n - FP0; + regopP->mode = 1; + regopP->special = 0; + return; + } + else if (IS_SF_REG (n) && SFR_OK (opdesc)) + { + /* Special-function register, and it's allowed. */ + regopP->n = n - SF0; + regopP->mode = 0; + regopP->special = 1; + if (!targ_has_sfr (regopP->n)) + as_bad (_("no such sfr in this architecture")); - -norelax: - Conditional branch instructions that require displacements - greater than 13 bits (or that have external targets) should - generate errors. The default is to replace each such - instruction with the corresponding compare (or chkbit) and - branch instructions. Note that the Intel "j" cobr directives - are ALWAYS "de-optimized" in this way when necessary, - regardless of the setting of this option. + return; + } + } + else if (LIT_OK (opdesc)) + { + /* How about a literal? */ + regopP->mode = 1; + regopP->special = 0; + if (FP_OK (opdesc)) + { + /* Floating point literal acceptable. */ + /* Skip over 0f, 0d, or 0e prefix. */ + if ((optext[0] == '0') + && (optext[1] >= 'd') + && (optext[1] <= 'f')) + optext += 2; - -b: - Add code to collect information about branches taken, for - later optimization of branch prediction bits by a separate - tool. COBR and CNTL format instructions have branch - prediction bits (in the CX architecture); if "BR" represents - an instruction in one of these classes, the following rep- - resents the code generated by the assembler: + if (!strcmp (optext, "0.0") || !strcmp (optext, "0")) + { + regopP->n = 0x10; + return; + } - call - .word 0 # pre-counter - Label: BR - call - .word 0 # post-counter + if (!strcmp (optext, "1.0") || !strcmp (optext, "1")) + { + regopP->n = 0x16; + return; + } + } + else + { + /* Fixed point literal acceptable. */ + parse_expr (optext, &e); + if (e.X_op != O_constant + || (offs (e) < 0) || (offs (e) > 31)) + { + as_bad (_("illegal literal")); + offs (e) = 0; + } + regopP->n = offs (e); + return; + } + } - A table of all such "Labels" is also generated. + /* Nothing worked. */ + syntax (); + regopP->mode = 0; /* Register r0 is always a good one. */ + regopP->n = 0; + regopP->special = 0; +} - -AKA, -AKB, -AKC, -ASA, -ASB, -AMC, -ACA: - Select the 80960 architecture. Instructions or features not - supported by the selected architecture cause fatal errors. - The default is to generate code for any instruction or feature - that is supported by SOME version of the 960 (even if this - means mixing architectures!). +/* get_ispec: parse a memory operand for an index specification + + Here, an "index specification" is taken to be anything surrounded + by square brackets and NOT followed by anything else. - ****************************************************************************/ + If it's found, detach it from the input string, remove the surrounding + square brackets, and return a pointer to it. Otherwise, return NULL. */ -const char *md_shortopts = "A:b"; -struct option md_longopts[] = +static char * +get_ispec (char *textP) /* Pointer to memory operand from source instruction, no white space. */ + { -#define OPTION_LINKRELAX (OPTION_MD_BASE) - {"linkrelax", no_argument, NULL, OPTION_LINKRELAX}, - {"link-relax", no_argument, NULL, OPTION_LINKRELAX}, -#define OPTION_NORELAX (OPTION_MD_BASE + 1) - {"norelax", no_argument, NULL, OPTION_NORELAX}, - {"no-relax", no_argument, NULL, OPTION_NORELAX}, - {NULL, no_argument, NULL, 0} -}; -size_t md_longopts_size = sizeof (md_longopts); + /* Points to start of index specification. */ + char *start; + /* Points to end of index specification. */ + char *end; -struct tabentry - { - char *flag; - int arch; - }; -static const struct tabentry arch_tab[] = -{ - {"KA", ARCH_KA}, - {"KB", ARCH_KB}, - {"SA", ARCH_KA}, /* Synonym for KA */ - {"SB", ARCH_KB}, /* Synonym for KB */ - {"KC", ARCH_MC}, /* Synonym for MC */ - {"MC", ARCH_MC}, - {"CA", ARCH_CA}, - {"JX", ARCH_JX}, - {"HX", ARCH_HX}, - {NULL, 0} -}; + /* Find opening square bracket, if any. */ + start = strchr (textP, '['); -int -md_parse_option (c, arg) - int c; - char *arg; -{ - switch (c) + if (start != NULL) { - case OPTION_LINKRELAX: - linkrelax = 1; - flag_keep_locals = 1; - break; + /* Eliminate '[', detach from rest of operand. */ + *start++ = '\0'; - case OPTION_NORELAX: - norelax = 1; - break; + end = strchr (start, ']'); - case 'b': - instrument_branches = 1; - break; + if (end == NULL) + as_bad (_("unmatched '['")); + else + { + /* Eliminate ']' and make sure it was the last thing + in the string. */ + *end = '\0'; + if (*(end + 1) != '\0') + as_bad (_("garbage after index spec ignored")); + } + } + return start; +} - case 'A': - { - const struct tabentry *tp; - char *p = arg; +/* parse_memop: parse a memory operand - for (tp = arch_tab; tp->flag != NULL; tp++) - if (!strcmp (p, tp->flag)) - break; + This routine is based on the observation that the 4 mode bits of the + MEMB format, taken individually, have fairly consistent meaning: - if (tp->flag == NULL) - { - as_bad (_("invalid architecture %s"), p); - return 0; - } - else - architecture = tp->arch; - } - break; + M3 (bit 13): 1 if displacement is present (D_BIT) + M2 (bit 12): 1 for MEMB instructions (MEMB_BIT) + M1 (bit 11): 1 if index is present (I_BIT) + M0 (bit 10): 1 if abase is present (A_BIT) - default: - return 0; - } + So we parse the memory operand and set bits in the mode as we find + things. Then at the end, if we go to MEMB format, we need only set + the MEMB bit (M2) and our mode is built for us. - return 1; -} + Unfortunately, I said "fairly consistent". The exceptions: -void -md_show_usage (stream) - FILE *stream; -{ - int i; - fprintf (stream, _("I960 options:\n")); - for (i = 0; arch_tab[i].flag; i++) - fprintf (stream, "%s-A%s", i ? " | " : "", arch_tab[i].flag); - fprintf (stream, _("\n\ - specify variant of 960 architecture\n\ --b add code to collect statistics about branches taken\n\ --link-relax preserve individual alignment directives so linker\n\ - can do relaxing (b.out format only)\n\ --no-relax don't alter compare-and-branch instructions for\n\ - long displacements\n")); -} - + DBIA + 0100 Would seem illegal, but means "abase-only". -/***************************************************************************** - md_convert_frag: - Called by base assembler after address relaxation is finished: modify - variable fragments according to how much relaxation was done. + 0101 Would seem to mean "abase-only" -- it means IP-relative. + Must be converted to 0100. - If the fragment substate is still 1, a 13-bit displacement was enough - to reach the symbol in question. Set up an address fixup, but otherwise - leave the cobr instruction alone. + 0110 Would seem to mean "index-only", but is reserved. + We turn on the D bit and provide a 0 displacement. - If the fragment substate is 2, a 13-bit displacement was not enough. - Replace the cobr with a two instructions (a compare and a branch). + The other thing to observe is that we parse from the right, peeling + things * off as we go: first any index spec, then any abase, then + the displacement. */ - *************************************************************************** */ -#ifndef BFD_ASSEMBLER -void -md_convert_frag (headers, seg, fragP) - object_headers *headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - fragS *fragP; -#else -void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS *fragP; -#endif +static void +parse_memop (memS *memP, /* Where to put the results. */ + char *argP, /* Text of the operand to be parsed. */ + int optype) /* MEM1, MEM2, MEM4, MEM8, MEM12, or MEM16. */ { - fixS *fixP; /* Structure describing needed address fix */ - - switch (fragP->fr_subtype) - { - case 1: - /* LEAVE SINGLE COBR INSTRUCTION */ - fixP = fix_new (fragP, - fragP->fr_opcode - fragP->fr_literal, - 4, - fragP->fr_symbol, - fragP->fr_offset, - 1, - NO_RELOC); - - fixP->fx_bit_fixP = (bit_fixS *) 13; /* size of bit field */ - break; - case 2: - /* REPLACE COBR WITH COMPARE/BRANCH INSTRUCTIONS */ - relax_cobr (fragP); - break; - default: - BAD_CASE (fragP->fr_subtype); - break; - } -} - -/***************************************************************************** - md_estimate_size_before_relax: How much does it look like *fragP will grow? + char *indexP; /* Pointer to index specification with "[]" removed. */ + char *p; /* Temp char pointer. */ + char iprel_flag; /* True if this is an IP-relative operand. */ + int regnum; /* Register number. */ + /* Scale factor: 1,2,4,8, or 16. Later converted to internal format + (0,1,2,3,4 respectively). */ + int scale; + int mode; /* MEMB mode bits. */ + int *intP; /* Pointer to register number. */ - Called by base assembler just before address relaxation. - Return the amount by which the fragment will grow. + /* The following table contains the default scale factors for each + type of memory instruction. It is accessed using (optype-MEM1) + as an index -- thus it assumes the 'optype' constants are + assigned consecutive values, in the order they appear in this + table. */ + static const int def_scale[] = + { + 1, /* MEM1 */ + 2, /* MEM2 */ + 4, /* MEM4 */ + 8, /* MEM8 */ + -1, /* MEM12 -- no valid default */ + 16 /* MEM16 */ + }; - Any symbol that is now undefined will not become defined; cobr's - based on undefined symbols will have to be replaced with a compare - instruction and a branch instruction, and the code fragment will grow - by 4 bytes. + iprel_flag = mode = 0; - *************************************************************************** */ -int -md_estimate_size_before_relax (fragP, segment_type) - register fragS *fragP; - register segT segment_type; -{ - /* If symbol is undefined in this segment, go to "relaxed" state - (compare and branch instructions instead of cobr) right now. */ - if (S_GET_SEGMENT (fragP->fr_symbol) != segment_type) + /* Any index present? */ + indexP = get_ispec (argP); + if (indexP) { - relax_cobr (fragP); - return 4; - } - - return md_relax_table[fragP->fr_subtype].rlx_length; -} /* md_estimate_size_before_relax() */ + p = strchr (indexP, '*'); + if (p == NULL) + { + /* No explicit scale -- use default for this instruction + type and assembler mode. */ + if (flag_mri) + scale = 1; + else + /* GNU960 compatibility */ + scale = def_scale[optype - MEM1]; + } + else + { + *p++ = '\0'; /* Eliminate '*' */ -#if defined(OBJ_AOUT) | defined(OBJ_BOUT) + /* Now indexP->a '\0'-terminated register name, + and p->a scale factor. */ -/***************************************************************************** - md_ri_to_chars: - This routine exists in order to overcome machine byte-order problems - when dealing with bit-field entries in the relocation_info struct. + if (!strcmp (p, "16")) + scale = 16; + else if (strchr ("1248", *p) && (p[1] == '\0')) + scale = *p - '0'; + else + scale = -1; + } - But relocation info will be used on the host machine only (only - executable code is actually downloaded to the i80960). Therefore, - we leave it in host byte order. + regnum = get_regnum (indexP); /* Get index reg. # */ + if (!IS_RG_REG (regnum)) + { + as_bad (_("invalid index register")); + return; + } - *************************************************************************** */ -static void md_ri_to_chars PARAMS ((char *, struct relocation_info *)); + /* Convert scale to its binary encoding. */ + switch (scale) + { + case 1: + scale = 0 << 7; + break; + case 2: + scale = 1 << 7; + break; + case 4: + scale = 2 << 7; + break; + case 8: + scale = 3 << 7; + break; + case 16: + scale = 4 << 7; + break; + default: + as_bad (_("invalid scale factor")); + return; + }; -static void -md_ri_to_chars (where, ri) - char *where; - struct relocation_info *ri; -{ - host_number_to_chars (where, ri->r_address, 4); - host_number_to_chars (where + 4, ri->r_index, 3); -#if WORDS_BIGENDIAN - where[7] = (ri->r_pcrel << 7 - | ri->r_length << 5 - | ri->r_extern << 4 - | ri->r_bsr << 3 - | ri->r_disp << 2 - | ri->r_callj << 1 - | ri->nuthin << 0); -#else - where[7] = (ri->r_pcrel << 0 - | ri->r_length << 1 - | ri->r_extern << 3 - | ri->r_bsr << 4 - | ri->r_disp << 5 - | ri->r_callj << 6 - | ri->nuthin << 7); -#endif -} + memP->opcode |= scale | regnum; /* Set index bits in opcode. */ + mode |= I_BIT; /* Found a valid index spec. */ + } -#endif /* defined(OBJ_AOUT) | defined(OBJ_BOUT) */ + /* Any abase (Register Indirect) specification present? */ + if ((p = strrchr (argP, '(')) != NULL) + { + /* "(" is there -- does it start a legal abase spec? If not, it + could be part of a displacement expression. */ + intP = (int *) hash_find (areg_hash, p); + if (intP != NULL) + { + /* Got an abase here. */ + regnum = *intP; + *p = '\0'; /* Discard register spec. */ + if (regnum == IPREL) + /* We have to specialcase ip-rel mode. */ + iprel_flag = 1; + else + { + memP->opcode |= regnum << 14; + mode |= A_BIT; + } + } + } - -/* FOLLOWING ARE THE LOCAL ROUTINES, IN ALPHABETICAL ORDER */ + /* Any expression present? */ + memP->e = argP; + if (*argP != '\0') + mode |= D_BIT; -/***************************************************************************** - brcnt_emit: Emit code to increment inline branch counter. + /* Special-case ip-relative addressing. */ + if (iprel_flag) + { + if (mode & I_BIT) + syntax (); + else + { + memP->opcode |= 5 << 10; /* IP-relative mode. */ + memP->disp = 32; + } + return; + } - See the comments above the declaration of 'br_cnt' for details on - branch-prediction instrumentation. - *************************************************************************** */ -static void -brcnt_emit () -{ - ctrl_fmt (BR_CNT_FUNC, CALL, 1); /* Emit call to "increment" routine */ - emit (0); /* Emit inline counter to be incremented */ -} + /* Handle all other modes. */ + switch (mode) + { + case D_BIT | A_BIT: + /* Go with MEMA instruction format for now (grow to MEMB later + if 12 bits is not enough for the displacement). MEMA format + has a single mode bit: set it to indicate that abase is + present. */ + memP->opcode |= MEMA_ABASE; + memP->disp = 12; + break; -/***************************************************************************** - brlab_next: generate the next branch local label + case D_BIT: + /* Go with MEMA instruction format for now (grow to MEMB later + if 12 bits is not enough for the displacement). */ + memP->disp = 12; + break; - See the comments above the declaration of 'br_cnt' for details on - branch-prediction instrumentation. - *************************************************************************** */ -static char * -brlab_next () -{ - static char buf[20]; + case A_BIT: + /* For some reason, the bit string for this mode is not + consistent: it should be 0 (exclusive of the MEMB bit), so we + set it "by hand" here. */ + memP->opcode |= MEMB_BIT; + break; - sprintf (buf, "%s%d", BR_LABEL_BASE, br_cnt++); - return buf; -} + case A_BIT | I_BIT: + /* set MEMB bit in mode, and OR in mode bits. */ + memP->opcode |= mode | MEMB_BIT; + break; -/***************************************************************************** - brtab_emit: generate the fetch-prediction branch table. + case I_BIT: + /* Treat missing displacement as displacement of 0. */ + mode |= D_BIT; + /* Fall into next case. */ + case D_BIT | A_BIT | I_BIT: + case D_BIT | I_BIT: + /* Set MEMB bit in mode, and OR in mode bits. */ + memP->opcode |= mode | MEMB_BIT; + memP->disp = 32; + break; - See the comments above the declaration of 'br_cnt' for details on - branch-prediction instrumentation. + default: + syntax (); + break; + } +} - The code emitted here would be functionally equivalent to the following - example assembler source. +/* Generate a MEMA- or MEMB-format instruction. */ - .data - .align 2 - BR_TAB_NAME: - .word 0 # link to next table - .word 3 # length of table - .word LBRANCH0 # 1st entry in table proper - .word LBRANCH1 - .word LBRANCH2 - **************************************************************************** */ -void -brtab_emit () +static void +mem_fmt (char *args[], /* args[0]->opcode mnemonic, args[1-3]->operands. */ + struct i960_opcode *oP,/* Pointer to description of instruction. */ + int callx) /* Is this a callx opcode. */ { - int i; - char buf[20]; - char *p; /* Where the binary was output to */ - /* Pointer to description of deferred address fixup. */ + int i; /* Loop counter. */ + struct regop regop; /* Description of register operand. */ + char opdesc; /* Operand descriptor byte. */ + memS instr; /* Description of binary to be output. */ + char *outP; /* Where the binary was output to. */ + expressionS expr; /* Parsed expression. */ + /* ->description of deferred address fixup. */ fixS *fixP; - if (!instrument_branches) - { - return; - } +#ifdef OBJ_COFF + /* COFF support isn't in place yet for callx relaxing. */ + callx = 0; +#endif - subseg_set (data_section, 0); /* .data */ - frag_align (2, 0, 0); /* .align 2 */ - record_alignment (now_seg, 2); - colon (BR_TAB_NAME); /* BR_TAB_NAME: */ - emit (0); /* .word 0 #link to next table */ - emit (br_cnt); /* .word n #length of table */ + memset (&instr, '\0', sizeof (memS)); + instr.opcode = oP->opcode; - for (i = 0; i < br_cnt; i++) + /* Process operands. */ + for (i = 1; i <= oP->num_ops; i++) { - sprintf (buf, "%s%d", BR_LABEL_BASE, i); - p = emit (0); - fixP = fix_new (frag_now, - p - frag_now->fr_literal, - 4, - symbol_find (buf), - 0, - 0, - NO_RELOC); + opdesc = oP->operand[i - 1]; + + if (MEMOP (opdesc)) + parse_memop (&instr, args[i], oP->format); + else + { + parse_regop (®op, args[i], opdesc); + instr.opcode |= regop.n << 19; + } } -} -/***************************************************************************** - cobr_fmt: generate a COBR-format instruction + /* Parse the displacement; this must be done before emitting the + opcode, in case it is an expression using `.'. */ + parse_expr (instr.e, &expr); - *************************************************************************** */ -static void -cobr_fmt (arg, opcode, oP) - /* arg[0]->opcode mnemonic, arg[1-3]->operands (ascii) */ - char *arg[]; - /* Opcode, with branch-prediction bits already set if necessary. */ - long opcode; - /* Pointer to description of instruction. */ - struct i960_opcode *oP; -{ - long instr; /* 32-bit instruction */ - struct regop regop; /* Description of register operand */ - int n; /* Number of operands */ - int var_frag; /* 1 if varying length code fragment should - * be emitted; 0 if an address fix - * should be emitted. - */ + /* Output opcode. */ + outP = emit (instr.opcode); - instr = opcode; - n = oP->num_ops; + if (instr.disp == 0) + return; - if (n >= 1) - { - /* First operand (if any) of a COBR is always a register - operand. Parse it. */ - parse_regop (®op, arg[1], oP->operand[0]); - instr |= (regop.n << 19) | (regop.mode << 13); - } - if (n >= 2) + /* Process the displacement. */ + switch (expr.X_op) { - /* Second operand (if any) of a COBR is always a register - operand. Parse it. */ - parse_regop (®op, arg[2], oP->operand[1]); - instr |= (regop.n << 14) | regop.special; - } + case O_illegal: + as_bad (_("expression syntax error")); + break; - if (n < 3) - { - emit (instr); + case O_constant: + if (instr.disp == 32) + (void) emit (offs (expr)); /* Output displacement. */ + else + { + /* 12-bit displacement. */ + if (offs (expr) & ~0xfff) + { + /* Won't fit in 12 bits: convert already-output + 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. */ + instr.opcode |= offs (expr); + md_number_to_chars (outP, instr.opcode, 4); + } + } + break; + default: + if (instr.disp == 12) + /* Displacement is dependent on a symbol, whose value + may change at link time. We HAVE to reserve 32 bits. + Convert already-output opcode to MEMB format. */ + mema_to_memb (outP); + + /* Output 0 displacement and set up address fixup for when + this symbol's value becomes known. */ + outP = emit ((long) 0); + fixP = fix_new_exp (frag_now, + outP - frag_now->fr_literal, + 4, & expr, 0, NO_RELOC); + /* Steve's linker relaxing hack. Mark this 32-bit relocation as + being in the instruction stream, specifically as part of a callx + instruction. */ + fixP->fx_bsr = callx; + break; } - else +} + +/* targ_has_iclass: + + Return TRUE iff the target architecture supports the indicated + class of instructions. */ + +static int +targ_has_iclass (int ic) /* Instruction class; one of: + I_BASE, I_CX, I_DEC, I_KX, I_FP, I_MIL, I_CASIM, I_CX2, I_HX, I_HX2. */ +{ + iclasses_seen |= ic; + + switch (architecture) { - if (instrument_branches) + case ARCH_KA: + return ic & (I_BASE | I_KX); + case ARCH_KB: + return ic & (I_BASE | I_KX | I_FP | I_DEC); + case ARCH_MC: + return ic & (I_BASE | I_KX | I_FP | I_DEC | I_MIL); + case ARCH_CA: + return ic & (I_BASE | I_CX | I_CX2 | I_CASIM); + case ARCH_JX: + return ic & (I_BASE | I_CX2 | I_JX); + case ARCH_HX: + return ic & (I_BASE | I_CX2 | I_JX | I_HX); + default: + if ((iclasses_seen & (I_KX | I_FP | I_DEC | I_MIL)) + && (iclasses_seen & (I_CX | I_CX2))) { - brcnt_emit (); - colon (brlab_next ()); + as_warn (_("architecture of opcode conflicts with that of earlier instruction(s)")); + iclasses_seen &= ~ic; } + return 1; + } +} - /* A third operand to a COBR is always a displacement. Parse - it; if it's relaxable (a cobr "j" directive, or any cobr - other than bbs/bbc when the "-norelax" option is not in use) - set up a variable code fragment; otherwise set up an address - fix. */ - var_frag = !norelax || (oP->format == COJ); /* TRUE or FALSE */ - get_cdisp (arg[3], "COBR", instr, 13, var_frag, 0); +/* shift_ok: + Determine if a "shlo" instruction can be used to implement a "ldconst". + This means that some number X < 32 can be shifted left to produce the + constant of interest. - if (instrument_branches) + Return the shift count, or 0 if we can't do it. + Caller calculates X by shifting original constant right 'shift' places. */ + +static int +shift_ok (int n) /* The constant of interest. */ +{ + int shift; /* The shift count. */ + + if (n <= 0) + /* Can't do it for negative numbers. */ + return 0; + + /* Shift 'n' right until a 1 is about to be lost. */ + for (shift = 0; (n & 1) == 0; shift++) + n >>= 1; + + if (n >= 32) + return 0; + + return shift; +} + +/* parse_ldcont: + Parse and replace a 'ldconst' pseudo-instruction with an appropriate + i80960 instruction. + + Assumes the input consists of: + arg[0] opcode mnemonic ('ldconst') + arg[1] first operand (constant) + arg[2] name of register to be loaded + + Replaces opcode and/or operands as appropriate. + + Returns the new number of arguments, or -1 on failure. */ + +static int +parse_ldconst (char *arg[]) /* See above. */ +{ + int n; /* Constant to be loaded. */ + int shift; /* Shift count for "shlo" instruction. */ + static char buf[5]; /* Literal for first operand. */ + static char buf2[5]; /* Literal for second operand. */ + expressionS e; /* Parsed expression. */ + + arg[3] = NULL; /* So we can tell at the end if it got used or not. */ + + parse_expr (arg[1], &e); + switch (e.X_op) + { + default: + /* We're dependent on one or more symbols -- use "lda". */ + arg[0] = "lda"; + break; + + case O_constant: + /* Try the following mappings: + ldconst 0, -> mov 0, + ldconst 31, -> mov 31, + ldconst 32, -> addo 1,31, + ldconst 62, -> addo 31,31, + ldconst 64, -> shlo 8,3, + ldconst -1, -> subo 1,0, + ldconst -31, -> subo 31,0, + + Anything else becomes: + lda xxx,. */ + n = offs (e); + if ((0 <= n) && (n <= 31)) + arg[0] = "mov"; + else if ((-31 <= n) && (n <= -1)) { - brcnt_emit (); + arg[0] = "subo"; + arg[3] = arg[2]; + sprintf (buf, "%d", -n); + arg[1] = buf; + arg[2] = "0"; + } + else if ((32 <= n) && (n <= 62)) + { + arg[0] = "addo"; + arg[3] = arg[2]; + arg[1] = "31"; + sprintf (buf, "%d", n - 31); + arg[2] = buf; } + else if ((shift = shift_ok (n)) != 0) + { + arg[0] = "shlo"; + arg[3] = arg[2]; + sprintf (buf, "%d", shift); + arg[1] = buf; + sprintf (buf2, "%d", n >> shift); + arg[2] = buf2; + } + else + arg[0] = "lda"; + break; + + case O_illegal: + as_bad (_("invalid constant")); + return -1; + break; } -} /* cobr_fmt() */ + return (arg[3] == 0) ? 2 : 3; +} -/***************************************************************************** - ctrl_fmt: generate a CTRL-format instruction +/* reg_fmt: generate a REG-format instruction. */ - *************************************************************************** */ static void -ctrl_fmt (targP, opcode, num_ops) - char *targP; /* Pointer to text of lone operand (if any) */ - long opcode; /* Template of instruction */ - int num_ops; /* Number of operands */ +reg_fmt (char *args[], /* args[0]->opcode mnemonic, args[1-3]->operands. */ + struct i960_opcode *oP)/* Pointer to description of instruction. */ { - int instrument; /* TRUE iff we should add instrumentation to track - * how often the branch is taken - */ + long instr; /* Binary to be output. */ + struct regop regop; /* Description of register operand. */ + int n_ops; /* Number of operands. */ - if (num_ops == 0) - { - emit (opcode); /* Output opcode */ - } - else - { + instr = oP->opcode; + n_ops = oP->num_ops; - instrument = instrument_branches && (opcode != CALL) - && (opcode != B) && (opcode != RET) && (opcode != BAL); + if (n_ops >= 1) + { + parse_regop (®op, args[1], oP->operand[0]); - if (instrument) + if ((n_ops == 1) && !(instr & M3)) { - brcnt_emit (); - colon (brlab_next ()); + /* 1-operand instruction in which the dst field should + be used (instead of src1). */ + regop.n <<= 19; + if (regop.special) + regop.mode = regop.special; + regop.mode <<= 13; + regop.special = 0; } - - /* The operand MUST be an ip-relative displacement. Parse it - * and set up address fix for the instruction we just output. - */ - get_cdisp (targP, "CTRL", opcode, 24, 0, 0); - - if (instrument) + else { - brcnt_emit (); + /* regop.n goes in bit 0, needs no shifting. */ + regop.mode <<= 11; + regop.special <<= 5; } + instr |= regop.n | regop.mode | regop.special; } -} - -/***************************************************************************** - emit: output instruction binary - - Output instruction binary, in target byte order, 4 bytes at a time. - Return pointer to where it was placed. - - *************************************************************************** */ -static char * -emit (instr) - long instr; /* Word to be output, host byte order */ -{ - char *toP; /* Where to output it */ + if (n_ops >= 2) + { + parse_regop (®op, args[2], oP->operand[1]); - toP = frag_more (4); /* Allocate storage */ - md_number_to_chars (toP, instr, 4); /* Convert to target byte order */ - return toP; + if ((n_ops == 2) && !(instr & M3)) + { + /* 2-operand instruction in which the dst field should + be used instead of src2). */ + regop.n <<= 19; + if (regop.special) + regop.mode = regop.special; + regop.mode <<= 13; + regop.special = 0; + } + else + { + regop.n <<= 14; + regop.mode <<= 12; + regop.special <<= 6; + } + instr |= regop.n | regop.mode | regop.special; + } + if (n_ops == 3) + { + parse_regop (®op, args[3], oP->operand[2]); + if (regop.special) + regop.mode = regop.special; + instr |= (regop.n <<= 19) | (regop.mode <<= 13); + } + emit (instr); } -/***************************************************************************** - get_args: break individual arguments out of comma-separated list +/* get_args: break individual arguments out of comma-separated list Input assumptions: - all comments and labels have been removed @@ -1373,1050 +1395,576 @@ emit (instr) - contain no whitespace Return value: - Number of operands (0,1,2, or 3) or -1 on error. + Number of operands (0,1,2, or 3) or -1 on error. */ - *************************************************************************** */ static int -get_args (p, args) - /* Pointer to comma-separated operands; MUCKED BY US */ - register char *p; - /* Output arg: pointers to operands placed in args[1-3]. MUST - ACCOMMODATE 4 ENTRIES (args[0-3]). */ - char *args[]; +get_args (char *p, /* Pointer to comma-separated operands; Mucked by us. */ + char *args[]) /* Output arg: pointers to operands placed in args[1-3]. + Must accommodate 4 entries (args[0-3]). */ + { - register int n; /* Number of operands */ - register char *to; + int n; /* Number of operands. */ + char *to; - /* Skip lead white space */ + /* Skip lead white space. */ while (*p == ' ') - { - p++; - } + p++; if (*p == '\0') - { - return 0; - } + return 0; n = 1; args[1] = p; /* Squeze blanks out by moving non-blanks toward start of string. - * Isolate operands, whenever comma is found. - */ + Isolate operands, whenever comma is found. */ to = p; while (*p != '\0') { - if (*p == ' ' && (! ISALNUM (p[1]) || ! ISALNUM (p[-1]))) - { - p++; - - } + p++; else if (*p == ',') { - - /* Start of operand */ + /* Start of operand. */ if (n == 3) { as_bad (_("too many operands")); return -1; } - *to++ = '\0'; /* Terminate argument */ - args[++n] = to; /* Start next argument */ + *to++ = '\0'; /* Terminate argument. */ + args[++n] = to; /* Start next argument. */ p++; - } else - { - *to++ = *p++; - } + *to++ = *p++; } *to = '\0'; return n; } -/***************************************************************************** - get_cdisp: handle displacement for a COBR or CTRL instruction. +/* i_scan: perform lexical scan of ascii assembler instruction. - Parse displacement for a COBR or CTRL instruction. + Input assumptions: + - input string is an i80960 instruction (not a pseudo-op) + - all comments and labels have been removed + - all strings of whitespace have been collapsed to a single blank. - If successful, output the instruction opcode and set up for it, - depending on the arg 'var_frag', either: - o an address fixup to be done when all symbol values are known, or - o a varying length code fragment, with address fixup info. This - will be done for cobr instructions that may have to be relaxed - in to compare/branch instructions (8 bytes) if the final - address displacement is greater than 13 bits. - - ****************************************************************************/ -static void -get_cdisp (dispP, ifmtP, instr, numbits, var_frag, callj) - /* displacement as specified in source instruction */ - char *dispP; - /* "COBR" or "CTRL" (for use in error message) */ - char *ifmtP; - /* Instruction needing the displacement */ - long instr; - /* # bits of displacement (13 for COBR, 24 for CTRL) */ - int numbits; - /* 1 if varying length code fragment should be emitted; - * 0 if an address fix should be emitted. - */ - int var_frag; - /* 1 if callj relocation should be done; else 0 */ - int callj; -{ - expressionS e; /* Parsed expression */ - fixS *fixP; /* Structure describing needed address fix */ - char *outP; /* Where instruction binary is output to */ - - fixP = NULL; - - parse_expr (dispP, &e); - switch (e.X_op) - { - case O_illegal: - as_bad (_("expression syntax error")); - - case O_symbol: - if (S_GET_SEGMENT (e.X_add_symbol) == now_seg - || 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); - } - 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_tcbit = 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 *) (size_t) numbits; - } - } - else - as_bad (_("attempt to branch into different segment")); - break; - - default: - as_bad (_("target of %s instruction must be a label"), ifmtP); - break; - } -} - -/***************************************************************************** - get_ispec: parse a memory operand for an index specification - - Here, an "index specification" is taken to be anything surrounded - by square brackets and NOT followed by anything else. - - If it's found, detach it from the input string, remove the surrounding - square brackets, and return a pointer to it. Otherwise, return NULL. - - *************************************************************************** */ -static char * -get_ispec (textP) - /* Pointer to memory operand from source instruction, no white space. */ - char *textP; -{ - /* Points to start of index specification. */ - char *start; - /* Points to end of index specification. */ - char *end; - - /* Find opening square bracket, if any. */ - start = strchr (textP, '['); - - if (start != NULL) - { - - /* Eliminate '[', detach from rest of operand */ - *start++ = '\0'; - - end = strchr (start, ']'); - - if (end == NULL) - { - as_bad (_("unmatched '['")); - - } - else - { - /* Eliminate ']' and make sure it was the last thing - * in the string. - */ - *end = '\0'; - if (*(end + 1) != '\0') - { - as_bad (_("garbage after index spec ignored")); - } - } - } - return start; -} - -/***************************************************************************** - get_regnum: - - Look up a (suspected) register name in the register table and return the - associated register number (or -1 if not found). - - *************************************************************************** */ -static int -get_regnum (regname) - char *regname; /* Suspected register name */ -{ - int *rP; - - rP = (int *) hash_find (reg_hash, regname); - return (rP == NULL) ? -1 : *rP; -} - -/***************************************************************************** - i_scan: perform lexical scan of ascii assembler instruction. - - Input assumptions: - - input string is an i80960 instruction (not a pseudo-op) - - all comments and labels have been removed - - all strings of whitespace have been collapsed to a single blank. - - Output: - args[0] points to opcode, other entries point to operands. All strings: - - are NULL-terminated - - contain no whitespace - - have character constants ('x') replaced with a decimal number + Output: + args[0] points to opcode, other entries point to operands. All strings: + - are NULL-terminated + - contain no whitespace + - have character constants ('x') replaced with a decimal number Return value: - Number of operands (0,1,2, or 3) or -1 on error. + Number of operands (0,1,2, or 3) or -1 on error. */ - *************************************************************************** */ static int -i_scan (iP, args) - /* Pointer to ascii instruction; MUCKED BY US. */ - register char *iP; - /* Output arg: pointers to opcode and operands placed here. MUST - ACCOMMODATE 4 ENTRIES. */ - char *args[]; +i_scan (char *iP, /* Pointer to ascii instruction; Mucked by us. */ + char *args[]) /* Output arg: pointers to opcode and operands placed here. + Must accommodate 4 entries. */ { - - /* Isolate opcode */ + /* Isolate opcode. */ if (*(iP) == ' ') - { - iP++; - } /* Skip lead space, if any */ + iP++; + args[0] = iP; for (; *iP != ' '; iP++) { if (*iP == '\0') { - /* There are no operands */ + /* There are no operands. */ if (args[0] == iP) { - /* We never moved: there was no opcode either! */ + /* We never moved: there was no opcode either! */ as_bad (_("missing opcode")); return -1; } return 0; } } - *iP++ = '\0'; /* Terminate opcode */ + *iP++ = '\0'; return (get_args (iP, args)); -} /* i_scan() */ - -/***************************************************************************** - mem_fmt: generate a MEMA- or MEMB-format instruction +} - *************************************************************************** */ static void -mem_fmt (args, oP, callx) - char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */ - struct i960_opcode *oP; /* Pointer to description of instruction */ - int callx; /* Is this a callx opcode */ -{ - int i; /* Loop counter */ - struct regop regop; /* Description of register operand */ - char opdesc; /* Operand descriptor byte */ - memS instr; /* Description of binary to be output */ - char *outP; /* Where the binary was output to */ - expressionS expr; /* Parsed expression */ - /* ->description of deferred address fixup */ - fixS *fixP; +brcnt_emit (void) +{ + /* Emit call to "increment" routine. */ + ctrl_fmt (BR_CNT_FUNC, CALL, 1); + /* Emit inline counter to be incremented. */ + emit (0); +} -#ifdef OBJ_COFF - /* COFF support isn't in place yet for callx relaxing. */ - callx = 0; -#endif +static char * +brlab_next (void) +{ + static char buf[20]; - memset (&instr, '\0', sizeof (memS)); - instr.opcode = oP->opcode; + sprintf (buf, "%s%d", BR_LABEL_BASE, br_cnt++); + return buf; +} - /* Process operands. */ - for (i = 1; i <= oP->num_ops; i++) +static void +ctrl_fmt (char *targP, /* Pointer to text of lone operand (if any). */ + long opcode, /* Template of instruction. */ + int num_ops) /* Number of operands. */ +{ + int instrument; /* TRUE iff we should add instrumentation to track + how often the branch is taken. */ + + if (num_ops == 0) + emit (opcode); /* Output opcode. */ + else { - opdesc = oP->operand[i - 1]; + instrument = instrument_branches && (opcode != CALL) + && (opcode != B) && (opcode != RET) && (opcode != BAL); - if (MEMOP (opdesc)) - { - parse_memop (&instr, args[i], oP->format); - } - else + if (instrument) { - parse_regop (®op, args[i], opdesc); - instr.opcode |= regop.n << 19; + brcnt_emit (); + colon (brlab_next ()); } + + /* The operand MUST be an ip-relative displacement. Parse it + and set up address fix for the instruction we just output. */ + get_cdisp (targP, "CTRL", opcode, 24, 0, 0); + + if (instrument) + brcnt_emit (); } +} - /* Parse the displacement; this must be done before emitting the - opcode, in case it is an expression using `.'. */ - parse_expr (instr.e, &expr); +static void +cobr_fmt (/* arg[0]->opcode mnemonic, arg[1-3]->operands (ascii) */ + char *arg[], + /* Opcode, with branch-prediction bits already set if necessary. */ + long opcode, + /* Pointer to description of instruction. */ + struct i960_opcode *oP) +{ + long instr; /* 32-bit instruction. */ + struct regop regop; /* Description of register operand. */ + int n; /* Number of operands. */ + int var_frag; /* 1 if varying length code fragment should + be emitted; 0 if an address fix + should be emitted. */ - /* Output opcode */ - outP = emit (instr.opcode); + instr = opcode; + n = oP->num_ops; - if (instr.disp == 0) + if (n >= 1) { - return; + /* First operand (if any) of a COBR is always a register + operand. Parse it. */ + parse_regop (®op, arg[1], oP->operand[0]); + instr |= (regop.n << 19) | (regop.mode << 13); } - /* Process the displacement */ - switch (expr.X_op) + if (n >= 2) { - case O_illegal: - as_bad (_("expression syntax error")); - break; + /* Second operand (if any) of a COBR is always a register + operand. Parse it. */ + parse_regop (®op, arg[2], oP->operand[1]); + instr |= (regop.n << 14) | regop.special; + } - case O_constant: - if (instr.disp == 32) - { - (void) emit (offs (expr)); /* Output displacement */ - } - else + if (n < 3) + emit (instr); + else + { + if (instrument_branches) { - /* 12-bit displacement */ - if (offs (expr) & ~0xfff) - { - /* Won't fit in 12 bits: convert already-output - * 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 - */ - instr.opcode |= offs (expr); - md_number_to_chars (outP, instr.opcode, 4); - } + brcnt_emit (); + colon (brlab_next ()); } - break; - default: - if (instr.disp == 12) - { - /* Displacement is dependent on a symbol, whose value - * may change at link time. We HAVE to reserve 32 bits. - * Convert already-output opcode to MEMB format. - */ - mema_to_memb (outP); - } + /* A third operand to a COBR is always a displacement. Parse + it; if it's relaxable (a cobr "j" directive, or any cobr + other than bbs/bbc when the "-norelax" option is not in use) + set up a variable code fragment; otherwise set up an address + fix. */ + var_frag = !norelax || (oP->format == COJ); /* TRUE or FALSE */ + get_cdisp (arg[3], "COBR", instr, 13, var_frag, 0); - /* Output 0 displacement and set up address fixup for when - * this symbol's value becomes known. - */ - outP = emit ((long) 0); - fixP = fix_new_exp (frag_now, - outP - frag_now->fr_literal, - 4, - &expr, - 0, - NO_RELOC); - /* Steve's linker relaxing hack. Mark this 32-bit relocation as - being in the instruction stream, specifically as part of a callx - instruction. */ - fixP->fx_bsr = callx; - break; + if (instrument_branches) + brcnt_emit (); } -} /* memfmt() */ +} -/***************************************************************************** - mema_to_memb: convert a MEMA-format opcode to a MEMB-format opcode. +/* Assumptions about the passed-in text: + - all comments, labels removed + - text is an instruction + - all white space compressed to single blanks + - all character constants have been replaced with decimal. */ - There are 2 possible MEMA formats: - - displacement only - - displacement + abase +void +md_assemble (char *textP) +{ + /* Parsed instruction text, containing NO whitespace: arg[0]->opcode + mnemonic arg[1-3]->operands, with char constants replaced by + decimal numbers. */ + char *args[4]; + /* Number of instruction operands. */ + int n_ops; + /* Pointer to instruction description. */ + struct i960_opcode *oP; + /* TRUE iff opcode mnemonic included branch-prediction suffix (".f" + or ".t"). */ + int branch_predict; + /* Setting of branch-prediction bit(s) to be OR'd into instruction + opcode of CTRL/COBR format instructions. */ + long bp_bits; + /* Offset of last character in opcode mnemonic. */ + int n; + const char *bp_error_msg = _("branch prediction invalid on this opcode"); - They are distinguished by the setting of the MEMA_ABASE bit. + /* Parse instruction into opcode and operands. */ + memset (args, '\0', sizeof (args)); - *************************************************************************** */ -static void -mema_to_memb (opcodeP) - char *opcodeP; /* Where to find the opcode, in target byte order */ -{ - long opcode; /* Opcode in host byte order */ - long mode; /* Mode bits for MEMB instruction */ + n_ops = i_scan (textP, args); - opcode = md_chars_to_number (opcodeP, 4); - know (!(opcode & MEMB_BIT)); + if (n_ops == -1) + return; /* Error message already issued. */ - mode = MEMB_BIT | D_BIT; - if (opcode & MEMA_ABASE) + /* Do "macro substitution" (sort of) on 'ldconst' pseudo-instruction. */ + if (!strcmp (args[0], "ldconst")) { - mode |= A_BIT; + n_ops = parse_ldconst (args); + if (n_ops == -1) + return; } - opcode &= 0xffffc000; /* Clear MEMA offset and mode bits */ - opcode |= mode; /* Set MEMB mode bits */ - - md_number_to_chars (opcodeP, opcode, 4); -} /* mema_to_memb() */ - -/***************************************************************************** - parse_expr: parse an expression - - Use base assembler's expression parser to parse an expression. - It, unfortunately, runs off a global which we have to save/restore - in order to make it work for us. - - An empty expression string is treated as an absolute 0. - - Sets O_illegal regardless of expression evaluation if entire input - string is not consumed in the evaluation -- tolerate no dangling junk! - - *************************************************************************** */ -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 */ - symbolS *symP; - - know (textP); - - if (*textP == '\0') - { - /* Treat empty string as absolute 0 */ - expP->X_add_symbol = expP->X_op_symbol = NULL; - expP->X_add_number = 0; - expP->X_op = O_constant; - } - else - { - save_in = input_line_pointer; /* Save global */ - input_line_pointer = textP; /* Make parser work for us */ - - (void) expression (expP); - if ((size_t) (input_line_pointer - textP) != strlen (textP)) - { - /* Did not consume all of the input */ - 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 */ - /* FIXME: this isn't much of a check any more. */ - expP->X_op = O_illegal; - } - - input_line_pointer = save_in; /* Restore global */ - } -} - -/***************************************************************************** - parse_ldcont: - Parse and replace a 'ldconst' pseudo-instruction with an appropriate - i80960 instruction. - - Assumes the input consists of: - arg[0] opcode mnemonic ('ldconst') - arg[1] first operand (constant) - arg[2] name of register to be loaded - - Replaces opcode and/or operands as appropriate. - - Returns the new number of arguments, or -1 on failure. - - *************************************************************************** */ -static int -parse_ldconst (arg) - char *arg[]; /* See above */ -{ - int n; /* Constant to be loaded */ - int shift; /* Shift count for "shlo" instruction */ - static char buf[5]; /* Literal for first operand */ - static char buf2[5]; /* Literal for second operand */ - expressionS e; /* Parsed expression */ - - arg[3] = NULL; /* So we can tell at the end if it got used or not */ + /* Check for branch-prediction suffix on opcode mnemonic, strip it off. */ + n = strlen (args[0]) - 1; + branch_predict = 0; + bp_bits = 0; - parse_expr (arg[1], &e); - switch (e.X_op) + if (args[0][n - 1] == '.' && (args[0][n] == 't' || args[0][n] == 'f')) { - default: - /* We're dependent on one or more symbols -- use "lda" */ - arg[0] = "lda"; - break; - - case O_constant: - /* Try the following mappings: - * ldconst 0, ->mov 0, - * ldconst 31, ->mov 31, - * ldconst 32, ->addo 1,31, - * ldconst 62, ->addo 31,31, - * ldconst 64, ->shlo 8,3, - * ldconst -1, ->subo 1,0, - * ldconst -31,->subo 31,0, - * - * anything else becomes: - * lda xxx, - */ - n = offs (e); - if ((0 <= n) && (n <= 31)) - { - arg[0] = "mov"; - - } - else if ((-31 <= n) && (n <= -1)) - { - arg[0] = "subo"; - arg[3] = arg[2]; - sprintf (buf, "%d", -n); - arg[1] = buf; - arg[2] = "0"; - - } - else if ((32 <= n) && (n <= 62)) - { - arg[0] = "addo"; - arg[3] = arg[2]; - arg[1] = "31"; - sprintf (buf, "%d", n - 31); - arg[2] = buf; - - } - else if ((shift = shift_ok (n)) != 0) - { - arg[0] = "shlo"; - arg[3] = arg[2]; - sprintf (buf, "%d", shift); - arg[1] = buf; - sprintf (buf2, "%d", n >> shift); - arg[2] = buf2; - - } - else - { - arg[0] = "lda"; - } - break; - - case O_illegal: - as_bad (_("invalid constant")); - return -1; - break; + /* We could check here to see if the target architecture + supports branch prediction, but why bother? The bit will + just be ignored by processors that don't use it. */ + branch_predict = 1; + bp_bits = (args[0][n] == 't') ? BP_TAKEN : BP_NOT_TAKEN; + args[0][n - 1] = '\0'; /* Strip suffix from opcode mnemonic */ } - return (arg[3] == 0) ? 2 : 3; -} - -/***************************************************************************** - parse_memop: parse a memory operand - - This routine is based on the observation that the 4 mode bits of the - MEMB format, taken individually, have fairly consistent meaning: - M3 (bit 13): 1 if displacement is present (D_BIT) - M2 (bit 12): 1 for MEMB instructions (MEMB_BIT) - M1 (bit 11): 1 if index is present (I_BIT) - M0 (bit 10): 1 if abase is present (A_BIT) - - So we parse the memory operand and set bits in the mode as we find - things. Then at the end, if we go to MEMB format, we need only set - the MEMB bit (M2) and our mode is built for us. - - Unfortunately, I said "fairly consistent". The exceptions: - - DBIA - 0100 Would seem illegal, but means "abase-only". - - 0101 Would seem to mean "abase-only" -- it means IP-relative. - Must be converted to 0100. - - 0110 Would seem to mean "index-only", but is reserved. - We turn on the D bit and provide a 0 displacement. - - The other thing to observe is that we parse from the right, peeling - things * off as we go: first any index spec, then any abase, then - the displacement. - - *************************************************************************** */ -static void -parse_memop (memP, argP, optype) - memS *memP; /* Where to put the results */ - char *argP; /* Text of the operand to be parsed */ - int optype; /* MEM1, MEM2, MEM4, MEM8, MEM12, or MEM16 */ -{ - char *indexP; /* Pointer to index specification with "[]" removed */ - char *p; /* Temp char pointer */ - char iprel_flag; /* True if this is an IP-relative operand */ - int regnum; /* Register number */ - /* Scale factor: 1,2,4,8, or 16. Later converted to internal format - (0,1,2,3,4 respectively). */ - int scale; - int mode; /* MEMB mode bits */ - int *intP; /* Pointer to register number */ - - /* The following table contains the default scale factors for each - type of memory instruction. It is accessed using (optype-MEM1) - as an index -- thus it assumes the 'optype' constants are - assigned consecutive values, in the order they appear in this - table. */ - static const int def_scale[] = - { - 1, /* MEM1 */ - 2, /* MEM2 */ - 4, /* MEM4 */ - 8, /* MEM8 */ - -1, /* MEM12 -- no valid default */ - 16 /* MEM16 */ - }; - - iprel_flag = mode = 0; - - /* Any index present? */ - indexP = get_ispec (argP); - if (indexP) + /* Look up opcode mnemonic in table and check number of operands. + Check that opcode is legal for the target architecture. If all + looks good, assemble instruction. */ + oP = (struct i960_opcode *) hash_find (op_hash, args[0]); + if (!oP || !targ_has_iclass (oP->iclass)) + as_bad (_("invalid opcode, \"%s\"."), args[0]); + else if (n_ops != oP->num_ops) + as_bad (_("improper number of operands. expecting %d, got %d"), + oP->num_ops, n_ops); + else { - p = strchr (indexP, '*'); - if (p == NULL) - { - /* No explicit scale -- use default for this instruction - type and assembler mode. */ - if (flag_mri) - scale = 1; - else - /* GNU960 compatibility */ - scale = def_scale[optype - MEM1]; - } - else - { - *p++ = '\0'; /* Eliminate '*' */ - - /* Now indexP->a '\0'-terminated register name, - * and p->a scale factor. - */ - - if (!strcmp (p, "16")) - { - scale = 16; - } - else if (strchr ("1248", *p) && (p[1] == '\0')) - { - scale = *p - '0'; - } - else - { - scale = -1; - } - } - - regnum = get_regnum (indexP); /* Get index reg. # */ - if (!IS_RG_REG (regnum)) - { - as_bad (_("invalid index register")); - return; - } - - /* Convert scale to its binary encoding */ - switch (scale) + switch (oP->format) { - case 1: - scale = 0 << 7; + case FBRA: + case CTRL: + ctrl_fmt (args[1], oP->opcode | bp_bits, oP->num_ops); + if (oP->format == FBRA) + /* Now generate a 'bno' to same arg */ + ctrl_fmt (args[1], BNO | bp_bits, 1); break; - case 2: - scale = 1 << 7; + case COBR: + case COJ: + cobr_fmt (args, oP->opcode | bp_bits, oP); break; - case 4: - scale = 2 << 7; + case REG: + if (branch_predict) + as_warn (bp_error_msg); + reg_fmt (args, oP); break; - case 8: - scale = 3 << 7; + case MEM1: + if (args[0][0] == 'c' && args[0][1] == 'a') + { + if (branch_predict) + as_warn (bp_error_msg); + mem_fmt (args, oP, 1); + break; + } + case MEM2: + case MEM4: + case MEM8: + case MEM12: + case MEM16: + if (branch_predict) + as_warn (bp_error_msg); + mem_fmt (args, oP, 0); break; - case 16: - scale = 4 << 7; + case CALLJ: + if (branch_predict) + as_warn (bp_error_msg); + /* Output opcode & set up "fixup" (relocation); flag + relocation as 'callj' type. */ + know (oP->num_ops == 1); + get_cdisp (args[1], "CTRL", oP->opcode, 24, 0, 1); break; default: - as_bad (_("invalid scale factor")); - return; - }; - - memP->opcode |= scale | regnum; /* Set index bits in opcode */ - mode |= I_BIT; /* Found a valid index spec */ - } - - /* Any abase (Register Indirect) specification present? */ - if ((p = strrchr (argP, '(')) != NULL) - { - /* "(" is there -- does it start a legal abase spec? If not, it - could be part of a displacement expression. */ - intP = (int *) hash_find (areg_hash, p); - if (intP != NULL) - { - /* Got an abase here */ - regnum = *intP; - *p = '\0'; /* discard register spec */ - if (regnum == IPREL) - { - /* We have to specialcase ip-rel mode */ - iprel_flag = 1; - } - else - { - memP->opcode |= regnum << 14; - mode |= A_BIT; - } - } - } - - /* Any expression present? */ - memP->e = argP; - if (*argP != '\0') - { - mode |= D_BIT; - } - - /* Special-case ip-relative addressing */ - if (iprel_flag) - { - if (mode & I_BIT) - { - syntax (); - } - else - { - memP->opcode |= 5 << 10; /* IP-relative mode */ - memP->disp = 32; + BAD_CASE (oP->format); + break; } - return; } +} - /* Handle all other modes */ - switch (mode) - { - case D_BIT | A_BIT: - /* Go with MEMA instruction format for now (grow to MEMB later - if 12 bits is not enough for the displacement). MEMA format - has a single mode bit: set it to indicate that abase is - present. */ - memP->opcode |= MEMA_ABASE; - memP->disp = 12; - break; - - case D_BIT: - /* Go with MEMA instruction format for now (grow to MEMB later - if 12 bits is not enough for the displacement). */ - memP->disp = 12; - break; - - case A_BIT: - /* For some reason, the bit string for this mode is not - consistent: it should be 0 (exclusive of the MEMB bit), so we - set it "by hand" here. */ - memP->opcode |= MEMB_BIT; - break; +void +md_number_to_chars (char *buf, + valueT value, + int n) +{ + number_to_chars_littleendian (buf, value, n); +} - case A_BIT | I_BIT: - /* set MEMB bit in mode, and OR in mode bits */ - memP->opcode |= mode | MEMB_BIT; - break; +#define MAX_LITTLENUMS 6 +#define LNUM_SIZE sizeof (LITTLENUM_TYPE) - case I_BIT: - /* Treat missing displacement as displacement of 0. */ - mode |= D_BIT; - /* Fall into next case. */ - case D_BIT | A_BIT | I_BIT: - case D_BIT | I_BIT: - /* set MEMB bit in mode, and OR in mode bits */ - memP->opcode |= mode | MEMB_BIT; - memP->disp = 32; - break; +/* md_atof: convert ascii to floating point - default: - syntax (); - break; - } -} + Turn a string at input_line_pointer into a floating point constant of type + 'type', and store the appropriate bytes at *litP. The number of LITTLENUMS + emitted is returned at 'sizeP'. An error message is returned, or a pointer + to an empty message if OK. -/***************************************************************************** - parse_po: parse machine-dependent pseudo-op + Note we call the i386 floating point routine, rather than complicating + things with more files or symbolic links. */ - This is a top-level routine for machine-dependent pseudo-ops. It slurps - up the rest of the input line, breaks out the individual arguments, - and dispatches them to the correct handler. - *************************************************************************** */ -static void -parse_po (po_num) - int po_num; /* Pseudo-op number: currently S_LEAFPROC or S_SYSPROC */ +char * +md_atof (int type, char *litP, int *sizeP) { - /* Pointers operands, with no embedded whitespace. - arg[0] unused, arg[1-3]->operands */ - char *args[4]; - int n_ops; /* Number of operands */ - char *p; /* Pointer to beginning of unparsed argument string */ - char eol; /* Character that indicated end of line */ - - extern char is_end_of_line[]; - - /* Advance input pointer to end of line. */ - p = input_line_pointer; - while (!is_end_of_line[(unsigned char) *input_line_pointer]) - { - input_line_pointer++; - } - eol = *input_line_pointer; /* Save end-of-line char */ - *input_line_pointer = '\0'; /* Terminate argument list */ + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + int prec; + char *t; - /* Parse out operands */ - n_ops = get_args (p, args); - if (n_ops == -1) + switch (type) { - return; - } + case 'f': + case 'F': + prec = 2; + break; - /* Dispatch to correct handler */ - switch (po_num) - { - case S_SYSPROC: - s_sysproc (n_ops, args); + case 'd': + case 'D': + prec = 4; break; - case S_LEAFPROC: - s_leafproc (n_ops, args); + + case 't': + case 'T': + prec = 5; + type = 'x'; /* That's what atof_ieee() understands. */ break; + default: - BAD_CASE (po_num); - break; + *sizeP = 0; + return _("Bad call to md_atof()"); } - /* Restore eol, so line numbers get updated correctly. Base - assembler assumes we leave input pointer pointing at char - following the eol. */ - *input_line_pointer++ = eol; -} - -/***************************************************************************** - parse_regop: parse a register operand. - - In case of illegal operand, issue a message and return some valid - information so instruction processing can continue. - *************************************************************************** */ -static void -parse_regop (regopP, optext, opdesc) - struct regop *regopP; /* Where to put description of register operand */ - char *optext; /* Text of operand */ - char opdesc; /* Descriptor byte: what's legal for this operand */ -{ - int n; /* Register number */ - expressionS e; /* Parsed expression */ - - /* See if operand is a register */ - n = get_regnum (optext); - if (n >= 0) - { - if (IS_RG_REG (n)) - { - /* global or local register */ - if (!REG_ALIGN (opdesc, n)) - { - as_bad (_("unaligned register")); - } - regopP->n = n; - regopP->mode = 0; - regopP->special = 0; - return; - } - else if (IS_FP_REG (n) && FP_OK (opdesc)) - { - /* Floating point register, and it's allowed */ - regopP->n = n - FP0; - regopP->mode = 1; - regopP->special = 0; - return; - } - else if (IS_SF_REG (n) && SFR_OK (opdesc)) - { - /* Special-function register, and it's allowed */ - regopP->n = n - SF0; - regopP->mode = 0; - regopP->special = 1; - if (!targ_has_sfr (regopP->n)) - { - as_bad (_("no such sfr in this architecture")); - } - return; - } - } - else if (LIT_OK (opdesc)) - { - /* How about a literal? */ - regopP->mode = 1; - regopP->special = 0; - if (FP_OK (opdesc)) - { /* floating point literal acceptable */ - /* Skip over 0f, 0d, or 0e prefix */ - if ((optext[0] == '0') - && (optext[1] >= 'd') - && (optext[1] <= 'f')) - { - optext += 2; - } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; - if (!strcmp (optext, "0.0") || !strcmp (optext, "0")) - { - regopP->n = 0x10; - return; - } - if (!strcmp (optext, "1.0") || !strcmp (optext, "1")) - { - regopP->n = 0x16; - return; - } + *sizeP = prec * LNUM_SIZE; - } - else - { /* fixed point literal acceptable */ - parse_expr (optext, &e); - if (e.X_op != O_constant - || (offs (e) < 0) || (offs (e) > 31)) - { - as_bad (_("illegal literal")); - offs (e) = 0; - } - regopP->n = offs (e); - return; - } + /* Output the LITTLENUMs in REVERSE order in accord with i80960 + word-order. (Dunno why atof_ieee doesn't do it in the right + order in the first place -- probably because it's a hack of + atof_m68k.) */ + for (wordP = words + prec - 1; prec--;) + { + md_number_to_chars (litP, (long) (*wordP--), LNUM_SIZE); + litP += sizeof (LITTLENUM_TYPE); } - /* Nothing worked */ - syntax (); - regopP->mode = 0; /* Register r0 is always a good one */ - regopP->n = 0; - regopP->special = 0; -} /* parse_regop() */ + return 0; +} -/***************************************************************************** - reg_fmt: generate a REG-format instruction +static void +md_number_to_imm (char *buf, long val, int n) +{ + md_number_to_chars (buf, val, n); +} - *************************************************************************** */ static void -reg_fmt (args, oP) - char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */ - struct i960_opcode *oP; /* Pointer to description of instruction */ +md_number_to_field (char *instrP, /* Pointer to instruction to be fixed. */ + long val, /* Address fixup value. */ + bit_fixS *bfixP) /* Description of bit field to be fixed up. */ { - long instr; /* Binary to be output */ - struct regop regop; /* Description of register operand */ - int n_ops; /* Number of operands */ + int numbits; /* Length of bit field to be fixed. */ + long instr; /* 32-bit instruction to be fixed-up. */ + long sign; /* 0 or -1, according to sign bit of 'val'. */ - instr = oP->opcode; - n_ops = oP->num_ops; + /* Convert instruction back to host byte order. */ + instr = md_chars_to_number (instrP, 4); - if (n_ops >= 1) - { - parse_regop (®op, args[1], oP->operand[0]); + /* Surprise! -- we stored the number of bits to be modified rather + than a pointer to a structure. */ + numbits = (int) (size_t) bfixP; + if (numbits == 1) + /* This is a no-op, stuck here by reloc_callj(). */ + return; - if ((n_ops == 1) && !(instr & M3)) - { - /* 1-operand instruction in which the dst field should - * be used (instead of src1). - */ - regop.n <<= 19; - if (regop.special) - { - regop.mode = regop.special; - } - regop.mode <<= 13; - regop.special = 0; - } - else - { - /* regop.n goes in bit 0, needs no shifting */ - regop.mode <<= 11; - regop.special <<= 5; - } - instr |= regop.n | regop.mode | regop.special; - } + know ((numbits == 13) || (numbits == 24)); - if (n_ops >= 2) + /* Propagate sign bit of 'val' for the given number of bits. Result + should be all 0 or all 1. */ + sign = val >> ((int) numbits - 1); + if (((val < 0) && (sign != -1)) + || ((val > 0) && (sign != 0))) + as_bad (_("Fixup of %ld too large for field width of %d"), + val, numbits); + else { - parse_regop (®op, args[2], oP->operand[1]); - - if ((n_ops == 2) && !(instr & M3)) - { - /* 2-operand instruction in which the dst field should - * be used instead of src2). - */ - regop.n <<= 19; - if (regop.special) - { - regop.mode = regop.special; - } - regop.mode <<= 13; - regop.special = 0; - } - else - { - regop.n <<= 14; - regop.mode <<= 12; - regop.special <<= 6; - } - instr |= regop.n | regop.mode | regop.special; + /* Put bit field into instruction and write back in target + * byte order. */ + val &= ~(-1 << (int) numbits); /* Clear unused sign bits. */ + instr |= val; + md_number_to_chars (instrP, instr, 4); } - if (n_ops == 3) +} + + +/* md_parse_option + Invocation line includes a switch not recognized by the base assembler. + See if it's a processor-specific option. For the 960, these are: + + -norelax: + Conditional branch instructions that require displacements + greater than 13 bits (or that have external targets) should + generate errors. The default is to replace each such + instruction with the corresponding compare (or chkbit) and + branch instructions. Note that the Intel "j" cobr directives + are ALWAYS "de-optimized" in this way when necessary, + regardless of the setting of this option. + + -b: + Add code to collect information about branches taken, for + later optimization of branch prediction bits by a separate + tool. COBR and CNTL format instructions have branch + prediction bits (in the CX architecture); if "BR" represents + an instruction in one of these classes, the following rep- + resents the code generated by the assembler: + + call + .word 0 # pre-counter + Label: BR + call + .word 0 # post-counter + + A table of all such "Labels" is also generated. + + -AKA, -AKB, -AKC, -ASA, -ASB, -AMC, -ACA: + Select the 80960 architecture. Instructions or features not + supported by the selected architecture cause fatal errors. + The default is to generate code for any instruction or feature + that is supported by SOME version of the 960 (even if this + means mixing architectures!). */ + +const char *md_shortopts = "A:b"; +struct option md_longopts[] = +{ +#define OPTION_LINKRELAX (OPTION_MD_BASE) + {"linkrelax", no_argument, NULL, OPTION_LINKRELAX}, + {"link-relax", no_argument, NULL, OPTION_LINKRELAX}, +#define OPTION_NORELAX (OPTION_MD_BASE + 1) + {"norelax", no_argument, NULL, OPTION_NORELAX}, + {"no-relax", no_argument, NULL, OPTION_NORELAX}, + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof (md_longopts); + +struct tabentry +{ + char *flag; + int arch; +}; +static const struct tabentry arch_tab[] = +{ + {"KA", ARCH_KA}, + {"KB", ARCH_KB}, + {"SA", ARCH_KA}, /* Synonym for KA. */ + {"SB", ARCH_KB}, /* Synonym for KB. */ + {"KC", ARCH_MC}, /* Synonym for MC. */ + {"MC", ARCH_MC}, + {"CA", ARCH_CA}, + {"JX", ARCH_JX}, + {"HX", ARCH_HX}, + {NULL, 0} +}; + +int +md_parse_option (int c, char *arg) +{ + switch (c) { - parse_regop (®op, args[3], oP->operand[2]); - if (regop.special) - { - regop.mode = regop.special; - } - instr |= (regop.n <<= 19) | (regop.mode <<= 13); + case OPTION_LINKRELAX: + linkrelax = 1; + flag_keep_locals = 1; + break; + + case OPTION_NORELAX: + norelax = 1; + break; + + case 'b': + instrument_branches = 1; + break; + + case 'A': + { + const struct tabentry *tp; + char *p = arg; + + for (tp = arch_tab; tp->flag != NULL; tp++) + if (!strcmp (p, tp->flag)) + break; + + if (tp->flag == NULL) + { + as_bad (_("invalid architecture %s"), p); + return 0; + } + else + architecture = tp->arch; + } + break; + + default: + return 0; } - emit (instr); + + return 1; } -/***************************************************************************** - relax_cobr: - Replace cobr instruction in a code fragment with equivalent branch and - compare instructions, so it can reach beyond a 13-bit displacement. - Set up an address fix/relocation for the new branch instruction. +void +md_show_usage (FILE *stream) +{ + int i; - *************************************************************************** */ + fprintf (stream, _("I960 options:\n")); + for (i = 0; arch_tab[i].flag; i++) + fprintf (stream, "%s-A%s", i ? " | " : "", arch_tab[i].flag); + fprintf (stream, _("\n\ + specify variant of 960 architecture\n\ +-b add code to collect statistics about branches taken\n\ +-link-relax preserve individual alignment directives so linker\n\ + can do relaxing (b.out format only)\n\ +-no-relax don't alter compare-and-branch instructions for\n\ + long displacements\n")); +} + +/* relax_cobr: + Replace cobr instruction in a code fragment with equivalent branch and + compare instructions, so it can reach beyond a 13-bit displacement. + Set up an address fix/relocation for the new branch instruction. */ /* This "conditional jump" table maps cobr instructions into equivalent compare and branch opcodes. */ + static const struct { @@ -2445,39 +1993,37 @@ coj[] = }; static void -relax_cobr (fragP) - register fragS *fragP; /* fragP->fr_opcode is assumed to point to - * the cobr instruction, which comes at the - * end of the code fragment. - */ +relax_cobr (fragS *fragP) /* fragP->fr_opcode is assumed to point to + the cobr instruction, which comes at the + end of the code fragment. */ { int opcode, src1, src2, m1, s2; - /* Bit fields from cobr instruction */ - long bp_bits; /* Branch prediction bits from cobr instruction */ - long instr; /* A single i960 instruction */ - /* ->instruction to be replaced */ + /* Bit fields from cobr instruction. */ + long bp_bits; /* Branch prediction bits from cobr instruction. */ + long instr; /* A single i960 instruction. */ + /* ->instruction to be replaced. */ char *iP; - fixS *fixP; /* Relocation that can be done at assembly time */ + fixS *fixP; /* Relocation that can be done at assembly time. */ - /* PICK UP & PARSE COBR INSTRUCTION */ + /* Pick up & parse cobr instruction. */ iP = fragP->fr_opcode; instr = md_chars_to_number (iP, 4); - opcode = ((instr >> 24) & 0xff) - 0x30; /* "-0x30" for table index */ + opcode = ((instr >> 24) & 0xff) - 0x30; /* "-0x30" for table index. */ src1 = (instr >> 19) & 0x1f; m1 = (instr >> 13) & 1; s2 = instr & 1; src2 = (instr >> 14) & 0x1f; bp_bits = instr & BP_MASK; - /* GENERATE AND OUTPUT COMPARE INSTRUCTION */ + /* Generate and output compare instruction. */ instr = coj[opcode].compare | src1 | (m1 << 11) | (s2 << 6) | (src2 << 14); md_number_to_chars (iP, instr, 4); - /* OUTPUT BRANCH INSTRUCTION */ + /* Output branch instruction. */ md_number_to_chars (iP + 4, coj[opcode].branch | bp_bits, 4); - /* SET UP ADDRESS FIXUP/RELOCATION */ + /* Set up address fixup/relocation. */ fixP = fix_new (fragP, iP + 4 - fragP->fr_literal, 4, @@ -2486,81 +2032,172 @@ relax_cobr (fragP) 1, NO_RELOC); - fixP->fx_bit_fixP = (bit_fixS *) 24; /* Store size of bit field */ + fixP->fx_bit_fixP = (bit_fixS *) 24; /* Store size of bit field. */ + + fragP->fr_fix += 4; + frag_wane (fragP); +} + +/* md_convert_frag: + + Called by base assembler after address relaxation is finished: modify + variable fragments according to how much relaxation was done. + + If the fragment substate is still 1, a 13-bit displacement was enough + to reach the symbol in question. Set up an address fixup, but otherwise + leave the cobr instruction alone. + + If the fragment substate is 2, a 13-bit displacement was not enough. + Replace the cobr with a two instructions (a compare and a branch). */ + +#ifndef BFD_ASSEMBLER +void +md_convert_frag (object_headers *headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + fragS *fragP) +#else +void +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS *fragP) +#endif +{ + /* Structure describing needed address fix. */ + fixS *fixP; + + switch (fragP->fr_subtype) + { + case 1: + /* Leave single cobr instruction. */ + fixP = fix_new (fragP, + fragP->fr_opcode - fragP->fr_literal, + 4, + fragP->fr_symbol, + fragP->fr_offset, + 1, + NO_RELOC); + + fixP->fx_bit_fixP = (bit_fixS *) 13; /* Size of bit field. */ + break; + case 2: + /* Replace cobr with compare/branch instructions. */ + relax_cobr (fragP); + break; + default: + BAD_CASE (fragP->fr_subtype); + break; + } +} + +/* md_estimate_size_before_relax: How much does it look like *fragP will grow? + + Called by base assembler just before address relaxation. + Return the amount by which the fragment will grow. + + Any symbol that is now undefined will not become defined; cobr's + based on undefined symbols will have to be replaced with a compare + instruction and a branch instruction, and the code fragment will grow + by 4 bytes. */ + +int +md_estimate_size_before_relax (fragS *fragP, segT segment_type) +{ + /* If symbol is undefined in this segment, go to "relaxed" state + (compare and branch instructions instead of cobr) right now. */ + if (S_GET_SEGMENT (fragP->fr_symbol) != segment_type) + { + relax_cobr (fragP); + return 4; + } + + return md_relax_table[fragP->fr_subtype].rlx_length; +} + +#if defined(OBJ_AOUT) | defined(OBJ_BOUT) + +/* md_ri_to_chars: + This routine exists in order to overcome machine byte-order problems + when dealing with bit-field entries in the relocation_info struct. - fragP->fr_fix += 4; - frag_wane (fragP); + But relocation info will be used on the host machine only (only + executable code is actually downloaded to the i80960). Therefore, + we leave it in host byte order. */ + +static void +md_ri_to_chars (char *where, struct relocation_info *ri) +{ + host_number_to_chars (where, ri->r_address, 4); + host_number_to_chars (where + 4, ri->r_index, 3); +#if WORDS_BIGENDIAN + where[7] = (ri->r_pcrel << 7 + | ri->r_length << 5 + | ri->r_extern << 4 + | ri->r_bsr << 3 + | ri->r_disp << 2 + | ri->r_callj << 1 + | ri->nuthin << 0); +#else + where[7] = (ri->r_pcrel << 0 + | ri->r_length << 1 + | ri->r_extern << 3 + | ri->r_bsr << 4 + | ri->r_disp << 5 + | ri->r_callj << 6 + | ri->nuthin << 7); +#endif } -/***************************************************************************** - reloc_callj: Relocate a 'callj' instruction +#endif /* defined(OBJ_AOUT) | defined(OBJ_BOUT) */ - This is a "non-(GNU)-standard" machine-dependent hook. The base - assembler calls it when it decides it can relocate an address at - assembly time instead of emitting a relocation directive. + +/* brtab_emit: generate the fetch-prediction branch table. - Check to see if the relocation involves a 'callj' instruction to a: - sysproc: Replace the default 'call' instruction with a 'calls' - leafproc: Replace the default 'call' instruction with a 'bal'. - other proc: Do nothing. + See the comments above the declaration of 'br_cnt' for details on + branch-prediction instrumentation. - See b.out.h for details on the 'n_other' field in a symbol structure. + The code emitted here would be functionally equivalent to the following + example assembler source. - IMPORTANT!: - Assumes the caller has already figured out, in the case of a leafproc, - to use the 'bal' entry point, and has substituted that symbol into the - passed fixup structure. + .data + .align 2 + BR_TAB_NAME: + .word 0 # link to next table + .word 3 # length of table + .word LBRANCH0 # 1st entry in table proper + .word LBRANCH1 + .word LBRANCH2 */ - *************************************************************************** */ -int -reloc_callj (fixP) - /* Relocation that can be done at assembly time */ - fixS *fixP; +void +brtab_emit (void) { - /* Points to the binary for the instruction being relocated. */ - char *where; - - if (!fixP->fx_tcbit) - { - /* This wasn't a callj instruction in the first place */ - return 0; - } + int i; + char buf[20]; + /* Where the binary was output to. */ + char *p; + /* Pointer to description of deferred address fixup. */ + fixS *fixP; - where = fixP->fx_frag->fr_literal + fixP->fx_where; + if (!instrument_branches) + return; - if (TC_S_IS_SYSPROC (fixP->fx_addsy)) - { - /* Symbol is a .sysproc: replace 'call' with 'calls'. System - procedure number is (other-1). */ - md_number_to_chars (where, CALLS | TC_S_GET_SYSPROC (fixP->fx_addsy), 4); + subseg_set (data_section, 0); /* .data */ + frag_align (2, 0, 0); /* .align 2 */ + record_alignment (now_seg, 2); + colon (BR_TAB_NAME); /* BR_TAB_NAME: */ + emit (0); /* .word 0 #link to next table */ + emit (br_cnt); /* .word n #length of table */ - /* Nothing else needs to be done for this instruction. Make - sure 'md_number_to_field()' will perform a no-op. */ - fixP->fx_bit_fixP = (bit_fixS *) 1; - } - else if (TC_S_IS_CALLNAME (fixP->fx_addsy)) - { - /* Should not happen: see block comment above */ - as_fatal (_("Trying to 'bal' to %s"), S_GET_NAME (fixP->fx_addsy)); - } - else if (TC_S_IS_BALNAME (fixP->fx_addsy)) + for (i = 0; i < br_cnt; i++) { - /* Replace 'call' with 'bal'; both instructions have the same - format, so calling code should complete relocation as if - nothing happened here. */ - md_number_to_chars (where, BAL, 4); + sprintf (buf, "%s%d", BR_LABEL_BASE, i); + p = emit (0); + fixP = fix_new (frag_now, + p - frag_now->fr_literal, + 4, symbol_find (buf), 0, 0, NO_RELOC); } - else if (TC_S_IS_BADPROC (fixP->fx_addsy)) - { - as_bad (_("Looks like a proc, but can't tell what kind.\n")); - } /* switch on proc type */ - - /* else Symbol is neither a sysproc nor a leafproc */ - return 0; } -/***************************************************************************** - s_leafproc: process .leafproc pseudo-op +/* s_leafproc: process .leafproc pseudo-op .leafproc takes two arguments, the second one is optional: arg[1]: name of 'call' entry point to leaf procedure @@ -2571,39 +2208,33 @@ reloc_callj (fixP) If there are 2 distinct arguments, we must make sure that the 'bal' entry point immediately follows the 'call' entry point in the linked - list of symbols. + list of symbols. */ - *************************************************************************** */ static void -s_leafproc (n_ops, args) - int n_ops; /* Number of operands */ - char *args[]; /* args[1]->1st operand, args[2]->2nd operand */ +s_leafproc (int n_ops, /* Number of operands. */ + char *args[]) /* args[1]->1st operand, args[2]->2nd operand. */ { - symbolS *callP; /* Pointer to leafproc 'call' entry point symbol */ - symbolS *balP; /* Pointer to leafproc 'bal' entry point symbol */ + symbolS *callP; /* Pointer to leafproc 'call' entry point symbol. */ + symbolS *balP; /* Pointer to leafproc 'bal' entry point symbol. */ if ((n_ops != 1) && (n_ops != 2)) { as_bad (_("should have 1 or 2 operands")); return; - } /* Check number of arguments */ + } /* Find or create symbol for 'call' entry point. */ callP = symbol_find_or_make (args[1]); if (TC_S_IS_CALLNAME (callP)) - { - as_warn (_("Redefining leafproc %s"), S_GET_NAME (callP)); - } /* is leafproc */ + as_warn (_("Redefining leafproc %s"), S_GET_NAME (callP)); /* If that was the only argument, use it as the 'bal' entry point. - * Otherwise, mark it as the 'call' entry point and find or create - * another symbol for the 'bal' entry point. - */ + Otherwise, mark it as the 'call' entry point and find or create + another symbol for the 'bal' entry point. */ if ((n_ops == 1) || !strcmp (args[1], args[2])) { TC_S_FORCE_TO_BALNAME (callP); - } else { @@ -2611,32 +2242,30 @@ s_leafproc (n_ops, args) balP = symbol_find_or_make (args[2]); if (TC_S_IS_CALLNAME (balP)) - { - as_warn (_("Redefining leafproc %s"), S_GET_NAME (balP)); - } + as_warn (_("Redefining leafproc %s"), S_GET_NAME (balP)); + TC_S_FORCE_TO_BALNAME (balP); #ifndef OBJ_ELF tc_set_bal_of_call (callP, balP); #endif - } /* if only one arg, or the args are the same */ + } } -/* - s_sysproc: process .sysproc pseudo-op +/* s_sysproc: process .sysproc pseudo-op - .sysproc takes two arguments: - arg[1]: name of entry point to system procedure - arg[2]: 'entry_num' (index) of system procedure in the range - [0,31] inclusive. + .sysproc takes two arguments: + arg[1]: name of entry point to system procedure + arg[2]: 'entry_num' (index) of system procedure in the range + [0,31] inclusive. + + For [ab].out, we store the 'entrynum' in the 'n_other' field of + the symbol. Since that entry is normally 0, we bias 'entrynum' + by adding 1 to it. It must be unbiased before it is used. */ - For [ab].out, we store the 'entrynum' in the 'n_other' field of - the symbol. Since that entry is normally 0, we bias 'entrynum' - by adding 1 to it. It must be unbiased before it is used. */ static void -s_sysproc (n_ops, args) - int n_ops; /* Number of operands */ - char *args[]; /* args[1]->1st operand, args[2]->2nd operand */ +s_sysproc (int n_ops, /* Number of operands. */ + char *args[]) /* args[1]->1st operand, args[2]->2nd operand. */ { expressionS exp; symbolS *symP; @@ -2645,7 +2274,7 @@ s_sysproc (n_ops, args) { as_bad (_("should have two operands")); return; - } /* bad arg count */ + } /* Parse "entry_num" argument and check it for validity. */ parse_expr (args[2], &exp); @@ -2657,127 +2286,130 @@ s_sysproc (n_ops, args) return; } - /* Find/make symbol and stick entry number (biased by +1) into it */ + /* Find/make symbol and stick entry number (biased by +1) into it. */ symP = symbol_find_or_make (args[1]); if (TC_S_IS_SYSPROC (symP)) - { - as_warn (_("Redefining entrynum for sysproc %s"), S_GET_NAME (symP)); - } /* redefining */ + as_warn (_("Redefining entrynum for sysproc %s"), S_GET_NAME (symP)); - TC_S_SET_SYSPROC (symP, offs (exp)); /* encode entry number */ + TC_S_SET_SYSPROC (symP, offs (exp)); /* Encode entry number. */ TC_S_FORCE_TO_SYSPROC (symP); } -/***************************************************************************** - shift_ok: - Determine if a "shlo" instruction can be used to implement a "ldconst". - This means that some number X < 32 can be shifted left to produce the - constant of interest. +/* parse_po: parse machine-dependent pseudo-op - Return the shift count, or 0 if we can't do it. - Caller calculates X by shifting original constant right 'shift' places. + This is a top-level routine for machine-dependent pseudo-ops. It slurps + up the rest of the input line, breaks out the individual arguments, + and dispatches them to the correct handler. */ - *************************************************************************** */ -static int -shift_ok (n) - int n; /* The constant of interest */ +static void +parse_po (int po_num) /* Pseudo-op number: currently S_LEAFPROC or S_SYSPROC. */ { - int shift; /* The shift count */ + /* Pointers operands, with no embedded whitespace. + arg[0] unused, arg[1-3]->operands. */ + char *args[4]; + int n_ops; /* Number of operands. */ + char *p; /* Pointer to beginning of unparsed argument string. */ + char eol; /* Character that indicated end of line. */ - if (n <= 0) - { - /* Can't do it for negative numbers */ - return 0; - } + extern char is_end_of_line[]; - /* Shift 'n' right until a 1 is about to be lost */ - for (shift = 0; (n & 1) == 0; shift++) - { - n >>= 1; - } + /* Advance input pointer to end of line. */ + p = input_line_pointer; + while (!is_end_of_line[(unsigned char) *input_line_pointer]) + input_line_pointer++; - if (n >= 32) + eol = *input_line_pointer; /* Save end-of-line char. */ + *input_line_pointer = '\0'; /* Terminate argument list. */ + + /* Parse out operands. */ + n_ops = get_args (p, args); + if (n_ops == -1) + return; + + /* Dispatch to correct handler. */ + switch (po_num) { - return 0; + case S_SYSPROC: + s_sysproc (n_ops, args); + break; + case S_LEAFPROC: + s_leafproc (n_ops, args); + break; + default: + BAD_CASE (po_num); + break; } - return shift; + + /* Restore eol, so line numbers get updated correctly. Base + assembler assumes we leave input pointer pointing at char + following the eol. */ + *input_line_pointer++ = eol; } -/* syntax: issue syntax error */ +/* reloc_callj: Relocate a 'callj' instruction -static void -syntax () -{ - as_bad (_("syntax error")); -} /* syntax() */ + This is a "non-(GNU)-standard" machine-dependent hook. The base + assembler calls it when it decides it can relocate an address at + assembly time instead of emitting a relocation directive. -/* targ_has_sfr: + Check to see if the relocation involves a 'callj' instruction to a: + sysproc: Replace the default 'call' instruction with a 'calls' + leafproc: Replace the default 'call' instruction with a 'bal'. + other proc: Do nothing. - Return TRUE iff the target architecture supports the specified - special-function register (sfr). */ + See b.out.h for details on the 'n_other' field in a symbol structure. -static int -targ_has_sfr (n) - int n; /* Number (0-31) of sfr */ + IMPORTANT!: + Assumes the caller has already figured out, in the case of a leafproc, + to use the 'bal' entry point, and has substituted that symbol into the + passed fixup structure. */ + +int +reloc_callj (fixS *fixP) /* Relocation that can be done at assembly time. */ { - switch (architecture) - { - case ARCH_KA: - case ARCH_KB: - case ARCH_MC: - case ARCH_JX: - return 0; - case ARCH_HX: - return ((0 <= n) && (n <= 4)); - case ARCH_CA: - default: - return ((0 <= n) && (n <= 2)); - } -} + /* Points to the binary for the instruction being relocated. */ + char *where; -/* targ_has_iclass: + if (!fixP->fx_tcbit) + /* This wasn't a callj instruction in the first place. */ + return 0; - Return TRUE iff the target architecture supports the indicated - class of instructions. */ -static int -targ_has_iclass (ic) - /* Instruction class; one of: - I_BASE, I_CX, I_DEC, I_KX, I_FP, I_MIL, I_CASIM, I_CX2, I_HX, I_HX2 - */ - int ic; -{ - iclasses_seen |= ic; - switch (architecture) + where = fixP->fx_frag->fr_literal + fixP->fx_where; + + if (TC_S_IS_SYSPROC (fixP->fx_addsy)) { - case ARCH_KA: - return ic & (I_BASE | I_KX); - case ARCH_KB: - return ic & (I_BASE | I_KX | I_FP | I_DEC); - case ARCH_MC: - return ic & (I_BASE | I_KX | I_FP | I_DEC | I_MIL); - case ARCH_CA: - return ic & (I_BASE | I_CX | I_CX2 | I_CASIM); - case ARCH_JX: - return ic & (I_BASE | I_CX2 | I_JX); - case ARCH_HX: - return ic & (I_BASE | I_CX2 | I_JX | I_HX); - default: - if ((iclasses_seen & (I_KX | I_FP | I_DEC | I_MIL)) - && (iclasses_seen & (I_CX | I_CX2))) - { - as_warn (_("architecture of opcode conflicts with that of earlier instruction(s)")); - iclasses_seen &= ~ic; - } - return 1; + /* Symbol is a .sysproc: replace 'call' with 'calls'. System + procedure number is (other-1). */ + md_number_to_chars (where, CALLS | TC_S_GET_SYSPROC (fixP->fx_addsy), 4); + + /* Nothing else needs to be done for this instruction. Make + sure 'md_number_to_field()' will perform a no-op. */ + fixP->fx_bit_fixP = (bit_fixS *) 1; + } + else if (TC_S_IS_CALLNAME (fixP->fx_addsy)) + { + /* Should not happen: see block comment above. */ + as_fatal (_("Trying to 'bal' to %s"), S_GET_NAME (fixP->fx_addsy)); + } + else if (TC_S_IS_BALNAME (fixP->fx_addsy)) + { + /* Replace 'call' with 'bal'; both instructions have the same + format, so calling code should complete relocation as if + nothing happened here. */ + md_number_to_chars (where, BAL, 4); } + else if (TC_S_IS_BADPROC (fixP->fx_addsy)) + as_bad (_("Looks like a proc, but can't tell what kind.\n")); + + /* Otherwise Symbol is neither a sysproc nor a leafproc. */ + return 0; } /* Handle the MRI .endian pseudo-op. */ static void -s_endian (ignore) - int ignore ATTRIBUTE_UNUSED; +s_endian (int ignore ATTRIBUTE_UNUSED) { char *name; char c; @@ -2799,8 +2431,7 @@ s_endian (ignore) /* We have no need to default values of symbols. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -2809,17 +2440,15 @@ md_undefined_symbol (name) On the i960, they're relative to the address of the instruction, which we have set up as the address of the fixup too. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { return fixP->fx_where + fixP->fx_frag->fr_address; } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, + valueT *valP, + segT seg ATTRIBUTE_UNUSED) { long val = *valP; char *place = fixP->fx_where + fixP->fx_frag->fr_literal; @@ -2858,10 +2487,9 @@ md_apply_fix3 (fixP, valP, seg) #if defined(OBJ_AOUT) | defined(OBJ_BOUT) void -tc_bout_fix_to_chars (where, fixP, segment_address_in_file) - char *where; - fixS *fixP; - relax_addressT segment_address_in_file; +tc_bout_fix_to_chars (char *where, + fixS *fixP, + relax_addressT segment_address_in_file) { static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2}; struct relocation_info ri; @@ -2920,8 +2548,7 @@ tc_bout_fix_to_chars (where, fixP, segment_address_in_file) #if defined (OBJ_COFF) && defined (BFD) short -tc_coff_fix2rtype (fixP) - fixS *fixP; +tc_coff_fix2rtype (fixS *fixP) { if (fixP->fx_bsr) abort (); @@ -2937,8 +2564,7 @@ tc_coff_fix2rtype (fixP) } int -tc_coff_sizemachdep (frag) - fragS *frag; +tc_coff_sizemachdep (fragS *frag) { if (frag->fr_next) return frag->fr_next->fr_address - frag->fr_address; @@ -2948,12 +2574,13 @@ tc_coff_sizemachdep (frag) #endif /* Align an address by rounding it up to the specified boundary. */ + valueT -md_section_align (seg, addr) - segT seg; - valueT addr; /* Address to be rounded up */ +md_section_align (segT seg, + valueT addr) /* Address to be rounded up. */ { int align; + #ifdef BFD_ASSEMBLER align = bfd_get_section_alignment (stdoutput, seg); #else @@ -2966,8 +2593,7 @@ extern int coff_flags; #ifdef OBJ_COFF void -tc_headers_hook (headers) - object_headers *headers; +tc_headers_hook (object_headers *headers) { switch (architecture) { @@ -3048,8 +2674,7 @@ tc_headers_hook (headers) contains the bal entry point. The bal symbol becomes a label. */ void -tc_crawl_symbol_chain (headers) - object_headers *headers ATTRIBUTE_UNUSED; +tc_crawl_symbol_chain (object_headers *headers ATTRIBUTE_UNUSED) { symbolS *symbolP; @@ -3058,27 +2683,24 @@ tc_crawl_symbol_chain (headers) #ifdef OBJ_COFF if (TC_S_IS_SYSPROC (symbolP)) { - /* second aux entry already contains the sysproc number */ + /* Second aux entry already contains the sysproc number. */ S_SET_NUMBER_AUXILIARY (symbolP, 2); S_SET_STORAGE_CLASS (symbolP, C_SCALL); S_SET_DATA_TYPE (symbolP, S_GET_DATA_TYPE (symbolP) | (DT_FCN << N_BTSHFT)); continue; - } /* rewrite sysproc */ + } #endif /* OBJ_COFF */ if (!TC_S_IS_BALNAME (symbolP) && !TC_S_IS_CALLNAME (symbolP)) - { - continue; - } /* Not a leafproc symbol */ + continue; if (!S_IS_DEFINED (symbolP)) - { - as_bad (_("leafproc symbol '%s' undefined"), S_GET_NAME (symbolP)); - } /* undefined leaf */ + as_bad (_("leafproc symbol '%s' undefined"), S_GET_NAME (symbolP)); if (TC_S_IS_CALLNAME (symbolP)) { symbolS *balP = tc_get_bal_of_call (symbolP); + if (S_IS_EXTERNAL (symbolP) != S_IS_EXTERNAL (balP)) { S_SET_EXTERNAL (symbolP); @@ -3106,9 +2728,8 @@ tc_crawl_symbol_chain (headers) #endif void -tc_set_bal_of_call (callP, balP) - symbolS *callP ATTRIBUTE_UNUSED; - symbolS *balP ATTRIBUTE_UNUSED; +tc_set_bal_of_call (symbolS *callP ATTRIBUTE_UNUSED, + symbolS *balP ATTRIBUTE_UNUSED) { know (TC_S_IS_CALLNAME (callP)); know (TC_S_IS_BALNAME (balP)); @@ -3122,8 +2743,7 @@ tc_set_bal_of_call (callP, balP) #ifdef OBJ_ABOUT /* If the 'bal' entry doesn't immediately follow the 'call' - * symbol, unlink it from the symbol list and re-insert it. - */ + symbol, unlink it from the symbol list and re-insert it. */ if (symbol_next (callP) != balP) { symbol_remove (balP, &symbol_rootP, &symbol_lastP); @@ -3137,8 +2757,7 @@ tc_set_bal_of_call (callP, balP) } symbolS * -tc_get_bal_of_call (callP) - symbolS *callP ATTRIBUTE_UNUSED; +tc_get_bal_of_call (symbolS *callP ATTRIBUTE_UNUSED) { symbolS *retval; @@ -3156,12 +2775,11 @@ tc_get_bal_of_call (callP) know (TC_S_IS_BALNAME (retval)); return retval; -} /* _tc_get_bal_of_call() */ +} #ifdef OBJ_COFF void -tc_coff_symbol_emit_hook (symbolP) - symbolS *symbolP ATTRIBUTE_UNUSED; +tc_coff_symbol_emit_hook (symbolS *symbolP ATTRIBUTE_UNUSED) { if (TC_S_IS_CALLNAME (symbolP)) { @@ -3173,25 +2791,22 @@ tc_coff_symbol_emit_hook (symbolP) else S_SET_STORAGE_CLASS (symbolP, C_LEAFSTAT); S_SET_DATA_TYPE (symbolP, S_GET_DATA_TYPE (symbolP) | (DT_FCN << N_BTSHFT)); - /* fix up the bal symbol */ + /* Fix up the bal symbol. */ S_SET_STORAGE_CLASS (balP, C_LABEL); - } /* only on calls */ + } } #endif /* OBJ_COFF */ void -i960_handle_align (fragp) - fragS *fragp ATTRIBUTE_UNUSED; +i960_handle_align (fragS *fragp ATTRIBUTE_UNUSED) { if (!linkrelax) return; #ifndef OBJ_BOUT - as_bad (_("option --link-relax is only supported in b.out format")); linkrelax = 0; return; - #else /* The text section "ends" with another alignment reloc, to which we @@ -3207,15 +2822,12 @@ i960_handle_align (fragp) } int -i960_validate_fix (fixP, this_segment_type) - fixS *fixP; - segT this_segment_type ATTRIBUTE_UNUSED; +i960_validate_fix (fixS *fixP, segT this_segment_type ATTRIBUTE_UNUSED) { if (fixP->fx_tcbit && TC_S_IS_CALLNAME (fixP->fx_addsy)) { /* Relocation should be done via the associated 'bal' entry point symbol. */ - if (!TC_S_IS_BALNAME (tc_get_bal_of_call (fixP->fx_addsy))) { as_bad_where (fixP->fx_file, fixP->fx_line, @@ -3233,11 +2845,8 @@ i960_validate_fix (fixP, this_segment_type) /* From cgen.c: */ -static short tc_bfd_fix2rtype PARAMS ((fixS *)); - static short -tc_bfd_fix2rtype (fixP) - fixS *fixP; +tc_bfd_fix2rtype (fixS *fixP) { if (fixP->fx_pcrel == 0 && fixP->fx_size == 4) return BFD_RELOC_32; @@ -3255,19 +2864,17 @@ tc_bfd_fix2rtype (fixP) FIXME: To what extent can we get all relevant targets to use this? */ arelent * -tc_gen_reloc (section, fixP) - asection *section ATTRIBUTE_UNUSED; - fixS *fixP; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) { arelent * reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc = xmalloc (sizeof (arelent)); - /* HACK: Is this right? */ + /* HACK: Is this right? */ fixP->fx_r_type = tc_bfd_fix2rtype (fixP); reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); - if (reloc->howto == (reloc_howto_type *) NULL) + if (reloc->howto == NULL) { as_bad_where (fixP->fx_file, fixP->fx_line, "internal error: can't export reloc type %d (`%s')", @@ -3278,7 +2885,7 @@ tc_gen_reloc (section, fixP) assert (!fixP->fx_pcrel == !reloc->howto->pc_relative); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; reloc->addend = fixP->fx_addnumber; @@ -3290,4 +2897,16 @@ tc_gen_reloc (section, fixP) #endif /* BFD_ASSEMBLER */ -/* end of tc-i960.c */ +const pseudo_typeS md_pseudo_table[] = +{ + {"bss", s_lcomm, 1}, + {"endian", s_endian, 0}, + {"extended", float_cons, 't'}, + {"leafproc", parse_po, S_LEAFPROC}, + {"sysproc", parse_po, S_SYSPROC}, + + {"word", cons, 4}, + {"quad", cons, 16}, + + {0, 0, 0} +}; diff --git a/gas/config/tc-ip2k.c b/gas/config/tc-ip2k.c index 8a3befb9b7c..b89f67041a2 100644 --- a/gas/config/tc-ip2k.c +++ b/gas/config/tc-ip2k.c @@ -57,8 +57,52 @@ const char line_separator_chars[] = ""; const char EXP_CHARS[] = "eE"; const char FLT_CHARS[] = "dD"; -static void ip2k_elf_section_text (int); -static void ip2k_elf_section_rtn (int); +/* Flag to detect when switching to code section where insn alignment is + implied. */ +static int force_code_align = 0; + +/* Mach selected from command line. */ +static int ip2k_mach = 0; +static unsigned ip2k_mach_bitmask = 0; + + +static void +ip2k_elf_section_rtn (int i) +{ + obj_elf_section(i); + + if (force_code_align) + { + /* The s_align_ptwo function expects that we are just after a .align + directive and it will either try and read the align value or stop + if end of line so we must fake it out so it thinks we are at the + end of the line. */ + char *old_input_line_pointer = input_line_pointer; + input_line_pointer = "\n"; + s_align_ptwo (1); + force_code_align = 0; + /* Restore. */ + input_line_pointer = old_input_line_pointer; + } +} + +static void +ip2k_elf_section_text (int i) +{ + char *old_input_line_pointer; + obj_elf_text(i); + + /* the s_align_ptwo function expects that we are just after a .align + directive and it will either try and read the align value or stop if + end of line so we must fake it out so it thinks we are at the end of + the line. */ + old_input_line_pointer = input_line_pointer; + input_line_pointer = "\n"; + s_align_ptwo (1); + force_code_align = 0; + /* Restore. */ + input_line_pointer = old_input_line_pointer; +} /* The target specific pseudo-ops which we support. */ const pseudo_typeS md_pseudo_table[] = @@ -70,8 +114,11 @@ const pseudo_typeS md_pseudo_table[] = -#define OPTION_CPU_IP2022 (OPTION_MD_BASE) -#define OPTION_CPU_IP2022EXT (OPTION_MD_BASE+1) +enum options +{ + OPTION_CPU_IP2022 = OPTION_MD_BASE, + OPTION_CPU_IP2022EXT +}; struct option md_longopts[] = { @@ -83,18 +130,8 @@ size_t md_longopts_size = sizeof (md_longopts); const char * md_shortopts = ""; -/* Flag to detect when switching to code section where insn alignment is - implied. */ -static int force_code_align = 0; - -/* Mach selected from command line. */ -int ip2k_mach = 0; -unsigned ip2k_mach_bitmask = 0; - int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char * arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) { switch (c) { @@ -115,10 +152,8 @@ md_parse_option (c, arg) return 1; } - void -md_show_usage (stream) - FILE * stream; +md_show_usage (FILE * stream) { fprintf (stream, _("IP2K specific command line options:\n")); fprintf (stream, _(" -mip2022 restrict to IP2022 insns \n")); @@ -127,7 +162,7 @@ md_show_usage (stream) void -md_begin () +md_begin (void) { /* Initialize the `cgen' interface. */ @@ -148,8 +183,7 @@ md_begin () void -md_assemble (str) - char * str; +md_assemble (char * str) { ip2k_insn insn; char * errmsg; @@ -194,9 +228,7 @@ md_assemble (str) } valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); @@ -205,16 +237,14 @@ md_section_align (segment, size) symbolS * -md_undefined_symbol (name) - char * name ATTRIBUTE_UNUSED; +md_undefined_symbol (char * name ATTRIBUTE_UNUSED) { return 0; } int -md_estimate_size_before_relax (fragP, segment) - fragS * fragP ATTRIBUTE_UNUSED; - segT segment ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, + segT segment ATTRIBUTE_UNUSED) { as_fatal (_("md_estimate_size_before_relax\n")); return 1; @@ -229,10 +259,9 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_subtype is the subtype of what the address relaxed to. */ void -md_convert_frag (abfd, sec, fragP) - bfd * abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS * fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS * fragP ATTRIBUTE_UNUSED) { } @@ -240,8 +269,7 @@ md_convert_frag (abfd, sec, fragP) /* Functions concerning relocs. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { as_fatal (_("md_pcrel_from\n")); @@ -255,10 +283,9 @@ md_pcrel_from (fixP) *FIXP may be modified if desired. */ bfd_reloc_code_real_type -md_cgen_lookup_reloc (insn, operand, fixP) - const CGEN_INSN * insn ATTRIBUTE_UNUSED; - const CGEN_OPERAND * operand; - fixS * fixP ATTRIBUTE_UNUSED; +md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED, + const CGEN_OPERAND * operand, + fixS * fixP ATTRIBUTE_UNUSED) { bfd_reloc_code_real_type result; @@ -300,10 +327,7 @@ md_cgen_lookup_reloc (insn, operand, fixP) /* Write a value out to the object file, using the appropriate endianness. */ void -md_number_to_chars (buf, val, n) - char * buf; - valueT val; - int n; +md_number_to_chars (char * buf, valueT val, int n) { number_to_chars_bigendian (buf, val, n); } @@ -317,10 +341,7 @@ md_number_to_chars (buf, val, n) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char * litP; - int * sizeP; +md_atof (int type, char * litP, int * sizeP) { int prec; LITTLENUM_TYPE words [MAX_LITTLENUMS]; @@ -374,8 +395,7 @@ md_atof (type, litP, sizeP) the instruction it will be eventually encoded within. */ int -ip2k_force_relocation (fix) - fixS * fix; +ip2k_force_relocation (fixS * fix) { switch (fix->fx_r_type) { @@ -411,16 +431,13 @@ ip2k_force_relocation (fix) } void -ip2k_apply_fix3 (fixP, valueP, seg) - fixS *fixP; - valueT *valueP; - segT seg; +ip2k_apply_fix3 (fixS *fixP, valueT *valueP, segT seg) { if (fixP->fx_r_type == BFD_RELOC_IP2K_TEXT && ! fixP->fx_addsy && ! fixP->fx_subsy) { - *valueP = ((int)(*valueP)) / 2; + *valueP = ((int)(* valueP)) / 2; fixP->fx_r_type = BFD_RELOC_16; } else if (fixP->fx_r_type == BFD_RELOC_UNUSED + IP2K_OPERAND_FR) @@ -446,10 +463,9 @@ ip2k_apply_fix3 (fixP, valueP, seg) } int -ip2k_elf_section_flags (flags, attr, type) - int flags; - int attr ATTRIBUTE_UNUSED; - int type ATTRIBUTE_UNUSED; +ip2k_elf_section_flags (int flags, + int attr ATTRIBUTE_UNUSED, + int type ATTRIBUTE_UNUSED) { /* This is used to detect when the section changes to an executable section. This function is called by the elf section processing. When we note an @@ -461,40 +477,3 @@ ip2k_elf_section_flags (flags, attr, type) return flags; } -static void -ip2k_elf_section_rtn (int i) -{ - obj_elf_section(i); - - if (force_code_align) - { - /* The s_align_ptwo function expects that we are just after a .align - directive and it will either try and read the align value or stop - if end of line so we must fake it out so it thinks we are at the - end of the line. */ - char *old_input_line_pointer = input_line_pointer; - input_line_pointer = "\n"; - s_align_ptwo (1); - force_code_align = 0; - /* Restore. */ - input_line_pointer = old_input_line_pointer; - } -} - -static void -ip2k_elf_section_text (int i) -{ - char *old_input_line_pointer; - obj_elf_text(i); - - /* the s_align_ptwo function expects that we are just after a .align - directive and it will either try and read the align value or stop if - end of line so we must fake it out so it thinks we are at the end of - the line. */ - old_input_line_pointer = input_line_pointer; - input_line_pointer = "\n"; - s_align_ptwo (1); - force_code_align = 0; - /* Restore. */ - input_line_pointer = old_input_line_pointer; -} diff --git a/gas/config/tc-ip2k.h b/gas/config/tc-ip2k.h index 3ce0f5b031d..25f04cd084e 100644 --- a/gas/config/tc-ip2k.h +++ b/gas/config/tc-ip2k.h @@ -1,5 +1,5 @@ /* tc-ip2k.h -- Header file for tc-ip2k.c. - Copyright (C) 2000, 2002 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -59,12 +59,12 @@ #define EXTERN_FORCE_RELOC 0 #define TC_FORCE_RELOCATION(FIX) ip2k_force_relocation (FIX) -extern int ip2k_force_relocation PARAMS ((struct fix *)); +extern int ip2k_force_relocation (struct fix *); #define tc_gen_reloc gas_cgen_tc_gen_reloc #define md_elf_section_flags ip2k_elf_section_flags -extern int ip2k_elf_section_flags PARAMS ((int, int, int)); +extern int ip2k_elf_section_flags (int, int, int); #define md_operand(x) gas_cgen_md_operand (x) -extern void gas_cgen_md_operand PARAMS ((expressionS *)); +extern void gas_cgen_md_operand (expressionS *); diff --git a/gas/config/tc-m32r.c b/gas/config/tc-m32r.c index ed729223c2f..ab574fe71f4 100644 --- a/gas/config/tc-m32r.c +++ b/gas/config/tc-m32r.c @@ -166,7 +166,8 @@ struct m32r_hi_fixup static struct m32r_hi_fixup *m32r_hi_fixup_list; -struct { +struct +{ enum bfd_architecture bfd_mach; int mach_flags; } mach_table[] = @@ -176,8 +177,6 @@ struct { { bfd_mach_m32r2, (1<insn); const CGEN_OPINST *b_ops = CGEN_INSN_OPERANDS (b->insn); @@ -858,11 +823,8 @@ first_writes_to_seconds_operands (a, b, check_outputs) /* Returns true if the insn can (potentially) alter the program counter. */ -static int writes_to_pc PARAMS ((m32r_insn *)); - static int -writes_to_pc (a) - m32r_insn *a; +writes_to_pc (m32r_insn *a) { if (CGEN_INSN_ATTR_VALUE (a->insn, CGEN_INSN_UNCOND_CTI) || CGEN_INSN_ATTR_VALUE (a->insn, CGEN_INSN_COND_CTI)) @@ -873,12 +835,8 @@ writes_to_pc (a) /* Return NULL if the two 16 bit insns can be executed in parallel. Otherwise return a pointer to an error message explaining why not. */ -static const char *can_make_parallel PARAMS ((m32r_insn *, m32r_insn *)); - static const char * -can_make_parallel (a, b) - m32r_insn *a; - m32r_insn *b; +can_make_parallel (m32r_insn *a, m32r_insn *b) { PIPE_ATTR a_pipe; PIPE_ATTR b_pipe; @@ -912,11 +870,8 @@ can_make_parallel (a, b) /* Force the top bit of the second 16-bit insn to be set. */ -static void make_parallel PARAMS ((CGEN_INSN_BYTES_PTR)); - static void -make_parallel (buffer) - CGEN_INSN_BYTES_PTR buffer; +make_parallel (CGEN_INSN_BYTES_PTR buffer) { #if CGEN_INT_INSN_P *buffer |= 0x8000; @@ -928,11 +883,8 @@ make_parallel (buffer) /* Same as make_parallel except buffer contains the bytes in target order. */ -static void target_make_parallel PARAMS ((char *)); - static void -target_make_parallel (buffer) - char *buffer; +target_make_parallel (char *buffer) { buffer[CGEN_CPU_ENDIAN (gas_cgen_cpu_desc) == CGEN_ENDIAN_BIG ? 0 : 1] |= 0x80; @@ -941,13 +893,8 @@ target_make_parallel (buffer) /* Assemble two instructions with an explicit parallel operation (||) or sequential operation (->). */ -static void assemble_two_insns PARAMS ((char *, char *, int)); - static void -assemble_two_insns (str, str2, parallel_p) - char *str; - char *str2; - int parallel_p; +assemble_two_insns (char *str1, char *str2, int parallel_p) { char *str3; m32r_insn first; @@ -971,7 +918,7 @@ assemble_two_insns (str, str2, parallel_p) /* Parse the first instruction. */ if (! (first.insn = m32r_cgen_assemble_insn - (gas_cgen_cpu_desc, str, & first.fields, first.buffer, & errmsg))) + (gas_cgen_cpu_desc, str1, & first.fields, first.buffer, & errmsg))) { as_bad (errmsg); return; @@ -981,7 +928,7 @@ assemble_two_insns (str, str2, parallel_p) if (CGEN_FIELDS_BITSIZE (&first.fields) != 16) { /* xgettext:c-format */ - as_bad (_("not a 16 bit instruction '%s'"), str); + as_bad (_("not a 16 bit instruction '%s'"), str1); return; } #ifdef E_M32R2_ARCH @@ -993,7 +940,7 @@ assemble_two_insns (str, str2, parallel_p) & (1 << MACH_M32RX))))) { /* xgettext:c-format */ - as_bad (_("instruction '%s' is for the M32R2 only"), str); + as_bad (_("instruction '%s' is for the M32R2 only"), str1); return; } else if ((! enable_special @@ -1006,7 +953,7 @@ assemble_two_insns (str, str2, parallel_p) #endif { /* xgettext:c-format */ - as_bad (_("unknown instruction '%s'"), str); + as_bad (_("unknown instruction '%s'"), str1); return; } else if (! enable_m32rx @@ -1015,7 +962,7 @@ assemble_two_insns (str, str2, parallel_p) == (1 << MACH_M32RX))) { /* xgettext:c-format */ - as_bad (_("instruction '%s' is for the M32RX only"), str); + as_bad (_("instruction '%s' is for the M32RX only"), str1); return; } @@ -1024,7 +971,7 @@ assemble_two_insns (str, str2, parallel_p) && CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_PIPE) == PIPE_NONE) { /* xgettext:c-format */ - as_bad (_("instruction '%s' cannot be executed in parallel."), str); + as_bad (_("instruction '%s' cannot be executed in parallel."), str1); return; } @@ -1032,10 +979,10 @@ assemble_two_insns (str, str2, parallel_p) *str2 = save_str2; /* Save the original string pointer. */ - str3 = str; + str3 = str1; /* Advanced past the parsed string. */ - str = str2 + 2; + str1 = str2 + 2; /* Remember the entire string in case it is needed for error messages. */ @@ -1043,7 +990,7 @@ assemble_two_insns (str, str2, parallel_p) /* Convert the opcode to lower case. */ { - char *s2 = str; + char *s2 = str1; while (ISSPACE (*s2++)) continue; @@ -1085,7 +1032,7 @@ assemble_two_insns (str, str2, parallel_p) /* Parse the second instruction. */ if (! (second.insn = m32r_cgen_assemble_insn - (gas_cgen_cpu_desc, str, & second.fields, second.buffer, & errmsg))) + (gas_cgen_cpu_desc, str1, & second.fields, second.buffer, & errmsg))) { as_bad (errmsg); return; @@ -1095,7 +1042,7 @@ assemble_two_insns (str, str2, parallel_p) if (CGEN_FIELDS_BITSIZE (&second.fields) != 16) { /* xgettext:c-format */ - as_bad (_("not a 16 bit instruction '%s'"), str); + as_bad (_("not a 16 bit instruction '%s'"), str1); return; } #ifdef E_M32R2_ARCH @@ -1107,7 +1054,7 @@ assemble_two_insns (str, str2, parallel_p) & (1 << MACH_M32RX))))) { /* xgettext:c-format */ - as_bad (_("instruction '%s' is for the M32R2 only"), str); + as_bad (_("instruction '%s' is for the M32R2 only"), str1); return; } else if ((! enable_special @@ -1120,14 +1067,14 @@ assemble_two_insns (str, str2, parallel_p) #endif { /* xgettext:c-format */ - as_bad (_("unknown instruction '%s'"), str); + as_bad (_("unknown instruction '%s'"), str1); return; } else if (! enable_m32rx && CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_MACH) == (1 << MACH_M32RX)) { /* xgettext:c-format */ - as_bad (_("instruction '%s' is for the M32RX only"), str); + as_bad (_("instruction '%s' is for the M32RX only"), str1); return; } @@ -1136,7 +1083,7 @@ assemble_two_insns (str, str2, parallel_p) && CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_PIPE) == PIPE_NONE) { /* xgettext:c-format */ - as_bad (_("instruction '%s' cannot be executed in parallel."), str); + as_bad (_("instruction '%s' cannot be executed in parallel."), str1); return; } @@ -1246,8 +1193,7 @@ assemble_two_insns (str, str2, parallel_p) } void -md_assemble (str) - char *str; +md_assemble (char *str) { m32r_insn insn; char *errmsg; @@ -1494,8 +1440,7 @@ md_assemble (str) We just ignore it. */ void -md_operand (expressionP) - expressionS *expressionP; +md_operand (expressionS *expressionP) { if (*input_line_pointer == '#') { @@ -1505,17 +1450,15 @@ md_operand (expressionP) } valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); + return ((size + (1 << align) - 1) & (-1 << align)); } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -1528,14 +1471,13 @@ md_undefined_symbol (name) correctly link the object file. */ static void -m32r_scomm (ignore) - int ignore ATTRIBUTE_UNUSED; +m32r_scomm (int ignore ATTRIBUTE_UNUSED) { - register char *name; - register char c; - register char *p; + char *name; + char c; + char *p; offsetT size; - register symbolS *symbolP; + symbolS *symbolP; offsetT align; int align2; @@ -1652,6 +1594,21 @@ m32r_scomm (ignore) demand_empty_rest_of_line (); } + +/* The target specific pseudo-ops which we support. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "word", cons, 4 }, + { "fillinsn", fill_insn, 0 }, + { "scomm", m32r_scomm, 0 }, + { "debugsym", debug_sym, 0 }, + { "m32r", allow_m32rx, 0 }, + { "m32rx", allow_m32rx, 1 }, + { "m32r2", allow_m32rx, 2 }, + { "little", little, 1 }, + { "big", little, 0 }, + { NULL, NULL, 0 } +}; /* Interface to relax_segment. */ @@ -1684,10 +1641,7 @@ const relax_typeS md_relax_table[] = }; long -m32r_relax_frag (segment, fragP, stretch) - segT segment; - fragS *fragP; - long stretch; +m32r_relax_frag (segT segment, fragS *fragP, long stretch) { /* Address of branch insn. */ long address = fragP->fr_address + fragP->fr_fix - 2; @@ -1737,16 +1691,13 @@ m32r_relax_frag (segment, fragP, stretch) with a 0 value. */ int -md_estimate_size_before_relax (fragP, segment) - fragS *fragP; - segT segment; +md_estimate_size_before_relax (fragS *fragP, segT segment) { /* The only thing we have to handle here are symbols outside of the current segment. They may be undefined or in a different segment in which case linker scripts may place them anywhere. However, we can't finish the fragment here and emit the reloc as insn alignment requirements may move the insn about. */ - if (S_GET_SEGMENT (fragP->fr_symbol) != segment || S_IS_EXTERNAL (fragP->fr_symbol) || S_IS_WEAK (fragP->fr_symbol)) @@ -1791,10 +1742,9 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_subtype is the subtype of what the address relaxed to. */ void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec; - fragS *fragP; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + segT sec, + fragS *fragP) { char *opcode; char *displacement; @@ -1890,9 +1840,7 @@ md_convert_frag (abfd, sec, fragP) given a PC relative reloc. */ long -md_pcrel_from_section (fixP, sec) - fixS *fixP; - segT sec; +md_pcrel_from_section (fixS *fixP, segT sec) { if (fixP->fx_addsy != (symbolS *) NULL && (! S_IS_DEFINED (fixP->fx_addsy) @@ -1919,10 +1867,9 @@ md_pcrel_from_section (fixP, sec) *FIXP may be modified if desired. */ bfd_reloc_code_real_type -md_cgen_lookup_reloc (insn, operand, fixP) - const CGEN_INSN *insn ATTRIBUTE_UNUSED; - const CGEN_OPERAND *operand; - fixS *fixP; +md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED, + const CGEN_OPERAND *operand, + fixS *fixP) { switch (operand->type) { @@ -1946,21 +1893,17 @@ md_cgen_lookup_reloc (insn, operand, fixP) /* Record a HI16 reloc for later matching with its LO16 cousin. */ -static void m32r_record_hi16 PARAMS ((int, fixS *, segT)); - static void -m32r_record_hi16 (reloc_type, fixP, seg) - int reloc_type; - fixS *fixP; - segT seg ATTRIBUTE_UNUSED; +m32r_record_hi16 (int reloc_type, + fixS *fixP, + segT seg ATTRIBUTE_UNUSED) { struct m32r_hi_fixup *hi_fixup; assert (reloc_type == BFD_RELOC_M32R_HI16_SLO || reloc_type == BFD_RELOC_M32R_HI16_ULO); - hi_fixup = ((struct m32r_hi_fixup *) - xmalloc (sizeof (struct m32r_hi_fixup))); + hi_fixup = xmalloc (sizeof (* hi_fixup)); hi_fixup->fixp = fixP; hi_fixup->seg = now_seg; hi_fixup->next = m32r_hi_fixup_list; @@ -1972,14 +1915,13 @@ m32r_record_hi16 (reloc_type, fixP, seg) We need to check for HI16 relocs and queue them up for later sorting. */ fixS * -m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) - fragS *frag; - int where; - const CGEN_INSN *insn; - int length; - const CGEN_OPERAND *operand; - int opinfo; - expressionS *exp; +m32r_cgen_record_fixup_exp (fragS *frag, + int where, + const CGEN_INSN *insn, + int length, + const CGEN_OPERAND *operand, + int opinfo, + expressionS *exp) { fixS *fixP; bfd_reloc_code_real_type r_type = BFD_RELOC_UNUSED; @@ -2018,6 +1960,7 @@ m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) else if (fixP->fx_cgen.opinfo == BFD_RELOC_M32R_LO16) r_type = BFD_RELOC_M32R_GOTPC_LO; break; + case BFD_RELOC_M32R_GOT24: if (fixP->fx_cgen.opinfo == BFD_RELOC_M32R_HI16_SLO) r_type = BFD_RELOC_M32R_GOT16_HI_SLO; @@ -2026,6 +1969,7 @@ m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) else if (fixP->fx_cgen.opinfo == BFD_RELOC_M32R_LO16) r_type = BFD_RELOC_M32R_GOT16_LO; break; + case BFD_RELOC_M32R_GOTOFF: if (fixP->fx_cgen.opinfo == BFD_RELOC_M32R_HI16_SLO) r_type = BFD_RELOC_M32R_GOTOFF_HI_SLO; @@ -2034,6 +1978,7 @@ m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) else if (fixP->fx_cgen.opinfo == BFD_RELOC_M32R_LO16) r_type = BFD_RELOC_M32R_GOTOFF_LO; break; + case BFD_RELOC_M32R_26_PLTREL: as_bad (_("Invalid PIC expression.")); break; @@ -2054,7 +1999,7 @@ m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) tc_gen_reloc. */ void -m32r_frob_file () +m32r_frob_file (void) { struct m32r_hi_fixup *l; @@ -2136,8 +2081,7 @@ m32r_frob_file () relaxing. */ int -m32r_force_relocation (fix) - fixS *fix; +m32r_force_relocation (fixS *fix) { if (generic_force_reloc (fix)) return 1; @@ -2151,10 +2095,7 @@ m32r_force_relocation (fix) /* Write a value out to the object file, using the appropriate endianness. */ void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { if (target_big_endian) number_to_chars_bigendian (buf, val, n); @@ -2171,10 +2112,7 @@ md_number_to_chars (buf, val, n) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int i; int prec; @@ -2233,7 +2171,7 @@ md_atof (type, litP, sizeP) } void -m32r_elf_section_change_hook () +m32r_elf_section_change_hook (void) { /* If we have reached the end of a section and we have just emitted a 16 bit insn, then emit a nop to make sure that the section ends on @@ -2247,8 +2185,7 @@ m32r_elf_section_change_hook () (such as .data) instead of relative to some symbol. */ bfd_boolean -m32r_fix_adjustable (fixP) - fixS *fixP; +m32r_fix_adjustable (fixS *fixP) { bfd_reloc_code_real_type reloc_type; @@ -2258,6 +2195,7 @@ m32r_fix_adjustable (fixP) int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex); + reloc_type = md_cgen_lookup_reloc (insn, operand, fixP); } else @@ -2310,16 +2248,14 @@ m32r_elf_final_processing (void) format. */ arelent * -tc_gen_reloc (section, fixP) - asection * section; - fixS * fixP; +tc_gen_reloc (asection * section, fixS * fixP) { arelent * reloc; bfd_reloc_code_real_type code; - reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc = xmalloc (sizeof (* reloc)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; @@ -2334,6 +2270,7 @@ printf("%s",bfd_get_reloc_code_name(code)); case BFD_RELOC_M32R_26_PCREL: code = BFD_RELOC_M32R_26_PLTREL; break; + case BFD_RELOC_M32R_24: if (fixP->fx_addsy != NULL && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) @@ -2341,6 +2278,7 @@ printf("%s",bfd_get_reloc_code_name(code)); else code = BFD_RELOC_M32R_GOT24; break; + case BFD_RELOC_M32R_HI16_ULO: if (fixP->fx_addsy != NULL && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) @@ -2348,6 +2286,7 @@ printf("%s",bfd_get_reloc_code_name(code)); else code = BFD_RELOC_M32R_GOT16_HI_ULO; break; + case BFD_RELOC_M32R_HI16_SLO: if (fixP->fx_addsy != NULL && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) @@ -2355,6 +2294,7 @@ printf("%s",bfd_get_reloc_code_name(code)); else code = BFD_RELOC_M32R_GOT16_HI_SLO; break; + case BFD_RELOC_M32R_LO16: if (fixP->fx_addsy != NULL && strcmp (S_GET_NAME (fixP->fx_addsy), GOT_NAME) == 0) @@ -2362,6 +2302,7 @@ printf("%s",bfd_get_reloc_code_name(code)); else code = BFD_RELOC_M32R_GOT16_LO; break; + default: break; } @@ -2371,10 +2312,12 @@ printf(" => %s",bfd_get_reloc_code_name(code)); } reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + #ifdef DEBUG_PIC printf(" => %s\n",reloc->howto->name); #endif - if (reloc->howto == (reloc_howto_type *) NULL) + + if (reloc->howto == (reloc_howto_type *) NULL) { as_bad_where (fixP->fx_file, fixP->fx_line, _("internal error: can't export reloc type %d (`%s')"), diff --git a/gas/config/tc-m32r.h b/gas/config/tc-m32r.h index 7d3be5763ec..d940410d373 100644 --- a/gas/config/tc-m32r.h +++ b/gas/config/tc-m32r.h @@ -35,7 +35,7 @@ /* The endianness of the target format may change based on command line arguments. */ #define TARGET_FORMAT m32r_target_format() -extern const char *m32r_target_format PARAMS ((void)); +extern const char *m32r_target_format (void); /* Default to big endian. */ #ifndef TARGET_BYTES_BIG_ENDIAN @@ -43,13 +43,13 @@ extern const char *m32r_target_format PARAMS ((void)); #endif /* Call md_pcrel_from_section, not md_pcrel_from. */ -long md_pcrel_from_section PARAMS ((struct fix *, segT)); +long md_pcrel_from_section (struct fix *, segT); #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC) /* Permit temporary numeric labels. */ #define LOCAL_LABELS_FB 1 -#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */ +#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs. */ /* We don't need to handle .word strangely. */ #define WORKING_DOT_WORD @@ -57,14 +57,16 @@ long md_pcrel_from_section PARAMS ((struct fix *, segT)); /* For 8 vs 16 vs 32 bit branch selection. */ extern const struct relax_type md_relax_table[]; #define TC_GENERIC_RELAX_TABLE md_relax_table -extern long m32r_relax_frag PARAMS ((segT, fragS *, long)); + +extern long m32r_relax_frag (segT, fragS *, long); #define md_relax_frag(segment, fragP, stretch) \ -m32r_relax_frag (segment, fragP, stretch) + m32r_relax_frag (segment, fragP, stretch) + /* Account for nop if 32 bit insn falls on odd halfword boundary. */ -#define TC_CGEN_MAX_RELAX(insn, len) (6) +#define TC_CGEN_MAX_RELAX(insn, len) 6 /* Fill in rs_align_code fragments. */ -extern void m32r_handle_align PARAMS ((fragS *)); +extern void m32r_handle_align (fragS *); #define HANDLE_ALIGN(f) m32r_handle_align (f) #define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2 + 4) @@ -75,19 +77,17 @@ extern void m32r_handle_align PARAMS ((fragS *)); #define md_apply_fix3 gas_cgen_md_apply_fix3 #define tc_fix_adjustable(FIX) m32r_fix_adjustable (FIX) -bfd_boolean m32r_fix_adjustable PARAMS ((struct fix *)); +bfd_boolean m32r_fix_adjustable (struct fix *); /* After creating a fixup for an instruction operand, we need to check for HI16 relocs and queue them up for later sorting. */ #define md_cgen_record_fixup_exp m32r_cgen_record_fixup_exp -/* #define tc_gen_reloc gas_cgen_tc_gen_reloc */ - #define TC_HANDLES_FX_DONE extern int pic_code; -extern bfd_boolean m32r_fix_adjustable PARAMS ((struct fix *)); +extern bfd_boolean m32r_fix_adjustable (struct fix *); /* This arranges for gas/write.c to not apply a relocation if obj_fix_adjustable() says it is not adjustable. */ @@ -101,7 +101,7 @@ extern bfd_boolean m32r_fix_adjustable PARAMS ((struct fix *)); && ! S_IS_COMMON ((FIX)->fx_addsy))) #define tc_frob_file_before_fix() m32r_frob_file () -extern void m32r_frob_file PARAMS ((void)); +extern void m32r_frob_file (void); /* No shared lib support, so we don't need to ensure externally visible symbols can be overridden. @@ -109,22 +109,22 @@ extern void m32r_frob_file PARAMS ((void)); /* When relaxing, we need to emit various relocs we otherwise wouldn't. */ #define TC_FORCE_RELOCATION(fix) m32r_force_relocation (fix) -extern int m32r_force_relocation PARAMS ((struct fix *)); +extern int m32r_force_relocation (struct fix *); /* Ensure insns at labels are aligned to 32 bit boundaries. */ -int m32r_fill_insn PARAMS ((int)); +int m32r_fill_insn (int); #define md_after_pass_hook() m32r_fill_insn (1) #define TC_START_LABEL(ch, ptr) (ch == ':' && m32r_fill_insn (0)) #define md_cleanup m32r_elf_section_change_hook #define md_elf_section_change_hook m32r_elf_section_change_hook -extern void m32r_elf_section_change_hook PARAMS ((void)); +extern void m32r_elf_section_change_hook (void); #define md_flush_pending_output() m32r_flush_pending_output () -extern void m32r_flush_pending_output PARAMS ((void)); +extern void m32r_flush_pending_output (void); #define elf_tc_final_processing m32r_elf_final_processing -extern void m32r_elf_final_processing PARAMS ((void)); +extern void m32r_elf_final_processing (void); #define md_parse_name(name, exprP, nextcharP) \ m32r_parse_name ((name), (exprP), (nextcharP)) @@ -136,4 +136,4 @@ extern int m32r_parse_name (char const *, expressionS *, char *); #define TC_CGEN_PARSE_FIX_EXP(opinfo, exp) \ m32r_cgen_parse_fix_exp(opinfo, exp) -extern int m32r_cgen_parse_fix_exp(int, expressionS *); +extern int m32r_cgen_parse_fix_exp (int, expressionS *); diff --git a/gas/config/tc-m88k.c b/gas/config/tc-m88k.c index 6a721e7147b..d2a12ad1065 100644 --- a/gas/config/tc-m88k.c +++ b/gas/config/tc-m88k.c @@ -2,25 +2,25 @@ Contributed by Devon Bowen of Buffalo University and Torbjorn Granlund of the Swedish Institute of Computer Science. Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, - 2000, 2001, 2002, 2003 + 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. -This file is part of GAS, the GNU Assembler. + This file is part of GAS, the GNU Assembler. -GAS is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. -GAS is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GAS; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ #include "as.h" #include "safe-ctype.h" @@ -80,7 +80,7 @@ struct field_val_assoc fcr_regs[] = struct field_val_assoc cmpslot[] = { -/* Integer Floating point */ +/* Integer Floating point. */ {"nc", 0}, {"cp", 1}, {"eq", 2}, @@ -122,30 +122,10 @@ struct m88k_insn enum reloc_type reloc; }; -static char *get_bf PARAMS ((char *param, unsigned *valp)); -static char *get_cmp PARAMS ((char *param, unsigned *valp)); -static char *get_cnd PARAMS ((char *param, unsigned *valp)); -static char *get_bf2 PARAMS ((char *param, int bc)); -static char *get_bf_offset_expression PARAMS ((char *param, unsigned *offsetp)); -static char *get_cr PARAMS ((char *param, unsigned *regnop)); -static char *get_fcr PARAMS ((char *param, unsigned *regnop)); -static char *get_imm16 PARAMS ((char *param, struct m88k_insn *insn)); -static char *get_o6 PARAMS ((char *param, unsigned *valp)); -static char *match_name PARAMS ((char *, struct field_val_assoc *, unsigned *)); -static char *get_reg PARAMS ((char *param, unsigned *regnop, unsigned int reg_prefix)); -static char *get_vec9 PARAMS ((char *param, unsigned *valp)); -static char *getval PARAMS ((char *param, unsigned int *valp)); - -static char *get_pcr PARAMS ((char *param, struct m88k_insn *insn, - enum reloc_type reloc)); - -static int calcop PARAMS ((struct m88k_opcode *format, - char *param, struct m88k_insn *insn)); - extern char *myname; static struct hash_control *op_hash = NULL; -/* These bits should be turned off in the first address of every segment */ +/* These bits should be turned off in the first address of every segment. */ int md_seg_align = 7; /* These chars start a comment anywhere in a source file (except inside @@ -157,32 +137,16 @@ const char line_comment_chars[] = "#"; const char line_separator_chars[] = ""; -/* Chars that can be used to separate mant from exp in floating point nums */ +/* Chars that can be used to separate mant from exp in floating point nums. */ const char EXP_CHARS[] = "eE"; -/* Chars that mean this number is a floating point constant */ -/* as in 0f123.456 */ -/* or 0H1.234E-12 (see exp chars above) */ +/* Chars that mean this number is a floating point constant. + as in 0f123.456 + or 0H1.234E-12 (see exp chars above). */ const char FLT_CHARS[] = "dDfF"; -const pseudo_typeS md_pseudo_table[] = -{ - {"align", s_align_bytes, 4}, - {"def", s_set, 0}, - {"dfloat", float_cons, 'd'}, - {"ffloat", float_cons, 'f'}, - {"half", cons, 2}, - {"bss", s_lcomm, 1}, - {"string", stringer, 0}, - {"word", cons, 4}, - /* Force set to be treated as an instruction. */ - {"set", NULL, 0}, - {".set", s_set, 0}, - {NULL, NULL, 0} -}; - void -md_begin () +md_begin (void) { const char *retval = NULL; unsigned int i = 0; @@ -208,264 +172,341 @@ md_begin () } const char *md_shortopts = ""; -struct option md_longopts[] = { +struct option md_longopts[] = +{ {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED) { return 0; } void -md_show_usage (stream) - FILE *stream ATTRIBUTE_UNUSED; +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) { } -void -md_assemble (op) - char *op; +static char * +get_o6 (char *param, unsigned *valp) { - char *param, *thisfrag; - char c; - struct m88k_opcode *format; - struct m88k_insn insn; + unsigned val; + char *save_ptr; - assert (op); + save_ptr = input_line_pointer; + input_line_pointer = param; + val = get_absolute_expression (); + param = input_line_pointer; + input_line_pointer = save_ptr; - /* Skip over instruction to find parameters. */ - for (param = op; *param != 0 && !ISSPACE (*param); param++) - ; - c = *param; - *param++ = '\0'; + if (val & 0x3) + as_warn (_("Removed lower 2 bits of expression")); - /* Try to find the instruction in the hash table. */ - if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL) + *valp = val; + + return (param); +} + +static char * +get_vec9 (char *param, unsigned *valp) +{ + unsigned val; + char *save_ptr; + + save_ptr = input_line_pointer; + input_line_pointer = param; + val = get_absolute_expression (); + param = input_line_pointer; + input_line_pointer = save_ptr; + + if (val >= 1 << 9) + as_warn (_("Expression truncated to 9 bits")); + + *valp = val % (1 << 9); + + return param; +} + +static char * +get_bf2 (char *param, int bc) +{ + int depth = 0; + int c; + + for (;;) { - as_bad (_("Invalid mnemonic '%s'"), op); - return; + c = *param; + if (c == 0) + return param; + else if (c == '(') + depth++; + else if (c == ')') + depth--; + else if (c == bc && depth <= 0) + return param; + param++; } +} - /* Try parsing this instruction into insn. */ - insn.exp.X_add_symbol = 0; - insn.exp.X_op_symbol = 0; - insn.exp.X_add_number = 0; - insn.exp.X_op = O_illegal; - insn.reloc = NO_RELOC; +static char * +match_name (char *param, + struct field_val_assoc *assoc_tab, + unsigned *valp) +{ + int i; + char *name; + int name_len; - while (!calcop (format, param, &insn)) + for (i = 0;; i++) { - /* If it doesn't parse try the next instruction. */ - if (!strcmp (format[0].name, format[1].name)) - format++; - else + name = assoc_tab[i].name; + if (name == NULL) + return NULL; + name_len = strlen (name); + if (!strncmp (param, name, name_len)) { - as_fatal (_("Parameter syntax error")); - return; + *valp = assoc_tab[i].val; + return param + name_len; } } +} - /* Grow the current frag and plop in the opcode. */ - thisfrag = frag_more (4); - md_number_to_chars (thisfrag, insn.opcode, 4); +static char * +get_bf_offset_expression (char *param, unsigned *offsetp) +{ + unsigned offset; - /* If this instruction requires labels mark it for later. */ - switch (insn.reloc) + if (ISALPHA (param[0])) { - case NO_RELOC: - break; - - case RELOC_LO16: - case RELOC_HI16: - fix_new_exp (frag_now, - thisfrag - frag_now->fr_literal + 2, - 2, - &insn.exp, - 0, - insn.reloc); - break; - - case RELOC_IW16: - fix_new_exp (frag_now, - thisfrag - frag_now->fr_literal, - 4, - &insn.exp, - 0, - insn.reloc); - break; - - case RELOC_PC16: - fix_new_exp (frag_now, - thisfrag - frag_now->fr_literal + 2, - 2, - &insn.exp, - 1, - insn.reloc); - break; + param[0] = TOLOWER (param[0]); + param[1] = TOLOWER (param[1]); - case RELOC_PC26: - fix_new_exp (frag_now, - thisfrag - frag_now->fr_literal, - 4, - &insn.exp, - 1, - insn.reloc); - break; + param = match_name (param, cmpslot, offsetp); - default: - as_fatal (_("Unknown relocation type")); - break; + return param; } + else + { + input_line_pointer = param; + offset = get_absolute_expression (); + param = input_line_pointer; + } + + *offsetp = offset; + return param; } -static int -calcop (format, param, insn) - struct m88k_opcode *format; - char *param; - struct m88k_insn *insn; +static char * +get_bf (char *param, unsigned *valp) { - char *fmt = format->op_spec; - int f; - unsigned val; - unsigned opcode; - unsigned int reg_prefix = 'r'; + unsigned offset = 0; + unsigned width = 0; + char *xp; + char *save_ptr; - insn->opcode = format->opcode; - opcode = 0; + xp = get_bf2 (param, '<'); - for (;;) + save_ptr = input_line_pointer; + input_line_pointer = param; + if (*xp == 0) { - if (param == 0) - return 0; - f = *fmt++; - switch (f) - { - case 0: - insn->opcode |= opcode; - return (*param == 0 || *param == '\n'); + /* We did not find '<'. We have an offset (width implicitly 32). */ + param = get_bf_offset_expression (param, &offset); + input_line_pointer = save_ptr; + if (param == NULL) + return NULL; + } + else + { + *xp++ = 0; /* Overwrite the '<'. */ + param = get_bf2 (xp, '>'); + if (*param == 0) + return NULL; + *param++ = 0; /* Overwrite the '>'. */ - default: - if (f != *param++) - return 0; - break; + width = get_absolute_expression (); + xp = get_bf_offset_expression (xp, &offset); + input_line_pointer = save_ptr; - case 'd': - param = get_reg (param, &val, reg_prefix); - reg_prefix = 'r'; - opcode |= val << 21; - break; + if (xp + 1 != param) + return NULL; + } - case 'o': - param = get_o6 (param, &val); - opcode |= ((val >> 2) << 7); - break; + *valp = ((width % 32) << 5) | (offset % 32); - case 'x': - reg_prefix = 'x'; - break; + return param; +} - case '1': - param = get_reg (param, &val, reg_prefix); - reg_prefix = 'r'; - opcode |= val << 16; - break; +static char * +get_cr (char *param, unsigned *regnop) +{ + unsigned regno; + unsigned c; - case '2': - param = get_reg (param, &val, reg_prefix); - reg_prefix = 'r'; - opcode |= val; - break; + if (!strncmp (param, "cr", 2)) + { + param += 2; - case '3': - param = get_reg (param, &val, 'r'); - opcode |= (val << 16) | val; - break; + regno = *param++ - '0'; + if (regno < 10) + { + if (regno == 0) + { + *regnop = 0; + return param; + } + c = *param - '0'; + if (c < 10) + { + regno = regno * 10 + c; + if (c < 64) + { + *regnop = regno; + return param + 1; + } + } + else + { + *regnop = regno; + return param; + } + } + return NULL; + } - case 'I': - param = get_imm16 (param, insn); - break; + param = match_name (param, cr_regs, regnop); - case 'b': - param = get_bf (param, &val); - opcode |= val; - break; + return param; +} - case 'p': - param = get_pcr (param, insn, RELOC_PC16); - break; +static char * +get_fcr (char *param, unsigned *regnop) +{ + unsigned regno; + unsigned c; - case 'P': - param = get_pcr (param, insn, RELOC_PC26); - break; + if (!strncmp (param, "fcr", 3)) + { + param += 3; - case 'B': - param = get_cmp (param, &val); - opcode |= val; - break; + regno = *param++ - '0'; + if (regno < 10) + { + if (regno == 0) + { + *regnop = 0; + return param; + } + c = *param - '0'; + if (c < 10) + { + regno = regno * 10 + c; + if (c < 64) + { + *regnop = regno; + return param + 1; + } + } + else + { + *regnop = regno; + return param; + } + } + return NULL; + } - case 'M': - param = get_cnd (param, &val); - opcode |= val; - break; + param = match_name (param, fcr_regs, regnop); - case 'c': - param = get_cr (param, &val); - opcode |= val << 5; - break; + return param; +} - case 'f': - param = get_fcr (param, &val); - opcode |= val << 5; - break; +#define hexval(z) \ + (ISDIGIT (z) ? (z) - '0' : \ + ISLOWER (z) ? (z) - 'a' + 10 : \ + ISUPPER (z) ? (z) - 'A' + 10 : (unsigned) -1) - case 'V': - param = get_vec9 (param, &val); - opcode |= val; - break; +static char * +getval (char *param, unsigned int *valp) +{ + unsigned int val = 0; + unsigned int c; - case '?': - /* Having this here repeats the warning somtimes. - But can't we stand that? */ - as_warn (_("Use of obsolete instruction")); - break; + c = *param++; + if (c == '0') + { + c = *param++; + if (c == 'x' || c == 'X') + { + c = *param++; + c = hexval (c); + while (c < 16) + { + val = val * 16 + c; + c = *param++; + c = hexval (c); + } + } + else + { + c -= '0'; + while (c < 8) + { + val = val * 8 + c; + c = *param++ - '0'; + } + } + } + else + { + c -= '0'; + while (c < 10) + { + val = val * 10 + c; + c = *param++ - '0'; } } + + *valp = val; + return param - 1; } static char * -match_name (param, assoc_tab, valp) - char *param; - struct field_val_assoc *assoc_tab; - unsigned *valp; +get_cnd (char *param, unsigned *valp) { - int i; - char *name; - int name_len; + unsigned int val; - for (i = 0;; i++) + if (ISDIGIT (*param)) { - name = assoc_tab[i].name; - if (name == NULL) - return NULL; - name_len = strlen (name); - if (!strncmp (param, name, name_len)) + param = getval (param, &val); + + if (val >= 32) { - *valp = assoc_tab[i].val; - return param + name_len; + as_warn (_("Expression truncated to 5 bits")); + val %= 32; } } + else + { + param[0] = TOLOWER (param[0]); + param[1] = TOLOWER (param[1]); + + param = match_name (param, cndmsk, valp); + + if (param == NULL) + return NULL; + + val = *valp; + } + + *valp = val << 21; + return param; } static char * -get_reg (param, regnop, reg_prefix) - char *param; - unsigned *regnop; - unsigned int reg_prefix; +get_reg (char *param, unsigned *regnop, unsigned int reg_prefix) { unsigned c; unsigned regno; @@ -509,9 +550,7 @@ get_reg (param, regnop, reg_prefix) } static char * -get_imm16 (param, insn) - char *param; - struct m88k_insn *insn; +get_imm16 (char *param, struct m88k_insn *insn) { enum reloc_type reloc = NO_RELOC; unsigned int val; @@ -568,10 +607,7 @@ get_imm16 (param, insn) } static char * -get_pcr (param, insn, reloc) - char *param; - struct m88k_insn *insn; - enum reloc_type reloc; +get_pcr (char *param, struct m88k_insn *insn, enum reloc_type reloc) { char *saveptr, *saveparam; @@ -590,9 +626,7 @@ get_pcr (param, insn, reloc) } static char * -get_cmp (param, valp) - char *param; - unsigned *valp; +get_cmp (char *param, unsigned *valp) { unsigned int val; char *save_ptr; @@ -623,322 +657,216 @@ get_cmp (param, valp) return param; } -static char * -get_cnd (param, valp) - char *param; - unsigned *valp; +static int +calcop (struct m88k_opcode *format, + char *param, + struct m88k_insn *insn) { - unsigned int val; - - if (ISDIGIT (*param)) - { - param = getval (param, &val); - - if (val >= 32) - { - as_warn (_("Expression truncated to 5 bits")); - val %= 32; - } - } - else - { - param[0] = TOLOWER (param[0]); - param[1] = TOLOWER (param[1]); - - param = match_name (param, cndmsk, valp); - - if (param == NULL) - return NULL; - - val = *valp; - } - - *valp = val << 21; - return param; -} + char *fmt = format->op_spec; + int f; + unsigned val; + unsigned opcode; + unsigned int reg_prefix = 'r'; -static char * -get_bf2 (param, bc) - char *param; - int bc; -{ - int depth = 0; - int c; + insn->opcode = format->opcode; + opcode = 0; for (;;) { - c = *param; - if (c == 0) - return param; - else if (c == '(') - depth++; - else if (c == ')') - depth--; - else if (c == bc && depth <= 0) - return param; - param++; - } -} - -static char * -get_bf_offset_expression (param, offsetp) - char *param; - unsigned *offsetp; -{ - unsigned offset; - - if (ISALPHA (param[0])) - { - param[0] = TOLOWER (param[0]); - param[1] = TOLOWER (param[1]); - - param = match_name (param, cmpslot, offsetp); - - return param; - } - else - { - input_line_pointer = param; - offset = get_absolute_expression (); - param = input_line_pointer; - } - - *offsetp = offset; - return param; -} - -static char * -get_bf (param, valp) - char *param; - unsigned *valp; -{ - unsigned offset = 0; - unsigned width = 0; - char *xp; - char *save_ptr; - - xp = get_bf2 (param, '<'); - - save_ptr = input_line_pointer; - input_line_pointer = param; - if (*xp == 0) - { - /* We did not find '<'. We have an offset (width implicitly 32). */ - param = get_bf_offset_expression (param, &offset); - input_line_pointer = save_ptr; - if (param == NULL) - return NULL; - } - else - { - *xp++ = 0; /* Overwrite the '<' */ - param = get_bf2 (xp, '>'); - if (*param == 0) - return NULL; - *param++ = 0; /* Overwrite the '>' */ - - width = get_absolute_expression (); - xp = get_bf_offset_expression (xp, &offset); - input_line_pointer = save_ptr; - - if (xp + 1 != param) - return NULL; - } - - *valp = ((width % 32) << 5) | (offset % 32); + if (param == 0) + return 0; + f = *fmt++; + switch (f) + { + case 0: + insn->opcode |= opcode; + return (*param == 0 || *param == '\n'); - return param; -} + default: + if (f != *param++) + return 0; + break; -static char * -get_cr (param, regnop) - char *param; - unsigned *regnop; -{ - unsigned regno; - unsigned c; + case 'd': + param = get_reg (param, &val, reg_prefix); + reg_prefix = 'r'; + opcode |= val << 21; + break; - if (!strncmp (param, "cr", 2)) - { - param += 2; + case 'o': + param = get_o6 (param, &val); + opcode |= ((val >> 2) << 7); + break; - regno = *param++ - '0'; - if (regno < 10) - { - if (regno == 0) - { - *regnop = 0; - return param; - } - c = *param - '0'; - if (c < 10) - { - regno = regno * 10 + c; - if (c < 64) - { - *regnop = regno; - return param + 1; - } - } - else - { - *regnop = regno; - return param; - } - } - return NULL; - } + case 'x': + reg_prefix = 'x'; + break; - param = match_name (param, cr_regs, regnop); + case '1': + param = get_reg (param, &val, reg_prefix); + reg_prefix = 'r'; + opcode |= val << 16; + break; - return param; -} + case '2': + param = get_reg (param, &val, reg_prefix); + reg_prefix = 'r'; + opcode |= val; + break; -static char * -get_fcr (param, regnop) - char *param; - unsigned *regnop; -{ - unsigned regno; - unsigned c; + case '3': + param = get_reg (param, &val, 'r'); + opcode |= (val << 16) | val; + break; - if (!strncmp (param, "fcr", 3)) - { - param += 3; + case 'I': + param = get_imm16 (param, insn); + break; - regno = *param++ - '0'; - if (regno < 10) - { - if (regno == 0) - { - *regnop = 0; - return param; - } - c = *param - '0'; - if (c < 10) - { - regno = regno * 10 + c; - if (c < 64) - { - *regnop = regno; - return param + 1; - } - } - else - { - *regnop = regno; - return param; - } - } - return NULL; - } + case 'b': + param = get_bf (param, &val); + opcode |= val; + break; - param = match_name (param, fcr_regs, regnop); + case 'p': + param = get_pcr (param, insn, RELOC_PC16); + break; - return param; -} + case 'P': + param = get_pcr (param, insn, RELOC_PC26); + break; -static char * -get_vec9 (param, valp) - char *param; - unsigned *valp; -{ - unsigned val; - char *save_ptr; + case 'B': + param = get_cmp (param, &val); + opcode |= val; + break; - save_ptr = input_line_pointer; - input_line_pointer = param; - val = get_absolute_expression (); - param = input_line_pointer; - input_line_pointer = save_ptr; + case 'M': + param = get_cnd (param, &val); + opcode |= val; + break; - if (val >= 1 << 9) - as_warn (_("Expression truncated to 9 bits")); + case 'c': + param = get_cr (param, &val); + opcode |= val << 5; + break; - *valp = val % (1 << 9); + case 'f': + param = get_fcr (param, &val); + opcode |= val << 5; + break; - return param; + case 'V': + param = get_vec9 (param, &val); + opcode |= val; + break; + + case '?': + /* Having this here repeats the warning somtimes. + But can't we stand that? */ + as_warn (_("Use of obsolete instruction")); + break; + } + } } -static char * -get_o6 (param, valp) - char *param; - unsigned *valp; +void +md_assemble (char *op) { - unsigned val; - char *save_ptr; - - save_ptr = input_line_pointer; - input_line_pointer = param; - val = get_absolute_expression (); - param = input_line_pointer; - input_line_pointer = save_ptr; - - if (val & 0x3) - as_warn (_("Removed lower 2 bits of expression")); + char *param, *thisfrag; + char c; + struct m88k_opcode *format; + struct m88k_insn insn; - *valp = val; + assert (op); - return (param); -} + /* Skip over instruction to find parameters. */ + for (param = op; *param != 0 && !ISSPACE (*param); param++) + ; + c = *param; + *param++ = '\0'; -#define hexval(z) \ - (ISDIGIT (z) ? (z) - '0' : \ - ISLOWER (z) ? (z) - 'a' + 10 : \ - ISUPPER (z) ? (z) - 'A' + 10 : (unsigned) -1) + /* Try to find the instruction in the hash table. */ + if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL) + { + as_bad (_("Invalid mnemonic '%s'"), op); + return; + } -static char * -getval (param, valp) - char *param; - unsigned int *valp; -{ - unsigned int val = 0; - unsigned int c; + /* Try parsing this instruction into insn. */ + insn.exp.X_add_symbol = 0; + insn.exp.X_op_symbol = 0; + insn.exp.X_add_number = 0; + insn.exp.X_op = O_illegal; + insn.reloc = NO_RELOC; - c = *param++; - if (c == '0') + while (!calcop (format, param, &insn)) { - c = *param++; - if (c == 'x' || c == 'X') - { - c = *param++; - c = hexval (c); - while (c < 16) - { - val = val * 16 + c; - c = *param++; - c = hexval (c); - } - } + /* If it doesn't parse try the next instruction. */ + if (!strcmp (format[0].name, format[1].name)) + format++; else { - c -= '0'; - while (c < 8) - { - val = val * 8 + c; - c = *param++ - '0'; - } + as_fatal (_("Parameter syntax error")); + return; } } - else + + /* Grow the current frag and plop in the opcode. */ + thisfrag = frag_more (4); + md_number_to_chars (thisfrag, insn.opcode, 4); + + /* If this instruction requires labels mark it for later. */ + switch (insn.reloc) { - c -= '0'; - while (c < 10) - { - val = val * 10 + c; - c = *param++ - '0'; - } - } + case NO_RELOC: + break; - *valp = val; - return param - 1; + case RELOC_LO16: + case RELOC_HI16: + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal + 2, + 2, + &insn.exp, + 0, + insn.reloc); + break; + + case RELOC_IW16: + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal, + 4, + &insn.exp, + 0, + insn.reloc); + break; + + case RELOC_PC16: + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal + 2, + 2, + &insn.exp, + 1, + insn.reloc); + break; + + case RELOC_PC26: + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal, + 4, + &insn.exp, + 1, + insn.reloc); + break; + + default: + as_fatal (_("Unknown relocation type")); + break; + } } void -md_number_to_chars (buf, val, nbytes) - char *buf; - valueT val; - int nbytes; +md_number_to_chars (char *buf, valueT val, int nbytes) { number_to_chars_bigendian (buf, val, nbytes); } @@ -947,13 +875,10 @@ md_number_to_chars (buf, val, nbytes) /* Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS - emitted is stored in *sizeP . An error message is returned, or NULL on OK. - */ + emitted is stored in *sizeP . An error message is returned, or NULL on OK. */ + char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -1006,12 +931,11 @@ md_atof (type, litP, sizeP) int md_short_jump_size = 4; void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr ATTRIBUTE_UNUSED; - addressT to_addr ATTRIBUTE_UNUSED; - fragS *frag; - symbolS *to_symbol; +md_create_short_jump (char *ptr, + addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, + fragS *frag, + symbolS *to_symbol) { ptr[0] = (char) 0xc0; ptr[1] = 0x00; @@ -1029,12 +953,11 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) int md_long_jump_size = 4; void -md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr ATTRIBUTE_UNUSED; - addressT to_addr ATTRIBUTE_UNUSED; - fragS *frag; - symbolS *to_symbol; +md_create_long_jump (char *ptr, + addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, + fragS *frag, + symbolS *to_symbol) { ptr[0] = (char) 0xc0; ptr[1] = 0x00; @@ -1050,12 +973,11 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) } int -md_estimate_size_before_relax (fragP, segment_type) - fragS *fragP ATTRIBUTE_UNUSED; - segT segment_type ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, + segT segment_type ATTRIBUTE_UNUSED) { as_fatal (_("Relaxation should never occur")); - return (-1); + return -1; } #ifdef M88KCOFF @@ -1070,8 +992,7 @@ md_estimate_size_before_relax (fragP, segment_type) return the BFD relocation type to use for it. */ short -tc_coff_fix2rtype (fixp) - fixS *fixp; +tc_coff_fix2rtype (fixS *fixp) { switch (fixp->fx_r_type) { @@ -1097,10 +1018,7 @@ tc_coff_fix2rtype (fixp) file itself. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED) { long val = * (long *) valP; char *buf; @@ -1159,8 +1077,7 @@ md_apply_fix3 (fixP, valP, seg) are calculated from just after the instruction. */ long -md_pcrel_from (fixp) - fixS *fixp; +md_pcrel_from (fixS *fixp) { switch (fixp->fx_r_type) { @@ -1171,14 +1088,12 @@ md_pcrel_from (fixp) default: abort (); } - /*NOTREACHED*/ } /* Fill in rs_align_code fragments. */ void -m88k_handle_align (fragp) - fragS *fragp; +m88k_handle_align (fragS *fragp) { static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 }; @@ -1205,3 +1120,19 @@ m88k_handle_align (fragp) } #endif /* M88KCOFF */ + +const pseudo_typeS md_pseudo_table[] = +{ + {"align", s_align_bytes, 4}, + {"def", s_set, 0}, + {"dfloat", float_cons, 'd'}, + {"ffloat", float_cons, 'f'}, + {"half", cons, 2}, + {"bss", s_lcomm, 1}, + {"string", stringer, 0}, + {"word", cons, 4}, + /* Force set to be treated as an instruction. */ + {"set", NULL, 0}, + {".set", s_set, 0}, + {NULL, NULL, 0} +}; diff --git a/gas/config/tc-m88k.h b/gas/config/tc-m88k.h index 5b0a8351529..65ecff3625e 100644 --- a/gas/config/tc-m88k.h +++ b/gas/config/tc-m88k.h @@ -2,49 +2,49 @@ Contributed by Devon Bowen of Buffalo University and Torbjorn Granlund of the Swedish Institute of Computer Science. Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000, - 2002 Free Software Foundation, Inc. + 2002, 2005 Free Software Foundation, Inc. -This file is part of GAS, the GNU Assembler. + This file is part of GAS, the GNU Assembler. -GAS is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. -GAS is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GAS; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ #define TC_M88K #define TARGET_BYTES_BIG_ENDIAN 1 #ifdef M88KCOFF -#define COFF_MAGIC MC88OMAGIC -#define BFD_ARCH bfd_arch_m88k -#define COFF_FLAGS F_AR32W +#define COFF_MAGIC MC88OMAGIC +#define BFD_ARCH bfd_arch_m88k +#define COFF_FLAGS F_AR32W #endif #define NEED_FX_R_TYPE #define TC_KEEP_FX_OFFSET #define TC_CONS_RELOC RELOC_32 -/* different type of relocation available in the m88k */ +/* Different type of relocation available in the m88k. */ enum reloc_type { - RELOC_LO16, /* lo16(sym) */ - RELOC_HI16, /* hi16(sym) */ - RELOC_PC16, /* bb0, bb1, bcnd */ - RELOC_PC26, /* br, bsr */ - RELOC_32, /* jump tables, etc */ - RELOC_IW16, /* global access through linker regs 28 */ + RELOC_LO16, /* lo16(sym). */ + RELOC_HI16, /* hi16(sym). */ + RELOC_PC16, /* bb0, bb1, bcnd. */ + RELOC_PC26, /* br, bsr. */ + RELOC_32, /* Jump tables, etc. */ + RELOC_IW16, /* Global access through linker regs 28. */ NO_RELOC }; @@ -101,7 +101,7 @@ struct reloc_info_m88k #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) max (section_alignment[(int) (SEG)], 4) /* Fill in rs_align_code fragments. */ -extern void m88k_handle_align PARAMS ((fragS *)); +extern void m88k_handle_align (fragS *); #define HANDLE_ALIGN(frag) m88k_handle_align (frag) #define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4) diff --git a/gas/config/tc-mcore.c b/gas/config/tc-mcore.c index 7a1499745a2..6319f337ab7 100644 --- a/gas/config/tc-mcore.c +++ b/gas/config/tc-mcore.c @@ -37,31 +37,6 @@ #endif /* Forward declarations for dumb compilers. */ -static void mcore_s_literals PARAMS ((int)); -static void mcore_pool_count PARAMS ((void (*) (int), int)); -static void mcore_cons PARAMS ((int)); -static void mcore_float_cons PARAMS ((int)); -static void mcore_stringer PARAMS ((int)); -static void mcore_fill PARAMS ((int)); -static int mylog2 PARAMS ((unsigned int)); -static char * parse_reg PARAMS ((char *, unsigned *)); -static char * parse_creg PARAMS ((char *, unsigned *)); -static char * parse_exp PARAMS ((char *, expressionS *)); -static char * parse_rt PARAMS ((char *, char **, int, expressionS *)); -static char * parse_imm PARAMS ((char *, unsigned *, unsigned, unsigned)); -static char * parse_mem PARAMS ((char *, unsigned *, unsigned *, unsigned)); -static char * parse_psrmod PARAMS ((char *, unsigned *)); -static void make_name PARAMS ((char *, char *, int)); -static int enter_literal PARAMS ((expressionS *, int)); -static void dump_literals PARAMS ((int)); -static void check_literals PARAMS ((int, int)); -static void mcore_s_text PARAMS ((int)); -static void mcore_s_data PARAMS ((int)); -static void mcore_s_section PARAMS ((int)); -static void mcore_s_bss PARAMS ((int)); -#ifdef OBJ_ELF -static void mcore_s_comm PARAMS ((int)); -#endif /* Several places in this file insert raw instructions into the object. They should use MCORE_INST_XXX macros to get the opcodes @@ -89,7 +64,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define C(what,length) (((what) << 2) + (length)) #define GET_WHAT(x) ((x >> 2)) -/* These are the two types of relaxable instruction */ +/* These are the two types of relaxable instruction. */ #define COND_JUMP 1 #define UNCD_JUMP 2 @@ -99,9 +74,9 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define UNDEF_WORD_DISP 3 #define C12_LEN 2 -#define C32_LEN 10 /* allow for align */ +#define C32_LEN 10 /* Allow for align. */ #define U12_LEN 2 -#define U32_LEN 8 /* allow for align */ +#define U32_LEN 8 /* Allow for align. */ typedef enum { @@ -113,7 +88,8 @@ cpu_type; cpu_type cpu = M340; /* Initialize the relax table. */ -const relax_typeS md_relax_table[] = { +const relax_typeS md_relax_table[] = +{ { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, @@ -163,68 +139,76 @@ static unsigned long poolspan; #define SPANPANIC (1016) /* 1024 - 1 entry - 2 byte rounding. */ #define SPANCLOSE (900) #define SPANEXIT (600) -static symbolS * poolsym; /* label for current pool. */ +static symbolS * poolsym; /* Label for current pool. */ static char poolname[8]; static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */ -/* This table describes all the machine specific pseudo-ops the assembler - has to support. The fields are: - Pseudo-op name without dot - Function to call to execute this pseudo-op - Integer arg to pass to the function. */ -const pseudo_typeS md_pseudo_table[] = +#define POOL_END_LABEL ".LE" +#define POOL_START_LABEL ".LS" + +static void +make_name (char * s, char * p, int n) { - { "export", s_globl, 0 }, - { "import", s_ignore, 0 }, - { "literals", mcore_s_literals, 0 }, - { "page", listing_eject, 0 }, + static const char hex[] = "0123456789ABCDEF"; - /* The following are to intercept the placement of data into the text - section (eg addresses for a switch table), so that the space they - occupy can be taken into account when deciding whether or not to - dump the current literal pool. - XXX - currently we do not cope with the .space and .dcb.d directives. */ - { "ascii", mcore_stringer, 0 }, - { "asciz", mcore_stringer, 1 }, - { "byte", mcore_cons, 1 }, - { "dc", mcore_cons, 2 }, - { "dc.b", mcore_cons, 1 }, - { "dc.d", mcore_float_cons, 'd'}, - { "dc.l", mcore_cons, 4 }, - { "dc.s", mcore_float_cons, 'f'}, - { "dc.w", mcore_cons, 2 }, - { "dc.x", mcore_float_cons, 'x'}, - { "double", mcore_float_cons, 'd'}, - { "float", mcore_float_cons, 'f'}, - { "hword", mcore_cons, 2 }, - { "int", mcore_cons, 4 }, - { "long", mcore_cons, 4 }, - { "octa", mcore_cons, 16 }, - { "quad", mcore_cons, 8 }, - { "short", mcore_cons, 2 }, - { "single", mcore_float_cons, 'f'}, - { "string", mcore_stringer, 1 }, - { "word", mcore_cons, 2 }, - { "fill", mcore_fill, 0 }, + s[0] = p[0]; + s[1] = p[1]; + s[2] = p[2]; + s[3] = hex[(n >> 12) & 0xF]; + s[4] = hex[(n >> 8) & 0xF]; + s[5] = hex[(n >> 4) & 0xF]; + s[6] = hex[(n) & 0xF]; + s[7] = 0; +} - /* Allow for the effect of section changes. */ - { "text", mcore_s_text, 0 }, - { "data", mcore_s_data, 0 }, - { "bss", mcore_s_bss, 1 }, -#ifdef OBJ_ELF - { "comm", mcore_s_comm, 0 }, -#endif - { "section", mcore_s_section, 0 }, - { "section.s", mcore_s_section, 0 }, - { "sect", mcore_s_section, 0 }, - { "sect.s", mcore_s_section, 0 }, +static void +dump_literals (int isforce) +{ + unsigned int i; + struct literal * p; + symbolS * brarsym = NULL; - { 0, 0, 0 } -}; + if (poolsize == 0) + return; + + /* Must we branch around the literal table? */ + if (isforce) + { + char * output; + char brarname[8]; + + make_name (brarname, POOL_END_LABEL, poolnumber); + + brarsym = symbol_make (brarname); + + symbol_table_insert (brarsym); + + output = frag_var (rs_machine_dependent, + md_relax_table[C (UNCD_JUMP, DISP32)].rlx_length, + md_relax_table[C (UNCD_JUMP, DISP12)].rlx_length, + C (UNCD_JUMP, 0), brarsym, 0, 0); + output[0] = INST_BYTE0 (MCORE_INST_BR); /* br .+xxx */ + output[1] = INST_BYTE1 (MCORE_INST_BR); + } + + /* Make sure that the section is sufficiently aligned and that + the literal table is aligned within it. */ + record_alignment (now_seg, 2); + frag_align (2, 0, 0); + + colon (S_GET_NAME (poolsym)); + + for (i = 0, p = litpool; i < poolsize; i++, p++) + emit_expr (& p->e, 4); + + if (brarsym != NULL) + colon (S_GET_NAME (brarsym)); + + poolsize = 0; +} static void -mcore_s_literals (ignore) - int ignore ATTRIBUTE_UNUSED; +mcore_s_literals (int ignore ATTRIBUTE_UNUSED) { dump_literals (0); demand_empty_rest_of_line (); @@ -233,9 +217,7 @@ mcore_s_literals (ignore) /* Perform FUNC (ARG), and track number of bytes added to frag. */ static void -mcore_pool_count (func, arg) - void (*func) PARAMS ((int)); - int arg; +mcore_pool_count (void (*func) (int), int arg) { const fragS *curr_frag = frag_now; offsetT added = -frag_now_fix_octets (); @@ -253,8 +235,42 @@ mcore_pool_count (func, arg) } static void -mcore_cons (nbytes) - int nbytes; +check_literals (int kind, int offset) +{ + poolspan += offset; + + /* SPANCLOSE and SPANEXIT are smaller numbers than SPANPANIC. + SPANPANIC means that we must dump now. + kind == 0 is any old instruction. + kind > 0 means we just had a control transfer instruction. + kind == 1 means within a function + kind == 2 means we just left a function + + The dump_literals (1) call inserts a branch around the table, so + we first look to see if its a situation where we won't have to + insert a branch (e.g., the previous instruction was an unconditional + branch). + + SPANPANIC is the point where we must dump a single-entry pool. + it accounts for alignments and an inserted branch. + the 'poolsize*2' accounts for the scenario where we do: + lrw r1,lit1; lrw r2,lit2; lrw r3,lit3 + Note that the 'lit2' reference is 2 bytes further along + but the literal it references will be 4 bytes further along, + so we must consider the poolsize into this equation. + This is slightly over-cautious, but guarantees that we won't + panic because a relocation is too distant. */ + + if (poolspan > SPANCLOSE && kind > 0) + dump_literals (0); + else if (poolspan > SPANEXIT && kind > 1) + dump_literals (0); + else if (poolspan >= (SPANPANIC - poolsize * 2)) + dump_literals (1); +} + +static void +mcore_cons (int nbytes) { if (now_seg == text_section) mcore_pool_count (cons, nbytes); @@ -269,8 +285,7 @@ mcore_cons (nbytes) } static void -mcore_float_cons (float_type) - int float_type; +mcore_float_cons (int float_type) { if (now_seg == text_section) mcore_pool_count (float_cons, float_type); @@ -285,8 +300,7 @@ mcore_float_cons (float_type) } static void -mcore_stringer (append_zero) - int append_zero; +mcore_stringer (int append_zero) { if (now_seg == text_section) mcore_pool_count (stringer, append_zero); @@ -302,8 +316,7 @@ mcore_stringer (append_zero) } static void -mcore_fill (unused) - int unused; +mcore_fill (int unused) { if (now_seg == text_section) mcore_pool_count (s_fill, unused); @@ -315,9 +328,9 @@ mcore_fill (unused) /* Handle the section changing pseudo-ops. These call through to the normal implementations, but they dump the literal pool first. */ + static void -mcore_s_text (ignore) - int ignore; +mcore_s_text (int ignore) { dump_literals (0); @@ -329,8 +342,7 @@ mcore_s_text (ignore) } static void -mcore_s_data (ignore) - int ignore; +mcore_s_data (int ignore) { dump_literals (0); @@ -342,8 +354,7 @@ mcore_s_data (ignore) } static void -mcore_s_section (ignore) - int ignore; +mcore_s_section (int ignore) { /* Scan forwards to find the name of the section. If the section being switched to is ".line" then this is a DWARF1 debug section @@ -371,8 +382,7 @@ mcore_s_section (ignore) } static void -mcore_s_bss (needs_align) - int needs_align; +mcore_s_bss (int needs_align) { dump_literals (0); @@ -381,8 +391,7 @@ mcore_s_bss (needs_align) #ifdef OBJ_ELF static void -mcore_s_comm (needs_align) - int needs_align; +mcore_s_comm (int needs_align) { dump_literals (0); @@ -390,17 +399,73 @@ mcore_s_comm (needs_align) } #endif +/* This table describes all the machine specific pseudo-ops the assembler + has to support. The fields are: + Pseudo-op name without dot + Function to call to execute this pseudo-op + Integer arg to pass to the function. */ +const pseudo_typeS md_pseudo_table[] = +{ + { "export", s_globl, 0 }, + { "import", s_ignore, 0 }, + { "literals", mcore_s_literals, 0 }, + { "page", listing_eject, 0 }, + + /* The following are to intercept the placement of data into the text + section (eg addresses for a switch table), so that the space they + occupy can be taken into account when deciding whether or not to + dump the current literal pool. + XXX - currently we do not cope with the .space and .dcb.d directives. */ + { "ascii", mcore_stringer, 0 }, + { "asciz", mcore_stringer, 1 }, + { "byte", mcore_cons, 1 }, + { "dc", mcore_cons, 2 }, + { "dc.b", mcore_cons, 1 }, + { "dc.d", mcore_float_cons, 'd'}, + { "dc.l", mcore_cons, 4 }, + { "dc.s", mcore_float_cons, 'f'}, + { "dc.w", mcore_cons, 2 }, + { "dc.x", mcore_float_cons, 'x'}, + { "double", mcore_float_cons, 'd'}, + { "float", mcore_float_cons, 'f'}, + { "hword", mcore_cons, 2 }, + { "int", mcore_cons, 4 }, + { "long", mcore_cons, 4 }, + { "octa", mcore_cons, 16 }, + { "quad", mcore_cons, 8 }, + { "short", mcore_cons, 2 }, + { "single", mcore_float_cons, 'f'}, + { "string", mcore_stringer, 1 }, + { "word", mcore_cons, 2 }, + { "fill", mcore_fill, 0 }, + + /* Allow for the effect of section changes. */ + { "text", mcore_s_text, 0 }, + { "data", mcore_s_data, 0 }, + { "bss", mcore_s_bss, 1 }, +#ifdef OBJ_ELF + { "comm", mcore_s_comm, 0 }, +#endif + { "section", mcore_s_section, 0 }, + { "section.s", mcore_s_section, 0 }, + { "sect", mcore_s_section, 0 }, + { "sect.s", mcore_s_section, 0 }, + + { 0, 0, 0 } +}; + /* This function is called once, at assembler startup time. This should set up all the tables, etc that the MD part of the assembler needs. */ + void -md_begin () +md_begin (void) { const mcore_opcode_info * opcode; char * prev_name = ""; opcode_hash_control = hash_new (); - /* Insert unique names into hash table */ + /* Insert unique names into hash table. */ for (opcode = mcore_table; opcode->name; opcode ++) { if (! streq (prev_name, opcode->name)) @@ -412,25 +477,25 @@ md_begin () } /* Get a log2(val). */ + static int -mylog2 (val) - unsigned int val; +mylog2 (unsigned int val) { - int log = -1; - while (val != 0) + int log = -1; + + while (val != 0) { log ++; val >>= 1; } - return log; + return log; } /* Try to parse a reg name. */ + static char * -parse_reg (s, reg) - char * s; - unsigned * reg; +parse_reg (char * s, unsigned * reg) { /* Strip leading whitespace. */ while (ISSPACE (* s)) @@ -486,9 +551,7 @@ cregs[] = }; static char * -parse_creg (s, reg) - char * s; - unsigned * reg; +parse_creg (char * s, unsigned * reg) { int i; @@ -548,9 +611,7 @@ parse_creg (s, reg) } static char * -parse_psrmod (s, reg) - char * s; - unsigned * reg; +parse_psrmod (char * s, unsigned * reg) { int i; char buf[10]; @@ -588,9 +649,7 @@ parse_psrmod (s, reg) } static char * -parse_exp (s, e) - char * s; - expressionS * e; +parse_exp (char * s, expressionS * e) { char * save; char * new; @@ -613,129 +672,20 @@ parse_exp (s, e) return new; } -static void -make_name (s, p, n) - char * s; - char * p; - int n; -{ - static const char hex[] = "0123456789ABCDEF"; - - s[0] = p[0]; - s[1] = p[1]; - s[2] = p[2]; - s[3] = hex[(n >> 12) & 0xF]; - s[4] = hex[(n >> 8) & 0xF]; - s[5] = hex[(n >> 4) & 0xF]; - s[6] = hex[(n) & 0xF]; - s[7] = 0; -} - -#define POOL_END_LABEL ".LE" -#define POOL_START_LABEL ".LS" - -static void -dump_literals (isforce) - int isforce; -{ - unsigned int i; - struct literal * p; - symbolS * brarsym = NULL; - - if (poolsize == 0) - return; - - /* Must we branch around the literal table? */ - if (isforce) - { - char * output; - char brarname[8]; - - make_name (brarname, POOL_END_LABEL, poolnumber); - - brarsym = symbol_make (brarname); - - symbol_table_insert (brarsym); - - output = frag_var (rs_machine_dependent, - md_relax_table[C (UNCD_JUMP, DISP32)].rlx_length, - md_relax_table[C (UNCD_JUMP, DISP12)].rlx_length, - C (UNCD_JUMP, 0), brarsym, 0, 0); - output[0] = INST_BYTE0 (MCORE_INST_BR); /* br .+xxx */ - output[1] = INST_BYTE1 (MCORE_INST_BR); - } - - /* Make sure that the section is sufficiently aligned and that - the literal table is aligned within it. */ - record_alignment (now_seg, 2); - frag_align (2, 0, 0); - - colon (S_GET_NAME (poolsym)); - - for (i = 0, p = litpool; i < poolsize; i++, p++) - emit_expr (& p->e, 4); - - if (brarsym != NULL) - colon (S_GET_NAME (brarsym)); - - poolsize = 0; -} - -static void -check_literals (kind, offset) - int kind; - int offset; -{ - poolspan += offset; - - /* SPANCLOSE and SPANEXIT are smaller numbers than SPANPANIC. - SPANPANIC means that we must dump now. - kind == 0 is any old instruction. - kind > 0 means we just had a control transfer instruction. - kind == 1 means within a function - kind == 2 means we just left a function - - The dump_literals (1) call inserts a branch around the table, so - we first look to see if its a situation where we won't have to - insert a branch (e.g., the previous instruction was an unconditional - branch). - - SPANPANIC is the point where we must dump a single-entry pool. - it accounts for alignments and an inserted branch. - the 'poolsize*2' accounts for the scenario where we do: - lrw r1,lit1; lrw r2,lit2; lrw r3,lit3 - Note that the 'lit2' reference is 2 bytes further along - but the literal it references will be 4 bytes further along, - so we must consider the poolsize into this equation. - This is slightly over-cautious, but guarantees that we won't - panic because a relocation is too distant. */ - - if (poolspan > SPANCLOSE && kind > 0) - dump_literals (0); - else if (poolspan > SPANEXIT && kind > 1) - dump_literals (0); - else if (poolspan >= (SPANPANIC - poolsize * 2)) - dump_literals (1); -} - static int -enter_literal (e, ispcrel) - expressionS * e; - int ispcrel; +enter_literal (expressionS * e, int ispcrel) { unsigned int i; struct literal * p; if (poolsize >= MAX_POOL_SIZE - 2) - { - /* The literal pool is as full as we can handle. We have - to be 2 entries shy of the 1024/4=256 entries because we - have to allow for the branch (2 bytes) and the alignment - (2 bytes before the first insn referencing the pool and - 2 bytes before the pool itself) == 6 bytes, rounds up - to 2 entries. */ - dump_literals (1); - } + /* The literal pool is as full as we can handle. We have + to be 2 entries shy of the 1024/4=256 entries because we + have to allow for the branch (2 bytes) and the alignment + (2 bytes before the first insn referencing the pool and + 2 bytes before the pool itself) == 6 bytes, rounds up + to 2 entries. */ + dump_literals (1); if (poolsize == 0) { @@ -774,12 +724,12 @@ enter_literal (e, ispcrel) /* Parse a literal specification. -- either new or old syntax. old syntax: the user supplies the label and places the literal. new syntax: we put it into the literal pool. */ + static char * -parse_rt (s, outputp, ispcrel, ep) - char * s; - char ** outputp; - int ispcrel; - expressionS * ep; +parse_rt (char * s, + char ** outputp, + int ispcrel, + expressionS * ep) { expressionS e; int n; @@ -821,11 +771,10 @@ parse_rt (s, outputp, ispcrel, ep) } static char * -parse_imm (s, val, min, max) - char * s; - unsigned * val; - unsigned min; - unsigned max; +parse_imm (char * s, + unsigned * val, + unsigned min, + unsigned max) { char * new; expressionS e; @@ -846,11 +795,10 @@ parse_imm (s, val, min, max) } static char * -parse_mem (s, reg, off, siz) - char * s; - unsigned * reg; - unsigned * off; - unsigned siz; +parse_mem (char * s, + unsigned * reg, + unsigned * off, + unsigned siz) { * off = 0; @@ -904,8 +852,7 @@ parse_mem (s, reg, off, siz) the frags/bytes it assembles to. */ void -md_assemble (str) - char * str; +md_assemble (char * str) { char * op_start; char * op_end; @@ -993,15 +940,15 @@ md_assemble (str) if (sifilter_mode) { - /* Replace with: bsr .+2 ; addi r15,6; jmp rx ; jmp rx */ - inst = MCORE_INST_BSR; /* with 0 displacement */ + /* Replace with: bsr .+2 ; addi r15,6; jmp rx ; jmp rx. */ + inst = MCORE_INST_BSR; /* With 0 displacement. */ output[0] = INST_BYTE0 (inst); output[1] = INST_BYTE1 (inst); output = frag_more (2); inst = MCORE_INST_ADDI; - inst |= 15; /* addi r15,6 */ - inst |= (6 - 1) << 4; /* over the jmp's */ + inst |= 15; /* addi r15,6 */ + inst |= (6 - 1) << 4; /* Over the jmp's. */ output[0] = INST_BYTE0 (inst); output[1] = INST_BYTE1 (inst); @@ -1010,7 +957,8 @@ md_assemble (str) output[0] = INST_BYTE0 (inst); output[1] = INST_BYTE1 (inst); - output = frag_more (2); /* 2nd emitted in fallthru */ + /* 2nd emitted in fallthrough. */ + output = frag_more (2); } break; @@ -1057,14 +1005,15 @@ md_assemble (str) output = frag_more (2); break; - case X1: /* Handle both syntax-> xtrb- r1,rx OR xtrb- rx */ + case X1: + /* Handle both syntax-> xtrb- r1,rx OR xtrb- rx. */ op_end = parse_reg (op_end + 1, & reg); /* Skip whitespace. */ while (ISSPACE (* op_end)) ++ op_end; - if (* op_end == ',') /* xtrb- r1,rx */ + if (* op_end == ',') /* xtrb- r1,rx. */ { if (reg != 1) as_bad (_("destination register must be r1")); @@ -1076,7 +1025,7 @@ md_assemble (str) output = frag_more (2); break; - case O1R1: /* div- rx,r1 */ + case O1R1: /* div- rx,r1. */ op_end = parse_reg (op_end + 1, & reg); inst |= reg; @@ -1134,7 +1083,8 @@ md_assemble (str) output = frag_more (2); break; - case OB2: /* like OB, but arg is 2^n instead of n */ + case OB2: + /* Like OB, but arg is 2^n instead of n. */ op_end = parse_reg (op_end + 1, & reg); inst |= reg; @@ -1174,7 +1124,7 @@ md_assemble (str) if (* op_end == ',') { op_end = parse_imm (op_end + 1, & reg, 0, 31); - /* immediate values of 0 -> 6 translate to movi */ + /* Immediate values of 0 -> 6 translate to movi. */ if (reg <= 6) { inst = (inst & 0xF) | MCORE_INST_BGENI_ALT; @@ -1190,7 +1140,7 @@ md_assemble (str) output = frag_more (2); break; - case OBR2: /* like OBR, but arg is 2^n instead of n */ + case OBR2: /* Like OBR, but arg is 2^n instead of n. */ op_end = parse_reg (op_end + 1, & reg); inst |= reg; @@ -1543,7 +1493,8 @@ md_assemble (str) } break; - case RSI: /* SI, but imm becomes 32-imm */ + case RSI: + /* SI, but imm becomes 32-imm. */ op_end = parse_reg (op_end + 1, & reg); inst |= reg; @@ -1657,31 +1608,28 @@ md_assemble (str) } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } void -md_mcore_end () +md_mcore_end (void) { dump_literals (0); subseg_set (text_section, 0); } /* Various routines to kill one day. */ -/* Equal to MAX_PRECISION in atof-ieee.c */ +/* Equal to MAX_PRECISION in atof-ieee.c. */ #define MAX_LITTLENUMS 6 /* Turn a string in input_line_pointer into a floating point constant of type type, and store the appropriate bytes in *litP. The number of LITTLENUMS - emitted is stored in *sizeP. An error message is returned, or NULL on OK.*/ + emitted is stored in *sizeP. An error message is returned, or NULL on OK. */ + char * -md_atof (type, litP, sizeP) - int type; - char * litP; - int * sizeP; +md_atof (int type, char * litP, int * sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -1748,13 +1696,16 @@ md_atof (type, litP, sizeP) const char * md_shortopts = ""; -#define OPTION_JSRI2BSR_ON (OPTION_MD_BASE + 0) -#define OPTION_JSRI2BSR_OFF (OPTION_MD_BASE + 1) -#define OPTION_SIFILTER_ON (OPTION_MD_BASE + 2) -#define OPTION_SIFILTER_OFF (OPTION_MD_BASE + 3) -#define OPTION_CPU (OPTION_MD_BASE + 4) -#define OPTION_EB (OPTION_MD_BASE + 5) -#define OPTION_EL (OPTION_MD_BASE + 6) +enum options +{ + OPTION_JSRI2BSR_ON = OPTION_MD_BASE, + OPTION_JSRI2BSR_OFF, + OPTION_SIFILTER_ON, + OPTION_SIFILTER_OFF, + OPTION_CPU, + OPTION_EB, + OPTION_EL, +}; struct option md_longopts[] = { @@ -1771,9 +1722,7 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c; - char * arg; +md_parse_option (int c, char * arg) { switch (c) { @@ -1802,8 +1751,7 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE * stream; +md_show_usage (FILE * stream) { fprintf (stream, _("\ MCORE specific options:\n\ @@ -1817,33 +1765,31 @@ MCORE specific options:\n\ int md_short_jump_size; void -md_create_short_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) - char * ptr ATTRIBUTE_UNUSED; - addressT from_Nddr ATTRIBUTE_UNUSED; - addressT to_Nddr ATTRIBUTE_UNUSED; - fragS * frag ATTRIBUTE_UNUSED; - symbolS * to_symbol ATTRIBUTE_UNUSED; +md_create_short_jump (char * ptr ATTRIBUTE_UNUSED, + addressT from_Nddr ATTRIBUTE_UNUSED, + addressT to_Nddr ATTRIBUTE_UNUSED, + fragS * frag ATTRIBUTE_UNUSED, + symbolS * to_symbol ATTRIBUTE_UNUSED) { as_fatal (_("failed sanity check: short_jump")); } void -md_create_long_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) - char * ptr ATTRIBUTE_UNUSED; - addressT from_Nddr ATTRIBUTE_UNUSED; - addressT to_Nddr ATTRIBUTE_UNUSED; - fragS * frag ATTRIBUTE_UNUSED; - symbolS * to_symbol ATTRIBUTE_UNUSED; +md_create_long_jump (char * ptr ATTRIBUTE_UNUSED, + addressT from_Nddr ATTRIBUTE_UNUSED, + addressT to_Nddr ATTRIBUTE_UNUSED, + fragS * frag ATTRIBUTE_UNUSED, + symbolS * to_symbol ATTRIBUTE_UNUSED) { as_fatal (_("failed sanity check: long_jump")); } /* Called after relaxing, change the frags so they know how big they are. */ + void -md_convert_frag (abfd, sec, fragP) - bfd * abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - register fragS * fragP; +md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS * fragP) { char *buffer; int targ_addr = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; @@ -1890,47 +1836,46 @@ md_convert_frag (abfd, sec, fragP) case C (COND_JUMP, UNDEF_WORD_DISP): { /* A conditional branch wont fit into 12 bits so: - * b!cond 1f - * jmpi 0f - * .align 2 - * 0: .long disp - * 1: - * - * if the b!cond is 4 byte aligned, the literal which would - * go at x+4 will also be aligned. - */ + b!cond 1f + jmpi 0f + .align 2 + 0: .long disp + 1: + + If the b!cond is 4 byte aligned, the literal which would + go at x+4 will also be aligned. */ int first_inst = fragP->fr_fix + fragP->fr_address; int needpad = (first_inst & 3); if (! target_big_endian) buffer[1] ^= 0x08; else - buffer[0] ^= 0x08; /* Toggle T/F bit */ + buffer[0] ^= 0x08; /* Toggle T/F bit. */ - buffer[2] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi */ + buffer[2] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi. */ buffer[3] = INST_BYTE1 (MCORE_INST_JMPI); if (needpad) { if (! target_big_endian) { - buffer[0] = 4; /* branch over jmpi, pad, and ptr */ - buffer[2] = 1; /* jmpi offset of 1 gets the pointer */ + buffer[0] = 4; /* Branch over jmpi, pad, and ptr. */ + buffer[2] = 1; /* Jmpi offset of 1 gets the pointer. */ } else { - buffer[1] = 4; /* branch over jmpi, pad, and ptr */ - buffer[3] = 1; /* jmpi offset of 1 gets the pointer */ + buffer[1] = 4; /* Branch over jmpi, pad, and ptr. */ + buffer[3] = 1; /* Jmpi offset of 1 gets the pointer. */ } - buffer[4] = 0; /* alignment/pad */ + buffer[4] = 0; /* Alignment/pad. */ buffer[5] = 0; - buffer[6] = 0; /* space for 32 bit address */ + buffer[6] = 0; /* Space for 32 bit address. */ buffer[7] = 0; buffer[8] = 0; buffer[9] = 0; - /* Make reloc for the long disp */ + /* Make reloc for the long disp. */ fix_new (fragP, fragP->fr_fix + 6, 4, fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_32); @@ -1944,16 +1889,16 @@ md_convert_frag (abfd, sec, fragP) for this fragment. */ if (! target_big_endian) { - buffer[0] = 3; /* branch over jmpi, and ptr */ - buffer[2] = 0; /* jmpi offset of 0 gets the pointer */ + buffer[0] = 3; /* Branch over jmpi, and ptr. */ + buffer[2] = 0; /* Jmpi offset of 0 gets the pointer. */ } else { - buffer[1] = 3; /* branch over jmpi, and ptr */ - buffer[3] = 0; /* jmpi offset of 0 gets the pointer */ + buffer[1] = 3; /* Branch over jmpi, and ptr. */ + buffer[3] = 0; /* Jmpi offset of 0 gets the pointer. */ } - buffer[4] = 0; /* space for 32 bit address */ + buffer[4] = 0; /* Space for 32 bit address. */ buffer[5] = 0; buffer[6] = 0; buffer[7] = 0; @@ -1969,9 +1914,9 @@ md_convert_frag (abfd, sec, fragP) full length of the fragment, not just what we actually filled in. */ if (! target_big_endian) - buffer[0] = 4; /* jmpi, ptr, and the 'tail pad' */ + buffer[0] = 4; /* Jmpi, ptr, and the 'tail pad'. */ else - buffer[1] = 4; /* jmpi, ptr, and the 'tail pad' */ + buffer[1] = 4; /* Jmpi, ptr, and the 'tail pad'. */ } } break; @@ -1985,22 +1930,22 @@ md_convert_frag (abfd, sec, fragP) .align 2 0: .long disp we need a pad if "first_inst" is 4 byte aligned. - [because the natural literal place is x + 2] */ + [because the natural literal place is x + 2]. */ int first_inst = fragP->fr_fix + fragP->fr_address; int needpad = !(first_inst & 3); - buffer[0] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi */ + buffer[0] = INST_BYTE0 (MCORE_INST_JMPI); /* Build jmpi. */ buffer[1] = INST_BYTE1 (MCORE_INST_JMPI); if (needpad) { if (! target_big_endian) - buffer[0] = 1; /* jmpi offset of 1 since padded */ + buffer[0] = 1; /* Jmpi offset of 1 since padded. */ else - buffer[1] = 1; /* jmpi offset of 1 since padded */ - buffer[2] = 0; /* alignment */ + buffer[1] = 1; /* Jmpi offset of 1 since padded. */ + buffer[2] = 0; /* Alignment. */ buffer[3] = 0; - buffer[4] = 0; /* space for 32 bit address */ + buffer[4] = 0; /* Space for 32 bit address. */ buffer[5] = 0; buffer[6] = 0; buffer[7] = 0; @@ -2014,10 +1959,10 @@ md_convert_frag (abfd, sec, fragP) else { if (! target_big_endian) - buffer[0] = 0; /* jmpi offset of 0 if no pad */ + buffer[0] = 0; /* Jmpi offset of 0 if no pad. */ else - buffer[1] = 0; /* jmpi offset of 0 if no pad */ - buffer[2] = 0; /* space for 32 bit address */ + buffer[1] = 0; /* Jmpi offset of 0 if no pad. */ + buffer[2] = 0; /* Space for 32 bit address. */ buffer[3] = 0; buffer[4] = 0; buffer[5] = 0; @@ -2039,10 +1984,9 @@ md_convert_frag (abfd, sec, fragP) Also sets up addends for 'rela' type relocations. */ void -md_apply_fix3 (fixP, valP, segment) - fixS * fixP; - valueT * valP; - segT segment ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS * fixP, + valueT * valP, + segT segment ATTRIBUTE_UNUSED) { char * buf = fixP->fx_where + fixP->fx_frag->fr_literal; char * file = fixP->fx_file ? fixP->fx_file : _("unknown"); @@ -2068,7 +2012,8 @@ md_apply_fix3 (fixP, valP, segment) switch (fixP->fx_r_type) { - case BFD_RELOC_MCORE_PCREL_IMM11BY2: /* second byte of 2 byte opcode */ + /* Second byte of 2 byte opcode. */ + case BFD_RELOC_MCORE_PCREL_IMM11BY2: if ((val & 1) != 0) as_bad_where (file, fixP->fx_line, _("odd distance branch (0x%lx bytes)"), (long) val); @@ -2089,7 +2034,8 @@ md_apply_fix3 (fixP, valP, segment) } break; - case BFD_RELOC_MCORE_PCREL_IMM8BY4: /* lower 8 bits of 2 byte opcode */ + /* Lower 8 bits of 2 byte opcode. */ + case BFD_RELOC_MCORE_PCREL_IMM8BY4: val += 3; val /= 4; if (val & ~0xff) @@ -2102,7 +2048,8 @@ md_apply_fix3 (fixP, valP, segment) buf[1] |= (val & 0xff); break; - case BFD_RELOC_MCORE_PCREL_IMM4BY2: /* loopt instruction */ + /* Loopt instruction. */ + case BFD_RELOC_MCORE_PCREL_IMM4BY2: if ((val < -32) || (val > -2)) as_bad_where (file, fixP->fx_line, _("pcrel for loopt too far (0x%lx)"), (long) val); @@ -2162,8 +2109,7 @@ md_apply_fix3 (fixP, valP, segment) } void -md_operand (expressionP) - expressionS * expressionP; +md_operand (expressionS * expressionP) { /* Ignore leading hash symbol, if poresent. */ if (* input_line_pointer == '#') @@ -2178,9 +2124,7 @@ int md_long_jump_size; /* Called just before address relaxation, return the length by which a fragment must grow to reach it's destination. */ int -md_estimate_size_before_relax (fragP, segment_type) - register fragS * fragP; - register segT segment_type; +md_estimate_size_before_relax (fragS * fragP, segT segment_type) { switch (fragP->fr_subtype) { @@ -2190,38 +2134,26 @@ md_estimate_size_before_relax (fragP, segment_type) case C (UNCD_JUMP, UNDEF_DISP): /* Used to be a branch to somewhere which was unknown. */ if (!fragP->fr_symbol) - { - fragP->fr_subtype = C (UNCD_JUMP, DISP12); - } + fragP->fr_subtype = C (UNCD_JUMP, DISP12); else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) - { - fragP->fr_subtype = C (UNCD_JUMP, DISP12); - } + fragP->fr_subtype = C (UNCD_JUMP, DISP12); else - { - fragP->fr_subtype = C (UNCD_JUMP, UNDEF_WORD_DISP); - } + fragP->fr_subtype = C (UNCD_JUMP, UNDEF_WORD_DISP); break; case C (COND_JUMP, UNDEF_DISP): /* Used to be a branch to somewhere which was unknown. */ if (fragP->fr_symbol && S_GET_SEGMENT (fragP->fr_symbol) == segment_type) - { - /* Got a symbol and it's defined in this segment, become byte - sized - maybe it will fix up */ - fragP->fr_subtype = C (COND_JUMP, DISP12); - } + /* Got a symbol and it's defined in this segment, become byte + sized - maybe it will fix up */ + fragP->fr_subtype = C (COND_JUMP, DISP12); else if (fragP->fr_symbol) - { - /* Its got a segment, but its not ours, so it will always be long. */ - fragP->fr_subtype = C (COND_JUMP, UNDEF_WORD_DISP); - } + /* Its got a segment, but its not ours, so it will always be long. */ + fragP->fr_subtype = C (COND_JUMP, UNDEF_WORD_DISP); else - { - /* We know the abs value. */ - fragP->fr_subtype = C (COND_JUMP, DISP12); - } + /* We know the abs value. */ + fragP->fr_subtype = C (COND_JUMP, DISP12); break; case C (UNCD_JUMP, DISP12): @@ -2239,47 +2171,45 @@ md_estimate_size_before_relax (fragP, segment_type) } /* Put number into target byte order. */ + void -md_number_to_chars (ptr, use, nbytes) - char * ptr; - valueT use; - int nbytes; +md_number_to_chars (char * ptr, valueT use, int nbytes) { if (! target_big_endian) switch (nbytes) { - case 4: ptr[3] = (use >> 24) & 0xff; /* fall through */ - case 3: ptr[2] = (use >> 16) & 0xff; /* fall through */ - case 2: ptr[1] = (use >> 8) & 0xff; /* fall through */ + case 4: ptr[3] = (use >> 24) & 0xff; /* Fall through. */ + case 3: ptr[2] = (use >> 16) & 0xff; /* Fall through. */ + case 2: ptr[1] = (use >> 8) & 0xff; /* Fall through. */ case 1: ptr[0] = (use >> 0) & 0xff; break; default: abort (); } else switch (nbytes) { - case 4: *ptr++ = (use >> 24) & 0xff; /* fall through */ - case 3: *ptr++ = (use >> 16) & 0xff; /* fall through */ - case 2: *ptr++ = (use >> 8) & 0xff; /* fall through */ + case 4: *ptr++ = (use >> 24) & 0xff; /* Fall through. */ + case 3: *ptr++ = (use >> 16) & 0xff; /* Fall through. */ + case 2: *ptr++ = (use >> 8) & 0xff; /* Fall through. */ case 1: *ptr++ = (use >> 0) & 0xff; break; default: abort (); } } /* Round up a section size to the appropriate boundary. */ + valueT -md_section_align (segment, size) - segT segment ATTRIBUTE_UNUSED; - valueT size; +md_section_align (segT segment ATTRIBUTE_UNUSED, + valueT size) { - return size; /* Byte alignment is fine */ + /* Byte alignment is fine. */ + return size; } /* The location from which a PC relative jump should be calculated, given a PC relative reloc. */ + long -md_pcrel_from_section (fixp, sec) - fixS * fixp; - segT sec ATTRIBUTE_UNUSED; +md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED) { #ifdef OBJ_ELF /* If the symbol is undefined or defined in another section @@ -2303,9 +2233,7 @@ md_pcrel_from_section (fixp, sec) #define MAP(SZ,PCREL,TYPE) case F (SZ, PCREL): code = (TYPE); break arelent * -tc_gen_reloc (section, fixp) - asection * section ATTRIBUTE_UNUSED; - fixS * fixp; +tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) { arelent * rel; bfd_reloc_code_real_type code; @@ -2341,8 +2269,8 @@ tc_gen_reloc (section, fixp) break; } - rel = (arelent *) xmalloc (sizeof (arelent)); - rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + rel = xmalloc (sizeof (arelent)); + rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); rel->address = fixp->fx_frag->fr_address + fixp->fx_where; /* Always pass the addend along! */ @@ -2369,8 +2297,7 @@ tc_gen_reloc (section, fixp) This is used to force out switch and PC relative relocations when relaxing. */ int -mcore_force_relocation (fix) - fixS * fix; +mcore_force_relocation (fixS * fix) { if (fix->fx_r_type == BFD_RELOC_RVA) return 1; @@ -2380,9 +2307,9 @@ mcore_force_relocation (fix) /* Return true if the fix can be handled by GAS, false if it must be passed through to the linker. */ + bfd_boolean -mcore_fix_adjustable (fixP) - fixS * fixP; +mcore_fix_adjustable (fixS * fixP) { /* We need the symbol name for the VTABLE entries. */ if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT diff --git a/gas/config/tc-mcore.h b/gas/config/tc-mcore.h index b685a4ef49b..210faf24f9f 100644 --- a/gas/config/tc-mcore.h +++ b/gas/config/tc-mcore.h @@ -1,6 +1,6 @@ /* This file is tc-mcore.h - Copyright 1999, 2000, 2001, 2002, 2003 + Copyright 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -52,7 +52,7 @@ #define LOCAL_LABELS_FB 1 #define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep (frag) -int tc_coff_sizemachdep PARAMS ((struct frag *)); +int tc_coff_sizemachdep (struct frag *); extern const struct relax_type md_relax_table[]; #define TC_GENERIC_RELAX_TABLE md_relax_table @@ -89,10 +89,8 @@ struct mcore_tc_sy /* When relaxing, we need to emit various relocs we otherwise wouldn't. */ #define TC_FORCE_RELOCATION(fix) mcore_force_relocation (fix) -extern int mcore_force_relocation PARAMS ((struct fix *)); #define tc_fix_adjustable(FIX) mcore_fix_adjustable (FIX) -extern bfd_boolean mcore_fix_adjustable PARAMS ((struct fix *)); /* Values passed to md_apply_fix3 don't include the symbol value. */ #define MD_APPLY_SYM_VALUE(FIX) 0 @@ -105,8 +103,10 @@ extern bfd_boolean mcore_fix_adjustable PARAMS ((struct fix *)); #include "write.h" /* For definition of fixS */ -extern void md_mcore_end PARAMS ((void)); -extern long md_pcrel_from_section PARAMS ((fixS *, segT)); -extern arelent * tc_gen_reloc PARAMS ((asection *, fixS *)); +extern void md_mcore_end (void); +extern long md_pcrel_from_section (fixS *, segT); +extern arelent * tc_gen_reloc (asection *, fixS *); +extern int mcore_force_relocation (fixS *); +extern bfd_boolean mcore_fix_adjustable (fixS *); #endif /* TC_MCORE */ diff --git a/gas/config/tc-mn10200.c b/gas/config/tc-mn10200.c index ad7b756f0d9..8806910208d 100644 --- a/gas/config/tc-mn10200.c +++ b/gas/config/tc-mn10200.c @@ -1,6 +1,6 @@ /* tc-mn10200.c -- Assembler code for the Matsushita 10200 - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -53,7 +53,8 @@ const char EXP_CHARS[] = "eE"; as in 0d1.0. */ const char FLT_CHARS[] = "dD"; -const relax_typeS md_relax_table[] = { +const relax_typeS md_relax_table[] = + { /* bCC relaxing */ {0x81, -0x7e, 2, 1}, {0x8004, -0x7ffb, 5, 2}, @@ -72,34 +73,27 @@ const relax_typeS md_relax_table[] = { }; -/* Local functions. */ -static void mn10200_insert_operand PARAMS ((unsigned long *, unsigned long *, - const struct mn10200_operand *, - offsetT, char *, unsigned, - unsigned)); -static unsigned long check_operand PARAMS ((unsigned long, - const struct mn10200_operand *, - offsetT)); -static int reg_name_search PARAMS ((const struct reg_name *, int, const char *)); -static bfd_boolean data_register_name PARAMS ((expressionS *expressionP)); -static bfd_boolean address_register_name PARAMS ((expressionS *expressionP)); -static bfd_boolean other_register_name PARAMS ((expressionS *expressionP)); /* Fixups. */ -#define MAX_INSN_FIXUPS (5) +#define MAX_INSN_FIXUPS 5 + struct mn10200_fixup { expressionS exp; int opindex; bfd_reloc_code_real_type reloc; }; + struct mn10200_fixup fixups[MAX_INSN_FIXUPS]; static int fc; const char *md_shortopts = ""; -struct option md_longopts[] = { + +struct option md_longopts[] = +{ {NULL, no_argument, NULL, 0} }; + size_t md_longopts_size = sizeof (md_longopts); /* The target specific pseudo-ops which we support. */ @@ -145,10 +139,9 @@ static const struct reg_name other_registers[] = number from the array on success, or -1 on failure. */ static int -reg_name_search (regs, regcount, name) - const struct reg_name *regs; - int regcount; - const char *name; +reg_name_search (const struct reg_name *regs, + int regcount, + const char *name) { int middle, low, high; int cmp; @@ -172,19 +165,17 @@ reg_name_search (regs, regcount, name) } /* Summary of register_name(). - * - * in: Input_line_pointer points to 1st char of operand. - * - * out: An expressionS. - * The operand may have been a register: in this case, X_op == O_register, - * X_add_number is set to the register number, and truth is returned. - * Input_line_pointer->(next non-blank) char after operand, or is in - * its original state. - */ + + in: Input_line_pointer points to 1st char of operand. + + out: An expressionS. + The operand may have been a register: in this case, X_op == O_register, + X_add_number is set to the register number, and truth is returned. + Input_line_pointer->(next non-blank) char after operand, or is in + its original state. */ static bfd_boolean -data_register_name (expressionP) - expressionS *expressionP; +data_register_name (expressionS *expressionP) { int reg_number; char *name; @@ -219,19 +210,17 @@ data_register_name (expressionP) } /* Summary of register_name(). - * - * in: Input_line_pointer points to 1st char of operand. - * - * out: An expressionS. - * The operand may have been a register: in this case, X_op == O_register, - * X_add_number is set to the register number, and truth is returned. - * Input_line_pointer->(next non-blank) char after operand, or is in - * its original state. - */ + + in: Input_line_pointer points to 1st char of operand. + + out: An expressionS. + The operand may have been a register: in this case, X_op == O_register, + X_add_number is set to the register number, and truth is returned. + Input_line_pointer->(next non-blank) char after operand, or is in + its original state. */ static bfd_boolean -address_register_name (expressionP) - expressionS *expressionP; +address_register_name (expressionS *expressionP) { int reg_number; char *name; @@ -266,19 +255,17 @@ address_register_name (expressionP) } /* Summary of register_name(). - * - * in: Input_line_pointer points to 1st char of operand. - * - * out: An expressionS. - * The operand may have been a register: in this case, X_op == O_register, - * X_add_number is set to the register number, and truth is returned. - * Input_line_pointer->(next non-blank) char after operand, or is in - * its original state. - */ + + in: Input_line_pointer points to 1st char of operand. + + out: An expressionS. + The operand may have been a register: in this case, X_op == O_register, + X_add_number is set to the register number, and truth is returned. + Input_line_pointer->(next non-blank) char after operand, or is in + its original state. */ static bfd_boolean -other_register_name (expressionP) - expressionS *expressionP; +other_register_name (expressionS *expressionP) { int reg_number; char *name; @@ -313,33 +300,27 @@ other_register_name (expressionP) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("MN10200 options:\n\ none yet\n")); } int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, + char *arg ATTRIBUTE_UNUSED) { return 0; } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } char * -md_atof (type, litp, sizep) - int type; - char *litp; - int *sizep; +md_atof (int type, char *litp, int *sizep) { int prec; LITTLENUM_TYPE words[4]; @@ -377,10 +358,9 @@ md_atof (type, litp, sizep) } void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec; - fragS *fragP; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + fragS *fragP) { static unsigned long label_count = 0; char buf[40]; @@ -728,16 +708,14 @@ md_convert_frag (abfd, sec, fragP) } valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg, valueT addr) { int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align)); } void -md_begin () +md_begin (void) { char *prev_name = ""; register const struct mn10200_opcode *op; @@ -766,9 +744,169 @@ md_begin () linkrelax = 1; } +static unsigned long +check_operand (unsigned long insn ATTRIBUTE_UNUSED, + const struct mn10200_operand *operand, + offsetT val) +{ + /* No need to check 24bit or 32bit operands for a bit. */ + if (operand->bits < 24 + && (operand->flags & MN10200_OPERAND_NOCHECK) == 0) + { + long min, max; + offsetT test; + + if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) + { + max = (1 << (operand->bits - 1)) - 1; + min = - (1 << (operand->bits - 1)); + } + else + { + max = (1 << operand->bits) - 1; + min = 0; + } + + test = val; + + if (test < (offsetT) min || test > (offsetT) max) + return 0; + else + return 1; + } + return 1; +} +/* If while processing a fixup, a reloc really needs to be created + Then it is done here. */ + +arelent * +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) +{ + arelent *reloc; + reloc = xmalloc (sizeof (arelent)); + + if (fixp->fx_subsy != NULL) + { + if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy) + && S_IS_DEFINED (fixp->fx_subsy)) + { + fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy); + fixp->fx_subsy = NULL; + } + else + /* FIXME: We should try more ways to resolve difference expressions + here. At least this is better than silently ignoring the + subtrahend. */ + as_bad_where (fixp->fx_file, fixp->fx_line, + _("can't resolve `%s' {%s section} - `%s' {%s section}"), + fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0", + segment_name (fixp->fx_addsy + ? S_GET_SEGMENT (fixp->fx_addsy) + : absolute_section), + S_GET_NAME (fixp->fx_subsy), + segment_name (S_GET_SEGMENT (fixp->fx_addsy))); + } + + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + if (reloc->howto == NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("reloc %d not supported by object file format"), + (int) fixp->fx_r_type); + return NULL; + } + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->addend = fixp->fx_offset; + return reloc; +} + +int +md_estimate_size_before_relax (fragS *fragp, asection *seg) +{ + if (fragp->fr_subtype == 6 + && (!S_IS_DEFINED (fragp->fr_symbol) + || seg != S_GET_SEGMENT (fragp->fr_symbol))) + fragp->fr_subtype = 7; + else if (fragp->fr_subtype == 8 + && (!S_IS_DEFINED (fragp->fr_symbol) + || seg != S_GET_SEGMENT (fragp->fr_symbol))) + fragp->fr_subtype = 10; + + if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) + abort (); + + return md_relax_table[fragp->fr_subtype].rlx_length; +} + +long +md_pcrel_from (fixS *fixp) +{ + return fixp->fx_frag->fr_address; +} + void -md_assemble (str) - char *str; +md_apply_fix3 (fixS * fixP, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED) +{ + /* We shouldn't ever get here because linkrelax is nonzero. */ + abort (); + fixP->fx_done = 1; +} + +/* Insert an operand value into an instruction. */ + +static void +mn10200_insert_operand (unsigned long *insnp, + unsigned long *extensionp, + const struct mn10200_operand *operand, + offsetT val, + char *file, + unsigned int line, + unsigned int shift) +{ + /* No need to check 24 or 32bit operands for a bit. */ + if (operand->bits < 24 + && (operand->flags & MN10200_OPERAND_NOCHECK) == 0) + { + long min, max; + offsetT test; + + if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) + { + max = (1 << (operand->bits - 1)) - 1; + min = - (1 << (operand->bits - 1)); + } + else + { + max = (1 << operand->bits) - 1; + min = 0; + } + + test = val; + + if (test < (offsetT) min || test > (offsetT) max) + as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line); + } + + if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0) + { + *insnp |= (((long) val & ((1 << operand->bits) - 1)) + << (operand->shift + shift)); + + if ((operand->flags & MN10200_OPERAND_REPEATED) != 0) + *insnp |= (((long) val & ((1 << operand->bits) - 1)) + << (operand->shift + shift + 2)); + } + else + { + *extensionp |= (val >> 16) & 0xff; + *insnp |= val & 0xffff; + } +} + +void +md_assemble (char *str) { char *s; struct mn10200_opcode *opcode; @@ -957,7 +1095,7 @@ md_assemble (str) extra_shift = 0; mn10200_insert_operand (&insn, &extension, operand, - ex.X_add_number, (char *) NULL, + ex.X_add_number, NULL, 0, extra_shift); break; @@ -976,7 +1114,7 @@ md_assemble (str) } mn10200_insert_operand (&insn, &extension, operand, - ex.X_add_number, (char *) NULL, + ex.X_add_number, NULL, 0, 0); break; @@ -1051,7 +1189,6 @@ keep_going: abort (); /* Write out the instruction. */ - if (relaxable && fc > 0) { int type; @@ -1094,7 +1231,6 @@ keep_going: else number_to_chars_bigendian (f + size, 0, 8 - size); } - else { f = frag_more (size); @@ -1118,9 +1254,7 @@ keep_going: number_to_chars_littleendian (f + 4, extension & 0xff, 1); } else - { - number_to_chars_bigendian (f, insn, size > 4 ? 4 : size); - } + number_to_chars_bigendian (f, insn, size > 4 ? 4 : size); /* Create any fixups. */ for (i = 0; i < fc; i++) @@ -1222,174 +1356,3 @@ keep_going: } } -/* If while processing a fixup, a reloc really needs to be created - Then it is done here. */ - -arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; -{ - arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); - - if (fixp->fx_subsy != NULL) - { - if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy) - && S_IS_DEFINED (fixp->fx_subsy)) - { - fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy); - fixp->fx_subsy = NULL; - } - else - /* FIXME: We should try more ways to resolve difference expressions - here. At least this is better than silently ignoring the - subtrahend. */ - as_bad_where (fixp->fx_file, fixp->fx_line, - _("can't resolve `%s' {%s section} - `%s' {%s section}"), - fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0", - segment_name (fixp->fx_addsy - ? S_GET_SEGMENT (fixp->fx_addsy) - : absolute_section), - S_GET_NAME (fixp->fx_subsy), - segment_name (S_GET_SEGMENT (fixp->fx_addsy))); - } - - reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); - if (reloc->howto == (reloc_howto_type *) NULL) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - _("reloc %d not supported by object file format"), - (int) fixp->fx_r_type); - return NULL; - } - reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); - *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); - reloc->addend = fixp->fx_offset; - return reloc; -} - -int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp; - asection *seg; -{ - if (fragp->fr_subtype == 6 - && (!S_IS_DEFINED (fragp->fr_symbol) - || seg != S_GET_SEGMENT (fragp->fr_symbol))) - fragp->fr_subtype = 7; - else if (fragp->fr_subtype == 8 - && (!S_IS_DEFINED (fragp->fr_symbol) - || seg != S_GET_SEGMENT (fragp->fr_symbol))) - fragp->fr_subtype = 10; - - if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) - abort (); - - return md_relax_table[fragp->fr_subtype].rlx_length; -} - -long -md_pcrel_from (fixp) - fixS *fixp; -{ - return fixp->fx_frag->fr_address; -} - -void -md_apply_fix3 (fixP, valP, seg) - fixS * fixP; - valueT * valP ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; -{ - /* We shouldn't ever get here because linkrelax is nonzero. */ - abort (); - fixP->fx_done = 1; -} - -/* Insert an operand value into an instruction. */ - -static void -mn10200_insert_operand (insnp, extensionp, operand, val, file, line, shift) - unsigned long *insnp; - unsigned long *extensionp; - const struct mn10200_operand *operand; - offsetT val; - char *file; - unsigned int line; - unsigned int shift; -{ - /* No need to check 24 or 32bit operands for a bit. */ - if (operand->bits < 24 - && (operand->flags & MN10200_OPERAND_NOCHECK) == 0) - { - long min, max; - offsetT test; - - if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) - { - max = (1 << (operand->bits - 1)) - 1; - min = - (1 << (operand->bits - 1)); - } - else - { - max = (1 << operand->bits) - 1; - min = 0; - } - - test = val; - - if (test < (offsetT) min || test > (offsetT) max) - as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line); - } - - if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0) - { - *insnp |= (((long) val & ((1 << operand->bits) - 1)) - << (operand->shift + shift)); - - if ((operand->flags & MN10200_OPERAND_REPEATED) != 0) - *insnp |= (((long) val & ((1 << operand->bits) - 1)) - << (operand->shift + shift + 2)); - } - else - { - *extensionp |= (val >> 16) & 0xff; - *insnp |= val & 0xffff; - } -} - -static unsigned long -check_operand (insn, operand, val) - unsigned long insn ATTRIBUTE_UNUSED; - const struct mn10200_operand *operand; - offsetT val; -{ - /* No need to check 24bit or 32bit operands for a bit. */ - if (operand->bits < 24 - && (operand->flags & MN10200_OPERAND_NOCHECK) == 0) - { - long min, max; - offsetT test; - - if ((operand->flags & MN10200_OPERAND_SIGNED) != 0) - { - max = (1 << (operand->bits - 1)) - 1; - min = - (1 << (operand->bits - 1)); - } - else - { - max = (1 << operand->bits) - 1; - min = 0; - } - - test = val; - - if (test < (offsetT) min || test > (offsetT) max) - return 0; - else - return 1; - } - return 1; -} diff --git a/gas/config/tc-ns32k.c b/gas/config/tc-ns32k.c index 9d7ef82d977..feae0fd36ef 100644 --- a/gas/config/tc-ns32k.c +++ b/gas/config/tc-ns32k.c @@ -38,17 +38,17 @@ encountered. */ #define IIF(ptr,a1,c1,e1,g1,i1,k1,m1,o1,q1,s1,u1) \ - iif.iifP[ptr].type= a1; \ - iif.iifP[ptr].size= c1; \ - iif.iifP[ptr].object= e1; \ - iif.iifP[ptr].object_adjust= g1; \ - iif.iifP[ptr].pcrel= i1; \ - iif.iifP[ptr].pcrel_adjust= k1; \ - iif.iifP[ptr].im_disp= m1; \ - iif.iifP[ptr].relax_substate= o1; \ - iif.iifP[ptr].bit_fixP= q1; \ - iif.iifP[ptr].addr_mode= s1; \ - iif.iifP[ptr].bsr= u1; + iif.iifP[ptr].type = a1; \ + iif.iifP[ptr].size = c1; \ + iif.iifP[ptr].object = e1; \ + iif.iifP[ptr].object_adjust = g1; \ + iif.iifP[ptr].pcrel = i1; \ + iif.iifP[ptr].pcrel_adjust = k1; \ + iif.iifP[ptr].im_disp = m1; \ + iif.iifP[ptr].relax_substate = o1; \ + iif.iifP[ptr].bit_fixP = q1; \ + iif.iifP[ptr].addr_mode = s1; \ + iif.iifP[ptr].bsr = u1; #ifdef SEQUENT_COMPATABILITY #define LINE_COMMENT_CHARS "|" @@ -70,21 +70,21 @@ static int default_disp_size = 4; /* Displacement size for external refs. */ #endif struct addr_mode - { - signed char mode; /* Addressing mode of operand (0-31). */ - signed char scaled_mode; /* Mode combined with scaled mode. */ - char scaled_reg; /* Register used in scaled+1 (1-8). */ - char float_flag; /* Set if R0..R7 was F0..F7 ie a +{ + signed char mode; /* Addressing mode of operand (0-31). */ + signed char scaled_mode; /* Mode combined with scaled mode. */ + char scaled_reg; /* Register used in scaled+1 (1-8). */ + char float_flag; /* Set if R0..R7 was F0..F7 ie a floating-point-register. */ - char am_size; /* Estimated max size of general addr-mode + char am_size; /* Estimated max size of general addr-mode parts. */ - char im_disp; /* If im_disp==1 we have a displacement. */ - char pcrel; /* 1 if pcrel, this is really redundant info. */ - char disp_suffix[2]; /* Length of displacement(s), 0=undefined. */ - char *disp[2]; /* Pointer(s) at displacement(s) + char im_disp; /* If im_disp==1 we have a displacement. */ + char pcrel; /* 1 if pcrel, this is really redundant info. */ + char disp_suffix[2]; /* Length of displacement(s), 0=undefined. */ + char *disp[2]; /* Pointer(s) at displacement(s) or immediates(s) (ascii). */ - char index_byte; /* Index byte. */ - }; + char index_byte; /* Index byte. */ +}; typedef struct addr_mode addr_modeS; char *freeptr, *freeptr_static; /* Points at some number of free bytes. */ @@ -112,27 +112,27 @@ struct ns32k_option }; typedef struct - { - int type; /* How to interpret object. */ - int size; /* Estimated max size of object. */ - unsigned long object; /* Binary data. */ - int object_adjust; /* Number added to object. */ - int pcrel; /* True if object is pcrel. */ - int pcrel_adjust; /* Length in bytes from the instruction +{ + int type; /* How to interpret object. */ + int size; /* Estimated max size of object. */ + unsigned long object; /* Binary data. */ + int object_adjust; /* Number added to object. */ + int pcrel; /* True if object is pcrel. */ + int pcrel_adjust; /* Length in bytes from the instruction start to the displacement. */ - int im_disp; /* True if the object is a displacement. */ - relax_substateT relax_substate; /* Initial relaxsubstate. */ - bit_fixS *bit_fixP; /* Pointer at bit_fix struct. */ - int addr_mode; /* What addrmode do we associate with this + int im_disp; /* True if the object is a displacement. */ + relax_substateT relax_substate;/*Initial relaxsubstate. */ + bit_fixS *bit_fixP; /* Pointer at bit_fix struct. */ + int addr_mode; /* What addrmode do we associate with this iif-entry. */ - char bsr; /* Sequent hack. */ - } iif_entryT; /* Internal Instruction Format. */ + char bsr; /* Sequent hack. */ +} iif_entryT; /* Internal Instruction Format. */ struct int_ins_form - { - int instr_size; /* Max size of instruction in bytes. */ - iif_entryT iifP[IIF_ENTRIES + 1]; - }; +{ + int instr_size; /* Max size of instruction in bytes. */ + iif_entryT iifP[IIF_ENTRIES + 1]; +}; struct int_ins_form iif; expressionS exprP; @@ -367,11 +367,6 @@ char disp_test[] = char disp_size[] = {4, 1, 2, 0, 4}; -static void evaluate_expr PARAMS ((expressionS * resultP, char *)); -static void md_number_to_disp PARAMS ((char *, long, int)); -static void md_number_to_imm PARAMS ((char *, long, int)); -static void md_number_to_field PARAMS ((char *, long, bit_fixS *)); - /* Parse a general operand into an addressingmode struct In: pointer at operand in ascii form @@ -380,13 +375,10 @@ static void md_number_to_field PARAMS ((char *, long, bit_fixS *)); Out: data in addr_mode struct. */ -static int addr_mode PARAMS ((char *, addr_modeS *, int)); - static int -addr_mode (operand, addr_modeP, recursive_level) - char *operand; - addr_modeS *addr_modeP; - int recursive_level; +addr_mode (char *operand, + addr_modeS *addr_modeP, + int recursive_level) { char *str; int i; @@ -657,17 +649,25 @@ addr_mode (operand, addr_modeP, recursive_level) return -1; } +static void +evaluate_expr (expressionS *resultP, char *ptr) +{ + char *tmp_line; + + tmp_line = input_line_pointer; + input_line_pointer = ptr; + expression (resultP); + input_line_pointer = tmp_line; +} + /* ptr points at string addr_modeP points at struct with result This routine calls addr_mode to determine the general addr.mode of the operand. When this is ready it parses the displacements for size specifying suffixes and determines size of immediate mode via ns32k-opcode. Also builds index bytes if needed. */ -static int get_addr_mode PARAMS ((char *, addr_modeS *)); static int -get_addr_mode (ptr, addr_modeP) - char *ptr; - addr_modeS *addr_modeP; +get_addr_mode (char *ptr, addr_modeS *addr_modeP) { int tmp; @@ -801,12 +801,10 @@ get_addr_mode (ptr, addr_modeP) /* Read an optionlist. */ -static void optlist PARAMS ((char *, struct ns32k_option *, unsigned long *)); static void -optlist (str, optionP, default_map) - char *str; /* The string to extract options from. */ - struct ns32k_option *optionP; /* How to search the string. */ - unsigned long *default_map; /* Default pattern and output. */ +optlist (char *str, /* The string to extract options from. */ + struct ns32k_option *optionP, /* How to search the string. */ + unsigned long *default_map) /* Default pattern and output. */ { int i, j, k, strlen1, strlen2; char *patternP, *strP; @@ -845,13 +843,10 @@ optlist (str, optionP, default_map) the instructions lmr, smr, lpr, spr return true if str is found in list. */ -static int list_search PARAMS ((char *, struct ns32k_option *, unsigned long *)); - static int -list_search (str, optionP, default_map) - char *str; /* The string to match. */ - struct ns32k_option *optionP; /* List to search. */ - unsigned long *default_map; /* Default pattern and output. */ +list_search (char *str, /* The string to match. */ + struct ns32k_option *optionP, /* List to search. */ + unsigned long *default_map) /* Default pattern and output. */ { int i; @@ -870,37 +865,49 @@ list_search (str, optionP, default_map) as_bad (_("No such entry in list. (cpu/mmu register)")); return 0; } + +/* Create a bit_fixS in obstack 'notes'. + This struct is used to profile the normal fix. If the bit_fixP is a + valid pointer (not NULL) the bit_fix data will be used to format + the fix. */ -static void -evaluate_expr (resultP, ptr) - expressionS *resultP; - char *ptr; +static bit_fixS * +bit_fix_new (int size, /* Length of bitfield. */ + int offset, /* Bit offset to bitfield. */ + long min, /* Signextended min for bitfield. */ + long max, /* Signextended max for bitfield. */ + long add, /* Add mask, used for huffman prefix. */ + long base_type, /* 0 or 1, if 1 it's exploded to opcode ptr. */ + long base_adj) { - char *tmp_line; + bit_fixS *bit_fixP; - tmp_line = input_line_pointer; - input_line_pointer = ptr; - expression (resultP); - input_line_pointer = tmp_line; + bit_fixP = (bit_fixS *) obstack_alloc (¬es, sizeof (bit_fixS)); + + bit_fixP->fx_bit_size = size; + bit_fixP->fx_bit_offset = offset; + bit_fixP->fx_bit_base = base_type; + bit_fixP->fx_bit_base_adj = base_adj; + bit_fixP->fx_bit_max = max; + bit_fixP->fx_bit_min = min; + bit_fixP->fx_bit_add = add; + + return bit_fixP; } - + /* Convert operands to iif-format and adds bitfields to the opcode. Operands are parsed in such an order that the opcode is updated from its most significant bit, that is when the operand need to alter the opcode. Be careful not to put to objects in the same iif-slot. */ -static void encode_operand - PARAMS ((int, char **, const char *, const char *, char, char)); - static void -encode_operand (argc, argv, operandsP, suffixP, im_size, opcode_bit_ptr) - int argc; - char **argv; - const char *operandsP; - const char *suffixP; - char im_size ATTRIBUTE_UNUSED; - char opcode_bit_ptr; +encode_operand (int argc, + char **argv, + const char *operandsP, + const char *suffixP, + char im_size ATTRIBUTE_UNUSED, + char opcode_bit_ptr) { int i, j; char d; @@ -1079,12 +1086,8 @@ encode_operand (argc, argv, operandsP, suffixP, im_size, opcode_bit_ptr) Return-value = recursive_level. */ /* Build iif of one assembly text line. */ -static int parse PARAMS ((const char *, int)); - static int -parse (line, recursive_level) - const char *line; - int recursive_level; +parse (const char *line, int recursive_level) { const char *lineptr; char c, suffix_separator; @@ -1109,9 +1112,7 @@ parse (line, recursive_level) *(char *) lineptr = c; } else - { - lineptr = line; - } + lineptr = line; argc = 0; @@ -1208,9 +1209,7 @@ parse (line, recursive_level) lineptr += 1; } else - { - as_fatal (_("Too many operands passed to instruction")); - } + as_fatal (_("Too many operands passed to instruction")); } } } @@ -1225,9 +1224,7 @@ parse (line, recursive_level) as_fatal (_("Wrong numbers of operands in default, check ns32k-opcodes.h")); } else - { - as_fatal (_("Wrong number of operands")); - } + as_fatal (_("Wrong number of operands")); } for (i = 0; i < IIF_ENTRIES; i++) @@ -1240,183 +1237,531 @@ parse (line, recursive_level) /* This call encodes operands to iif format. */ if (argc) - { - encode_operand (argc, - argv, - &desc->operands[0], - &suffix[0], - desc->im_size, - desc->opcode_size); - } + encode_operand (argc, argv, &desc->operands[0], + &suffix[0], desc->im_size, desc->opcode_size); + return recursive_level; } -/* Convert iif to fragments. From this point we start to dribble with - functions in other files than this one.(Except hash.c) So, if it's - possible to make an iif for an other CPU, you don't need to know - what frags, relax, obstacks, etc is in order to port this - assembler. You only need to know if it's possible to reduce your - cpu-instruction to iif-format (takes some work) and adopt the other - md_? parts according to given instructions Note that iif was - invented for the clean ns32k`s architecture. */ - -/* GAS for the ns32k has a problem. PC relative displacements are - relative to the address of the opcode, not the address of the - operand. We used to keep track of the offset between the operand - and the opcode in pcrel_adjust for each frag and each fix. However, - we get into trouble where there are two or more pc-relative - operands and the size of the first one can't be determined. Then in - the relax phase, the size of the first operand will change and - pcrel_adjust will no longer be correct. The current solution is - keep a pointer to the frag with the opcode in it and the offset in - that frag for each frag and each fix. Then, when needed, we can - always figure out how far it is between the opcode and the pcrel - object. See also md_pcrel_adjust and md_fix_pcrel_adjust. For - objects not part of an instruction, the pointer to the opcode frag - is always zero. */ +#ifdef BFD_ASSEMBLER +/* This functionality should really be in the bfd library. */ -static void convert_iif PARAMS ((void)); -static void -convert_iif () +static bfd_reloc_code_real_type +reloc (int size, int pcrel, int type) { - int i; - bit_fixS *j; - fragS *inst_frag; - unsigned int inst_offset; - char *inst_opcode; - char *memP; - int l; - int k; - char type; - char size = 0; + int length, index; + bfd_reloc_code_real_type relocs[] = + { + BFD_RELOC_NS32K_IMM_8, + BFD_RELOC_NS32K_IMM_16, + BFD_RELOC_NS32K_IMM_32, + BFD_RELOC_NS32K_IMM_8_PCREL, + BFD_RELOC_NS32K_IMM_16_PCREL, + BFD_RELOC_NS32K_IMM_32_PCREL, - frag_grow (iif.instr_size); /* This is important. */ - memP = frag_more (0); - inst_opcode = memP; - inst_offset = (memP - frag_now->fr_literal); - inst_frag = frag_now; + /* ns32k displacements. */ + BFD_RELOC_NS32K_DISP_8, + BFD_RELOC_NS32K_DISP_16, + BFD_RELOC_NS32K_DISP_32, + BFD_RELOC_NS32K_DISP_8_PCREL, + BFD_RELOC_NS32K_DISP_16_PCREL, + BFD_RELOC_NS32K_DISP_32_PCREL, - for (i = 0; i < IIF_ENTRIES; i++) + /* Normal 2's complement. */ + BFD_RELOC_8, + BFD_RELOC_16, + BFD_RELOC_32, + BFD_RELOC_8_PCREL, + BFD_RELOC_16_PCREL, + BFD_RELOC_32_PCREL + }; + + switch (size) { - if ((type = iif.iifP[i].type)) - { - /* The object exist, so handle it. */ - switch (size = iif.iifP[i].size) - { - case 42: - size = 0; - /* It's a bitfix that operates on an existing object. */ - if (iif.iifP[i].bit_fixP->fx_bit_base) - /* Expand fx_bit_base to point at opcode. */ - iif.iifP[i].bit_fixP->fx_bit_base = (long) inst_opcode; - /* Fall through. */ + case 1: + length = 0; + break; + case 2: + length = 1; + break; + case 4: + length = 2; + break; + default: + length = -1; + break; + } - case 8: /* bignum or doublefloat. */ - case 1: - case 2: - case 3: - case 4: - /* The final size in objectmemory is known. */ - memP = frag_more (size); - j = iif.iifP[i].bit_fixP; + index = length + 3 * pcrel + 6 * type; - switch (type) - { - case 1: /* The object is pure binary. */ - if (j) - { - md_number_to_field(memP, exprP.X_add_number, j); - } - else if (iif.iifP[i].pcrel) - { - fix_new_ns32k (frag_now, - (long) (memP - frag_now->fr_literal), - size, - 0, - iif.iifP[i].object, - iif.iifP[i].pcrel, - iif.iifP[i].im_disp, - 0, - iif.iifP[i].bsr, /* Sequent hack. */ - inst_frag, inst_offset); - } - else - { - /* Good, just put them bytes out. */ - switch (iif.iifP[i].im_disp) - { - case 0: - md_number_to_chars (memP, iif.iifP[i].object, size); - break; - case 1: - md_number_to_disp (memP, iif.iifP[i].object, size); - break; - default: - as_fatal (_("iif convert internal pcrel/binary")); - } - } - break; + if (index >= 0 && (unsigned int) index < sizeof (relocs) / sizeof (relocs[0])) + return relocs[index]; - case 2: - /* The object is a pointer at an expression, so - unpack it, note that bignums may result from the - expression. */ - evaluate_expr (&exprP, (char *) iif.iifP[i].object); - if (exprP.X_op == O_big || size == 8) - { - if ((k = exprP.X_add_number) > 0) - { - /* We have a bignum ie a quad. This can only - happens in a long suffixed instruction. */ - if (k * 2 > size) - as_bad (_("Bignum too big for long")); + if (pcrel) + as_bad (_("Can not do %d byte pc-relative relocation for storage type %d"), + size, type); + else + as_bad (_("Can not do %d byte relocation for storage type %d"), + size, type); - if (k == 3) - memP += 2; + return BFD_RELOC_NONE; - for (l = 0; k > 0; k--, l += 2) - md_number_to_chars (memP + l, - generic_bignum[l >> 1], - sizeof (LITTLENUM_TYPE)); - } - else - { - /* flonum. */ - LITTLENUM_TYPE words[4]; +} +#endif - switch (size) - { - case 4: - gen_to_words (words, 2, 8); - md_number_to_imm (memP, (long) words[0], - sizeof (LITTLENUM_TYPE)); - md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), - (long) words[1], - sizeof (LITTLENUM_TYPE)); - break; - case 8: - gen_to_words (words, 4, 11); - md_number_to_imm (memP, (long) words[0], - sizeof (LITTLENUM_TYPE)); - md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), - (long) words[1], - sizeof (LITTLENUM_TYPE)); - md_number_to_imm ((memP + 2 - * sizeof (LITTLENUM_TYPE)), - (long) words[2], - sizeof (LITTLENUM_TYPE)); - md_number_to_imm ((memP + 3 - * sizeof (LITTLENUM_TYPE)), - (long) words[3], - sizeof (LITTLENUM_TYPE)); - break; - } - } - break; - } - if (exprP.X_add_symbol || - exprP.X_op_symbol || - iif.iifP[i].pcrel) +static void +fix_new_ns32k (fragS *frag, /* Which frag? */ + int where, /* Where in that frag? */ + int size, /* 1, 2 or 4 usually. */ + symbolS *add_symbol, /* X_add_symbol. */ + long offset, /* X_add_number. */ + int pcrel, /* True if PC-relative relocation. */ + char im_disp, /* True if the value to write is a + displacement. */ + bit_fixS *bit_fixP, /* Pointer at struct of bit_fix's, ignored if + NULL. */ + char bsr, /* Sequent-linker-hack: 1 when relocobject is + a bsr. */ + fragS *opcode_frag, + unsigned int opcode_offset) +{ + fixS *fixP = fix_new (frag, where, size, add_symbol, + offset, pcrel, +#ifdef BFD_ASSEMBLER + bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp) +#else + NO_RELOC +#endif + ); + + fix_opcode_frag (fixP) = opcode_frag; + fix_opcode_offset (fixP) = opcode_offset; + fix_im_disp (fixP) = im_disp; + fix_bsr (fixP) = bsr; + fix_bit_fixP (fixP) = bit_fixP; + /* We have a MD overflow check for displacements. */ + fixP->fx_no_overflow = (im_disp != 0); +} + +static void +fix_new_ns32k_exp (fragS *frag, /* Which frag? */ + int where, /* Where in that frag? */ + int size, /* 1, 2 or 4 usually. */ + expressionS *exp, /* Expression. */ + int pcrel, /* True if PC-relative relocation. */ + char im_disp, /* True if the value to write is a + displacement. */ + bit_fixS *bit_fixP, /* Pointer at struct of bit_fix's, ignored if + NULL. */ + char bsr, /* Sequent-linker-hack: 1 when relocobject is + a bsr. */ + fragS *opcode_frag, + unsigned int opcode_offset) +{ + fixS *fixP = fix_new_exp (frag, where, size, exp, pcrel, +#ifdef BFD_ASSEMBLER + bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp) +#else + NO_RELOC +#endif + ); + + fix_opcode_frag (fixP) = opcode_frag; + fix_opcode_offset (fixP) = opcode_offset; + fix_im_disp (fixP) = im_disp; + fix_bsr (fixP) = bsr; + fix_bit_fixP (fixP) = bit_fixP; + /* We have a MD overflow check for displacements. */ + fixP->fx_no_overflow = (im_disp != 0); +} + +/* Convert number to chars in correct order. */ + +void +md_number_to_chars (char *buf, valueT value, int nbytes) +{ + number_to_chars_littleendian (buf, value, nbytes); +} + +/* This is a variant of md_numbers_to_chars. The reason for its' + existence is the fact that ns32k uses Huffman coded + displacements. This implies that the bit order is reversed in + displacements and that they are prefixed with a size-tag. + + binary: msb -> lsb + 0xxxxxxx byte + 10xxxxxx xxxxxxxx word + 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word + + This must be taken care of and we do it here! */ + +static void +md_number_to_disp (char *buf, long val, int n) +{ + switch (n) + { + case 1: + if (val < -64 || val > 63) + as_bad (_("value of %ld out of byte displacement range."), val); + val &= 0x7f; +#ifdef SHOW_NUM + printf ("%x ", val & 0xff); +#endif + *buf++ = val; + break; + + case 2: + if (val < -8192 || val > 8191) + as_bad (_("value of %ld out of word displacement range."), val); + val &= 0x3fff; + val |= 0x8000; +#ifdef SHOW_NUM + printf ("%x ", val >> 8 & 0xff); +#endif + *buf++ = (val >> 8); +#ifdef SHOW_NUM + printf ("%x ", val & 0xff); +#endif + *buf++ = val; + break; + + case 4: + if (val < -0x20000000 || val >= 0x20000000) + as_bad (_("value of %ld out of double word displacement range."), val); + val |= 0xc0000000; +#ifdef SHOW_NUM + printf ("%x ", val >> 24 & 0xff); +#endif + *buf++ = (val >> 24); +#ifdef SHOW_NUM + printf ("%x ", val >> 16 & 0xff); +#endif + *buf++ = (val >> 16); +#ifdef SHOW_NUM + printf ("%x ", val >> 8 & 0xff); +#endif + *buf++ = (val >> 8); +#ifdef SHOW_NUM + printf ("%x ", val & 0xff); +#endif + *buf++ = val; + break; + + default: + as_fatal (_("Internal logic error. line %d, file \"%s\""), + __LINE__, __FILE__); + } +} + +static void +md_number_to_imm (char *buf, long val, int n) +{ + switch (n) + { + case 1: +#ifdef SHOW_NUM + printf ("%x ", val & 0xff); +#endif + *buf++ = val; + break; + + case 2: +#ifdef SHOW_NUM + printf ("%x ", val >> 8 & 0xff); +#endif + *buf++ = (val >> 8); +#ifdef SHOW_NUM + printf ("%x ", val & 0xff); +#endif + *buf++ = val; + break; + + case 4: +#ifdef SHOW_NUM + printf ("%x ", val >> 24 & 0xff); +#endif + *buf++ = (val >> 24); +#ifdef SHOW_NUM + printf ("%x ", val >> 16 & 0xff); +#endif + *buf++ = (val >> 16); +#ifdef SHOW_NUM + printf ("%x ", val >> 8 & 0xff); +#endif + *buf++ = (val >> 8); +#ifdef SHOW_NUM + printf ("%x ", val & 0xff); +#endif + *buf++ = val; + break; + + default: + as_fatal (_("Internal logic error. line %d, file \"%s\""), + __LINE__, __FILE__); + } +} + +/* Fast bitfiddling support. */ +/* Mask used to zero bitfield before oring in the true field. */ + +static unsigned long l_mask[] = +{ + 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, + 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, + 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, + 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, + 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, + 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, + 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, + 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, +}; +static unsigned long r_mask[] = +{ + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, +}; +#define MASK_BITS 31 +/* Insert bitfield described by field_ptr and val at buf + This routine is written for modification of the first 4 bytes pointed + to by buf, to yield speed. + The ifdef stuff is for selection between a ns32k-dependent routine + and a general version. (My advice: use the general version!). */ + +static void +md_number_to_field (char *buf, long val, bit_fixS *field_ptr) +{ + unsigned long object; + unsigned long mask; + /* Define ENDIAN on a ns32k machine. */ +#ifdef ENDIAN + unsigned long *mem_ptr; +#else + char *mem_ptr; +#endif + + if (field_ptr->fx_bit_min <= val && val <= field_ptr->fx_bit_max) + { +#ifdef ENDIAN + if (field_ptr->fx_bit_base) + /* Override buf. */ + mem_ptr = (unsigned long *) field_ptr->fx_bit_base; + else + mem_ptr = (unsigned long *) buf; + + mem_ptr = ((unsigned long *) + ((char *) mem_ptr + field_ptr->fx_bit_base_adj)); +#else + if (field_ptr->fx_bit_base) + mem_ptr = (char *) field_ptr->fx_bit_base; + else + mem_ptr = buf; + + mem_ptr += field_ptr->fx_bit_base_adj; +#endif +#ifdef ENDIAN + /* We have a nice ns32k machine with lowbyte at low-physical mem. */ + object = *mem_ptr; /* get some bytes */ +#else /* OVE Goof! the machine is a m68k or dito. */ + /* That takes more byte fiddling. */ + object = 0; + object |= mem_ptr[3] & 0xff; + object <<= 8; + object |= mem_ptr[2] & 0xff; + object <<= 8; + object |= mem_ptr[1] & 0xff; + object <<= 8; + object |= mem_ptr[0] & 0xff; +#endif + mask = 0; + mask |= (r_mask[field_ptr->fx_bit_offset]); + mask |= (l_mask[field_ptr->fx_bit_offset + field_ptr->fx_bit_size]); + object &= mask; + val += field_ptr->fx_bit_add; + object |= ((val << field_ptr->fx_bit_offset) & (mask ^ 0xffffffff)); +#ifdef ENDIAN + *mem_ptr = object; +#else + mem_ptr[0] = (char) object; + object >>= 8; + mem_ptr[1] = (char) object; + object >>= 8; + mem_ptr[2] = (char) object; + object >>= 8; + mem_ptr[3] = (char) object; +#endif + } + else + as_bad (_("Bit field out of range")); +} + +/* Convert iif to fragments. From this point we start to dribble with + functions in other files than this one.(Except hash.c) So, if it's + possible to make an iif for an other CPU, you don't need to know + what frags, relax, obstacks, etc is in order to port this + assembler. You only need to know if it's possible to reduce your + cpu-instruction to iif-format (takes some work) and adopt the other + md_? parts according to given instructions Note that iif was + invented for the clean ns32k`s architecture. */ + +/* GAS for the ns32k has a problem. PC relative displacements are + relative to the address of the opcode, not the address of the + operand. We used to keep track of the offset between the operand + and the opcode in pcrel_adjust for each frag and each fix. However, + we get into trouble where there are two or more pc-relative + operands and the size of the first one can't be determined. Then in + the relax phase, the size of the first operand will change and + pcrel_adjust will no longer be correct. The current solution is + keep a pointer to the frag with the opcode in it and the offset in + that frag for each frag and each fix. Then, when needed, we can + always figure out how far it is between the opcode and the pcrel + object. See also md_pcrel_adjust and md_fix_pcrel_adjust. For + objects not part of an instruction, the pointer to the opcode frag + is always zero. */ + +static void +convert_iif (void) +{ + int i; + bit_fixS *j; + fragS *inst_frag; + unsigned int inst_offset; + char *inst_opcode; + char *memP; + int l; + int k; + char type; + char size = 0; + + frag_grow (iif.instr_size); /* This is important. */ + memP = frag_more (0); + inst_opcode = memP; + inst_offset = (memP - frag_now->fr_literal); + inst_frag = frag_now; + + for (i = 0; i < IIF_ENTRIES; i++) + { + if ((type = iif.iifP[i].type)) + { + /* The object exist, so handle it. */ + switch (size = iif.iifP[i].size) + { + case 42: + size = 0; + /* It's a bitfix that operates on an existing object. */ + if (iif.iifP[i].bit_fixP->fx_bit_base) + /* Expand fx_bit_base to point at opcode. */ + iif.iifP[i].bit_fixP->fx_bit_base = (long) inst_opcode; + /* Fall through. */ + + case 8: /* bignum or doublefloat. */ + case 1: + case 2: + case 3: + case 4: + /* The final size in objectmemory is known. */ + memP = frag_more (size); + j = iif.iifP[i].bit_fixP; + + switch (type) + { + case 1: /* The object is pure binary. */ + if (j) + md_number_to_field (memP, exprP.X_add_number, j); + + else if (iif.iifP[i].pcrel) + fix_new_ns32k (frag_now, + (long) (memP - frag_now->fr_literal), + size, + 0, + iif.iifP[i].object, + iif.iifP[i].pcrel, + iif.iifP[i].im_disp, + 0, + iif.iifP[i].bsr, /* Sequent hack. */ + inst_frag, inst_offset); + else + { + /* Good, just put them bytes out. */ + switch (iif.iifP[i].im_disp) + { + case 0: + md_number_to_chars (memP, iif.iifP[i].object, size); + break; + case 1: + md_number_to_disp (memP, iif.iifP[i].object, size); + break; + default: + as_fatal (_("iif convert internal pcrel/binary")); + } + } + break; + + case 2: + /* The object is a pointer at an expression, so + unpack it, note that bignums may result from the + expression. */ + evaluate_expr (&exprP, (char *) iif.iifP[i].object); + if (exprP.X_op == O_big || size == 8) + { + if ((k = exprP.X_add_number) > 0) + { + /* We have a bignum ie a quad. This can only + happens in a long suffixed instruction. */ + if (k * 2 > size) + as_bad (_("Bignum too big for long")); + + if (k == 3) + memP += 2; + + for (l = 0; k > 0; k--, l += 2) + md_number_to_chars (memP + l, + generic_bignum[l >> 1], + sizeof (LITTLENUM_TYPE)); + } + else + { + /* flonum. */ + LITTLENUM_TYPE words[4]; + + switch (size) + { + case 4: + gen_to_words (words, 2, 8); + md_number_to_imm (memP, (long) words[0], + sizeof (LITTLENUM_TYPE)); + md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), + (long) words[1], + sizeof (LITTLENUM_TYPE)); + break; + case 8: + gen_to_words (words, 4, 11); + md_number_to_imm (memP, (long) words[0], + sizeof (LITTLENUM_TYPE)); + md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), + (long) words[1], + sizeof (LITTLENUM_TYPE)); + md_number_to_imm ((memP + 2 + * sizeof (LITTLENUM_TYPE)), + (long) words[2], + sizeof (LITTLENUM_TYPE)); + md_number_to_imm ((memP + 3 + * sizeof (LITTLENUM_TYPE)), + (long) words[3], + sizeof (LITTLENUM_TYPE)); + break; + } + } + break; + } + if (exprP.X_add_symbol || + exprP.X_op_symbol || + iif.iifP[i].pcrel) { /* The expression was undefined due to an undefined label. Create a fix so we can fix @@ -1433,9 +1778,7 @@ convert_iif () inst_frag, inst_offset); } else if (j) - { - md_number_to_field(memP, exprP.X_add_number, j); - } + md_number_to_field (memP, exprP.X_add_number, j); else { /* Good, just put them bytes out. */ @@ -1488,10 +1831,8 @@ convert_iif () { /* Frag it. */ if (exprP.X_op_symbol) - { - /* We cant relax this case. */ - as_fatal (_("Can't relax difference")); - } + /* We cant relax this case. */ + as_fatal (_("Can't relax difference")); else { /* Size is not important. This gets fixed by @@ -1519,23 +1860,17 @@ convert_iif () { /* This duplicates code in md_number_to_disp. */ if (-64 <= exprP.X_add_number && exprP.X_add_number <= 63) - { - size = 1; - } + size = 1; else { if (-8192 <= exprP.X_add_number && exprP.X_add_number <= 8191) - { - size = 2; - } + size = 2; else { if (-0x20000000 <= exprP.X_add_number && exprP.X_add_number<=0x1fffffff) - { - size = 4; - } + size = 4; else { as_bad (_("Displacement to large for :d")); @@ -1554,392 +1889,89 @@ convert_iif () as_fatal (_("Internal logic error in iif.iifP[].type")); } } - } -} - -#ifdef BFD_ASSEMBLER -/* This functionality should really be in the bfd library. */ -static bfd_reloc_code_real_type -reloc (int size, int pcrel, int type) -{ - int length, index; - bfd_reloc_code_real_type relocs[] = - { - BFD_RELOC_NS32K_IMM_8, - BFD_RELOC_NS32K_IMM_16, - BFD_RELOC_NS32K_IMM_32, - BFD_RELOC_NS32K_IMM_8_PCREL, - BFD_RELOC_NS32K_IMM_16_PCREL, - BFD_RELOC_NS32K_IMM_32_PCREL, - - /* ns32k displacements. */ - BFD_RELOC_NS32K_DISP_8, - BFD_RELOC_NS32K_DISP_16, - BFD_RELOC_NS32K_DISP_32, - BFD_RELOC_NS32K_DISP_8_PCREL, - BFD_RELOC_NS32K_DISP_16_PCREL, - BFD_RELOC_NS32K_DISP_32_PCREL, - - /* Normal 2's complement. */ - BFD_RELOC_8, - BFD_RELOC_16, - BFD_RELOC_32, - BFD_RELOC_8_PCREL, - BFD_RELOC_16_PCREL, - BFD_RELOC_32_PCREL - }; - - switch (size) - { - case 1: - length = 0; - break; - case 2: - length = 1; - break; - case 4: - length = 2; - break; - default: - length = -1; - break; - } - - index = length + 3 * pcrel + 6 * type; - - if (index >= 0 && (unsigned int) index < sizeof (relocs) / sizeof (relocs[0])) - return relocs[index]; - - if (pcrel) - as_bad (_("Can not do %d byte pc-relative relocation for storage type %d"), - size, type); - else - as_bad (_("Can not do %d byte relocation for storage type %d"), - size, type); - - return BFD_RELOC_NONE; - -} -#endif - -void -md_assemble (line) - char *line; -{ - freeptr = freeptr_static; - parse (line, 0); /* Explode line to more fix form in iif. */ - convert_iif (); /* Convert iif to frags, fix's etc. */ -#ifdef SHOW_NUM - printf (" \t\t\t%s\n", line); -#endif -} - -void -md_begin () -{ - /* Build a hashtable of the instructions. */ - const struct ns32k_opcode *ptr; - const char *stat; - const struct ns32k_opcode *endop; - - inst_hash_handle = hash_new (); - - endop = ns32k_opcodes + sizeof (ns32k_opcodes) / sizeof (ns32k_opcodes[0]); - for (ptr = ns32k_opcodes; ptr < endop; ptr++) - { - if ((stat = hash_insert (inst_hash_handle, ptr->name, (char *) ptr))) - /* Fatal. */ - as_fatal (_("Can't hash %s: %s"), ptr->name, stat); - } - - /* Some private space please! */ - freeptr_static = (char *) malloc (PRIVATE_SIZE); -} - -/* Must be equal to MAX_PRECISON in atof-ieee.c. */ -#define MAX_LITTLENUMS 6 - -/* Turn the string pointed to by litP into a floating point constant - of type TYPE, and emit the appropriate bytes. The number of - LITTLENUMS emitted is stored in *SIZEP. An error message is - returned, or NULL on OK. */ - -char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; -{ - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - - switch (type) - { - case 'f': - prec = 2; - break; - - case 'd': - prec = 4; - break; - default: - *sizeP = 0; - return _("Bad call to MD_ATOF()"); - } - - t = atof_ieee (input_line_pointer, type, words); - if (t) - input_line_pointer = t; - - *sizeP = prec * sizeof (LITTLENUM_TYPE); - - for (wordP = words + prec; prec--;) - { - md_number_to_chars (litP, (long) (*--wordP), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - - return 0; -} - -/* Convert number to chars in correct order. */ - -void -md_number_to_chars (buf, value, nbytes) - char *buf; - valueT value; - int nbytes; -{ - number_to_chars_littleendian (buf, value, nbytes); -} - -/* This is a variant of md_numbers_to_chars. The reason for its' - existence is the fact that ns32k uses Huffman coded - displacements. This implies that the bit order is reversed in - displacements and that they are prefixed with a size-tag. - - binary: msb -> lsb - 0xxxxxxx byte - 10xxxxxx xxxxxxxx word - 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word - - This must be taken care of and we do it here! */ - -static void -md_number_to_disp (buf, val, n) - char *buf; - long val; - char n; -{ - switch (n) - { - case 1: - if (val < -64 || val > 63) - as_bad (_("value of %ld out of byte displacement range."), val); - val &= 0x7f; -#ifdef SHOW_NUM - printf ("%x ", val & 0xff); -#endif - *buf++ = val; - break; - case 2: - if (val < -8192 || val > 8191) - as_bad (_("value of %ld out of word displacement range."), val); - val &= 0x3fff; - val |= 0x8000; -#ifdef SHOW_NUM - printf ("%x ", val >> 8 & 0xff); -#endif - *buf++ = (val >> 8); -#ifdef SHOW_NUM - printf ("%x ", val & 0xff); -#endif - *buf++ = val; - break; - case 4: - if (val < -0x20000000 || val >= 0x20000000) - as_bad (_("value of %ld out of double word displacement range."), val); - val |= 0xc0000000; -#ifdef SHOW_NUM - printf ("%x ", val >> 24 & 0xff); -#endif - *buf++ = (val >> 24); -#ifdef SHOW_NUM - printf ("%x ", val >> 16 & 0xff); -#endif - *buf++ = (val >> 16); -#ifdef SHOW_NUM - printf ("%x ", val >> 8 & 0xff); -#endif - *buf++ = (val >> 8); + } +} + +void +md_assemble (char *line) +{ + freeptr = freeptr_static; + parse (line, 0); /* Explode line to more fix form in iif. */ + convert_iif (); /* Convert iif to frags, fix's etc. */ #ifdef SHOW_NUM - printf ("%x ", val & 0xff); + printf (" \t\t\t%s\n", line); #endif - *buf++ = val; - break; - default: - as_fatal (_("Internal logic error. line %d, file \"%s\""), - __LINE__, __FILE__); - } } -static void -md_number_to_imm (buf, val, n) - char *buf; - long val; - char n; +void +md_begin (void) { - switch (n) + /* Build a hashtable of the instructions. */ + const struct ns32k_opcode *ptr; + const char *stat; + const struct ns32k_opcode *endop; + + inst_hash_handle = hash_new (); + + endop = ns32k_opcodes + sizeof (ns32k_opcodes) / sizeof (ns32k_opcodes[0]); + for (ptr = ns32k_opcodes; ptr < endop; ptr++) { - case 1: -#ifdef SHOW_NUM - printf ("%x ", val & 0xff); -#endif - *buf++ = val; - break; - case 2: -#ifdef SHOW_NUM - printf ("%x ", val >> 8 & 0xff); -#endif - *buf++ = (val >> 8); -#ifdef SHOW_NUM - printf ("%x ", val & 0xff); -#endif - *buf++ = val; - break; - case 4: -#ifdef SHOW_NUM - printf ("%x ", val >> 24 & 0xff); -#endif - *buf++ = (val >> 24); -#ifdef SHOW_NUM - printf ("%x ", val >> 16 & 0xff); -#endif - *buf++ = (val >> 16); -#ifdef SHOW_NUM - printf ("%x ", val >> 8 & 0xff); -#endif - *buf++ = (val >> 8); -#ifdef SHOW_NUM - printf ("%x ", val & 0xff); -#endif - *buf++ = val; - break; - default: - as_fatal (_("Internal logic error. line %d, file \"%s\""), - __LINE__, __FILE__); + if ((stat = hash_insert (inst_hash_handle, ptr->name, (char *) ptr))) + /* Fatal. */ + as_fatal (_("Can't hash %s: %s"), ptr->name, stat); } + + /* Some private space please! */ + freeptr_static = (char *) malloc (PRIVATE_SIZE); } -/* Fast bitfiddling support. */ -/* Mask used to zero bitfield before oring in the true field. */ +/* Must be equal to MAX_PRECISON in atof-ieee.c. */ +#define MAX_LITTLENUMS 6 -static unsigned long l_mask[] = -{ - 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, - 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, - 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, - 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, - 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, - 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, - 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, - 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, -}; -static unsigned long r_mask[] = -{ - 0x00000000, 0x00000001, 0x00000003, 0x00000007, - 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, - 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, - 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, - 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, - 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, - 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, - 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, -}; -#define MASK_BITS 31 -/* Insert bitfield described by field_ptr and val at buf - This routine is written for modification of the first 4 bytes pointed - to by buf, to yield speed. - The ifdef stuff is for selection between a ns32k-dependent routine - and a general version. (My advice: use the general version!). */ +/* Turn the string pointed to by litP into a floating point constant + of type TYPE, and emit the appropriate bytes. The number of + LITTLENUMS emitted is stored in *SIZEP. An error message is + returned, or NULL on OK. */ -static void -md_number_to_field (buf, val, field_ptr) - char *buf; - long val; - bit_fixS *field_ptr; +char * +md_atof (int type, char *litP, int *sizeP) { - unsigned long object; - unsigned long mask; - /* Define ENDIAN on a ns32k machine. */ -#ifdef ENDIAN - unsigned long *mem_ptr; -#else - char *mem_ptr; -#endif + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; - if (field_ptr->fx_bit_min <= val && val <= field_ptr->fx_bit_max) + switch (type) { -#ifdef ENDIAN - if (field_ptr->fx_bit_base) - /* Override buf. */ - mem_ptr = (unsigned long *) field_ptr->fx_bit_base; - else - mem_ptr = (unsigned long *) buf; - - mem_ptr = ((unsigned long *) - ((char *) mem_ptr + field_ptr->fx_bit_base_adj)); -#else - if (field_ptr->fx_bit_base) - mem_ptr = (char *) field_ptr->fx_bit_base; - else - mem_ptr = buf; + case 'f': + prec = 2; + break; - mem_ptr += field_ptr->fx_bit_base_adj; -#endif -#ifdef ENDIAN - /* We have a nice ns32k machine with lowbyte at low-physical mem. */ - object = *mem_ptr; /* get some bytes */ -#else /* OVE Goof! the machine is a m68k or dito. */ - /* That takes more byte fiddling. */ - object = 0; - object |= mem_ptr[3] & 0xff; - object <<= 8; - object |= mem_ptr[2] & 0xff; - object <<= 8; - object |= mem_ptr[1] & 0xff; - object <<= 8; - object |= mem_ptr[0] & 0xff; -#endif - mask = 0; - mask |= (r_mask[field_ptr->fx_bit_offset]); - mask |= (l_mask[field_ptr->fx_bit_offset + field_ptr->fx_bit_size]); - object &= mask; - val += field_ptr->fx_bit_add; - object |= ((val << field_ptr->fx_bit_offset) & (mask ^ 0xffffffff)); -#ifdef ENDIAN - *mem_ptr = object; -#else - mem_ptr[0] = (char) object; - object >>= 8; - mem_ptr[1] = (char) object; - object >>= 8; - mem_ptr[2] = (char) object; - object >>= 8; - mem_ptr[3] = (char) object; -#endif + case 'd': + prec = 4; + break; + default: + *sizeP = 0; + return _("Bad call to MD_ATOF()"); } - else + + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * sizeof (LITTLENUM_TYPE); + + for (wordP = words + prec; prec--;) { - as_bad (_("Bit field out of range")); + md_number_to_chars (litP, (long) (*--wordP), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); } -} + return 0; +} + int -md_pcrel_adjust (fragP) - fragS *fragP; +md_pcrel_adjust (fragS *fragP) { fragS *opcode_frag; addressT opcode_address; @@ -1955,10 +1987,8 @@ md_pcrel_adjust (fragP) return fragP->fr_address + fragP->fr_fix - opcode_address; } -static int md_fix_pcrel_adjust PARAMS ((fixS *fixP)); static int -md_fix_pcrel_adjust (fixP) - fixS *fixP; +md_fix_pcrel_adjust (fixS *fixP) { fragS *opcode_frag; addressT opcode_address; @@ -1982,19 +2012,14 @@ md_fix_pcrel_adjust (fixP) They all get called from here. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED) { long val = * (long *) valP; char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; if (fix_bit_fixP (fixP)) - { - /* Bitfields to fix, sigh. */ - md_number_to_field (buf, val, fix_bit_fixP (fixP)); - } + /* Bitfields to fix, sigh. */ + md_number_to_field (buf, val, fix_bit_fixP (fixP)); else switch (fix_im_disp (fixP)) { case 0: @@ -2024,16 +2049,14 @@ md_apply_fix3 (fixP, valP, seg) #ifndef BFD_ASSEMBLER void -md_convert_frag (headers, sec, fragP) - object_headers *headers; - segT sec; - fragS *fragP; +md_convert_frag (object_headers *headers, + segT sec, + fragS *fragP) #else void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS *fragP; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS *fragP) #endif { long disp; @@ -2076,9 +2099,7 @@ md_convert_frag (abfd, sec, fragP) actually know it. */ int -md_estimate_size_before_relax (fragP, segment) - fragS *fragP; - segT segment; +md_estimate_size_before_relax (fragS *fragP, segT segment) { if (fragP->fr_subtype == IND (BRANCH, UNDEF)) { @@ -2119,11 +2140,11 @@ int md_long_jump_size = 5; const int md_reloc_size = 8; /* Size of relocation record. */ void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; +md_create_short_jump (char *ptr, + addressT from_addr, + addressT to_addr, + fragS *frag ATTRIBUTE_UNUSED, + symbolS *to_symbol ATTRIBUTE_UNUSED) { valueT offset; @@ -2133,11 +2154,11 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) } void -md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag ATTRIBUTE_UNUSED; - symbolS *to_symbol ATTRIBUTE_UNUSED; +md_create_long_jump (char *ptr, + addressT from_addr, + addressT to_addr, + fragS *frag ATTRIBUTE_UNUSED, + symbolS *to_symbol ATTRIBUTE_UNUSED) { valueT offset; @@ -2158,9 +2179,7 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { switch (c) { @@ -2204,8 +2223,7 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("\ NS32K options:\n\ @@ -2213,114 +2231,13 @@ NS32K options:\n\ --disp-size-default=<1|2|4>\n")); } -/* Create a bit_fixS in obstack 'notes'. - This struct is used to profile the normal fix. If the bit_fixP is a - valid pointer (not NULL) the bit_fix data will be used to format - the fix. */ - -bit_fixS * -bit_fix_new (size, offset, min, max, add, base_type, base_adj) - char size; /* Length of bitfield. */ - char offset; /* Bit offset to bitfield. */ - long min; /* Signextended min for bitfield. */ - long max; /* Signextended max for bitfield. */ - long add; /* Add mask, used for huffman prefix. */ - long base_type; /* 0 or 1, if 1 it's exploded to opcode ptr. */ - long base_adj; -{ - bit_fixS *bit_fixP; - - bit_fixP = (bit_fixS *) obstack_alloc (¬es, sizeof (bit_fixS)); - - bit_fixP->fx_bit_size = size; - bit_fixP->fx_bit_offset = offset; - bit_fixP->fx_bit_base = base_type; - bit_fixP->fx_bit_base_adj = base_adj; - bit_fixP->fx_bit_max = max; - bit_fixP->fx_bit_min = min; - bit_fixP->fx_bit_add = add; - - return bit_fixP; -} - -void -fix_new_ns32k (frag, where, size, add_symbol, offset, pcrel, - im_disp, bit_fixP, bsr, opcode_frag, opcode_offset) - fragS *frag; /* Which frag? */ - int where; /* Where in that frag? */ - int size; /* 1, 2 or 4 usually. */ - symbolS *add_symbol; /* X_add_symbol. */ - long offset; /* X_add_number. */ - int pcrel; /* True if PC-relative relocation. */ - char im_disp; /* True if the value to write is a - displacement. */ - bit_fixS *bit_fixP; /* Pointer at struct of bit_fix's, ignored if - NULL. */ - char bsr; /* Sequent-linker-hack: 1 when relocobject is - a bsr. */ - fragS *opcode_frag; - unsigned int opcode_offset; -{ - fixS *fixP = fix_new (frag, where, size, add_symbol, - offset, pcrel, -#ifdef BFD_ASSEMBLER - bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp) -#else - NO_RELOC -#endif - ); - - fix_opcode_frag (fixP) = opcode_frag; - fix_opcode_offset (fixP) = opcode_offset; - fix_im_disp (fixP) = im_disp; - fix_bsr (fixP) = bsr; - fix_bit_fixP (fixP) = bit_fixP; - /* We have a MD overflow check for displacements. */ - fixP->fx_no_overflow = (im_disp != 0); -} - -void -fix_new_ns32k_exp (frag, where, size, exp, pcrel, - im_disp, bit_fixP, bsr, opcode_frag, opcode_offset) - fragS *frag; /* Which frag? */ - int where; /* Where in that frag? */ - int size; /* 1, 2 or 4 usually. */ - expressionS *exp; /* Expression. */ - int pcrel; /* True if PC-relative relocation. */ - char im_disp; /* True if the value to write is a - displacement. */ - bit_fixS *bit_fixP; /* Pointer at struct of bit_fix's, ignored if - NULL. */ - char bsr; /* Sequent-linker-hack: 1 when relocobject is - a bsr. */ - fragS *opcode_frag; - unsigned int opcode_offset; -{ - fixS *fixP = fix_new_exp (frag, where, size, exp, pcrel, -#ifdef BFD_ASSEMBLER - bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp) -#else - NO_RELOC -#endif - ); - - fix_opcode_frag (fixP) = opcode_frag; - fix_opcode_offset (fixP) = opcode_offset; - fix_im_disp (fixP) = im_disp; - fix_bsr (fixP) = bsr; - fix_bit_fixP (fixP) = bit_fixP; - /* We have a MD overflow check for displacements. */ - fixP->fx_no_overflow = (im_disp != 0); -} - /* This is TC_CONS_FIX_NEW, called by emit_expr in read.c. */ void -cons_fix_new_ns32k (frag, where, size, exp) - fragS *frag; /* Which frag? */ - int where; /* Where in that frag? */ - int size; /* 1, 2 or 4 usually. */ - expressionS *exp; /* Expression. */ +cons_fix_new_ns32k (fragS *frag, /* Which frag? */ + int where, /* Where in that frag? */ + int size, /* 1, 2 or 4 usually. */ + expressionS *exp) /* Expression. */ { fix_new_ns32k_exp (frag, where, size, exp, 0, 2, 0, 0, 0, 0); @@ -2329,8 +2246,7 @@ cons_fix_new_ns32k (frag, where, size, exp) /* We have no need to default values of symbols. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -2338,9 +2254,7 @@ md_undefined_symbol (name) /* Round up a section size to the appropriate boundary. */ valueT -md_section_align (segment, size) - segT segment ATTRIBUTE_UNUSED; - valueT size; +md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) { return size; /* Byte alignment is fine. */ } @@ -2349,8 +2263,7 @@ md_section_align (segment, size) ns32k, they're relative to the start of the instruction. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { long res; @@ -2365,17 +2278,15 @@ md_pcrel_from (fixP) #ifdef BFD_ASSEMBLER arelent * -tc_gen_reloc (section, fixp) - asection *section ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) { arelent *rel; bfd_reloc_code_real_type code; code = reloc (fixp->fx_size, fixp->fx_pcrel, fix_im_disp (fixp)); - rel = (arelent *) xmalloc (sizeof (arelent)); - rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + rel = xmalloc (sizeof (arelent)); + rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); rel->address = fixp->fx_frag->fr_address + fixp->fx_where; if (fixp->fx_pcrel) @@ -2401,10 +2312,9 @@ tc_gen_reloc (section, fixp) #ifdef OBJ_AOUT void -cons_fix_new_ns32k (where, fixP, segment_address_in_file) - char *where; - struct fix *fixP; - relax_addressT segment_address_in_file; +cons_fix_new_ns32k (char *where, + struct fix *fixP, + relax_addressT segment_address_in_file) { /* In: Length of relocation (or of address) in chars: 1, 2 or 4. Out: GNU LD relocation length code: 0, 1, or 2. */ diff --git a/gas/config/tc-ns32k.h b/gas/config/tc-ns32k.h index e547bf59a9a..9325e22b9c0 100644 --- a/gas/config/tc-ns32k.h +++ b/gas/config/tc-ns32k.h @@ -1,5 +1,5 @@ /* tc-ns32k.h -- Opcode table for National Semi 32k processor - Copyright 1987, 1992, 1993, 1994, 1995, 1997, 2000, 2002 + Copyright 1987, 1992, 1993, 1994, 1995, 1997, 2000, 2002, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -24,14 +24,14 @@ #define TARGET_BYTES_BIG_ENDIAN 0 #define TC_PCREL_ADJUST(F) md_pcrel_adjust(F) -extern int md_pcrel_adjust PARAMS((fragS *fragP)); +extern int md_pcrel_adjust (fragS *); #ifdef BFD_ASSEMBLER #define NO_RELOC BFD_RELOC_NONE #define TARGET_ARCH bfd_arch_ns32k -#ifndef TARGET_FORMAT /* Maybe defined in te-*.h */ +#ifndef TARGET_FORMAT /* Maybe defined in te-*.h. */ #define TARGET_FORMAT "a.out-pc532-mach" #endif #else @@ -63,15 +63,7 @@ extern int md_pcrel_adjust PARAMS((fragS *fragP)); #define ARG_LEN 50 #define TC_CONS_FIX_NEW cons_fix_new_ns32k -extern void fix_new_ns32k_exp PARAMS ((fragS *, int, int, expressionS *, - int, int, bit_fixS *, int, fragS *, - unsigned int)); - -extern void fix_new_ns32k PARAMS ((fragS *, int, int, symbolS *, long, - int, int, bit_fixS *, int, fragS *, - unsigned int)); - -extern void cons_fix_new_ns32k PARAMS ((fragS *, int, int, expressionS *)); +extern void cons_fix_new_ns32k (fragS *, int, int, expressionS *); /* The NS32x32 has a non 0 nop instruction which should be used in aligns. */ #define NOP_OPCODE 0xa2 diff --git a/gas/config/tc-openrisc.c b/gas/config/tc-openrisc.c index 194fe4ba348..e167f4e0e6e 100644 --- a/gas/config/tc-openrisc.c +++ b/gas/config/tc-openrisc.c @@ -70,24 +70,18 @@ size_t md_longopts_size = sizeof (md_longopts); unsigned long openrisc_machine = 0; /* default */ int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char * arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) { return 0; } void -md_show_usage (stream) - FILE * stream ATTRIBUTE_UNUSED; +md_show_usage (FILE * stream ATTRIBUTE_UNUSED) { } -static void ignore_pseudo PARAMS ((int)); - static void -ignore_pseudo (val) - int val ATTRIBUTE_UNUSED; +ignore_pseudo (int val ATTRIBUTE_UNUSED) { discard_rest_of_line (); } @@ -106,7 +100,7 @@ const pseudo_typeS md_pseudo_table[] = void -md_begin () +md_begin (void) { /* Initialize the `cgen' interface. */ @@ -122,8 +116,7 @@ md_begin () } void -md_assemble (str) - char * str; +md_assemble (char * str) { static int last_insn_had_delay_slot = 0; openrisc_insn insn; @@ -154,8 +147,7 @@ md_assemble (str) We just ignore it. */ void -md_operand (expressionP) - expressionS * expressionP; +md_operand (expressionS * expressionP) { if (* input_line_pointer == '#') { @@ -165,17 +157,14 @@ md_operand (expressionP) } valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); return ((size + (1 << align) - 1) & (-1 << align)); } symbolS * -md_undefined_symbol (name) - char * name ATTRIBUTE_UNUSED; +md_undefined_symbol (char * name ATTRIBUTE_UNUSED) { return 0; } @@ -223,9 +212,7 @@ const relax_typeS md_relax_table[] = 0 value. */ int -md_estimate_size_before_relax (fragP, segment) - fragS * fragP; - segT segment; +md_estimate_size_before_relax (fragS * fragP, segT segment) { /* The only thing we have to handle here are symbols outside of the current segment. They may be undefined or in a different segment in @@ -275,10 +262,9 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_subtype is the subtype of what the address relaxed to. */ void -md_convert_frag (abfd, sec, fragP) - bfd * abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS * fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS * fragP ATTRIBUTE_UNUSED) { /* FIXME */ } @@ -290,18 +276,14 @@ md_convert_frag (abfd, sec, fragP) given a PC relative reloc. */ long -md_pcrel_from_section (fixP, sec) - fixS * fixP; - segT sec; +md_pcrel_from_section (fixS * fixP, segT sec) { if (fixP->fx_addsy != (symbolS *) NULL && (! S_IS_DEFINED (fixP->fx_addsy) || S_GET_SEGMENT (fixP->fx_addsy) != sec)) - { - /* The symbol is undefined (or is defined but not in this section). - Let the linker figure it out. */ - return 0; - } + /* The symbol is undefined (or is defined but not in this section). + Let the linker figure it out. */ + return 0; return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1; } @@ -312,10 +294,9 @@ md_pcrel_from_section (fixP, sec) *FIXP may be modified if desired. */ bfd_reloc_code_real_type -md_cgen_lookup_reloc (insn, operand, fixP) - const CGEN_INSN * insn ATTRIBUTE_UNUSED; - const CGEN_OPERAND * operand; - fixS * fixP; +md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED, + const CGEN_OPERAND * operand, + fixS * fixP) { bfd_reloc_code_real_type type; @@ -351,10 +332,7 @@ md_cgen_lookup_reloc (insn, operand, fixP) /* Write a value out to the object file, using the appropriate endianness. */ void -md_number_to_chars (buf, val, n) - char * buf; - valueT val; - int n; +md_number_to_chars (char * buf, valueT val, int n) { number_to_chars_bigendian (buf, val, n); } @@ -368,10 +346,7 @@ md_number_to_chars (buf, val, n) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char * litP; - int * sizeP; +md_atof (int type, char * litP, int * sizeP) { int i; int prec; @@ -417,16 +392,12 @@ md_atof (type, litP, sizeP) } bfd_boolean -openrisc_fix_adjustable (fixP) - fixS * fixP; +openrisc_fix_adjustable (fixS * fixP) { - /* We need the symbol name for the VTABLE entries */ + /* We need the symbol name for the VTABLE entries. */ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) return 0; return 1; } - - - diff --git a/gas/config/tc-openrisc.h b/gas/config/tc-openrisc.h index b822800efde..3369249dc69 100644 --- a/gas/config/tc-openrisc.h +++ b/gas/config/tc-openrisc.h @@ -1,5 +1,5 @@ /* tc-openrisc.h -- Header file for tc-openrisc.c. - Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -52,13 +52,13 @@ extern const char openrisc_comment_chars []; #define md_apply_fix3 gas_cgen_md_apply_fix3 -extern bfd_boolean openrisc_fix_adjustable PARAMS ((struct fix *)); +extern bfd_boolean openrisc_fix_adjustable (struct fix *); #define tc_fix_adjustable(FIX) openrisc_fix_adjustable (FIX) #define tc_gen_reloc gas_cgen_tc_gen_reloc /* Call md_pcrel_from_section(), not md_pcrel_from(). */ -extern long md_pcrel_from_section PARAMS ((struct fix *, segT)); +extern long md_pcrel_from_section (struct fix *, segT); #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC) /* For 8 vs 16 vs 32 bit branch selection. */ diff --git a/gas/config/tc-or32.c b/gas/config/tc-or32.c index 4ca2a10a322..69437315f93 100644 --- a/gas/config/tc-or32.c +++ b/gas/config/tc-or32.c @@ -47,31 +47,29 @@ static struct hash_control *op_hash = NULL; struct machine_it - { - char * error; - unsigned long opcode; - struct nlist * nlistp; - expressionS exp; - int pcrel; - int reloc_offset; /* Offset of reloc within insn. */ - int reloc; - } +{ + char * error; + unsigned long opcode; + struct nlist * nlistp; + expressionS exp; + int pcrel; + int reloc_offset; /* Offset of reloc within insn. */ + int reloc; +} the_insn; -static void machine_ip PARAMS ((char *)); - const pseudo_typeS md_pseudo_table[] = - { - {"align", s_align_bytes, 4 }, - {"space", s_space, 0 }, - {"cputype", s_ignore, 0 }, - {"reg", s_lsym, 0 }, /* Register equate, same as equ. */ - {"sect", s_ignore, 0 }, /* Creation of coff sections. */ - {"proc", s_ignore, 0 }, /* Start of a function. */ - {"endproc", s_ignore, 0 }, /* Function end. */ - {"word", cons, 4 }, - {NULL, 0, 0 }, - }; +{ + {"align", s_align_bytes, 4 }, + {"space", s_space, 0 }, + {"cputype", s_ignore, 0 }, + {"reg", s_lsym, 0 }, /* Register equate, same as equ. */ + {"sect", s_ignore, 0 }, /* Creation of coff sections. */ + {"proc", s_ignore, 0 }, /* Start of a function. */ + {"endproc", s_ignore, 0 }, /* Function end. */ + {"word", cons, 4 }, + {NULL, 0, 0 }, +}; int md_short_jump_size = 4; int md_long_jump_size = 4; @@ -114,20 +112,17 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; /* "l.jalr r9" precalculated opcode. */ static unsigned long jalr_r9_opcode; +static void machine_ip (char *); -static int check_invalid_opcode PARAMS ((unsigned long)); -static void encode PARAMS ((const struct machine_opcode *, unsigned long *, signed long, char)); -static char *parse_operand PARAMS ((char *, expressionS *, int)); /* Set bits in machine opcode according to insn->encoding description and passed operand. */ static void -encode (insn, opcode, param_val, param_ch) - const struct machine_opcode *insn; - unsigned long *opcode; - signed long param_val; - char param_ch; +encode (const struct machine_opcode *insn, + unsigned long *opcode, + signed long param_val, + char param_ch) { int opc_pos = 0; int param_pos = 0; @@ -195,7 +190,7 @@ encode (insn, opcode, param_val, param_ch) need. */ void -md_begin () +md_begin (void) { const char *retval = NULL; int lose = 0; @@ -215,7 +210,7 @@ md_begin () continue; } - retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]); + retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]); if (retval != NULL) { fprintf (stderr, "internal error: can't hash `%s': %s\n", @@ -233,8 +228,7 @@ md_begin () /* Returns non zero if instruction is to be used. */ static int -check_invalid_opcode (opcode) - unsigned long opcode; +check_invalid_opcode (unsigned long opcode) { return opcode == jalr_r9_opcode; } @@ -244,8 +238,7 @@ check_invalid_opcode (opcode) produce the bytes of data and relocation. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { char *toP; @@ -283,10 +276,7 @@ static int mask_or_shift = 0; #ifdef BFD_ASSEMBLER static char * -parse_operand (s, operandp, opt) - char *s; - expressionS *operandp; - int opt; +parse_operand (char *s, expressionS *operandp, int opt) { char *save = input_line_pointer; char *new; @@ -351,10 +341,7 @@ parse_operand (s, operandp, opt) #else static char * -parse_operand (s, operandp, opt) - char *s; - expressionS *operandp; - int opt; +parse_operand (char *s, expressionS *operandp, int opt) { char *save = input_line_pointer; char *new; @@ -381,7 +368,6 @@ parse_operand (s, operandp, opt) else mask_or_shift = 0; - expression (operandp); if (operandp->X_op == O_absent) @@ -430,8 +416,7 @@ parse_operand (s, operandp, opt) #ifdef BFD_ASSEMBLER static void -machine_ip (str) - char *str; +machine_ip (char *str) { char *s; const char *args; @@ -485,10 +470,8 @@ machine_ip (str) If an operand matches, we modify the_insn or opcode appropriately, and do a "continue". If an operand fails to match, we "break". */ if (insn->args[0] != '\0') - { - /* Prime the pump. */ - s = parse_operand (s, operand, insn->args[0] == 'I'); - } + /* Prime the pump. */ + s = parse_operand (s, operand, insn->args[0] == 'I'); for (args = insn->args;; ++args) { @@ -579,9 +562,7 @@ machine_ip (str) } if (*s == '(') - { - operand->X_op = O_constant; - } + operand->X_op = O_constant; else if (*s == ')') s += 1; #if DEBUG @@ -641,8 +622,7 @@ machine_ip (str) #else static void -machine_ip (str) - char *str; +machine_ip (char *str) { char *s; const char *args; @@ -790,9 +770,7 @@ machine_ip (str) } if (*s == '(') - { - operand->X_op = O_constant; - } + operand->X_op = O_constant; else if (*s == ')') s += 1; #if DEBUG @@ -861,10 +839,7 @@ machine_ip (str) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char * litP; - int * sizeP; +md_atof (int type, char * litP, int * sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -920,20 +895,14 @@ md_atof (type, litP, sizeP) /* Write out big-endian. */ void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { number_to_chars_bigendian (buf, val, n); } #ifdef BFD_ASSEMBLER void -md_apply_fix3 (fixP, val, seg) - fixS * fixP; - valueT * val; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS * fixP, valueT * val, segT seg ATTRIBUTE_UNUSED) { char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; long t_val; @@ -1029,10 +998,7 @@ md_apply_fix3 (fixP, val, seg) } #else void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT *valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { long val = *valP; char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; @@ -1155,8 +1121,7 @@ md_apply_fix3 (fixP, valP, seg) #ifdef OBJ_COFF short -tc_coff_fix2rtype (fixP) - fixS *fixP; +tc_coff_fix2rtype (fixS *fixP) { #if DEBUG printf ("tc_coff_fix2rtype\n"); @@ -1164,16 +1129,11 @@ tc_coff_fix2rtype (fixP) switch (fixP->fx_r_type) { - case RELOC_32: - return (R_WORD); - case RELOC_8: - return (R_BYTE); - case RELOC_CONST: - return (R_ILOHALF); - case RELOC_CONSTH: - return (R_IHIHALF); - case RELOC_JUMPTARG: - return (R_IREL); + case RELOC_32: return R_WORD; + case RELOC_8: return R_BYTE; + case RELOC_CONST: return R_ILOHALF; + case RELOC_CONSTH: return R_IHIHALF; + case RELOC_JUMPTARG: return R_IREL; default: printf ("need %d\n", fixP->fx_r_type); abort (); @@ -1187,12 +1147,11 @@ tc_coff_fix2rtype (fixP) /* Should never be called for or32. */ void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char * ptr ATTRIBUTE_UNUSED; - addressT from_addr ATTRIBUTE_UNUSED; - addressT to_addr ATTRIBUTE_UNUSED; - fragS * frag ATTRIBUTE_UNUSED; - symbolS * to_symbol ATTRIBUTE_UNUSED; +md_create_short_jump (char * ptr ATTRIBUTE_UNUSED, + addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, + fragS * frag ATTRIBUTE_UNUSED, + symbolS * to_symbol ATTRIBUTE_UNUSED) { as_fatal ("or32_create_short_jmp\n"); } @@ -1201,20 +1160,18 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) #ifndef BFD_ASSEMBLER void -md_convert_frag (headers, seg, fragP) - object_headers * headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - register fragS * fragP ATTRIBUTE_UNUSED; +md_convert_frag (object_headers * headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + register fragS * fragP ATTRIBUTE_UNUSED) { as_fatal ("or32_convert_frag\n"); } #else void -md_convert_frag (headers, seg, fragP) - bfd * headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - fragS * fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd * headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + fragS * fragP ATTRIBUTE_UNUSED) { as_fatal ("or32_convert_frag\n"); } @@ -1223,12 +1180,11 @@ md_convert_frag (headers, seg, fragP) /* Should never be called for or32. */ void -md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) - char * ptr ATTRIBUTE_UNUSED; - addressT from_addr ATTRIBUTE_UNUSED; - addressT to_addr ATTRIBUTE_UNUSED; - fragS * frag ATTRIBUTE_UNUSED; - symbolS * to_symbol ATTRIBUTE_UNUSED; +md_create_long_jump (char * ptr ATTRIBUTE_UNUSED, + addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, + fragS * frag ATTRIBUTE_UNUSED, + symbolS * to_symbol ATTRIBUTE_UNUSED) { as_fatal ("or32_create_long_jump\n"); } @@ -1236,9 +1192,8 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) /* Should never be called for or32. */ int -md_estimate_size_before_relax (fragP, segtype) - fragS * fragP ATTRIBUTE_UNUSED; - segT segtype ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, + segT segtype ATTRIBUTE_UNUSED) { as_fatal ("or32_estimate_size_before_relax\n"); return 0; @@ -1254,10 +1209,9 @@ md_estimate_size_before_relax (fragP, segtype) #ifdef OBJ_AOUT void -tc_aout_fix_to_chars (where, fixP, segment_address_in_file) - char *where; - fixS *fixP; - relax_addressT segment_address_in_file; +tc_aout_fix_to_chars (char *where, + fixS *fixP, + relax_addressT segment_address_in_file) { long r_symbolnum; @@ -1291,22 +1245,19 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) const char *md_shortopts = ""; struct option md_longopts[] = - { - { NULL, no_argument, NULL, 0 } - }; +{ + { NULL, no_argument, NULL, 0 } +}; size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char * arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) { return 0; } void -md_show_usage (stream) - FILE * stream ATTRIBUTE_UNUSED; +md_show_usage (FILE * stream ATTRIBUTE_UNUSED) { } @@ -1314,8 +1265,7 @@ md_show_usage (stream) definitions of or32 style local labels. */ int -or32_unrecognized_line (c) - int c; +or32_unrecognized_line (int c) { int lab; char *s; @@ -1350,38 +1300,12 @@ or32_unrecognized_line (c) return 1; } -#ifndef BFD_ASSEMBLER -/* Record a fixup for a cons expression. */ -/* - void -or32_cons_fix_new (frag, where, nbytes, exp) - fragS *frag; - int where; - int nbytes; - expressionS *exp; -{ - fix_new_exp (frag, where, nbytes, exp, 0, - nbytes == 5 ? RELOC_32 - : nbytes == 2 ? RELOC_16 - : RELOC_8); -} -void -tc_aout_pre_write_hook () -{ -#if DEBUG - printf ("In tc_aout_pre_write_hook()\n"); -#endif -} -*/ -#endif - /* Default the values of symbols known that should be "predefined". We don't bother to predefine them unless you actually use one, since there are a lot of them. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { #ifndef BFD_ASSEMBLER long regnum; @@ -1417,8 +1341,7 @@ md_undefined_symbol (name) /* Parse an operand that is machine-specific. */ void -md_operand (expressionP) - expressionS *expressionP; +md_operand (expressionS *expressionP) { #if DEBUG printf (" md_operand(input_line_pointer = %s)\n", input_line_pointer); @@ -1546,9 +1469,7 @@ md_operand (expressionP) /* Round up a section size to the appropriate boundary. */ valueT -md_section_align (segment, size) - segT segment ATTRIBUTE_UNUSED; - valueT size ATTRIBUTE_UNUSED; +md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size ATTRIBUTE_UNUSED) { return size; /* Byte alignment is fine. */ } @@ -1558,8 +1479,7 @@ md_section_align (segment, size) which we have set up as the address of the fixup too. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { return fixP->fx_where + fixP->fx_frag->fr_address; } @@ -1568,14 +1488,12 @@ md_pcrel_from (fixP) #ifdef BFD_ASSEMBLER arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc = xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; /* reloc->address = fixp->fx_frag->fr_address + fixp->fx_where + fixp->fx_addnumber;*/ @@ -1596,4 +1514,3 @@ tc_gen_reloc (seg, fixp) return reloc; } #endif - diff --git a/gas/config/tc-or32.h b/gas/config/tc-or32.h index 04287f252b4..456f3b5cf62 100644 --- a/gas/config/tc-or32.h +++ b/gas/config/tc-or32.h @@ -1,5 +1,5 @@ /* tc-or32.h -- Assemble for the OpenRISC 1000. - Copyright (C) 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2002, 2003. 2005 Free Software Foundation, Inc. Contributed by Damjan Lampret . Based upon a29k port. @@ -38,12 +38,12 @@ #define tc_unrecognized_line(c) or32_unrecognized_line (c) -extern int or32_unrecognized_line PARAMS ((int)); +extern int or32_unrecognized_line (int); -#define tc_headers_hook(a) ; /* not used */ -#define tc_headers_hook(a) ; /* not used */ -#define tc_crawl_symbol_chain(a) ; /* not used */ -#define tc_coff_symbol_emit_hook(a) ; /* not used */ +#define tc_headers_hook(a) ; /* Not used. */ +#define tc_headers_hook(a) ; /* Not used. */ +#define tc_crawl_symbol_chain(a) ; /* Not used. */ +#define tc_coff_symbol_emit_hook(a) ; /* Not used. */ #define AOUT_MACHTYPE 80 #define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype (fix_ptr) diff --git a/gas/config/tc-pdp11.h b/gas/config/tc-pdp11.h index d831ec39527..294faa3797a 100644 --- a/gas/config/tc-pdp11.h +++ b/gas/config/tc-pdp11.h @@ -1,5 +1,5 @@ /* tc-pdp11.h -- Header file for tc-pdp11.c. - Copyright 2001 Free Software Foundation, Inc. + Copyright 2001, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -28,6 +28,6 @@ #define md_operand(x) -long md_chars_to_number PARAMS ((unsigned char *, int)); +long md_chars_to_number (unsigned char *, int); /* end of tc-pdp11.h */ diff --git a/gas/config/tc-pj.c b/gas/config/tc-pj.c index d5e236081e4..5a71e4037f6 100644 --- a/gas/config/tc-pj.c +++ b/gas/config/tc-pj.c @@ -28,43 +28,27 @@ extern const pj_opc_info_t pj_opc_info[512]; -const char comment_chars[] = "!/"; +const char comment_chars[] = "!/"; const char line_separator_chars[] = ";"; -const char line_comment_chars[] = "/!#"; +const char line_comment_chars[] = "/!#"; static int pending_reloc; static struct hash_control *opcode_hash_control; -static void little - PARAMS ((int)); -static void big - PARAMS ((int)); -static char *parse_exp_save_ilp - PARAMS ((char *, expressionS *)); -static int c_to_r - PARAMS ((char)); -static void ipush_code - PARAMS ((pj_opc_info_t *, char *)); -static void fake_opcode - PARAMS ((const char *, void (*) (struct pj_opc_info_t *, char *))); -static void alias - PARAMS ((const char *, const char *)); - static void -little (ignore) - int ignore ATTRIBUTE_UNUSED; +little (int ignore ATTRIBUTE_UNUSED) { target_big_endian = 0; } static void -big (ignore) - int ignore ATTRIBUTE_UNUSED; +big (int ignore ATTRIBUTE_UNUSED) { target_big_endian = 1; } -const pseudo_typeS md_pseudo_table[] = { +const pseudo_typeS md_pseudo_table[] = +{ {"ml", little, 0}, {"mb", big, 0}, {0, 0, 0} @@ -74,8 +58,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; const char EXP_CHARS[] = "eE"; void -md_operand (op) - expressionS *op; +md_operand (expressionS *op) { if (strncmp (input_line_pointer, "%hi16", 5) == 0) { @@ -85,6 +68,7 @@ md_operand (op) input_line_pointer += 5; expression (op); } + if (strncmp (input_line_pointer, "%lo16", 5) == 0) { if (pending_reloc) @@ -98,11 +82,10 @@ md_operand (op) /* Parse an expression and then restore the input line pointer. */ static char * -parse_exp_save_ilp (s, op) - char *s; - expressionS *op; +parse_exp_save_ilp (char *s, expressionS *op) { char *save = input_line_pointer; + input_line_pointer = s; expression (op); s = input_line_pointer; @@ -115,11 +98,7 @@ parse_exp_save_ilp (s, op) we want to handle magic pending reloc expressions specially. */ void -pj_cons_fix_new_pj (frag, where, nbytes, exp) - fragS *frag; - int where; - int nbytes; - expressionS *exp; +pj_cons_fix_new_pj (fragS *frag, int where, int nbytes, expressionS *exp) { static int rv[5][2] = { { 0, 0 }, @@ -139,8 +118,7 @@ pj_cons_fix_new_pj (frag, where, nbytes, exp) code which BFD can handle. */ static int -c_to_r (x) - char x; +c_to_r (int x) { switch (x) { @@ -167,9 +145,7 @@ c_to_r (x) turns ipush into sipush lo16, sethi hi16. */ static void -ipush_code (opcode, str) - pj_opc_info_t *opcode ATTRIBUTE_UNUSED; - char *str; +ipush_code (pj_opc_info_t *opcode ATTRIBUTE_UNUSED, char *str) { char *b = frag_more (6); expressionS arg; @@ -193,11 +169,10 @@ ipush_code (opcode, str) not opcodes. The fakeness is indicated with an opcode of -1. */ static void -fake_opcode (name, func) - const char *name; - void (*func) PARAMS ((struct pj_opc_info_t *, char *)); +fake_opcode (const char *name, + void (*func) (struct pj_opc_info_t *, char *)) { - pj_opc_info_t *fake = (pj_opc_info_t *) xmalloc (sizeof (pj_opc_info_t)); + pj_opc_info_t * fake = xmalloc (sizeof (pj_opc_info_t)); fake->opcode = -1; fake->opcode_next = -1; @@ -209,9 +184,7 @@ fake_opcode (name, func) can have another name. */ static void -alias (new, old) - const char *new; - const char *old; +alias (const char *new, const char *old) { hash_insert (opcode_hash_control, new, (char *) hash_find (opcode_hash_control, old)); @@ -222,7 +195,7 @@ alias (new, old) some aliases for compatibility with other assemblers. */ void -md_begin () +md_begin (void) { const pj_opc_info_t *opcode; opcode_hash_control = hash_new (); @@ -251,8 +224,7 @@ md_begin () the frags/bytes it assembles to. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { char *op_start; char *op_end; @@ -348,10 +320,7 @@ md_assemble (str) returned, or NULL on OK. */ char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[4]; @@ -401,8 +370,8 @@ md_atof (type, litP, sizeP) const char *md_shortopts = ""; -struct option md_longopts[] = { - +struct option md_longopts[] = +{ #define OPTION_LITTLE (OPTION_MD_BASE) #define OPTION_BIG (OPTION_LITTLE + 1) @@ -413,9 +382,7 @@ struct option md_longopts[] = { size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) { switch (c) { @@ -432,8 +399,7 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("\ PJ options:\n\ @@ -444,10 +410,7 @@ PJ options:\n\ /* Apply a fixup to the object file. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED) { char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; long val = *valP; @@ -543,10 +506,7 @@ md_apply_fix3 (fixP, valP, seg) executable section into big endian order. */ void -md_number_to_chars (ptr, use, nbytes) - char *ptr; - valueT use; - int nbytes; +md_number_to_chars (char *ptr, valueT use, int nbytes) { if (target_big_endian || now_seg->flags & SEC_CODE) number_to_chars_bigendian (ptr, use, nbytes); @@ -558,15 +518,13 @@ md_number_to_chars (ptr, use, nbytes) format. */ arelent * -tc_gen_reloc (section, fixp) - asection *section ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) { arelent *rel; bfd_reloc_code_real_type r_type; - rel = (arelent *) xmalloc (sizeof (arelent)); - rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + rel = xmalloc (sizeof (arelent)); + rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); rel->address = fixp->fx_frag->fr_address + fixp->fx_where; diff --git a/gas/config/tc-pj.h b/gas/config/tc-pj.h index 8210992b811..6924f7e1f75 100644 --- a/gas/config/tc-pj.h +++ b/gas/config/tc-pj.h @@ -1,5 +1,5 @@ /* This file is tc-pj.h - Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. Contributed by Steve Chamberlain of Transmeta, sac@pobox.com @@ -31,8 +31,8 @@ ? "Pico Java GAS Big Endian" \ : "Pico Java GAS Little Endian") -void pj_cons_fix_new_pj PARAMS ((struct frag *, int, int, expressionS *)); -arelent *tc_gen_reloc PARAMS((asection *, struct fix *)); +void pj_cons_fix_new_pj (struct frag *, int, int, expressionS *); +arelent *tc_gen_reloc (asection *, struct fix *); #define md_section_align(SEGMENT, SIZE) (SIZE) #define md_convert_frag(B, S, F) (as_fatal (_("convert_frag\n")), 0) @@ -56,5 +56,5 @@ arelent *tc_gen_reloc PARAMS((asection *, struct fix *)); #define MD_APPLY_SYM_VALUE(FIX) 0 #define tc_fix_adjustable(FIX) \ - (! ((FIX)->fx_r_type == BFD_RELOC_VTABLE_INHERIT \ + (! ((FIX)->fx_r_type == BFD_RELOC_VTABLE_INHERIT \ || (FIX)->fx_r_type == BFD_RELOC_VTABLE_ENTRY)) diff --git a/gas/config/tc-tahoe.c b/gas/config/tc-tahoe.c index 5a8b44f3ac1..d5eeda027b4 100644 --- a/gas/config/tc-tahoe.c +++ b/gas/config/tc-tahoe.c @@ -1,7 +1,7 @@ /* This file is tc-tahoe.c Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1995, 2000, 2001, 2002, - 2003, 2004 Free Software Foundation, Inc. + 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -19,6 +19,7 @@ along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + #include "as.h" #include "safe-ctype.h" #include "obstack.h" @@ -31,50 +32,50 @@ typedef byte tahoe_opcodeT; /* This is part of tahoe-ins-parse.c & friends. We want to parse a tahoe instruction text into a tree defined here. */ -#define TIT_MAX_OPERANDS (4) /* maximum number of operands in one - single tahoe instruction */ +#define TIT_MAX_OPERANDS 4 /* Maximum number of operands in one + single tahoe instruction. */ -struct top /* tahoe instruction operand */ +struct top /* Tahoe instruction operand. */ { - int top_ndx; /* -1, or index register. eg 7=[R7] */ - int top_reg; /* -1, or register number. eg 7 = R7 or (R7) */ + int top_ndx; /* -1, or index register. eg 7=[R7]. */ + int top_reg; /* -1, or register number. eg 7 = R7 or (R7). */ byte top_mode; /* Addressing mode byte. This byte, defines which of the 11 modes opcode is. */ char top_access; /* Access type wanted for this operand - 'b'branch ' 'no-instruction 'amrvw' */ - char top_width; /* Operand width expected, one of "bwlq?-:!" */ + 'b'branch ' 'no-instruction 'amrvw'. */ + char top_width; /* Operand width expected, one of "bwlq?-:!". */ - char * top_error; /* Say if operand is inappropriate */ + char * top_error; /* Say if operand is inappropriate. */ - segT seg_of_operand; /* segment as returned by expression()*/ + segT seg_of_operand; /* Segment as returned by expression(). */ - expressionS exp_of_operand; /* The expression as parsed by expression()*/ + expressionS exp_of_operand; /* The expression as parsed by expression(). */ byte top_dispsize; /* Number of bytes in the displacement if we - can figure it out */ + can figure it out. */ }; /* The addressing modes for an operand. These numbers are the actual values for certain modes, so be careful if you screw with them. */ -#define TAHOE_DIRECT_REG (0x50) -#define TAHOE_REG_DEFERRED (0x60) +#define TAHOE_DIRECT_REG 0x50 +#define TAHOE_REG_DEFERRED 0x60 -#define TAHOE_REG_DISP (0xE0) -#define TAHOE_REG_DISP_DEFERRED (0xF0) +#define TAHOE_REG_DISP 0xE0 +#define TAHOE_REG_DISP_DEFERRED 0xF0 -#define TAHOE_IMMEDIATE (0x8F) -#define TAHOE_IMMEDIATE_BYTE (0x88) -#define TAHOE_IMMEDIATE_WORD (0x89) -#define TAHOE_IMMEDIATE_LONGWORD (0x8F) -#define TAHOE_ABSOLUTE_ADDR (0x9F) +#define TAHOE_IMMEDIATE 0x8F +#define TAHOE_IMMEDIATE_BYTE 0x88 +#define TAHOE_IMMEDIATE_WORD 0x89 +#define TAHOE_IMMEDIATE_LONGWORD 0x8F +#define TAHOE_ABSOLUTE_ADDR 0x9F -#define TAHOE_DISPLACED_RELATIVE (0xEF) -#define TAHOE_DISP_REL_DEFERRED (0xFF) +#define TAHOE_DISPLACED_RELATIVE 0xEF +#define TAHOE_DISP_REL_DEFERRED 0xFF -#define TAHOE_AUTO_DEC (0x7E) -#define TAHOE_AUTO_INC (0x8E) -#define TAHOE_AUTO_INC_DEFERRED (0x9E) +#define TAHOE_AUTO_DEC 0x7E +#define TAHOE_AUTO_INC 0x8E +#define TAHOE_AUTO_INC_DEFERRED 0x9E /* INDEXED_REG is decided by the existence or lack of a [reg]. */ /* These are encoded into top_width when top_access=='b' @@ -86,34 +87,33 @@ struct top /* tahoe instruction operand */ /* The hex code for certain tahoe commands and modes. This is just for readability. */ -#define TAHOE_JMP (0x71) -#define TAHOE_PC_REL_LONG (0xEF) -#define TAHOE_BRB (0x11) -#define TAHOE_BRW (0x13) +#define TAHOE_JMP 0x71 +#define TAHOE_PC_REL_LONG 0xEF +#define TAHOE_BRB 0x11 +#define TAHOE_BRW 0x13 /* These, when 'ored' with, or added to, a register number, set up the number for the displacement mode. */ -#define TAHOE_PC_OR_BYTE (0xA0) -#define TAHOE_PC_OR_WORD (0xC0) -#define TAHOE_PC_OR_LONG (0xE0) +#define TAHOE_PC_OR_BYTE 0xA0 +#define TAHOE_PC_OR_WORD 0xC0 +#define TAHOE_PC_OR_LONG 0xE0 struct tit /* Get it out of the sewer, it stands for tahoe instruction tree (Geeze!). */ { tahoe_opcodeT tit_opcode; /* The opcode. */ byte tit_operands; /* How many operands are here. */ - struct top tit_operand[TIT_MAX_OPERANDS]; /* Operands */ - char *tit_error; /* "" or fatal error text */ + struct top tit_operand[TIT_MAX_OPERANDS]; /* Operands. */ + char *tit_error; /* "" or fatal error text. */ }; /* end: tahoe-inst.h */ /* tahoe.c - tahoe-specific - - Not part of gas yet. - */ + Not part of gas yet. */ #include "opcode/tahoe.h" -/* This is the number to put at the beginning of the a.out file */ +/* This is the number to put at the beginning of the a.out file. */ long omagic = OMAGIC; /* These chars start a comment anywhere in a source file (except inside @@ -123,7 +123,7 @@ const char comment_chars[] = "#;"; /* These chars only start a comment at the beginning of a line. */ const char line_comment_chars[] = "#"; -/* Chars that can be used to separate mant from exp in floating point nums */ +/* Chars that can be used to separate mant from exp in floating point nums. */ const char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant @@ -136,8 +136,7 @@ const char FLT_CHARS[] = "df"; /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be changed in read.c . Ideally it shouldn't have to know about it at all, but nothing is ideal around here. - (The tahoe has plenty of room, so the change currently isn't needed.) - */ + (The tahoe has plenty of room, so the change currently isn't needed.) */ static struct tit t; /* A tahoe instruction after decoding. */ @@ -152,27 +151,25 @@ const pseudo_typeS md_pseudo_table[] = {0} }; -/* - * For Tahoe, relative addresses of "just the right length" are pretty easy. - * The branch displacement is always the last operand, even in - * synthetic instructions. - * For Tahoe, we encode the relax_substateTs (in e.g. fr_substate) as: - * - * 4 3 2 1 0 bit number - * ---/ /--+-------+-------+-------+-------+-------+ - * | what state ? | how long ? | - * ---/ /--+-------+-------+-------+-------+-------+ - * - * The "how long" bits are 00=byte, 01=word, 10=long. - * This is a Un*x convention. - * Not all lengths are legit for a given value of (what state). - * The four states are listed below. - * The "how long" refers merely to the displacement length. - * The address usually has some constant bytes in it as well. - * - -States for Tahoe address relaxing. -1. TAHOE_WIDTH_ALWAYS_JUMP (-) +/* For Tahoe, relative addresses of "just the right length" are pretty easy. + The branch displacement is always the last operand, even in + synthetic instructions. + For Tahoe, we encode the relax_substateTs (in e.g. fr_substate) as: + + 4 3 2 1 0 bit number + ---/ /--+-------+-------+-------+-------+-------+ + | what state ? | how long ? | + ---/ /--+-------+-------+-------+-------+-------+ + + The "how long" bits are 00=byte, 01=word, 10=long. + This is a Un*x convention. + Not all lengths are legit for a given value of (what state). + The four states are listed below. + The "how long" refers merely to the displacement length. + The address usually has some constant bytes in it as well. + + States for Tahoe address relaxing. + 1. TAHOE_WIDTH_ALWAYS_JUMP (-) Format: "b-" Tahoe opcodes are: (Hex) jr 11 @@ -181,7 +178,7 @@ States for Tahoe address relaxing. Always, 1 byte opcode, then displacement/absolute. If word or longword, change opcode to brw or jmp. -2. TAHOE_WIDTH_CONDITIONAL_JUMP (?) + 2. TAHOE_WIDTH_CONDITIONAL_JUMP (?) J where is a simple flag test. Format: "b?" Tahoe opcodes are: (Hex) @@ -200,7 +197,7 @@ States for Tahoe address relaxing. Always, you complement 4th bit to reverse the condition. Always, 1-byte opcode, then 1-byte displacement. -3. TAHOE_WIDTH_BIG_REV_JUMP (!) + 3. TAHOE_WIDTH_BIG_REV_JUMP (!) Jbc/Jbs where cond tests a memory bit. Format: "rlvlb!" Tahoe opcodes are: (Hex) @@ -209,7 +206,7 @@ States for Tahoe address relaxing. Always, you complement 4th bit to reverse the condition. Always, 1-byte opcde, longword, longword-address, 1-word-displacement -4. TAHOE_WIDTH_BIG_NON_REV_JUMP (:) + 4. TAHOE_WIDTH_BIG_NON_REV_JUMP (:) JaoblXX/Jbssi Format: "rlmlb:" Tahoe opcodes are: (Hex) @@ -221,13 +218,13 @@ States for Tahoe address relaxing. Always, we cannot reverse the sense of the branch; we have a word displacement. -We need to modify the opcode is for class 1, 2 and 3 instructions. -After relax() we may complement the 4th bit of 2 or 3 to reverse sense of -branch. + We need to modify the opcode is for class 1, 2 and 3 instructions. + After relax() we may complement the 4th bit of 2 or 3 to reverse sense of + branch. -We sometimes store context in the operand literal. This way we can figure out -after relax() what the original addressing mode was. (Was is pc_rel, or -pc_rel_disp? That sort of thing.) */ + We sometimes store context in the operand literal. This way we can figure out + after relax() what the original addressing mode was. (Was is pc_rel, or + pc_rel_disp? That sort of thing.) */ /* These displacements are relative to the START address of the displacement which is at the start of the displacement, not the end of @@ -237,28 +234,28 @@ pc_rel_disp? That sort of thing.) */ The first letter is Byte, Word. 2nd letter is Forward, Backward. */ -#define BF (1+ 127) -#define BB (1+-128) -#define WF (2+ 32767) -#define WB (2+-32768) +#define BF (1 + 127) +#define BB (1 + -128) +#define WF (2 + 32767) +#define WB (2 + -32768) /* Dont need LF, LB because they always reach. [They are coded as 0.] */ -#define C(a,b) ENCODE_RELAX(a,b) +#define C(a,b) ENCODE_RELAX(a, b) /* This macro has no side-effects. */ #define ENCODE_RELAX(what,length) (((what) << 2) + (length)) -#define RELAX_STATE(s) ((s) >> 2) -#define RELAX_LENGTH(s) ((s) & 3) +#define RELAX_STATE(s) ((s) >> 2) +#define RELAX_LENGTH(s) ((s) & 3) -#define STATE_ALWAYS_BRANCH (1) -#define STATE_CONDITIONAL_BRANCH (2) -#define STATE_BIG_REV_BRANCH (3) -#define STATE_BIG_NON_REV_BRANCH (4) -#define STATE_PC_RELATIVE (5) +#define STATE_ALWAYS_BRANCH 1 +#define STATE_CONDITIONAL_BRANCH 2 +#define STATE_BIG_REV_BRANCH 3 +#define STATE_BIG_NON_REV_BRANCH 4 +#define STATE_PC_RELATIVE 5 -#define STATE_BYTE (0) -#define STATE_WORD (1) -#define STATE_LONG (2) -#define STATE_UNDF (3) /* Symbol undefined in pass1 */ +#define STATE_BYTE 0 +#define STATE_WORD 1 +#define STATE_LONG 2 +#define STATE_UNDF 3 /* Symbol undefined in pass1. */ /* This is the table used by gas to figure out relaxing modes. The fields are forward_branch reach, backward_branch reach, number of bytes it would take, @@ -267,30 +264,30 @@ const relax_typeS md_relax_table[] = { { 1, 1, 0, 0 - }, /* error sentinel 0,0 */ + }, /* Error sentinel 0,0 */ { 1, 1, 0, 0 - }, /* unused 0,1 */ + }, /* Unused 0,1 */ { 1, 1, 0, 0 - }, /* unused 0,2 */ + }, /* Unused 0,2 */ { 1, 1, 0, 0 - }, /* unused 0,3 */ + }, /* Unused 0,3 */ /* Unconditional branch cases "jrb" The relax part is the actual displacement */ { BF, BB, 1, C (1, 1) - }, /* brb B`foo 1,0 */ + }, /* Brb B`foo 1,0 */ { WF, WB, 2, C (1, 2) - }, /* brw W`foo 1,1 */ + }, /* Brw W`foo 1,1 */ { 0, 0, 5, 0 }, /* Jmp L`foo 1,2 */ { 1, 1, 0, 0 - }, /* unused 1,3 */ + }, /* Unused 1,3 */ /* Reversible Conditional Branch. If the branch won't reach, reverse it, and jump over a brw or a jmp that will reach. The relax part is the actual address. */ @@ -305,12 +302,12 @@ const relax_typeS md_relax_table[] = }, /* brev over, jmp L`foo, over: 2,2 */ { 1, 1, 0, 0 - }, /* unused 2,3 */ + }, /* Unused 2,3 */ /* Another type of reversible branch. But this only has a word displacement. */ { 1, 1, 0, 0 - }, /* unused 3,0 */ + }, /* Unused 3,0 */ { WF, WB, 2, C (3, 2) }, /* jbX W`foo 3,1 */ @@ -319,7 +316,7 @@ const relax_typeS md_relax_table[] = }, /* jrevX over, jmp L`foo, over: 3,2 */ { 1, 1, 0, 0 - }, /* unused 3,3 */ + }, /* Unused 3,3 */ /* These are the non reversible branches, all of which have a word displacement. If I can't reach, branch over a byte branch, to a jump that will reach. The jumped branch jumps over the reaching @@ -327,7 +324,7 @@ const relax_typeS md_relax_table[] = leap frog. */ { 1, 1, 0, 0 - }, /* unused 4,0 */ + }, /* Unused 4,0 */ { WF, WB, 2, C (4, 2) }, /* aobl_ W`foo 4,1 */ @@ -336,7 +333,7 @@ const relax_typeS md_relax_table[] = }, /*aobl_ W`hop,br over,hop: jmp L^foo,over 4,2*/ { 1, 1, 0, 0 - }, /* unused 4,3 */ + }, /* Unused 4,3 */ /* Normal displacement mode, no jumping or anything like that. The relax points to one byte before the address, thats why all the numbers are up by one. */ @@ -351,7 +348,7 @@ const relax_typeS md_relax_table[] = }, /* L^"foo" 5,2 */ { 1, 1, 0, 0 - }, /* unused 5,3 */ + }, /* Unused 5,3 */ }; #undef C @@ -359,15 +356,16 @@ const relax_typeS md_relax_table[] = #undef BB #undef WF #undef WB -/* End relax stuff */ +/* End relax stuff. */ /* Handle of the OPCODE hash table. NULL means any use before md_begin() will crash. */ static struct hash_control *op_hash; /* Init function. Build the hash table. */ + void -md_begin () +md_begin (void) { struct tot *tP; char *errorval = 0; @@ -387,15 +385,16 @@ md_begin () } const char *md_shortopts = "ad:STt:V"; -struct option md_longopts[] = { + +struct option md_longopts[] = +{ {NULL, no_argument, NULL, 0} }; + size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { switch (c) { @@ -431,8 +430,7 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("\ Tahoe options:\n\ @@ -447,88 +445,42 @@ Tahoe options:\n\ /* The functions in this section take numbers in the machine format, and munges them into Tahoe byte order. - They exist primarily for cross assembly purpose. */ -void /* Knows about order of bytes in address. */ -md_number_to_chars (con, value, nbytes) - char con[]; /* Return 'nbytes' of chars here. */ - valueT value; /* The value of the bits. */ - int nbytes; /* Number of bytes in the output. */ -{ - number_to_chars_bigendian (con, value, nbytes); -} + They exist primarily for cross assembly purpose. + Knows about order of bytes in address. */ -#ifdef comment -void /* Knows about order of bytes in address. */ -md_number_to_imm (con, value, nbytes) - char con[]; /* Return 'nbytes' of chars here. */ - long int value; /* The value of the bits. */ - int nbytes; /* Number of bytes in the output. */ +void +md_number_to_chars (char con[], /* Return 'nbytes' of chars here. */ + valueT value, /* The value of the bits. */ + int nbytes) /* Number of bytes in the output. */ { - md_number_to_chars (con, value, nbytes); + number_to_chars_bigendian (con, value, nbytes); } -#endif /* comment */ - void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP ATTRIBUTE_UNUSED; - valueT * valP ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED: +md_apply_fix3 (fixS *fixP ATTRIBUTE_UNUSED, + valueT * valP ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED) { /* Should never be called. */ know (0); } -void /* Knows about order of bytes in address. */ -md_number_to_disp (con, value, nbytes) - char con[]; /* Return 'nbytes' of chars here. */ - long int value; /* The value of the bits. */ - int nbytes; /* Number of bytes in the output. */ -{ - md_number_to_chars (con, value, nbytes); -} - -void /* Knows about order of bytes in address. */ -md_number_to_field (con, value, nbytes) - char con[]; /* Return 'nbytes' of chars here. */ - long int value; /* The value of the bits. */ - int nbytes; /* Number of bytes in the output. */ +void +md_number_to_disp (char con[]m /* Return 'nbytes' of chars here. */ + long int value, /* The value of the bits. */ + int nbytes) /* Number of bytes in the output. */ { md_number_to_chars (con, value, nbytes); } -/* Put the bits in an order that a tahoe will understand, despite the ordering - of the native machine. - On Tahoe: first 4 bytes are normal unsigned big endian long, - next three bytes are symbolnum, in kind of 3 byte big endian (least sig. byte last). - The last byte is broken up with bit 7 as pcrel, - bits 6 & 5 as length, - bit 4 as extern and the last nibble as 'undefined'. */ - -#if comment void -md_ri_to_chars (ri_p, ri) - struct relocation_info *ri_p, ri; +md_number_to_field (char con[], /* Return 'nbytes' of chars here. */ + long int value, /* The value of the bits. */ + int nbytes) /* Number of bytes in the output. */ { - byte the_bytes[sizeof (struct relocation_info)]; - /* The reason I can't just encode these directly into ri_p is that - ri_p may point to ri. */ - - /* This is easy */ - md_number_to_chars (the_bytes, ri.r_address, sizeof (ri.r_address)); - - /* now the fun stuff */ - the_bytes[4] = (ri.r_symbolnum >> 16) & 0x0ff; - the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff; - the_bytes[6] = ri.r_symbolnum & 0x0ff; - the_bytes[7] = (((ri.r_extern << 4) & 0x10) | ((ri.r_length << 5) & 0x60) | - ((ri.r_pcrel << 7) & 0x80)) & 0xf0; - - bcopy (the_bytes, (char *) ri_p, sizeof (struct relocation_info)); + md_number_to_chars (con, value, nbytes); } -#endif /* comment */ - /* Put the bits in an order that a tahoe will understand, despite the ordering of the native machine. On Tahoe: first 4 bytes are normal unsigned big endian long, @@ -538,10 +490,9 @@ md_ri_to_chars (ri_p, ri) bit 4 as extern and the last nibble as 'undefined'. */ void -tc_aout_fix_to_chars (where, fixP, segment_address_in_file) - char *where; - fixS *fixP; - relax_addressT segment_address_in_file; +tc_aout_fix_to_chars (char *where, + fixS *fixP, + relax_addressT segment_address_in_file) { long r_symbolnum; @@ -569,17 +520,17 @@ tc_aout_fix_to_chars (where, fixP, segment_address_in_file) | ((!S_IS_DEFINED (fixP->fx_addsy) << 4) & 0x10)); } -/* Relocate byte stuff */ +/* Relocate byte stuff. */ /* This is for broken word. */ int md_short_jump_size = 3; void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag; - symbolS *to_symbol; +md_create_short_jump (char *ptr, + addressT from_addr, + addressT to_addr, + fragS *frag, + symbolS *to_symbol) { valueT offset; @@ -589,14 +540,14 @@ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) } int md_long_jump_size = 6; -const int md_reloc_size = 8; /* Size of relocation record */ +const int md_reloc_size = 8; /* Size of relocation record. */ void -md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr, to_addr; - fragS *frag; - symbolS *to_symbol; +md_create_long_jump (char *ptr, + addressT from_addr, + addressT to_addr, + fragS *frag, + symbolS *to_symbol) { valueT offset; @@ -610,10 +561,9 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) Any symbol that is now undefined will not become defined. Return the correct fr_subtype in the frag and the growth beyond fr_fix. */ + int -md_estimate_size_before_relax (fragP, segment_type) - register fragS *fragP; - segT segment_type; /* N_DATA or N_TEXT. */ +md_estimate_size_before_relax (fragS *fragP, segT segment_type) { if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF) { @@ -714,33 +664,27 @@ md_estimate_size_before_relax (fragP, segment_type) return md_relax_table[fragP->fr_subtype].rlx_length; } -/* - * md_convert_frag(); - * - * Called after relax() is finished. - * In: Address of frag. - * fr_type == rs_machine_dependent. - * fr_subtype is what the address relaxed to. - * - * Out: Any fixSs and constants are set up. - * Caller will turn frag into a ".space 0". - */ +/* Called after relax() is finished. + In: Address of frag. + fr_type == rs_machine_dependent. + fr_subtype is what the address relaxed to. + + Out: Any fixSs and constants are set up. + Caller will turn frag into a ".space 0". */ + void -md_convert_frag (headers, seg, fragP) - object_headers *headers; - segT seg; - register fragS *fragP; +md_convert_frag (object_headers *headers, segT seg, fragS *fragP) { - register char *addressP; /* -> _var to change. */ - register char *opcodeP; /* -> opcode char(s) to change. */ - register short int extension = 0; /* Size of relaxed address. - Added to fr_fix: incl. ALL var chars. */ - register symbolS *symbolP; - register long int where; - register long int address_of_var; - /* Where, in file space, is _var of *fragP? */ - register long int target_address; - /* Where, in file space, does addr point? */ + char *addressP; /* -> _var to change. */ + char *opcodeP; /* -> opcode char(s) to change. */ + short int extension = 0; /* Size of relaxed address. + Added to fr_fix: incl. ALL var chars. */ + symbolS *symbolP; + long int where; + long int address_of_var; + /* Where, in file space, is _var of *fragP? */ + long int target_address; + /* Where, in file space, does addr point? */ know (fragP->fr_type == rs_machine_dependent); where = fragP->fr_fix; @@ -750,11 +694,12 @@ md_convert_frag (headers, seg, fragP) know (symbolP); target_address = S_GET_VALUE (symbolP) + fragP->fr_offset; address_of_var = fragP->fr_address + where; + switch (fragP->fr_subtype) { case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE): /* *addressP holds the registers number, plus 0x10, if it's deferred - mode. To set up the right mode, just OR the size of this displacement */ + mode. To set up the right mode, just OR the size of this displacement. */ /* Byte displacement. */ *addressP++ |= TAHOE_PC_OR_BYTE; *addressP = target_address - (address_of_var + 2); @@ -782,7 +727,7 @@ md_convert_frag (headers, seg, fragP) case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD): *opcodeP ^= 0x10; /* Reverse sense of test. */ - *addressP++ = 3; /* Jump over word branch */ + *addressP++ = 3; /* Jump over word branch. */ *addressP++ = TAHOE_BRW; md_number_to_chars (addressP, target_address - (address_of_var + 4), 2); extension = 4; @@ -851,7 +796,7 @@ md_convert_frag (headers, seg, fragP) break; } fragP->fr_fix += extension; -} /* md_convert_frag */ +} /* This is the stuff for md_assemble. */ @@ -860,26 +805,24 @@ md_convert_frag (headers, seg, fragP) #define PC_REG 15 #define BIGGESTREG PC_REG -/* - * Parse the string pointed to by START - * If it represents a valid register, point START to the character after - * the last valid register char, and return the register number (0-15). - * If invalid, leave START alone, return -1. - * The format has to be exact. I don't do things like eat leading zeros - * or the like. - * Note: This doesn't check for the next character in the string making - * this invalid. Ex: R123 would return 12, it's the callers job to check - * what start is point to apon return. - * - * Valid registers are R1-R15, %1-%15, FP (13), SP (14), PC (15) - * Case doesn't matter. - */ +/* Parse the string pointed to by START + If it represents a valid register, point START to the character after + the last valid register char, and return the register number (0-15). + If invalid, leave START alone, return -1. + The format has to be exact. I don't do things like eat leading zeros + or the like. + Note: This doesn't check for the next character in the string making + this invalid. Ex: R123 would return 12, it's the callers job to check + what start is point to apon return. + + Valid registers are R1-R15, %1-%15, FP (13), SP (14), PC (15) + Case doesn't matter. */ + int -tahoe_reg_parse (start) - char **start; /* A pointer to the string to parse. */ +tahoe_reg_parse (char **start) /* A pointer to the string to parse. */ { - register char *regpoint = *start; - register int regnum = -1; + char *regpoint = *start; + int regnum = -1; switch (*regpoint++) { @@ -896,13 +839,11 @@ tahoe_reg_parse (start) /* Its a two digit number. */ regnum = 10 + (*regpoint++ - '0'); if (regnum > BIGGESTREG) - { /* Number too big? */ - regnum = -1; - } + regnum = -1; } } break; - case 'F': /* Is it the FP */ + case 'F': /* Is it the FP. */ case 'f': switch (*regpoint++) { @@ -911,7 +852,7 @@ tahoe_reg_parse (start) regnum = FP_REG; } break; - case 's': /* How about the SP */ + case 's': /* How about the SP. */ case 'S': switch (*regpoint++) { @@ -920,7 +861,7 @@ tahoe_reg_parse (start) regnum = SP_REG; } break; - case 'p': /* OR the PC even */ + case 'p': /* Or the PC even. */ case 'P': switch (*regpoint++) { @@ -932,101 +873,94 @@ tahoe_reg_parse (start) } if (regnum != -1) - { /* No error, so move string pointer */ - *start = regpoint; - } - return regnum; /* Return results */ -} /* tahoe_reg_parse */ + /* No error, so move string pointer. */ + *start = regpoint; + + return regnum; +} -/* - * This chops up an operand and figures out its modes and stuff. - * It's a little touchy about extra characters. - * Optex to start with one extra character so it can be overwritten for - * the backward part of the parsing. - * You can't put a bunch of extra characters in side to - * make the command look cute. ie: * foo ( r1 ) [ r0 ] - * If you like doing a lot of typing, try COBOL! - * Actually, this parser is a little weak all around. It's designed to be - * used with compliers, so I emphasize correct decoding of valid code quickly - * rather that catching every possible error. - * Note: This uses the expression function, so save input_line_pointer before - * calling. - * - * Sperry defines the semantics of address modes (and values) - * by a two-letter code, explained here. - * - * letter 1: access type - * - * a address calculation - no data access, registers forbidden - * b branch displacement - * m read - let go of bus - write back "modify" - * r read - * w write - * v bit field address: like 'a' but registers are OK - * - * letter 2: data type (i.e. width, alignment) - * - * b byte - * w word - * l longword - * q quadword (Even regs < 14 allowed) (if 12, you get a warning) - * - unconditional synthetic jbr operand - * ? simple synthetic reversible branch operand - * ! complex synthetic reversible branch operand - * : complex synthetic non-reversible branch operand - * - * The '-?!:' letter 2's are not for external consumption. They are used - * by GAS for psuedo ops relaxing code. - * - * After parsing topP has: - * - * top_ndx: -1, or the index register. eg 7=[R7] - * top_reg: -1, or register number. eg 7 = R7 or (R7) - * top_mode: The addressing mode byte. This byte, defines which of - * the 11 modes opcode is. - * top_access: Access type wanted for this operand 'b'branch ' ' - * no-instruction 'amrvw' - * top_width: Operand width expected, one of "bwlq?-:!" - * exp_of_operand: The expression as parsed by expression() - * top_dispsize: Number of bytes in the displacement if we can figure it - * out and it's relevant. - * - * Need syntax checks built. - */ +/* This chops up an operand and figures out its modes and stuff. + It's a little touchy about extra characters. + Optex to start with one extra character so it can be overwritten for + the backward part of the parsing. + You can't put a bunch of extra characters in side to + make the command look cute. ie: * foo ( r1 ) [ r0 ] + If you like doing a lot of typing, try COBOL! + Actually, this parser is a little weak all around. It's designed to be + used with compliers, so I emphasize correct decoding of valid code quickly + rather that catching every possible error. + Note: This uses the expression function, so save input_line_pointer before + calling. + + Sperry defines the semantics of address modes (and values) + by a two-letter code, explained here. + + letter 1: access type + + a address calculation - no data access, registers forbidden + b branch displacement + m read - let go of bus - write back "modify" + r read + w write + v bit field address: like 'a' but registers are OK + + letter 2: data type (i.e. width, alignment) + + b byte + w word + l longword + q quadword (Even regs < 14 allowed) (if 12, you get a warning) + - unconditional synthetic jbr operand + ? simple synthetic reversible branch operand + ! complex synthetic reversible branch operand + : complex synthetic non-reversible branch operand + + The '-?!:' letter 2's are not for external consumption. They are used + by GAS for psuedo ops relaxing code. + + After parsing topP has: + + top_ndx: -1, or the index register. eg 7=[R7] + top_reg: -1, or register number. eg 7 = R7 or (R7) + top_mode: The addressing mode byte. This byte, defines which of + the 11 modes opcode is. + top_access: Access type wanted for this operand 'b'branch ' ' + no-instruction 'amrvw' + top_width: Operand width expected, one of "bwlq?-:!" + exp_of_operand: The expression as parsed by expression() + top_dispsize: Number of bytes in the displacement if we can figure it + out and it's relevant. + + Need syntax checks built. */ void -tip_op (optex, topP) - char *optex; /* The users text input, with one leading character */ - struct top *topP; /* The tahoe instruction with some fields already set: - in: access, width - out: ndx, reg, mode, error, dispsize */ - +tip_op (char *optex, /* The users text input, with one leading character. */ + struct top *topP) /* The tahoe instruction with some fields already set: + in: access, width + out: ndx, reg, mode, error, dispsize. */ { int mode = 0; /* This operand's mode. */ char segfault = *optex; /* To keep the back parsing from freaking. */ char *point = optex + 1; /* Parsing from front to back. */ char *end; /* Parsing from back to front. */ - int reg = -1; /* major register, -1 means absent */ - int imreg = -1; /* Major register in immediate mode */ - int ndx = -1; /* index register number, -1 means absent */ + int reg = -1; /* major register, -1 means absent. */ + int imreg = -1; /* Major register in immediate mode. */ + int ndx = -1; /* index register number, -1 means absent. */ char dec_inc = ' '; /* Is the SP auto-incremented '+' or auto-decremented '-' or neither ' '. */ - int immediate = 0; /* 1 if '$' immediate mode */ - int call_width = 0; /* If the caller casts the displacement */ - int abs_width = 0; /* The width of the absolute displacement */ - int com_width = 0; /* Displacement width required by branch */ - int deferred = 0; /* 1 if '*' deferral is used */ - byte disp_size = 0; /* How big is this operand. 0 == don't know */ - char *op_bad = ""; /* Bad operand error */ - - char *tp, *temp, c; /* Temporary holders */ - - char access = topP->top_access; /* Save on a deref. */ + int immediate = 0; /* 1 if '$' immediate mode. */ + int call_width = 0; /* If the caller casts the displacement. */ + int abs_width = 0; /* The width of the absolute displacement. */ + int com_width = 0; /* Displacement width required by branch. */ + int deferred = 0; /* 1 if '*' deferral is used. */ + byte disp_size = 0; /* How big is this operand. 0 == don't know. */ + char *op_bad = ""; /* Bad operand error. */ + char *tp, *temp, c; /* Temporary holders. */ + char access = topP->top_access;/* Save on a deref. */ char width = topP->top_width; - int really_none = 0; /* Empty expressions evaluate to 0 - but I need to know if it's there or not */ - expressionS *expP; /* -> expression values for this operand */ + but I need to know if it's there or not. */ + expressionS *expP; /* -> expression values for this operand. */ /* Does this command restrict the displacement size. */ if (access == 'b') @@ -1035,23 +969,21 @@ tip_op (optex, topP) (width == 'l' ? 4 : 0))); *optex = '\0'; /* This is kind of a back stop for all - the searches to fail on if needed.*/ + the searches to fail on if needed. */ if (*point == '*') - { /* A dereference? */ + { + /* A dereference? */ deferred = 1; point++; } - /* Force words into a certain mode */ - /* Bitch, Bitch, Bitch! */ - /* - * Using the ^ operator is ambiguous. If I have an absolute label - * called 'w' set to, say 2, and I have the expression 'w^1', do I get - * 1, forced to be in word displacement mode, or do I get the value of - * 'w' or'ed with 1 (3 in this case). - * The default is 'w' as an offset, so that's what I use. - * Stick with `, it does the same, and isn't ambig. - */ + /* Force words into a certain mode. */ + /* Using the ^ operator is ambiguous. If I have an absolute label + called 'w' set to, say 2, and I have the expression 'w^1', do I get + 1, forced to be in word displacement mode, or do I get the value of + 'w' or'ed with 1 (3 in this case). + The default is 'w' as an offset, so that's what I use. + Stick with `, it does the same, and isn't ambig. */ if (*point != '\0' && ((point[1] == '^') || (point[1] == '`'))) switch (*point) @@ -1074,26 +1006,24 @@ tip_op (optex, topP) break; } - /* Setting immediate mode */ + /* Setting immediate mode. */ if (*point == '$') { immediate = 1; point++; } - /* - * I've pulled off all the easy stuff off the front, move to the end and - * yank. - */ + /* I've pulled off all the easy stuff off the front, move to the end and + yank. */ for (end = point; *end != '\0'; end++) /* Move to the end. */ ; - if (end != point) /* Null string? */ + if (end != point) /* Null string? */ end--; if (end > point && *end == ' ' && end[-1] != '\'') - end--; /* Hop white space */ + end--; /* Hop white space. */ /* Is this an index reg. */ if ((*end == ']') && (end[-1] != '\'')) @@ -1110,13 +1040,12 @@ tip_op (optex, topP) tp = end + 1; /* tp should point to the start of a reg. */ ndx = tahoe_reg_parse (&tp); if (tp != temp) - { /* Reg. parse error. */ - ndx = -1; - } + /* Reg. parse error. */ + ndx = -1; else - { - end--; /* Found it, move past brace. */ - } + /* Found it, move past brace. */ + end--; + if (ndx == -1) { op_bad = _("Couldn't parse the [index] in this operand."); @@ -1138,7 +1067,7 @@ tip_op (optex, topP) end--; } - /* register in parens? */ + /* Register in parens? */ if ((*end == ')') && (end[-1] != '\'')) { temp = end; @@ -1156,21 +1085,22 @@ tip_op (optex, topP) { /* Not a register, but could be part of the expression. */ reg = -1; - end = temp; /* Rest the pointer back */ + /* Rest the pointer back. */ + end = temp; } else - { - end--; /* Found the reg. move before opening paren. */ - } + /* Found the reg. move before opening paren. */ + end--; } else { op_bad = _("Couldn't find the opening '(' for the deref of this operand."); - end = point; /* Force all the rest of the tests to fail. */ + /* Force all the rest of the tests to fail. */ + end = point; } } - /* Pre decrement? */ + /* Pre decrement? */ if (*end == '-') { if (dec_inc != ' ') @@ -1181,22 +1111,18 @@ tip_op (optex, topP) else { dec_inc = '-'; - /* was: *end--; */ end--; } } - /* - * Everything between point and end is the 'expression', unless it's - * a register name. - */ - + /* Everything between point and end is the 'expression', unless it's + a register name. */ c = end[1]; end[1] = '\0'; tp = point; - imreg = tahoe_reg_parse (&point); /* Get the immediate register - if it is there.*/ + /* Get the immediate register if it is there. */ + imreg = tahoe_reg_parse (&point); if (*point != '\0') { /* If there is junk after point, then the it's not immediate reg. */ @@ -1207,12 +1133,9 @@ tip_op (optex, topP) if (imreg != -1 && reg != -1) op_bad = _("I parsed 2 registers in this operand."); - /* - * Evaluate whats left of the expression to see if it's valid. - * Note again: This assumes that the calling expression has saved - * input_line_pointer. (Nag, nag, nag!) - */ - + /* Evaluate whats left of the expression to see if it's valid. + Note again: This assumes that the calling expression has saved + input_line_pointer. (Nag, nag, nag!). */ if (*op_bad == '\0') { /* Statement has no syntax goofs yet: let's sniff the expression. */ @@ -1223,37 +1146,35 @@ tip_op (optex, topP) { case O_absent: /* No expression. For BSD4.2 compatibility, missing expression is - absolute 0 */ + absolute 0. */ expP->X_op = O_constant; expP->X_add_number = 0; really_none = 1; case O_constant: - /* for SEG_ABSOLUTE, we shouldn't need to set X_op_symbol, + /* For SEG_ABSOLUTE, we shouldn't 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. */ expP->X_add_symbol = NULL; expP->X_op_symbol = NULL; - /* How many bytes are needed to express this abs value? */ + /* 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); + ((((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 O_symbol: break; default: - /* - * Major bug. We can't handle the case of an operator - * expression in a synthetic opcode variable-length - * instruction. We don't have a frag type that is smart - * enough to relax an 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. - */ + /* Major bug. We can't handle the case of an operator + expression in a synthetic opcode variable-length + instruction. We don't have a frag type that is smart + enough to relax an 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; op_bad = _("Can't relocate expression error."); break; @@ -1265,35 +1186,32 @@ tip_op (optex, topP) op_bad = _("Expression is too large for a 32 bits."); break; } + if (*input_line_pointer != '\0') - { - op_bad = _("Junk at end of expression."); - } + op_bad = _("Junk at end of expression."); } end[1] = c; - /* I'm done, so restore optex */ + /* I'm done, so restore optex. */ *optex = segfault; - /* - * At this point in the game, we (in theory) have all the components of - * the operand at least parsed. Now it's time to check for syntax/semantic - * errors, and build the mode. - * This is what I have: - * deferred = 1 if '*' - * call_width = 0,1,2,4 - * abs_width = 0,1,2,4 - * com_width = 0,1,2,4 - * immediate = 1 if '$' - * ndx = -1 or reg num - * dec_inc = '-' or '+' or ' ' - * reg = -1 or reg num - * imreg = -1 or reg num - * topP->exp_of_operand - * really_none - */ - /* Is there a displacement size? */ + /* At this point in the game, we (in theory) have all the components of + the operand at least parsed. Now it's time to check for syntax/semantic + errors, and build the mode. + This is what I have: + deferred = 1 if '*' + call_width = 0,1,2,4 + abs_width = 0,1,2,4 + com_width = 0,1,2,4 + immediate = 1 if '$' + ndx = -1 or reg num + dec_inc = '-' or '+' or ' ' + reg = -1 or reg num + imreg = -1 or reg num + topP->exp_of_operand + really_none. */ + /* Is there a displacement size? */ disp_size = (call_width ? call_width : (com_width ? com_width : abs_width ? abs_width : 0)); @@ -1304,8 +1222,11 @@ tip_op (optex, topP) { /* Rn */ mode = TAHOE_DIRECT_REG; - if (deferred || immediate || (dec_inc != ' ') || - (reg != -1) || !really_none) + if (deferred + || immediate + || (dec_inc != ' ') + || (reg != -1) + || !really_none) op_bad = _("Syntax error in direct register mode."); else if (ndx != -1) op_bad = _("You can't index a register in direct register mode."); @@ -1323,14 +1244,14 @@ tip_op (optex, topP) if (*op_bad == '\0') { - /* No errors, check for warnings */ + /* No errors, check for warnings. */ if (width == 'q' && imreg == 12) as_warn (_("Using reg 14 for quadwords can tromp the FP register.")); reg = imreg; } - /* We know: imm = -1 */ + /* We know: imm = -1. */ } else if (dec_inc == '-') { @@ -1349,7 +1270,7 @@ tip_op (optex, topP) else if (width == 'q') op_bad = _("Auto dec won't work with quadwords."); - /* We know: imm = -1, dec_inc != '-' */ + /* We know: imm = -1, dec_inc != '-'. */ } else if (dec_inc == '+') { @@ -1382,7 +1303,7 @@ tip_op (optex, topP) op_bad = _("You can't have an index in auto inc mode."); } - /* We know: imm = -1, dec_inc == ' ' */ + /* We know: imm = -1, dec_inc == ' '. */ } else if (reg != -1) { @@ -1396,16 +1317,11 @@ tip_op (optex, topP) op_bad = _("Syntax error in register displaced mode."); } else if (really_none) - { - /* (Rn) */ - mode = TAHOE_REG_DEFERRED; - /* if reg = SP then cant be indexed */ - } + /* (Rn) */ + mode = TAHOE_REG_DEFERRED; else - { - /* (Rn) */ - mode = TAHOE_REG_DISP; - } + /* (Rn) */ + mode = TAHOE_REG_DISP; /* We know: imm = -1, dec_inc == ' ', Reg = -1 */ } @@ -1430,64 +1346,51 @@ tip_op (optex, topP) /* ponder the wisdom of a cast because it doesn't do any good. */ } else if (deferred) - { - /* * */ - mode = TAHOE_DISP_REL_DEFERRED; - } + /* * */ + mode = TAHOE_DISP_REL_DEFERRED; else - { - /* */ - mode = TAHOE_DISPLACED_RELATIVE; - } + /* */ + mode = TAHOE_DISPLACED_RELATIVE; } } - /* - * At this point, all the errors we can do have be checked for. - * We can build the 'top'. */ - + /* At this point, all the errors we can do have be checked for. + We can build the 'top'. */ topP->top_ndx = ndx; topP->top_reg = reg; topP->top_mode = mode; topP->top_error = op_bad; topP->top_dispsize = disp_size; -} /* tip_op */ +} -/* - * t i p ( ) - * - * This converts a string into a tahoe instruction. - * The string must be a bare single instruction in tahoe (with BSD4 frobs) - * format. - * It provides at most one fatal error message (which stops the scan) - * some warning messages as it finds them. - * The tahoe instruction is returned in exploded form. - * - * The exploded instruction is returned to a struct tit of your choice. - * #include "tahoe-inst.h" to know what a struct tit is. - * - */ +/* This converts a string into a tahoe instruction. + The string must be a bare single instruction in tahoe (with BSD4 frobs) + format. + It provides at most one fatal error message (which stops the scan) + some warning messages as it finds them. + The tahoe instruction is returned in exploded form. + + The exploded instruction is returned to a struct tit of your choice. + #include "tahoe-inst.h" to know what a struct tit is. */ static void -tip (titP, instring) - struct tit *titP; /* We build an exploded instruction here. */ - char *instring; /* Text of a vax instruction: we modify. */ +tip (struct tit *titP, /* We build an exploded instruction here. */ + char *instring) /* Text of a vax instruction: we modify. */ { - register struct tot_wot *twP = NULL; /* How to bit-encode this opcode. */ - register char *p; /* 1/skip whitespace.2/scan vot_how */ - register char *q; /* */ - register unsigned char count; /* counts number of operands seen */ - register struct top *operandp;/* scan operands in struct tit */ - register char *alloperr = ""; /* error over all operands */ - register char c; /* Remember char, (we clobber it - with '\0' temporarily). */ + struct tot_wot *twP = NULL; /* How to bit-encode this opcode. */ + char *p; /* 1/skip whitespace.2/scan vot_how. */ + char *q; + unsigned char count; /* Counts number of operands seen. */ + struct top *operandp; /* Scan operands in struct tit. */ + char *alloperr = ""; /* Error over all operands. */ + char c; /* Remember char, (we clobber it with '\0' temporarily). */ char *save_input_line_pointer; if (*instring == ' ') ++instring; /* Skip leading whitespace. */ for (p = instring; *p && *p != ' '; p++) - ; /* MUST end in end-of-string or - exactly 1 space. */ + ; + /* Scanned up to end of operation-code. */ /* Operation-code is ended with whitespace. */ if (p == instring) @@ -1500,13 +1403,13 @@ tip (titP, instring) { c = *p; *p = '\0'; - /* - * Here with instring pointing to what better be an op-name, and p - * pointing to character just past that. - * We trust instring points to an op-name, with no whitespace. - */ + + /* Here with instring pointing to what better be an op-name, and p + pointing to character just past that. + We trust instring points to an op-name, with no whitespace. */ twP = (struct tot_wot *) hash_find (op_hash, instring); - *p = c; /* Restore char after op-code. */ + /* Restore char after op-code. */ + *p = c; if (twP == 0) { titP->tit_error = _("Unknown operator"); @@ -1515,53 +1418,53 @@ tip (titP, instring) } else { - /* - * We found a match! So let's pick up as many operands as the - * instruction wants, and even gripe if there are too many. - * We expect comma to separate each operand. - * We let instring track the text, while p tracks a part of the - * struct tot. - */ - - count = 0; /* no operands seen yet */ - instring = p + (*p != '\0'); /* point past the operation code */ + /* We found a match! So let's pick up as many operands as the + instruction wants, and even gripe if there are too many. + We expect comma to separate each operand. + We let instring track the text, while p tracks a part of the + struct tot. */ + + /* No operands seen yet. */ + count = 0; + /* Point past the operation code. */ + instring = p + (*p != '\0'); /* tip_op() screws with the input_line_pointer, so save it before - I jump in */ + I jump in. */ save_input_line_pointer = input_line_pointer; + for (p = twP->args, operandp = titP->tit_operand; !*alloperr && *p; operandp++, p += 2) { - /* - * Here to parse one operand. Leave instring pointing just - * past any one ',' that marks the end of this operand. - */ + /* Here to parse one operand. Leave instring pointing just + past any one ',' that marks the end of this operand. */ if (!p[1]) as_fatal (_("Compiler bug: ODD number of bytes in arg structure %s."), twP->args); else if (*instring) { for (q = instring; (*q != ',' && *q != '\0'); q++) - { - if (*q == '\'' && q[1] != '\0') /* Jump quoted characters */ - q++; - } + /* Jump quoted characters. */ + if (*q == '\'' && q[1] != '\0') + q++; + c = *q; - /* - * Q points to ',' or '\0' that ends argument. C is that - * character. - */ + /* Q points to ',' or '\0' that ends argument. C is that + character. */ *q = '\0'; operandp->top_access = p[0]; operandp->top_width = p[1]; tip_op (instring - 1, operandp); - *q = c; /* Restore input text. */ + /* Restore input text. */ + *q = c; + if (*(operandp->top_error)) - { - alloperr = operandp->top_error; - } - instring = q + (c ? 1 : 0); /* next operand (if any) */ - count++; /* won another argument, may have an operr */ + alloperr = operandp->top_error; + + /* Next operand (if any). */ + instring = q + (c ? 1 : 0); + /* Won another argument, may have an operr. */ + count++; } else alloperr = _("Not enough operands"); @@ -1571,65 +1474,51 @@ tip (titP, instring) if (!*alloperr) { + /* Skip whitespace. */ if (*instring == ' ') - instring++; /* Skip whitespace. */ + instring ++; + if (*instring) alloperr = _("Too many operands"); } + titP->tit_error = alloperr; } } - titP->tit_opcode = twP->code; /* The op-code. */ + titP->tit_opcode = twP->code; titP->tit_operands = count; -} /* tip */ +} -/* md_assemble() emit frags for 1 instruction */ void -md_assemble (instruction_string) - char *instruction_string; /* A string: assemble 1 instruction. */ +md_assemble (char *instruction_string) { char *p; - register struct top *operandP;/* An operand. Scans all operands. */ - /* char c_save; fixme: remove this line *//* What used to live after an expression. */ - /* struct frag *fragP; fixme: remove this line *//* Fragment of code we just made. */ - /* register struct top *end_operandP; fixme: remove this line *//* -> slot just after last operand - Limit of the for (each operand). */ - register expressionS *expP; /* -> expression values for this operand */ - + struct top *operandP; /* An operand. Scans all operands. */ + expressionS *expP; /* -> expression values for this operand. */ /* These refer to an instruction operand expression. */ segT to_seg; /* Target segment of the address. */ - - register valueT this_add_number; - register symbolS *this_add_symbol; /* +ve (minuend) symbol. */ - - /* tahoe_opcodeT opcode_as_number; fixme: remove this line *//* The opcode as a number. */ + valueT this_add_number; + symbolS *this_add_symbol; /* +ve (minuend) symbol. */ char *opcodeP; /* Where it is in a frag. */ - /* char *opmodeP; fixme: remove this line *//* Where opcode type is, in a frag. */ - - int dispsize; /* From top_dispsize: tahoe_operand_width - (in bytes) */ - int is_undefined; /* 1 if operand expression's - segment not known yet. */ - int pc_rel; /* Is this operand pc relative? */ + int dispsize; /* From top_dispsize: tahoe_operand_width (in bytes). */ + int is_undefined; /* 1 if operand expression's segment not known yet. */ + int pc_rel; /* Is this operand pc relative? */ /* Decode the operand. */ tip (&t, instruction_string); - /* - * Check to see if this operand decode properly. - * Notice that we haven't made any frags yet. - * If it goofed, then this instruction will wedge in any pass, - * and we can safely flush it, without causing interpass symbol phase - * errors. That is, without changing label values in different passes. - */ + /* Check to see if this operand decode properly. + Notice that we haven't made any frags yet. + If it goofed, then this instruction will wedge in any pass, + and we can safely flush it, without causing interpass symbol phase + errors. That is, without changing label values in different passes. */ + if (*t.tit_error) - { - as_warn (_("Ignoring statement due to \"%s\""), t.tit_error); - } + as_warn (_("Ignoring statement due to \"%s\""), t.tit_error); else { - /* We saw no errors in any operands - try to make frag(s) */ + /* We saw no errors in any operands - try to make frag(s). */ /* Emit op-code. */ /* Remember where it is, in case we want to modify the op-code later. */ opcodeP = frag_more (1); @@ -1643,7 +1532,7 @@ md_assemble (instruction_string) if (operandP->top_ndx >= 0) { /* Indexed addressing byte - Legality of indexed mode already checked: it is OK */ + Legality of indexed mode already checked: it is OK. */ FRAG_APPEND_1_CHAR (0x40 + operandP->top_ndx); } /* if(top_ndx>=0) */ @@ -1651,28 +1540,27 @@ md_assemble (instruction_string) this_add_number = expP->X_add_number; this_add_symbol = expP->X_add_symbol; to_seg = operandP->seg_of_operand; - know (to_seg == SEG_UNKNOWN || \ - to_seg == SEG_ABSOLUTE || \ - to_seg == SEG_DATA || \ - to_seg == SEG_TEXT || \ - to_seg == SEG_BSS); + know (to_seg == SEG_UNKNOWN \ + || to_seg == SEG_ABSOLUTE \ + || to_seg == SEG_DATA \ + || to_seg == SEG_TEXT \ + || to_seg == SEG_BSS); is_undefined = (to_seg == SEG_UNKNOWN); - /* Do we know how big this operand is? */ + /* Do we know how big this operand is? */ dispsize = operandP->top_dispsize; pc_rel = 0; - /* Deal with the branch possibilities. (Note, this doesn't include - jumps.)*/ + /* Deal with the branch possibilities. (Note, this doesn't include jumps.) */ if (operandP->top_access == 'b') { /* Branches must be expressions. A psuedo branch can also jump to - an absolute address. */ + an absolute address. */ if (to_seg == now_seg || is_undefined) { /* If is_undefined, then it might BECOME now_seg by relax time. */ if (dispsize) { /* I know how big the branch is supposed to be (it's a normal - branch), so I set up the frag, and let GAS do the rest. */ + 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, this_add_number, @@ -1681,16 +1569,15 @@ md_assemble (instruction_string) } else { - /* (to_seg==now_seg || to_seg == SEG_UNKNOWN) && dispsize==0 */ /* If we don't know how big it is, then its a synthetic branch, - so we set up a simple relax state. */ + so we set up a simple relax state. */ switch (operandP->top_width) { case TAHOE_WIDTH_CONDITIONAL_JUMP: /* Simple (conditional) jump. I may have to reverse the - condition of opcodeP, and then jump to my destination. - I set 1 byte aside for the branch off set, and could need 6 - more bytes for the pc_rel jump */ + condition of opcodeP, and then jump to my destination. + I set 1 byte aside for the branch off set, and could need 6 + more bytes for the pc_rel jump. */ frag_var (rs_machine_dependent, 7, 1, ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, is_undefined ? STATE_UNDF : STATE_BYTE), @@ -1698,7 +1585,7 @@ md_assemble (instruction_string) break; case TAHOE_WIDTH_ALWAYS_JUMP: /* Simple (unconditional) jump. I may have to convert this to - a word branch, or an absolute jump. */ + a word branch, or an absolute jump. */ frag_var (rs_machine_dependent, 5, 1, ENCODE_RELAX (STATE_ALWAYS_BRANCH, is_undefined ? STATE_UNDF : STATE_BYTE), @@ -1728,24 +1615,24 @@ md_assemble (instruction_string) else { /* to_seg != now_seg && to_seg != seg_unknown (still in branch) - In other words, I'm jumping out of my segment so extend the - branches to jumps, and let GAS fix them. */ + In other words, I'm jumping out of my segment so extend the + branches to jumps, and let GAS fix them. */ /* These are "branches" what will always be branches around a jump - to the correct address in real life. - If to_seg is SEG_ABSOLUTE, just encode the branch in, - else let GAS fix the address. */ + to the correct address in real life. + If to_seg is SEG_ABSOLUTE, just encode the branch in, + else let GAS fix the address. */ switch (operandP->top_width) { /* The theory: - For SEG_ABSOLUTE, then mode is ABSOLUTE_ADDR, jump - to that address (not pc_rel). - For other segs, address is a long word PC rel jump. */ + For SEG_ABSOLUTE, then mode is ABSOLUTE_ADDR, jump + to that address (not pc_rel). + For other segs, address is a long word PC rel jump. */ case TAHOE_WIDTH_CONDITIONAL_JUMP: /* b */ /* To reverse the condition in a TAHOE branch, - complement bit 4 */ + complement bit 4 */ *opcodeP ^= 0x10; p = frag_more (7); *p++ = 6; @@ -1756,14 +1643,14 @@ md_assemble (instruction_string) fix_new (frag_now, p - frag_now->fr_literal, this_add_symbol, this_add_number, (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); - /* - * Now (eg) BLEQ 1f - * JMP foo - * 1: - */ + + /* Now (eg) BLEQ 1f + JMP foo + 1: */ break; + case TAHOE_WIDTH_ALWAYS_JUMP: - /* br, just turn it into a jump */ + /* Br, just turn it into a jump. */ *opcodeP = TAHOE_JMP; p = frag_more (5); *p++ = (operandP->top_mode == @@ -1772,8 +1659,9 @@ md_assemble (instruction_string) fix_new (frag_now, p - frag_now->fr_literal, this_add_symbol, this_add_number, (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); - /* Now (eg) JMP foo */ + /* Now (eg) JMP foo. */ break; + case TAHOE_WIDTH_BIG_REV_JUMP: p = frag_more (8); *opcodeP ^= 0x10; @@ -1786,12 +1674,11 @@ md_assemble (instruction_string) fix_new (frag_now, p - frag_now->fr_literal, this_add_symbol, this_add_number, (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); - /* - * Now (eg) ACBx 1f - * JMP foo - * 1: - */ + /* Now (eg) ACBx 1f + JMP foo + 1: */ break; + case TAHOE_WIDTH_BIG_NON_REV_JUMP: p = frag_more (10); *p++ = 0; @@ -1805,12 +1692,10 @@ md_assemble (instruction_string) fix_new (frag_now, p - frag_now->fr_literal, this_add_symbol, this_add_number, (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL); - /* - * Now (eg) xOBxxx 1f - * BRB 2f - * 1: JMP @#foo - * 2: - */ + /* Now (eg) xOBxxx 1f + BRB 2f + 1: JMP @#foo + 2: */ break; case 'b': case 'w': @@ -1829,7 +1714,7 @@ md_assemble (instruction_string) switch (operandP->top_mode) { /* Auto-foo access, only works for one reg (SP) - so the only thing needed is the mode. */ + so the only thing needed is the mode. */ case TAHOE_AUTO_DEC: case TAHOE_AUTO_INC: case TAHOE_AUTO_INC_DEFERRED: @@ -1837,14 +1722,14 @@ md_assemble (instruction_string) break; /* Numbered Register only access. Only thing needed is the - mode + Register number */ + mode + Register number. */ case TAHOE_DIRECT_REG: case TAHOE_REG_DEFERRED: FRAG_APPEND_1_CHAR (operandP->top_mode + operandP->top_reg); break; /* An absolute address. It's size is always 5 bytes. - (mode_type + 4 byte address). */ + (mode_type + 4 byte address). */ case TAHOE_ABSOLUTE_ADDR: know ((this_add_symbol == NULL)); p = frag_more (5); @@ -1853,7 +1738,7 @@ md_assemble (instruction_string) break; /* Immediate data. If the size isn't known, then it's an address - + and offset, which is 4 bytes big. */ + + and offset, which is 4 bytes big. */ case TAHOE_IMMEDIATE: if (this_add_symbol != NULL) { @@ -1867,10 +1752,8 @@ md_assemble (instruction_string) { /* It's an integer, and I know it's size. */ if ((unsigned) this_add_number < 0x40) - { - /* Will it fit in a literal? */ - FRAG_APPEND_1_CHAR ((byte) this_add_number); - } + /* Will it fit in a literal? */ + FRAG_APPEND_1_CHAR ((byte) this_add_number); else { p = frag_more (dispsize + 1); @@ -1894,9 +1777,9 @@ md_assemble (instruction_string) break; /* Distance from the PC. If the size isn't known, we have to relax - into it. The difference between this and disp(sp) is that - this offset is pc_rel, and disp(sp) isn't. - Note the drop through code. */ + into it. The difference between this and disp(sp) is that + this offset is pc_rel, and disp(sp) isn't. + Note the drop through code. */ case TAHOE_DISPLACED_RELATIVE: case TAHOE_DISP_REL_DEFERRED: @@ -1904,32 +1787,30 @@ md_assemble (instruction_string) pc_rel = 1; /* Register, plus a displacement mode. Save the register number, - and weather its deffered or not, and relax the size if it isn't - known. */ + and weather its deffered or not, and relax the size if it isn't + known. */ case TAHOE_REG_DISP: case TAHOE_REG_DISP_DEFERRED: - if (operandP->top_mode == TAHOE_DISP_REL_DEFERRED || - operandP->top_mode == TAHOE_REG_DISP_DEFERRED) - operandP->top_reg += 0x10; /* deffered mode is always 0x10 higher - than it's non-deffered sibling. */ + if (operandP->top_mode == TAHOE_DISP_REL_DEFERRED + || operandP->top_mode == TAHOE_REG_DISP_DEFERRED) + /* Deffered mode is always 0x10 higher than it's non-deffered sibling. */ + operandP->top_reg += 0x10; /* Is this a value out of this segment? - The first part of this conditional is a cludge to make gas - produce the same output as 'as' when there is a lable, in - the current segment, displacing a register. It's strange, - and no one in their right mind would do it, but it's easy - to cludge. */ - if ((dispsize == 0 && !pc_rel) || - (to_seg != now_seg && !is_undefined && to_seg != SEG_ABSOLUTE)) + The first part of this conditional is a cludge to make gas + produce the same output as 'as' when there is a lable, in + the current segment, displacing a register. It's strange, + and no one in their right mind would do it, but it's easy + to cludge. */ + if ((dispsize == 0 && !pc_rel) + || (to_seg != now_seg && !is_undefined && to_seg != SEG_ABSOLUTE)) dispsize = 4; if (dispsize == 0) { - /* - * We have a SEG_UNKNOWN symbol, or the size isn't cast. - * It might turn out to be in the same segment as - * the instruction, permitting relaxation. - */ + /* We have a SEG_UNKNOWN symbol, or the size isn't cast. + It might turn out to be in the same segment as + the instruction, permitting relaxation. */ p = frag_var (rs_machine_dependent, 5, 2, ENCODE_RELAX (STATE_PC_RELATIVE, is_undefined ? STATE_UNDF : STATE_BYTE), @@ -1961,35 +1842,34 @@ md_assemble (instruction_string) as_fatal (_("Barf, bad mode %x\n"), operandP->top_mode); } } - } /* for(operandP) */ - } /* if(!need_pass_2 && !goofed) */ -} /* tahoe_assemble() */ + } + } +} /* We have no need to default values of symbols. */ symbolS * -md_undefined_symbol (name) - char *name; +md_undefined_symbol (char *name) { return 0; -} /* md_undefined_symbol() */ +} /* Round up a section size to the appropriate boundary. */ + valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { - return ((size + 7) & ~7); /* Round all sects to multiple of 8 */ -} /* md_section_align() */ + /* Round all sects to multiple of 8. */ + return ((size + 7) & ~7); +} /* Exactly what point is a PC-relative offset relative TO? On the sparc, they're relative to the address of the offset, plus its size. This gets us to the following instruction. (??? Is this right? FIXME-SOON) */ + long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { return (((fixP->fx_type == FX_8 || fixP->fx_type == FX_PCREL8) @@ -2001,13 +1881,12 @@ md_pcrel_from (fixP) || fixP->fx_type == FX_PCREL32) ? 4 : 0))) + fixP->fx_where + fixP->fx_frag->fr_address); -} /* md_pcrel_from() */ +} int -tc_is_pcrel (fixP) - fixS *fixP; +tc_is_pcrel (fixS *fixP) { - /* should never be called */ + /* Should never be called. */ know (0); - return (0); -} /* tc_is_pcrel() */ + return 0; +} diff --git a/gas/config/tc-tic80.c b/gas/config/tc-tic80.c index 3c4c3035725..d803db72ee1 100644 --- a/gas/config/tc-tic80.c +++ b/gas/config/tc-tic80.c @@ -58,23 +58,19 @@ const char FLT_CHARS[] = "fF"; function to call to execute this pseudo-op integer arg to pass to the function */ -const pseudo_typeS md_pseudo_table[] = { - { "align", s_align_bytes, 4 }, /* Do byte alignment, default is a 4 byte boundary */ +const pseudo_typeS md_pseudo_table[] = +{ + { "align", s_align_bytes, 4 }, /* Do byte alignment, default is a 4 byte boundary. */ { "word", cons, 4 }, /* FIXME: Should this be machine independent? */ { "bss", s_lcomm_bytes, 1 }, - { "sect", obj_coff_section, 0}, /* For compatibility with TI tools */ - { "section", obj_coff_section, 0}, /* Standard COFF .section pseudo-op */ + { "sect", obj_coff_section, 0}, /* For compatibility with TI tools. */ + { "section", obj_coff_section, 0}, /* Standard COFF .section pseudo-op. */ { NULL, NULL, 0 } }; /* Opcode hash table. */ static struct hash_control *tic80_hash; -static struct tic80_opcode * find_opcode PARAMS ((struct tic80_opcode *, expressionS [])); -static void build_insn PARAMS ((struct tic80_opcode *, expressionS *)); -static int get_operands PARAMS ((expressionS exp[])); -static int const_overflow PARAMS ((unsigned long num, int bits, int flags)); - /* Replace short PC relative instructions with long form when necessary. Currently this is off by default or when given the -no-relax option. Turning it on by using the -relax option forces @@ -83,21 +79,19 @@ static int const_overflow PARAMS ((unsigned long num, int bits, int flags)); static int tic80_relax = 0; int -md_estimate_size_before_relax (fragP, segment_type) - fragS *fragP ATTRIBUTE_UNUSED; - segT segment_type ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, + segT segment_type ATTRIBUTE_UNUSED) { internal_error (_("Relaxation is a luxury we can't afford")); - return (-1); + return -1; } /* We have no need to default values of symbols. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { - return 0; + return NULL; } /* Turn a string in input_line_pointer into a floating point constant @@ -108,10 +102,7 @@ md_undefined_symbol (name) #define MAX_LITTLENUMS 4 char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -141,9 +132,7 @@ md_atof (type, litP, sizeP) t = atof_ieee (input_line_pointer, type, words); if (t) - { - input_line_pointer = t; - } + input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); @@ -152,17 +141,15 @@ md_atof (type, litP, sizeP) md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } - return (NULL); + + return NULL; } /* Check to see if the constant value in NUM will fit in a field of width BITS if it has flags FLAGS. */ static int -const_overflow (num, bits, flags) - unsigned long num; - int bits; - int flags; +const_overflow (unsigned long num, int bits, int flags) { long min, max; int retval = 0; @@ -195,8 +182,7 @@ const_overflow (num, bits, flags) Returns the number of expressions that were placed in EXP. */ static int -get_operands (exp) - expressionS exp[]; +get_operands (expressionS exp[]) { char *p = input_line_pointer; int numexp = 0; @@ -232,9 +218,8 @@ get_operands (exp) exp[numexp].X_add_number = TIC80_OPERAND_SCALED; } else - { - as_bad (_("':' not followed by 'm' or 's'")); - } + as_bad (_("':' not followed by 'm' or 's'")); + numexp++; continue; } @@ -267,18 +252,13 @@ get_operands (exp) } /* Begin operand parsing at the current scan point. */ - input_line_pointer = p; expression (&exp[numexp]); if (exp[numexp].X_op == O_illegal) - { - as_bad (_("illegal operand")); - } + as_bad (_("illegal operand")); else if (exp[numexp].X_op == O_absent) - { - as_bad (_("missing operand")); - } + as_bad (_("missing operand")); numexp++; p = input_line_pointer; @@ -293,7 +273,7 @@ get_operands (exp) /* Mark the end of the valid operands with an illegal expression. */ exp[numexp].X_op = O_illegal; - return (numexp); + return numexp; } /* find_opcode() gets a pointer to the entry in the opcode table that @@ -309,38 +289,32 @@ get_operands (exp) choose the correct opcode. */ static struct tic80_opcode * -find_opcode (opcode, myops) - struct tic80_opcode *opcode; - expressionS myops[]; +find_opcode (struct tic80_opcode *opcode, expressionS myops[]) { - int numexp; /* Number of expressions from parsing operands */ - int expi; /* Index of current expression to match */ - int opi; /* Index of current operand to match */ - int match = 0; /* Set to 1 when an operand match is found */ - struct tic80_opcode *opc = opcode; /* Pointer to current opcode table entry */ - const struct tic80_opcode *end; /* Pointer to end of opcode table */ + int numexp; /* Number of expressions from parsing operands. */ + int expi; /* Index of current expression to match. */ + int opi; /* Index of current operand to match. */ + int match = 0; /* Set to 1 when an operand match is found. */ + struct tic80_opcode *opc = opcode; /* Pointer to current opcode table entry. */ + const struct tic80_opcode *end; /* Pointer to end of opcode table. */ /* First parse all the operands so we only have to do it once. There may be more expressions generated than there are operands. */ - numexp = get_operands (myops); /* For each opcode with the same name, try to match it against the parsed operands. */ - end = tic80_opcodes + tic80_num_opcodes; while (!match && (opc < end) && (strcmp (opc->name, opcode->name) == 0)) { /* Start off assuming a match. If we find a mismatch, then this is reset and the operand/expr matching loop terminates with match equal to zero, which allows us to try the next opcode. */ - match = 1; /* For each expression, try to match it against the current operand for the current opcode. Upon any mismatch, we abandon further matching for the current opcode table entry. */ - for (expi = 0, opi = -1; (expi < numexp) && match; expi++) { int bits, flags, X_op, num; @@ -352,11 +326,8 @@ find_opcode (opcode, myops) recent non O_absent expression. So only increment the operand index when the current expression is not one of these special expressions. */ - if (X_op != O_absent) - { - opi++; - } + opi++; flags = tic80_operands[opc->operands[opi]].flags; bits = tic80_operands[opc->operands[opi]].bits; @@ -371,23 +342,20 @@ find_opcode (opcode, myops) ((flags & TIC80_OPERAND_CR) != (num & TIC80_OPERAND_CR)) || ((flags & TIC80_OPERAND_EVEN) && (num & 1)) || const_overflow (num & ~TIC80_OPERAND_MASK, bits, flags)) - { - match = 0; - } + match = 0; break; + case O_constant: if ((flags & TIC80_OPERAND_ENDMASK) && (num == 32)) - { - /* Endmask values of 0 and 32 give identical - results. */ - num = 0; - } + /* Endmask values of 0 and 32 give identical + results. */ + num = 0; + if ((flags & (TIC80_OPERAND_FPA | TIC80_OPERAND_GPR)) || const_overflow (num, bits, flags)) - { - match = 0; - } + match = 0; break; + case O_symbol: if ((bits < 32) && (flags & TIC80_OPERAND_PCREL) && !tic80_relax) @@ -414,6 +382,7 @@ find_opcode (opcode, myops) match = 0; } break; + case O_absent: /* If this is an O_absent expression, then it may be an expression that supplies additional information about @@ -422,16 +391,14 @@ find_opcode (opcode, myops) if (!((num & flags & TIC80_OPERAND_M_SI) || (num & flags & TIC80_OPERAND_M_LI) || (num & flags & TIC80_OPERAND_SCALED))) - { - match = 0; - } + match = 0; break; + case O_big: if ((num > 0) || !(flags & TIC80_OPERAND_FLOAT)) - { - match = 0; - } + match = 0; break; + case O_illegal: case O_symbol_rva: case O_uminus: @@ -465,7 +432,7 @@ find_opcode (opcode, myops) opc++; } - return (match ? opc : NULL); + return match ? opc : NULL; } @@ -477,17 +444,15 @@ find_opcode (opcode, myops) beginning of the next. */ static void -build_insn (opcode, opers) - struct tic80_opcode *opcode; - expressionS *opers; +build_insn (struct tic80_opcode *opcode, expressionS *opers) { - int expi; /* Index of current expression to match */ - int opi; /* Index of current operand to match */ - unsigned long insn[2]; /* Instruction and long immediate (if any) */ - char *f; /* Pointer to frag location for insn[0] */ - fragS *ffrag; /* Frag containing location f */ - char *fx = NULL; /* Pointer to frag location for insn[1] */ - fragS *fxfrag; /* Frag containing location fx */ + int expi; /* Index of current expression to match. */ + int opi; /* Index of current operand to match. */ + unsigned long insn[2]; /* Instruction and long immediate (if any). */ + char *f; /* Pointer to frag location for insn[0]. */ + fragS *ffrag; /* Frag containing location f. */ + char *fx = NULL; /* Pointer to frag location for insn[1]. */ + fragS *fxfrag; /* Frag containing location fx. */ /* Start with the raw opcode bits from the opcode table. */ insn[0] = opcode->opcode; @@ -495,7 +460,6 @@ build_insn (opcode, opers) /* We are going to insert at least one 32 bit opcode so get the frag now. */ - f = frag_more (4); ffrag = frag_now; @@ -512,11 +476,8 @@ build_insn (opcode, opers) recent non O_absent expression. So only increment the operand index when the current expression is not one of these special expressions. */ - if (X_op != O_absent) - { - opi++; - } + opi++; flags = tic80_operands[opcode->operands[opi]].flags; bits = tic80_operands[opcode->operands[opi]].bits; @@ -528,17 +489,15 @@ build_insn (opcode, opers) num &= ~TIC80_OPERAND_MASK; insn[0] = insn[0] | (num << shift); break; + case O_constant: if ((flags & TIC80_OPERAND_ENDMASK) && (num == 32)) - { - /* Endmask values of 0 and 32 give identical results. */ - num = 0; - } + /* Endmask values of 0 and 32 give identical results. */ + num = 0; else if ((flags & TIC80_OPERAND_BITNUM)) - { - /* BITNUM values are stored in one's complement form. */ - num = (~num & 0x1F); - } + /* BITNUM values are stored in one's complement form. */ + num = (~num & 0x1F); + /* Mask off upper bits, just it case it is signed and is negative. */ if (bits < 32) @@ -553,87 +512,66 @@ build_insn (opcode, opers) insn[1] = num; } break; + case O_symbol: if (bits == 32) { fx = frag_more (4); fxfrag = frag_now; insn[1] = 0; + if (flags & TIC80_OPERAND_PCREL) - { - fix_new_exp (fxfrag, - fx - (fxfrag->fr_literal), - 4, - &opers[expi], - 1, - R_MPPCR); - } + fix_new_exp (fxfrag, fx - (fxfrag->fr_literal), + 4, &opers[expi], 1, R_MPPCR); else - { - fix_new_exp (fxfrag, - fx - (fxfrag->fr_literal), - 4, - &opers[expi], - 0, - R_RELLONGX); - } + fix_new_exp (fxfrag, fx - (fxfrag->fr_literal), + 4, &opers[expi], 0, R_RELLONGX); } else if (flags & TIC80_OPERAND_PCREL) - { - fix_new_exp (ffrag, - f - (ffrag->fr_literal), - 4, /* FIXME! how is this used? */ - &opers[expi], - 1, - R_MPPCR15W); - } - else - { - internal_error (_("symbol reloc that is not PC relative or 32 bits")); - } + fix_new_exp (ffrag, f - (ffrag->fr_literal), + 4, /* FIXME! how is this used? */ + &opers[expi], 1, R_MPPCR15W); + else + internal_error (_("symbol reloc that is not PC relative or 32 bits")); break; + case O_absent: /* Each O_absent expression can indicate exactly one possible modifier. */ if ((num & TIC80_OPERAND_M_SI) && (flags & TIC80_OPERAND_M_SI)) - { - insn[0] = insn[0] | (1 << 17); - } + insn[0] = insn[0] | (1 << 17); else if ((num & TIC80_OPERAND_M_LI) && (flags & TIC80_OPERAND_M_LI)) - { - insn[0] = insn[0] | (1 << 15); - } + insn[0] = insn[0] | (1 << 15); else if ((num & TIC80_OPERAND_SCALED) && (flags & TIC80_OPERAND_SCALED)) - { - insn[0] = insn[0] | (1 << 11); - } + insn[0] = insn[0] | (1 << 11); else if ((num & TIC80_OPERAND_PARENS) && (flags & TIC80_OPERAND_PARENS)) - { - /* No code to generate, just accept and discard this - expression. */ - } + /* No code to generate, just accept and discard this + expression. */ + ; else - { - internal_error_a (_("unhandled operand modifier"), - (long) opers[expi].X_add_number); - } + internal_error_a (_("unhandled operand modifier"), + (long) opers[expi].X_add_number); break; + case O_big: fx = frag_more (4); fxfrag = frag_now; + { int precision = 2; long exponent_bits = 8L; LITTLENUM_TYPE words[2]; + /* Value is still in generic_floating_point_number. */ gen_to_words (words, precision, exponent_bits); insn[1] = (words[0] << 16) | words[1]; } break; + case O_illegal: case O_symbol_rva: case O_uminus: @@ -669,9 +607,7 @@ build_insn (opcode, opers) md_number_to_chars (f, insn[0], 4); if (fx != NULL) - { - md_number_to_chars (fx, insn[1], 4); - } + md_number_to_chars (fx, insn[1], 4); } /* This is the main entry point for the machine-dependent assembler. Gas @@ -682,8 +618,7 @@ build_insn (opcode, opers) function is supposed to emit the frags/bytes it assembles to. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { char *scan; char *input_line_save; @@ -735,7 +670,7 @@ md_assemble (str) the assembler will need. */ void -md_begin () +md_begin (void) { char *prev_name = ""; register const struct tic80_opcode *op; @@ -815,8 +750,8 @@ const char *md_shortopts = ""; /* The assembler adds md_longopts to the machine independent long options that are passed to getopt. */ -struct option md_longopts[] = { - +struct option md_longopts[] = +{ #define OPTION_RELAX (OPTION_MD_BASE) {"relax", no_argument, NULL, OPTION_RELAX}, @@ -833,9 +768,7 @@ size_t md_longopts_size = sizeof (md_longopts); appears in md_longopts for machine specific command line options. */ int -md_parse_option (c, arg) - int c; - char *arg ATTRIBUTE_UNUSED; +md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) { switch (c) { @@ -846,9 +779,9 @@ md_parse_option (c, arg) tic80_relax = 0; break; default: - return (0); + return 0; } - return (1); + return 1; } /* The md_show_usage function will be called whenever a usage message is @@ -856,8 +789,7 @@ md_parse_option (c, arg) found in md_longopts. */ void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, "\ TIc80 options:\n\ @@ -870,10 +802,7 @@ TIc80 options:\n\ To indicate that a fixup has been eliminated, set fixP->fx_done. */ void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED) { long val = * (long *) valP; char *dest = fixP->fx_frag->fr_literal + fixP->fx_where; @@ -886,17 +815,15 @@ md_apply_fix3 (fixP, valP, seg) break; case R_MPPCR: val >>= 2; - val += 1; /* Target address computed from inst start */ + val += 1; /* Target address computed from inst start. */ md_number_to_chars (dest, (valueT) val, 4); break; case R_MPPCR15W: overflow = (val < -65536L) || (val > 65532L); if (overflow) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("PC offset 0x%lx outside range 0x%lx-0x%lx"), - val, -65536L, 65532L); - } + as_bad_where (fixP->fx_file, fixP->fx_line, + _("PC offset 0x%lx outside range 0x%lx-0x%lx"), + val, -65536L, 65532L); else { val >>= 2; @@ -905,9 +832,11 @@ md_apply_fix3 (fixP, valP, seg) *dest = (*dest & 0x80) | (val & 0x7F); } break; + case R_ABS: md_number_to_chars (dest, (valueT) val, fixP->fx_size); break; + default: internal_error_a (_("unhandled relocation type in fixup"), (long) fixP->fx_r_type); @@ -927,42 +856,37 @@ md_apply_fix3 (fixP, valP, seg) the PC relative field. */ long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { return (fixP->fx_frag->fr_address + fixP->fx_where); } /* Called after relax() is finished. - * In: Address of frag. - * fr_type == rs_machine_dependent. - * fr_subtype is what the address relaxed to. - * - * Out: Any fixSs and constants are set up. - * Caller will turn frag into a ".space 0". - */ + In: Address of frag. + fr_type == rs_machine_dependent. + fr_subtype is what the address relaxed to. + + Out: Any fixSs and constants are set up. + Caller will turn frag into a ".space 0". */ void -md_convert_frag (headers, seg, fragP) - object_headers *headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - fragS *fragP ATTRIBUTE_UNUSED; +md_convert_frag (object_headers *headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + fragS *fragP ATTRIBUTE_UNUSED) { internal_error (_("md_convert_frag() not implemented yet")); abort (); } void -tc_coff_symbol_emit_hook (ignore) - symbolS *ignore ATTRIBUTE_UNUSED; +tc_coff_symbol_emit_hook (symbolS *ignore ATTRIBUTE_UNUSED) { } #if defined OBJ_COFF short -tc_coff_fix2rtype (fixP) - fixS *fixP; +tc_coff_fix2rtype (fixS *fixP) { return (fixP->fx_r_type); } diff --git a/gas/config/tc-tic80.h b/gas/config/tc-tic80.h index 9f98e3fca6c..65d52c49807 100644 --- a/gas/config/tc-tic80.h +++ b/gas/config/tc-tic80.h @@ -1,5 +1,5 @@ /* This file is tc-tic80.h - Copyright 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + Copyright 1996, 1997, 2000, 2002, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -56,6 +56,6 @@ #define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP) -extern short tc_coff_fix2rtype PARAMS ((struct fix *)); +extern short tc_coff_fix2rtype (struct fix *); #endif /* OBJ_COFF */ diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c index 2df12aae794..49590549b8d 100644 --- a/gas/config/tc-v850.c +++ b/gas/config/tc-v850.c @@ -43,7 +43,8 @@ static int machine = -1; static int processor_mask = -1; /* Structure to hold information about predefined registers. */ -struct reg_name { +struct reg_name +{ const char *name; int value; }; @@ -69,7 +70,8 @@ const char EXP_CHARS[] = "eE"; as in 0d1.0. */ const char FLT_CHARS[] = "dD"; -const relax_typeS md_relax_table[] = { +const relax_typeS md_relax_table[] = +{ /* Conditional branches. */ {0xff, -0x100, 2, 1}, {0x1fffff, -0x200000, 6, 0}, @@ -81,8 +83,10 @@ const relax_typeS md_relax_table[] = { static int v850_relax = 0; /* Fixups. */ -#define MAX_INSN_FIXUPS (5) -struct v850_fixup { +#define MAX_INSN_FIXUPS 5 + +struct v850_fixup +{ expressionS exp; int opindex; bfd_reloc_code_real_type reloc; @@ -152,20 +156,15 @@ struct v850_seg_entry v850_seg_table[] = #define CALL_TABLE_TEXT_SECTION 12 #define BSS_SECTION 13 -static void do_v850_seg PARAMS ((int, subsegT)); - static void -do_v850_seg (i, sub) - int i; - subsegT sub; +do_v850_seg (int i, subsegT sub) { struct v850_seg_entry *seg = v850_seg_table + i; obj_elf_section_change_hook (); + if (seg->s != NULL) - { - subseg_set (seg->s, sub); - } + subseg_set (seg->s, sub); else { seg->s = subseg_new (seg->name, sub); @@ -175,11 +174,8 @@ do_v850_seg (i, sub) } } -static void v850_seg PARAMS ((int i)); - static void -v850_seg (i) - int i; +v850_seg (int i) { subsegT sub = get_absolute_expression (); @@ -187,11 +183,8 @@ v850_seg (i) demand_empty_rest_of_line (); } -static void v850_offset PARAMS ((int)); - static void -v850_offset (ignore) - int ignore ATTRIBUTE_UNUSED; +v850_offset (int ignore ATTRIBUTE_UNUSED) { char *pfrag; int temp = get_absolute_expression (); @@ -205,11 +198,8 @@ v850_offset (ignore) /* Copied from obj_elf_common() in gas/config/obj-elf.c. */ -static void v850_comm PARAMS ((int)); - static void -v850_comm (area) - int area; +v850_comm (int area) { char *name; char c; @@ -261,11 +251,9 @@ v850_comm (area) if (S_GET_VALUE (symbolP) != 0) { if (S_GET_VALUE (symbolP) != size) - { - /* xgettext:c-format */ - as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."), - S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); - } + /* xgettext:c-format */ + as_warn (_("Length of .comm \"%s\" is already %ld. Not changed to %d."), + S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); } know (symbol_get_frag (symbolP) == &zero_address_frag); @@ -441,8 +429,10 @@ v850_comm (area) input_line_pointer--; goto bad_common_segment; } + while (*input_line_pointer++ != '"') ; + goto allocate_common; } @@ -466,11 +456,8 @@ v850_comm (area) } } -static void set_machine PARAMS ((int)); - static void -set_machine (number) - int number; +set_machine (int number) { machine = number; bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine); @@ -483,11 +470,8 @@ set_machine (number) } } -static void v850_longcode PARAMS ((int)); - static void -v850_longcode (type) - int type; +v850_longcode (int type) { expressionS ex; @@ -552,10 +536,10 @@ static struct hash_control *v850_hash; /* This table is sorted. Suitable for searching by a binary search. */ static const struct reg_name pre_defined_registers[] = { - { "ep", 30 }, /* ep - element ptr */ - { "gp", 4 }, /* gp - global ptr */ - { "hp", 2 }, /* hp - handler stack ptr */ - { "lp", 31 }, /* lp - link ptr */ + { "ep", 30 }, /* ep - element ptr. */ + { "gp", 4 }, /* gp - global ptr. */ + { "hp", 2 }, /* hp - handler stack ptr. */ + { "lp", 31 }, /* lp - link ptr. */ { "r0", 0 }, { "r1", 1 }, { "r10", 10 }, @@ -588,8 +572,8 @@ static const struct reg_name pre_defined_registers[] = { "r7", 7 }, { "r8", 8 }, { "r9", 9 }, - { "sp", 3 }, /* sp - stack ptr */ - { "tp", 5 }, /* tp - text ptr */ + { "sp", 3 }, /* sp - stack ptr. */ + { "tp", 5 }, /* tp - text ptr. */ { "zero", 0 }, }; @@ -663,15 +647,11 @@ static const struct reg_name cc_names[] = valid regiter name. Return the register number from the array on success, or -1 on failure. */ -static int reg_name_search - PARAMS ((const struct reg_name *, int, const char *, bfd_boolean)); - static int -reg_name_search (regs, regcount, name, accept_numbers) - const struct reg_name *regs; - int regcount; - const char *name; - bfd_boolean accept_numbers; +reg_name_search (const struct reg_name *regs, + int regcount, + const char *name, + bfd_boolean accept_numbers) { int middle, low, high; int cmp; @@ -683,10 +663,8 @@ reg_name_search (regs, regcount, name, accept_numbers) /* If the symbol is an alias for another name then use that. If the symbol is an alias for a number, then return the number. */ if (symbol_equated_p (symbolP)) - { - name - = S_GET_NAME (symbol_get_value_expression (symbolP)->X_add_symbol); - } + name + = S_GET_NAME (symbol_get_value_expression (symbolP)->X_add_symbol); else if (accept_numbers) { int reg = S_GET_VALUE (symbolP); @@ -726,11 +704,8 @@ reg_name_search (regs, regcount, name, accept_numbers) Input_line_pointer->(next non-blank) char after operand, or is in its original state. */ -static bfd_boolean register_name PARAMS ((expressionS *)); - static bfd_boolean -register_name (expressionP) - expressionS *expressionP; +register_name (expressionS *expressionP) { int reg_number; char *name; @@ -783,14 +758,10 @@ register_name (expressionP) Input_line_pointer->(next non-blank) char after operand, or is in its original state. */ -static bfd_boolean system_register_name - PARAMS ((expressionS *, bfd_boolean, bfd_boolean)); - static bfd_boolean -system_register_name (expressionP, accept_numbers, accept_list_names) - expressionS *expressionP; - bfd_boolean accept_numbers; - bfd_boolean accept_list_names; +system_register_name (expressionS *expressionP, + bfd_boolean accept_numbers, + bfd_boolean accept_list_names) { int reg_number; char *name; @@ -821,9 +792,7 @@ system_register_name (expressionP, accept_numbers, accept_list_names) if (reg_number < 0 || (reg_number > 5 && reg_number < 16) || reg_number > 27) - { - reg_number = -1; - } + reg_number = -1; } else if (accept_list_names) { @@ -867,11 +836,8 @@ system_register_name (expressionP, accept_numbers, accept_list_names) Input_line_pointer->(next non-blank) char after operand, or is in its original state. */ -static bfd_boolean cc_name PARAMS ((expressionS *)); - static bfd_boolean -cc_name (expressionP) - expressionS *expressionP; +cc_name (expressionS *expressionP) { int reg_number; char *name; @@ -908,10 +874,8 @@ cc_name (expressionP) } } -static void skip_white_space PARAMS ((void)); - static void -skip_white_space () +skip_white_space (void) { while (*input_line_pointer == ' ' || *input_line_pointer == '\t') @@ -943,23 +907,22 @@ skip_white_space () and so on upwards. System registers are considered to be very high numbers. */ -static char *parse_register_list - PARAMS ((unsigned long *, const struct v850_operand *)); - static char * -parse_register_list (insn, operand) - unsigned long *insn; - const struct v850_operand *operand; +parse_register_list (unsigned long *insn, + const struct v850_operand *operand) { - static int type1_regs[32] = { + static int type1_regs[32] = + { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; - static int type2_regs[32] = { + static int type2_regs[32] = + { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; - static int type3_regs[32] = { + static int type3_regs[32] = + { 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 }; @@ -1143,15 +1106,15 @@ parse_register_list (insn, operand) const char *md_shortopts = "m:"; -struct option md_longopts[] = { +struct option md_longopts[] = +{ {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _(" V850 options:\n")); fprintf (stream, _(" -mwarn-signed-overflow Warn if signed immediate values overflow\n")); @@ -1164,9 +1127,7 @@ md_show_usage (stream) } int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { if (c != 'm') return 0; @@ -1210,17 +1171,13 @@ md_parse_option (c, arg) } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } char * -md_atof (type, litp, sizep) - int type; - char *litp; - int *sizep; +md_atof (int type, char *litp, int *sizep) { int prec; LITTLENUM_TYPE words[4]; @@ -1260,10 +1217,9 @@ md_atof (type, litp, sizep) /* Very gross. */ void -md_convert_frag (abfd, sec, fragP) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec; - fragS *fragP; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + fragS *fragP) { subseg_change (sec, 0); @@ -1311,16 +1267,14 @@ md_convert_frag (abfd, sec, fragP) } valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg, valueT addr) { int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align)); } void -md_begin () +md_begin (void) { char *prev_name = ""; const struct v850_opcode *op; @@ -1394,12 +1348,8 @@ handle_lo16 (const struct v850_operand *operand) return BFD_RELOC_LO16; } -static bfd_reloc_code_real_type handle_ctoff - PARAMS ((const struct v850_operand *)); - static bfd_reloc_code_real_type -handle_ctoff (operand) - const struct v850_operand *operand; +handle_ctoff (const struct v850_operand *operand) { if (operand == NULL) return BFD_RELOC_V850_CALLT_16_16_OFFSET; @@ -1414,12 +1364,8 @@ handle_ctoff (operand) return BFD_RELOC_V850_CALLT_6_7_OFFSET; } -static bfd_reloc_code_real_type handle_sdaoff - PARAMS ((const struct v850_operand *)); - static bfd_reloc_code_real_type -handle_sdaoff (operand) - const struct v850_operand *operand; +handle_sdaoff (const struct v850_operand *operand) { if (operand == NULL) return BFD_RELOC_V850_SDA_16_16_OFFSET; @@ -1440,12 +1386,8 @@ handle_sdaoff (operand) return BFD_RELOC_V850_SDA_16_16_OFFSET; } -static bfd_reloc_code_real_type handle_zdaoff - PARAMS ((const struct v850_operand *)); - static bfd_reloc_code_real_type -handle_zdaoff (operand) - const struct v850_operand *operand; +handle_zdaoff (const struct v850_operand *operand) { if (operand == NULL) return BFD_RELOC_V850_ZDA_16_16_OFFSET; @@ -1467,31 +1409,27 @@ handle_zdaoff (operand) return BFD_RELOC_V850_ZDA_16_16_OFFSET; } -static bfd_reloc_code_real_type handle_tdaoff - PARAMS ((const struct v850_operand *)); - static bfd_reloc_code_real_type -handle_tdaoff (operand) - const struct v850_operand *operand; +handle_tdaoff (const struct v850_operand *operand) { if (operand == NULL) /* Data item, not an instruction. */ return BFD_RELOC_V850_TDA_7_7_OFFSET; if (operand->bits == 6 && operand->shift == 1) - /* sld.w/sst.w, operand: D8_6 */ + /* sld.w/sst.w, operand: D8_6. */ return BFD_RELOC_V850_TDA_6_8_OFFSET; if (operand->bits == 4 && operand->insert != NULL) - /* sld.hu, operand: D5-4 */ + /* sld.hu, operand: D5-4. */ return BFD_RELOC_V850_TDA_4_5_OFFSET; if (operand->bits == 4 && operand->insert == NULL) - /* sld.bu, operand: D4 */ + /* sld.bu, operand: D4. */ return BFD_RELOC_V850_TDA_4_4_OFFSET; if (operand->bits == 16 && operand->shift == 16) - /* set1 & chums, operands: D16 */ + /* set1 & chums, operands: D16. */ return BFD_RELOC_V850_TDA_16_16_OFFSET; if (operand->bits != 7) @@ -1502,20 +1440,16 @@ handle_tdaoff (operand) } return operand->insert != NULL - ? BFD_RELOC_V850_TDA_7_8_OFFSET /* sld.h/sst.h, operand: D8_7 */ - : BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, operand: D7 */ + ? BFD_RELOC_V850_TDA_7_8_OFFSET /* sld.h/sst.h, operand: D8_7. */ + : BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, operand: D7. */ } /* Warning: The code in this function relies upon the definitions in the v850_operands[] array (defined in opcodes/v850-opc.c) matching the hard coded values contained herein. */ -static bfd_reloc_code_real_type v850_reloc_prefix - PARAMS ((const struct v850_operand *)); - static bfd_reloc_code_real_type -v850_reloc_prefix (operand) - const struct v850_operand *operand; +v850_reloc_prefix (const struct v850_operand *operand) { bfd_boolean paren_skipped = FALSE; @@ -1551,18 +1485,13 @@ v850_reloc_prefix (operand) /* Insert an operand value into an instruction. */ -static unsigned long v850_insert_operand - PARAMS ((unsigned long, const struct v850_operand *, offsetT, char *, - unsigned int, char *)); - static unsigned long -v850_insert_operand (insn, operand, val, file, line, str) - unsigned long insn; - const struct v850_operand *operand; - offsetT val; - char *file; - unsigned int line; - char *str; +v850_insert_operand (unsigned long insn, + const struct v850_operand *operand, + offsetT val, + char *file, + unsigned int line, + char *str) { if (operand->insert) { @@ -1656,8 +1585,7 @@ v850_insert_operand (insn, operand, val, file, line, str) static char copy_of_instruction[128]; void -md_assemble (str) - char *str; +md_assemble (char *str) { char *s; char *start_of_operands; @@ -1731,9 +1659,7 @@ md_assemble (str) bfd_reloc_code_real_type reloc; if (next_opindex == 0) - { - operand = &v850_operands[*opindex_ptr]; - } + operand = &v850_operands[*opindex_ptr]; else { operand = &v850_operands[next_opindex]; @@ -1856,9 +1782,7 @@ md_assemble (str) if ((operand->flags & V850_OPERAND_REG) != 0) { if (!register_name (&ex)) - { - errmsg = _("invalid register name"); - } + errmsg = _("invalid register name"); else if ((operand->flags & V850_NOT_R0) && ex.X_add_number == 0) { @@ -1873,9 +1797,7 @@ md_assemble (str) else if ((operand->flags & V850_OPERAND_SRG) != 0) { if (!system_register_name (&ex, TRUE, FALSE)) - { - errmsg = _("invalid system register name"); - } + errmsg = _("invalid system register name"); } else if ((operand->flags & V850_OPERAND_EP) != 0) { @@ -1903,9 +1825,7 @@ md_assemble (str) else if ((operand->flags & V850_OPERAND_CC) != 0) { if (!cc_name (&ex)) - { - errmsg = _("invalid condition code name"); - } + errmsg = _("invalid condition code name"); } else if (operand->flags & V850E_PUSH_POP) { @@ -1997,14 +1917,12 @@ md_assemble (str) } else if (system_register_name (&ex, FALSE, FALSE) && (operand->flags & V850_OPERAND_SRG) == 0) - { - errmsg = _("syntax error: system register not expected"); - } + errmsg = _("syntax error: system register not expected"); + else if (cc_name (&ex) && (operand->flags & V850_OPERAND_CC) == 0) - { - errmsg = _("syntax error: condition code not expected"); - } + errmsg = _("syntax error: condition code not expected"); + else { expression (&ex); @@ -2041,14 +1959,12 @@ md_assemble (str) goto error; } insn = v850_insert_operand (insn, operand, ex.X_add_number, - (char *) NULL, 0, - copy_of_instruction); + NULL, 0, copy_of_instruction); break; case O_constant: insn = v850_insert_operand (insn, operand, ex.X_add_number, - (char *) NULL, 0, - copy_of_instruction); + NULL, 0, copy_of_instruction); break; default: @@ -2239,14 +2155,12 @@ md_assemble (str) then it is done here. */ arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc = xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; @@ -2267,7 +2181,7 @@ tc_gen_reloc (seg, fixp) reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); - if (reloc->howto == (reloc_howto_type *) NULL) + if (reloc->howto == NULL) { as_bad_where (fixp->fx_file, fixp->fx_line, /* xgettext:c-format */ @@ -2283,8 +2197,7 @@ tc_gen_reloc (seg, fixp) } void -v850_handle_align (frag) - fragS * frag; +v850_handle_align (fragS * frag) { if (v850_relax && frag->fr_type == rs_align @@ -2301,9 +2214,7 @@ v850_handle_align (frag) /* Return current size of variable part of frag. */ int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp; - asection *seg ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragp, asection *seg ATTRIBUTE_UNUSED) { if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) abort (); @@ -2312,9 +2223,7 @@ md_estimate_size_before_relax (fragp, seg) } long -v850_pcrel_from_section (fixp, section) - fixS *fixp; - segT section; +v850_pcrel_from_section (fixS *fixp, segT section) { /* If the symbol is undefined, or in a section other than our own, or it is weak (in which case it may well be in another section, @@ -2329,10 +2238,7 @@ v850_pcrel_from_section (fixp, section) } void -md_apply_fix3 (fixP, valueP, seg) - fixS *fixP; - valueT *valueP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED) { valueT value = * valueP; char *where; @@ -2361,11 +2267,9 @@ md_apply_fix3 (fixP, valueP, seg) if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section) value -= S_GET_VALUE (fixP->fx_subsy); else - { - /* We don't actually support subtracting a symbol. */ - as_bad_where (fixP->fx_file, fixP->fx_line, - _("expression too complex")); - } + /* We don't actually support subtracting a symbol. */ + as_bad_where (fixP->fx_file, fixP->fx_line, + _("expression too complex")); } fixP->fx_addnumber = value; } @@ -2432,8 +2336,7 @@ md_apply_fix3 (fixP, valueP, seg) on the v850. */ void -parse_cons_expression_v850 (exp) - expressionS *exp; +parse_cons_expression_v850 (expressionS *exp) { /* See if there's a reloc prefix like hi() we have to handle. */ hold_cons_reloc = v850_reloc_prefix (NULL); @@ -2447,11 +2350,10 @@ parse_cons_expression_v850 (exp) appropriate one based on the size of the expression. */ void -cons_fix_new_v850 (frag, where, size, exp) - fragS *frag; - int where; - int size; - expressionS *exp; +cons_fix_new_v850 (fragS *frag, + int where, + int size, + expressionS *exp) { if (hold_cons_reloc == BFD_RELOC_UNUSED) { @@ -2472,8 +2374,7 @@ cons_fix_new_v850 (frag, where, size, exp) } bfd_boolean -v850_fix_adjustable (fixP) - fixS *fixP; +v850_fix_adjustable (fixS *fixP) { if (fixP->fx_addsy == NULL) return 1; @@ -2491,8 +2392,7 @@ v850_fix_adjustable (fixP) } int -v850_force_relocation (fixP) - struct fix *fixP; +v850_force_relocation (struct fix *fixP) { if (fixP->fx_r_type == BFD_RELOC_V850_LONGCALL || fixP->fx_r_type == BFD_RELOC_V850_LONGJUMP) diff --git a/gas/config/tc-v850.h b/gas/config/tc-v850.h index 76b566ae801..98431a7216f 100644 --- a/gas/config/tc-v850.h +++ b/gas/config/tc-v850.h @@ -1,5 +1,5 @@ /* tc-v850.h -- Header file for tc-v850.c. - Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003 + Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -38,10 +38,10 @@ #define md_operand(x) #define tc_fix_adjustable(FIX) v850_fix_adjustable (FIX) -extern bfd_boolean v850_fix_adjustable PARAMS ((struct fix *)); +extern bfd_boolean v850_fix_adjustable (struct fix *); #define TC_FORCE_RELOCATION(FIX) v850_force_relocation(FIX) -extern int v850_force_relocation PARAMS ((struct fix *)); +extern int v850_force_relocation (struct fix *); #ifdef OBJ_ELF /* Values passed to md_apply_fix3 don't include the symbol value. */ @@ -61,10 +61,10 @@ extern int v850_force_relocation PARAMS ((struct fix *)); /* We need to handle lo(), hi(), etc etc in .hword, .word, etc directives, so we have to parse "cons" expressions ourselves. */ #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_cons_expression_v850 (EXP) -extern void parse_cons_expression_v850 PARAMS ((expressionS *)); +extern void parse_cons_expression_v850 (expressionS *); #define TC_CONS_FIX_NEW cons_fix_new_v850 -extern void cons_fix_new_v850 PARAMS ((fragS *, int, int, expressionS *)); +extern void cons_fix_new_v850 (fragS *, int, int, expressionS *); #define TC_GENERIC_RELAX_TABLE md_relax_table extern const struct relax_type md_relax_table[]; @@ -72,9 +72,9 @@ extern const struct relax_type md_relax_table[]; /* When relaxing, we need to generate relocations for alignment directives. */ #define HANDLE_ALIGN(frag) v850_handle_align (frag) -extern void v850_handle_align PARAMS ((fragS *)); +extern void v850_handle_align (fragS *); #define MD_PCREL_FROM_SECTION(FIX, SEC) v850_pcrel_from_section (FIX, SEC) -extern long v850_pcrel_from_section PARAMS ((struct fix *, asection *)); +extern long v850_pcrel_from_section (struct fix *, asection *); #define DWARF2_LINE_MIN_INSN_LENGTH 2 diff --git a/gas/config/tc-w65.c b/gas/config/tc-w65.c index f290354cd3a..3ff51a59182 100644 --- a/gas/config/tc-w65.c +++ b/gas/config/tc-w65.c @@ -28,16 +28,16 @@ #define DEFINE_TABLE #include "../opcodes/w65-opc.h" -const char comment_chars[] = "!"; +const char comment_chars[] = "!"; const char line_separator_chars[] = ";"; -const char line_comment_chars[] = "!#"; +const char line_comment_chars[] = "!#"; /* This table describes all the machine specific pseudo-ops the assembler has to support. The fields are: pseudo-op name without dot function to call to execute this pseudo-op - Integer arg to pass to the function */ + Integer arg to pass to the function. */ #define OP_BCC 0x90 #define OP_BCS 0xB0 @@ -50,14 +50,37 @@ const char line_comment_chars[] = "!#"; #define OP_BVC 0x50 #define OP_BVS 0x70 -static void s_longa PARAMS ((int)); -static char *parse_exp PARAMS ((char *)); -static char *get_operands PARAMS ((const struct opinfo *, char *)); -static const struct opinfo *get_specific PARAMS ((const struct opinfo *)); -static void build_Mytes PARAMS ((const struct opinfo *)); +static int M; /* M flag. */ +static int X; /* X flag. */ +/* This function is called once, at assembler startup time. This + should set up all the tables, etc that the MD part of the assembler + needs. */ + +static void +s_longa (int xmode) +{ + int *p = xmode ? &X : &M; + + while (*input_line_pointer == ' ') + input_line_pointer++; + if (strncmp (input_line_pointer, "on", 2) == 0) + { + input_line_pointer += 2; + *p = 0; + } + else if (strncmp (input_line_pointer, "off", 3) == 0) + { + *p = 1; + input_line_pointer += 3; + } + else + as_bad (_("need on or off.")); + demand_empty_rest_of_line (); +} -const pseudo_typeS md_pseudo_table[] = { +const pseudo_typeS md_pseudo_table[] = +{ {"int", cons, 2}, {"word", cons, 2}, {"longa", s_longa, 0}, @@ -75,29 +98,26 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; /* Opcode mnemonics */ static struct hash_control *opcode_hash_control; -int M; /* M flag */ -int X; /* X flag */ +#define C(a, b) ENCODE_RELAX(a,b) +#define ENCODE_RELAX(what, length) (((what) << 2) + (length)) -#define C(a,b) ENCODE_RELAX(a,b) -#define ENCODE_RELAX(what,length) (((what) << 2) + (length)) +#define GET_WHAT(x) (((x) >> 2)) -#define GET_WHAT(x) ((x>>2)) - -#define BYTE_DISP 1 -#define WORD_DISP 2 +#define BYTE_DISP 1 +#define WORD_DISP 2 #define UNDEF_BYTE_DISP 0 #define UNDEF_WORD_DISP 3 - #define COND_BRANCH 1 #define UNCOND_BRANCH 2 -#define END 3 +#define END 3 -#define BYTE_F 127 /* How far we can branch forwards */ -#define BYTE_B -126 /* How far we can branch backwards */ +#define BYTE_F 127 /* How far we can branch forwards. */ +#define BYTE_B -126 /* How far we can branch backwards. */ #define WORD_F 32767 #define WORD_B 32768 -relax_typeS md_relax_table[C (END, 0)] = { +relax_typeS md_relax_table[C (END, 0)] = +{ { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, @@ -114,37 +134,10 @@ relax_typeS md_relax_table[C (END, 0)] = { { BYTE_F, BYTE_B, 2, C (UNCOND_BRANCH, WORD_DISP) }, /* BYTE_DISP */ { WORD_F, WORD_B, 3, 0 }, /* WORD_DISP */ { 0, 0, 3, 0 } /* UNDEF_WORD_DISP */ - }; -/* This function is called once, at assembler startup time. This - should set up all the tables, etc that the MD part of the assembler - needs. */ - -static void -s_longa (xmode) - int xmode; -{ - int *p = xmode ? &X : &M; - while (*input_line_pointer == ' ') - input_line_pointer++; - if (strncmp (input_line_pointer, "on", 2) == 0) - { - input_line_pointer += 2; - *p = 0; - } - else if (strncmp (input_line_pointer, "off", 3) == 0) - { - *p = 1; - input_line_pointer += 3; - } - else - as_bad (_("need on or off.")); - demand_empty_rest_of_line (); -} - void -md_begin () +md_begin (void) { const struct opinfo *opcode; char *prev_name = ""; @@ -164,15 +157,14 @@ md_begin () flag_signed_overflow_ok = 1; } -static expressionS immediate; /* absolute expression */ -static expressionS immediate1; /* absolute expression */ +static expressionS immediate; /* Absolute expression. */ +static expressionS immediate1; /* Absolute expression. */ int expr_size; int expr_shift; int tc_cons_reloc; void -w65_expression (dest) - expressionS *dest; +w65_expression (expressionS *dest) { expr_size = 0; expr_shift = 0; @@ -202,8 +194,7 @@ w65_expression (dest) int amode; static char * -parse_exp (s) - char *s; +parse_exp (char *s) { char *save; char *new; @@ -219,12 +210,10 @@ parse_exp (s) } static char * -get_operands (info, ptr) - const struct opinfo *info; - char *ptr; +get_operands (const struct opinfo *info, char *ptr) { - register int override_len = 0; - register int bytes = 0; + int override_len = 0; + int bytes = 0; while (*ptr == ' ') ptr++; @@ -274,9 +263,7 @@ get_operands (info, ptr) ptr += 2; } else - { - as_bad (_("syntax error after code; for (; opcode->code == ocode; opcode++) - { - if (opcode->amode == amode) - return opcode; - } + if (opcode->amode == amode) + return opcode; + return 0; } /* Now we know what sort of opcodes it is, let's build the bytes. */ static void -build_Mytes (opcode) - const struct opinfo *opcode; +build_Mytes (const struct opinfo *opcode) { int size; int type; @@ -591,9 +570,8 @@ build_Mytes (opcode) char *output; if (opcode->amode == ADDR_IMPLIED) - { - output = frag_more (1); - } + output = frag_more (1); + else if (opcode->amode == ADDR_PC_REL) { int type; @@ -663,8 +641,7 @@ build_Mytes (opcode) the frags/bytes it assembles to. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { const struct opinfo *opcode; char name[20]; @@ -673,7 +650,7 @@ md_assemble (str) while (*str == ' ') str++; - /* all opcodes are three letters */ + /* All opcodes are three letters. */ name[0] = str[0]; name[1] = str[1]; name[2] = str[2]; @@ -712,8 +689,7 @@ md_assemble (str) } symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -728,10 +704,7 @@ md_undefined_symbol (name) returned, or NULL on OK. */ char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; +md_atof (int type, char *litP, int *sizeP) { int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; @@ -782,9 +755,7 @@ md_atof (type, litP, sizeP) } int -md_parse_option (c, a) - int c ATTRIBUTE_UNUSED; - char *a ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, char *a ATTRIBUTE_UNUSED) { return 0; } @@ -793,10 +764,9 @@ md_parse_option (c, a) are. */ void -md_convert_frag (headers, seg, fragP) - object_headers *headers ATTRIBUTE_UNUSED; - segT seg ATTRIBUTE_UNUSED; - fragS *fragP; +md_convert_frag (object_headers *headers ATTRIBUTE_UNUSED, + segT seg ATTRIBUTE_UNUSED, + fragS *fragP) { int disp_size = 0; int inst_size = 0; @@ -823,9 +793,9 @@ md_convert_frag (headers, seg, fragP) case OP_BPL: case OP_BVS: case OP_BVC: - /* Invert the sense of the test */ + /* Invert the sense of the test. */ buffer[0] ^= 0x20; - buffer[1] = 3; /* Jump over following brl */ + buffer[1] = 3; /* Jump over following brl. */ buffer[2] = OP_BRL; buffer[3] = 0; buffer[4] = 0; @@ -852,7 +822,7 @@ md_convert_frag (headers, seg, fragP) break; /* Got to create a branch over a reloc here. */ case C (COND_BRANCH, UNDEF_WORD_DISP): - buffer[0] ^= 0x20; /* invert test */ + buffer[0] ^= 0x20; /* Invert test. */ buffer[1] = 3; buffer[2] = OP_BRL; buffer[3] = 0; @@ -902,19 +872,14 @@ md_convert_frag (headers, seg, fragP) } valueT -md_section_align (seg, size) - segT seg; - valueT size; +md_section_align (segT seg, valueT size) { return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); } void -md_apply_fix3 (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix3 (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED) { long val = * (long *) valP; char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; @@ -973,40 +938,33 @@ md_apply_fix3 (fixP, valP, seg) /* Put number into target byte order. */ void -md_number_to_chars (ptr, use, nbytes) - char *ptr; - valueT use; - int nbytes; +md_number_to_chars (char *ptr, valueT use, int nbytes) { number_to_chars_littleendian (ptr, use, nbytes); } long -md_pcrel_from (fixP) - fixS *fixP; +md_pcrel_from (fixS *fixP) { int gap = fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address - 1; return gap; } void -tc_coff_symbol_emit_hook (x) - symbolS *x ATTRIBUTE_UNUSED; +tc_coff_symbol_emit_hook (symbolS *x ATTRIBUTE_UNUSED) { } short -tc_coff_fix2rtype (fix_ptr) - fixS *fix_ptr; +tc_coff_fix2rtype (fixS *fix_ptr) { return fix_ptr->fx_r_type; } void -tc_reloc_mangle (fix_ptr, intr, base) - fixS *fix_ptr; - struct internal_reloc *intr; - bfd_vma base; +tc_reloc_mangle (fixS *fix_ptr, + struct internal_reloc *intr, + bfd_vma base) { symbolS *symbol_ptr; @@ -1017,8 +975,7 @@ tc_reloc_mangle (fix_ptr, intr, base) to output it */ if (fix_ptr->fx_r_type == RELOC_32) { - /* cons likes to create reloc32's whatever the size of the reloc.. - */ + /* Cons likes to create reloc32's whatever the size of the reloc. */ switch (fix_ptr->fx_size) { case 2: @@ -1054,19 +1011,14 @@ tc_reloc_mangle (fix_ptr, intr, base) intr->r_symndx = dot->sy_number; } else - { - intr->r_symndx = symbol_ptr->sy_number; - } + intr->r_symndx = symbol_ptr->sy_number; } else - { - intr->r_symndx = -1; - } + intr->r_symndx = -1; } int -tc_coff_sizemachdep (frag) - fragS *frag; +tc_coff_sizemachdep (fragS *frag) { return md_relax_table[frag->fr_subtype].rlx_length; } @@ -1075,9 +1027,7 @@ tc_coff_sizemachdep (frag) fragment must grow to reach it's destination. */ int -md_estimate_size_before_relax (fragP, segment_type) - register fragS *fragP; - register segT segment_type; +md_estimate_size_before_relax (fragS *fragP, segT segment_type) { int what; @@ -1091,17 +1041,13 @@ md_estimate_size_before_relax (fragP, segment_type) what = GET_WHAT (fragP->fr_subtype); /* Used to be a branch to somewhere which was unknown. */ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) - { - /* Got a symbol and it's defined in this segment, become byte - sized - maybe it will fix up. */ - fragP->fr_subtype = C (what, BYTE_DISP); - } + /* Got a symbol and it's defined in this segment, become byte + sized - maybe it will fix up. */ + fragP->fr_subtype = C (what, BYTE_DISP); else - { - /* Its got a segment, but its not ours, so it will always be - long. */ - fragP->fr_subtype = C (what, UNDEF_WORD_DISP); - } + /* Its got a segment, but its not ours, so it will always be + long. */ + fragP->fr_subtype = C (what, UNDEF_WORD_DISP); break; case C (COND_BRANCH, BYTE_DISP): @@ -1120,14 +1066,14 @@ md_estimate_size_before_relax (fragP, segment_type) } const char *md_shortopts = ""; -struct option md_longopts[] = { +struct option md_longopts[] = +{ #define OPTION_RELAX (OPTION_MD_BASE) {NULL, no_argument, NULL, 0} }; void -md_show_usage (stream) - FILE *stream ATTRIBUTE_UNUSED; +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) { } diff --git a/gas/config/tc-w65.h b/gas/config/tc-w65.h index 91bf12843b1..dadd07d9ed3 100644 --- a/gas/config/tc-w65.h +++ b/gas/config/tc-w65.h @@ -1,5 +1,5 @@ /* This file is tc-w65.h - Copyright 1995, 1997, 1998, 2000, 2001, 2002 + Copyright 1995, 1997, 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -39,8 +39,7 @@ struct fix; #define IGNORE_NONSTANDARD_ESCAPES #define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle (a,b,c) -extern void tc_reloc_mangle - PARAMS ((struct fix *, struct internal_reloc *, bfd_vma)); +extern void tc_reloc_mangle (struct fix *, struct internal_reloc *, bfd_vma); #define DO_NOT_STRIP 0 #define LISTING_HEADER "W65816 GAS " @@ -48,10 +47,10 @@ extern void tc_reloc_mangle #define RELOC_32 1234 #define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep (frag) -int tc_coff_sizemachdep PARAMS ((fragS *)); +int tc_coff_sizemachdep (fragS *); #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) w65_expression (EXP) -void w65_expression PARAMS ((expressionS *)); +void w65_expression (expressionS *); #define TC_COUNT_RELOC(x) (1) #define TC_CONS_RELOC tc_cons_reloc diff --git a/gas/config/tc-xstormy16.c b/gas/config/tc-xstormy16.c index e27c7a74a96..d73633805c7 100644 --- a/gas/config/tc-xstormy16.c +++ b/gas/config/tc-xstormy16.c @@ -66,16 +66,14 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (c, arg) - int c ATTRIBUTE_UNUSED; - char * arg ATTRIBUTE_UNUSED; +md_parse_option (int c ATTRIBUTE_UNUSED, + char * arg ATTRIBUTE_UNUSED) { return 0; } void -md_show_usage (stream) - FILE * stream; +md_show_usage (FILE * stream) { fprintf (stream, _(" XSTORMY16 specific command line options:\n")); } @@ -89,7 +87,7 @@ const pseudo_typeS md_pseudo_table[] = void -md_begin () +md_begin (void) { /* Initialize the `cgen' interface. */ @@ -107,8 +105,7 @@ md_begin () static bfd_boolean skipping_fptr = FALSE; void -md_assemble (str) - char * str; +md_assemble (char * str) { xstormy16_insn insn; char * errmsg; @@ -135,8 +132,7 @@ md_assemble (str) } void -md_operand (e) - expressionS * e; +md_operand (expressionS * e) { if (*input_line_pointer != '@') return; @@ -195,11 +191,10 @@ md_operand (e) Create BFD_RELOC_XSTORMY16_FPTR16 relocations. */ void -xstormy16_cons_fix_new (f, where, nbytes, exp) - fragS *f; - int where; - int nbytes; - expressionS *exp; +xstormy16_cons_fix_new (fragS *f, + int where, + int nbytes, + expressionS *exp) { bfd_reloc_code_real_type code; fixS *fix; @@ -221,10 +216,12 @@ xstormy16_cons_fix_new (f, where, nbytes, exp) exp->X_op = O_symbol; code = BFD_RELOC_32; break; + case 2: exp->X_op = O_symbol; code = BFD_RELOC_XSTORMY16_FPTR16; break; + default: as_bad ("unsupported fptr fixup size %d", nbytes); return; @@ -249,14 +246,13 @@ xstormy16_cons_fix_new (f, where, nbytes, exp) Create BFD_RELOC_XSTORMY16_FPTR16 relocations. */ fixS * -xstormy16_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) - fragS * frag; - int where; - const CGEN_INSN * insn; - int length; - const CGEN_OPERAND * operand; - int opinfo; - expressionS * exp; +xstormy16_cgen_record_fixup_exp (fragS * frag, + int where, + const CGEN_INSN * insn, + int length, + const CGEN_OPERAND * operand, + int opinfo, + expressionS * exp) { fixS *fixP; operatorT op = exp->X_op; @@ -282,17 +278,15 @@ xstormy16_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp } valueT -md_section_align (segment, size) - segT segment; - valueT size; +md_section_align (segT segment, valueT size) { int align = bfd_get_section_alignment (stdoutput, segment); + return ((size + (1 << align) - 1) & (-1 << align)); } symbolS * -md_undefined_symbol (name) - char * name ATTRIBUTE_UNUSED; +md_undefined_symbol (char * name ATTRIBUTE_UNUSED) { return 0; } @@ -309,9 +303,8 @@ md_undefined_symbol (name) 0 value. */ int -md_estimate_size_before_relax (fragP, segment) - fragS * fragP ATTRIBUTE_UNUSED; - segT segment ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, + segT segment ATTRIBUTE_UNUSED) { /* No assembler relaxation is defined (or necessary) for this port. */ abort (); @@ -325,10 +318,9 @@ md_estimate_size_before_relax (fragP, segment) fragP->fr_subtype is the subtype of what the address relaxed to. */ void -md_convert_frag (abfd, sec, fragP) - bfd * abfd ATTRIBUTE_UNUSED; - segT sec ATTRIBUTE_UNUSED; - fragS * fragP ATTRIBUTE_UNUSED; +md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS * fragP ATTRIBUTE_UNUSED) { /* No assembler relaxation is defined (or necessary) for this port. */ abort (); @@ -340,9 +332,7 @@ md_convert_frag (abfd, sec, fragP) given a PC relative reloc. */ long -md_pcrel_from_section (fixP, sec) - fixS * fixP; - segT sec; +md_pcrel_from_section (fixS * fixP, segT sec) { if ((fixP->fx_addsy != (symbolS *) NULL && (! S_IS_DEFINED (fixP->fx_addsy) @@ -362,10 +352,9 @@ md_pcrel_from_section (fixP, sec) *FIXP may be modified if desired. */ bfd_reloc_code_real_type -md_cgen_lookup_reloc (insn, operand, fixP) - const CGEN_INSN * insn ATTRIBUTE_UNUSED; - const CGEN_OPERAND * operand; - fixS * fixP; +md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED, + const CGEN_OPERAND * operand, + fixS * fixP) { switch (operand->type) { @@ -419,8 +408,7 @@ md_cgen_lookup_reloc (insn, operand, fixP) relaxing. */ int -xstormy16_force_relocation (fix) - fixS * fix; +xstormy16_force_relocation (fixS * fix) { if (fix->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16) return 1; @@ -432,28 +420,26 @@ xstormy16_force_relocation (fix) a relocation against section+offset. */ bfd_boolean -xstormy16_fix_adjustable (fixP) - fixS * fixP; +xstormy16_fix_adjustable (fixS * fixP) { /* We need the symbol name for the VTABLE entries. */ if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) - return 0; + return FALSE; if (fixP->fx_r_type == BFD_RELOC_XSTORMY16_FPTR16) - return 0; + return FALSE; - return 1; + return TRUE; } /* This is a copy of gas_cgen_md_apply_fix3, with some enhancements to do various things that would not be valid for all ports. */ void -xstormy16_md_apply_fix3 (fixP, valueP, seg) - fixS * fixP; - valueT * valueP; - segT seg ATTRIBUTE_UNUSED; +xstormy16_md_apply_fix3 (fixS * fixP, + valueT * valueP, + segT seg ATTRIBUTE_UNUSED) { char *where = fixP->fx_frag->fr_literal + fixP->fx_where; valueT value = *valueP; @@ -470,8 +456,7 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg) it must deal with turning a BFD_RELOC_{8,16,32,64} into a BFD_RELOC_*_PCREL for the case of - .word something-. - */ + .word something-. */ if (fixP->fx_pcrel) switch (fixP->fx_r_type) { @@ -546,9 +531,7 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg) reloc_type = md_cgen_lookup_reloc (insn, operand, fixP); if (reloc_type != BFD_RELOC_NONE) - { - fixP->fx_r_type = reloc_type; - } + fixP->fx_r_type = reloc_type; else { as_bad_where (fixP->fx_file, fixP->fx_line, @@ -608,10 +591,7 @@ xstormy16_md_apply_fix3 (fixP, valueP, seg) /* Write a value out to the object file, using the appropriate endianness. */ void -md_number_to_chars (buf, val, n) - char * buf; - valueT val; - int n; +md_number_to_chars (char * buf, valueT val, int n) { number_to_chars_littleendian (buf, val, n); } @@ -625,10 +605,7 @@ md_number_to_chars (buf, val, n) #define MAX_LITTLENUMS 6 char * -md_atof (type, litP, sizeP) - char type; - char * litP; - int * sizeP; +md_atof (int type, char * litP, int * sizeP) { int prec; LITTLENUM_TYPE words [MAX_LITTLENUMS]; diff --git a/gas/config/tc-xstormy16.h b/gas/config/tc-xstormy16.h index cd0ebb96dc6..d19aaf707ca 100644 --- a/gas/config/tc-xstormy16.h +++ b/gas/config/tc-xstormy16.h @@ -1,5 +1,5 @@ /* tc-xstormy16.h -- Header file for tc-xstormy16.c. - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -21,7 +21,7 @@ #define TC_XSTORMY16 #ifndef BFD_ASSEMBLER -/* leading space so will compile with cc */ +/* Leading space so will compile with cc. */ #error XSTORMY16 support requires BFD_ASSEMBLER #endif @@ -37,7 +37,7 @@ /* Permit temporary numeric labels. */ #define LOCAL_LABELS_FB 1 -#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ +#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs. */ /* We don't need to handle .word strangely. */ #define WORKING_DOT_WORD @@ -48,10 +48,10 @@ #define md_apply_fix3 xstormy16_md_apply_fix3 #define tc_fix_adjustable(FIX) xstormy16_fix_adjustable (FIX) -extern bfd_boolean xstormy16_fix_adjustable PARAMS ((struct fix *)); +extern bfd_boolean xstormy16_fix_adjustable (struct fix *); #define TC_FORCE_RELOCATION(fix) xstormy16_force_relocation (fix) -extern int xstormy16_force_relocation PARAMS ((struct fix *)); +extern int xstormy16_force_relocation (struct fix *); #define TC_HANDLES_FX_DONE @@ -59,10 +59,10 @@ extern int xstormy16_force_relocation PARAMS ((struct fix *)); /* Call md_pcrel_from_section(), not md_pcrel_from(). */ #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC) -extern long md_pcrel_from_section PARAMS ((struct fix *, segT)); +extern long md_pcrel_from_section (struct fix *, segT); #define TC_CONS_FIX_NEW xstormy16_cons_fix_new -extern void xstormy16_cons_fix_new PARAMS ((fragS *f, int, int, expressionS *)); +extern void xstormy16_cons_fix_new (fragS *f, int, int, expressionS *); #define md_cgen_record_fixup_exp xstormy16_cgen_record_fixup_exp diff --git a/gas/write.h b/gas/write.h index cf593bc6786..2e5ff57b48b 100644 --- a/gas/write.h +++ b/gas/write.h @@ -182,9 +182,6 @@ COMMON fixS **seg_fix_rootP, **seg_fix_tailP; /* -> one of above. */ extern long string_byte_count; extern int section_alignment[]; -extern bit_fixS *bit_fix_new - (int size, int offset, long base_type, long base_adj, long min, - long max, long add); extern void append (char **charPP, char *fromP, unsigned long length); extern void record_alignment (segT seg, int align); extern int get_recorded_alignment (segT seg); -- 2.30.2