diff options
Diffstat (limited to 'contrib/binutils/gas/config')
50 files changed, 0 insertions, 32800 deletions
diff --git a/contrib/binutils/gas/config/aout_gnu.h b/contrib/binutils/gas/config/aout_gnu.h deleted file mode 100644 index badf9cb21c73..000000000000 --- a/contrib/binutils/gas/config/aout_gnu.h +++ /dev/null @@ -1,455 +0,0 @@ -/* This file is aout_gnu.h - - Copyright (C) 1987-1992 Free Software Foundation, Inc. - - 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 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. */ - -#ifndef __A_OUT_GNU_H__ -#define __A_OUT_GNU_H__ - -/* There are two main flavours of a.out, one which uses the standard - relocations, and one which uses extended relocations. - - Today, the extended reloc uses are - TC_SPARC, TC_A29K - - each must define the enum reloc_type - -*/ - -#define USE_EXTENDED_RELOC (defined(TC_SPARC) || defined(TC_A29K)) - -#if defined(TC_SPARC) || defined(TC_A29K) -enum reloc_type - { - RELOC_8, RELOC_16, RELOC_32,/* simple relocations */ - RELOC_DISP8, RELOC_DISP16, RELOC_DISP32, /* pc-rel displacement */ - RELOC_WDISP30, RELOC_WDISP22, - RELOC_HI22, RELOC_22, - RELOC_13, RELOC_LO10, - RELOC_SFA_BASE, RELOC_SFA_OFF13, - RELOC_BASE10, RELOC_BASE13, RELOC_BASE22, /* P.I.C. (base-relative) */ - RELOC_PC10, RELOC_PC22, /* for some sort of pc-rel P.I.C. (?) */ - RELOC_JMP_TBL, /* P.I.C. jump table */ - RELOC_SEGOFF16, /* reputedly for shared libraries somehow */ - RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE, - RELOC_10, RELOC_11, - RELOC_WDISP2_14, - RELOC_WDISP19, - RELOC_HHI22, - RELOC_HLO10, - - /* 29K relocation types */ - RELOC_JUMPTARG, RELOC_CONST, RELOC_CONSTH, - - RELOC_WDISP14, RELOC_WDISP21, - - NO_RELOC - }; - -#endif /* TC_SPARC or TC_A29K */ - - -#define __GNU_EXEC_MACROS__ - -#ifndef __STRUCT_EXEC_OVERRIDE__ - -/* This is the layout on disk of a Unix V7, Berkeley, SunOS, Vax Ultrix - "struct exec". Don't assume that on this machine, the "struct exec" - will lay out the same sizes or alignments. */ - -struct exec_bytes - { - unsigned char a_info[4]; - unsigned char a_text[4]; - unsigned char a_data[4]; - unsigned char a_bss[4]; - unsigned char a_syms[4]; - unsigned char a_entry[4]; - unsigned char a_trsize[4]; - unsigned char a_drsize[4]; - }; - -/* How big the "struct exec" is on disk */ -#define EXEC_BYTES_SIZE (8 * 4) - -/* This is the layout in memory of a "struct exec" while we process it. */ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#endif /* __STRUCT_EXEC_OVERRIDE__ */ - -/* these go in the N_MACHTYPE field */ -/* These symbols could be defined by code from Suns...punt 'em */ -#undef M_UNKNOWN -#undef M_68010 -#undef M_68020 -#undef M_SPARC -enum machine_type - { - M_UNKNOWN = 0, - M_68010 = 1, - M_68020 = 2, - M_SPARC = 3, - /* skip a bunch so we don't run into any of sun's numbers */ - M_386 = 100, - M_29K = 101, - M_RS6000 = 102, /* IBM RS/6000 */ - /* HP/BSD formats */ - M_HP200 = 200, /* hp200 (68010) BSD binary */ - M_HP300 = 300, /* hp300 (68020+68881) BSD binary */ - M_HPUX23 = 0x020C /* hp200/300 HPUX binary */ - }; - -#define N_MAGIC(exec) ((exec).a_info & 0xffff) -#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) -#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) -#define N_SET_INFO(exec, magic, type, flags) \ - ((exec).a_info = ((magic) & 0xffff) \ - | (((int)(type) & 0xff) << 16) \ - | (((flags) & 0xff) << 24)) -#define N_SET_MAGIC(exec, magic) \ - ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) - -#define N_SET_MACHTYPE(exec, machtype) \ - ((exec).a_info = \ - ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16)) - -#define N_SET_FLAGS(exec, flags) \ - ((exec).a_info = \ - ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24)) - -/* Code indicating object file or impure executable. */ -#ifndef OMAGIC -#define OMAGIC 0407 -#endif -/* Code indicating pure executable. */ -#define NMAGIC 0410 -/* Code indicating demand-paged executable. */ -#define ZMAGIC 0413 - -/* Virtual Address of text segment from the a.out file. For OMAGIC, - (almost always "unlinked .o's" these days), should be zero. - For linked files, should reflect reality if we know it. */ - -#ifndef N_TXTADDR -#define N_TXTADDR(x) (N_MAGIC(x)==OMAGIC? 0 : TEXT_START_ADDR) -#endif - -#ifndef N_BADMAG -#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ - && N_MAGIC(x) != NMAGIC \ - && N_MAGIC(x) != ZMAGIC) -#endif - -/* By default, segment size is constant. But on some machines, it can - be a function of the a.out header (e.g. machine type). */ -#ifndef N_SEGSIZE -#define N_SEGSIZE(x) SEGMENT_SIZE -#endif - -/* This complexity is for encapsulated COFF support */ -#ifndef _N_HDROFF -#define _N_HDROFF(x) (N_SEGSIZE(x) - sizeof (struct exec)) -#endif - -#ifndef N_TXTOFF -#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? \ - _N_HDROFF((x)) + sizeof (struct exec) : \ - sizeof (struct exec)) -#endif - - -#ifndef N_DATOFF -#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) -#endif - -#ifndef N_TRELOFF -#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data ) -#endif - -#ifndef N_DRELOFF -#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize ) -#endif - -#ifndef N_SYMOFF -#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize ) -#endif - -#ifndef N_STROFF -#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) -#endif - -/* Address of text segment in memory after it is loaded. */ -#ifndef N_TXTADDR -#define N_TXTADDR(x) 0 -#endif - -#ifndef N_DATADDR -#define N_DATADDR(x) \ - (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) \ - : (N_SEGSIZE(x) + ((N_TXTADDR(x)+(x).a_text-1) & ~(N_SEGSIZE(x)-1)))) -#endif - -/* Address of bss segment in memory after it is loaded. */ -#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) - -struct nlist - { - union - { - char *n_name; - struct nlist *n_next; - long n_strx; - } - n_un; - unsigned char n_type; - char n_other; - short n_desc; - unsigned long n_value; - }; - -#define N_UNDF 0 -#define N_ABS 2 -#define N_TEXT 4 -#define N_DATA 6 -#define N_BSS 8 -#define N_COMM 0x12 /* common (visible in shared lib commons) */ -#define N_FN 0x1F /* File name of a .o file */ - -/* Note: N_EXT can only usefully be OR-ed with N_UNDF, N_ABS, N_TEXT, - N_DATA, or N_BSS. When the low-order bit of other types is set, - (e.g. N_WARNING versus N_FN), they are two different types. */ -#define N_EXT 1 -#define N_TYPE 036 -#define N_STAB 0340 - -/* The following type indicates the definition of a symbol as being - an indirect reference to another symbol. The other symbol - appears as an undefined reference, immediately following this symbol. - - Indirection is asymmetrical. The other symbol's value will be used - to satisfy requests for the indirect symbol, but not vice versa. - If the other symbol does not have a definition, libraries will - be searched to find a definition. */ - -#define N_INDR 0xa - -/* The following symbols refer to set elements. - All the N_SET[ATDB] symbols with the same name form one set. - Space is allocated for the set in the text section, and each set - element's value is stored into one word of the space. - The first word of the space is the length of the set (number of elements). - - The address of the set is made into an N_SETV symbol - whose name is the same as the name of the set. - This symbol acts like a N_DATA global symbol - in that it can satisfy undefined external references. */ - -/* These appear as input to LD, in a .o file. */ -#define N_SETA 0x14 /* Absolute set element symbol */ -#define N_SETT 0x16 /* Text set element symbol */ -#define N_SETD 0x18 /* Data set element symbol */ -#define N_SETB 0x1A /* Bss set element symbol */ - -/* This is output from LD. */ -#define N_SETV 0x1C /* Pointer to set vector in data area. */ - -/* Warning symbol. The text gives a warning message, the next symbol - in the table will be undefined. When the symbol is referenced, the - message is printed. */ - -#define N_WARNING 0x1e - -/* Weak symbols. These are a GNU extension to the a.out format. The - semantics are those of ELF weak symbols. Weak symbols are always - externally visible. The N_WEAK? values are squeezed into the - available slots. The value of a N_WEAKU symbol is 0. The values - of the other types are the definitions. */ -#define N_WEAKU 0x0d /* Weak undefined symbol. */ -#define N_WEAKA 0x0e /* Weak absolute symbol. */ -#define N_WEAKT 0x0f /* Weak text symbol. */ -#define N_WEAKD 0x10 /* Weak data symbol. */ -#define N_WEAKB 0x11 /* Weak bss symbol. */ - -/* This structure describes a single relocation to be performed. - The text-relocation section of the file is a vector of these structures, - all of which apply to the text section. - Likewise, the data-relocation section applies to the data section. */ - -/* The following enum and struct were borrowed from SunOS's - /usr/include/sun4/a.out.h and extended to handle - other machines. It is currently used on SPARC and AMD 29000. - - reloc_ext_bytes is how it looks on disk. reloc_info_extended is - how we might process it on a native host. */ -#if USE_EXTENDED_RELOC - -struct reloc_ext_bytes - { - unsigned char r_address[4]; - unsigned char r_index[3]; - unsigned char r_bits[1]; - unsigned char r_addend[4]; - }; - - -#define RELOC_EXT_BITS_EXTERN_BIG 0x80 -#define RELOC_EXT_BITS_EXTERN_LITTLE 0x01 - -#define RELOC_EXT_BITS_TYPE_BIG 0x1F -#define RELOC_EXT_BITS_TYPE_SH_BIG 0 -#define RELOC_EXT_BITS_TYPE_LITTLE 0xF8 -#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3 - -#define RELOC_EXT_SIZE 12 /* Bytes per relocation entry */ - -struct reloc_info_extended -{ - unsigned long r_address; - unsigned int r_index:24; -# define r_symbolnum r_index - unsigned r_extern:1; - unsigned:2; - /* RS/6000 compiler does not support enum bitfield - enum reloc_type r_type:5; */ - enum reloc_type r_type; - long int r_addend; -}; - -#else - -/* The standard, old-fashioned, Berkeley compatible relocation struct */ - - - -#ifdef TC_I860 -/* NOTE: three bits max, see struct reloc_info_i860.r_type */ -enum i860_reloc_type - { - NO_RELOC = 0, BRADDR, LOW0, LOW1, LOW2, LOW3, LOW4, SPLIT0, SPLIT1, SPLIT2, RELOC_32, - }; - -typedef enum i860_reloc_type reloc_type; - -/* NOTE: two bits max, see reloc_info_i860.r_type */ -enum highlow_type - { - NO_SPEC = 0, PAIR, HIGH, HIGHADJ, - }; - - -struct reloc_info_i860 -{ - unsigned long r_address; - /* - * Using bit fields here is a bad idea because the order is not portable. :-( - */ - unsigned int r_symbolnum:24; - unsigned int r_pcrel:1; - unsigned int r_extern:1; - /* combining the two field simplifies the argument passing in "new_fix()" */ - /* and is compatible with the existing Sparc #ifdef's */ - /* r_type: highlow_type - bits 5,4; reloc_type - bits 3-0 */ - unsigned int r_type:6; - long r_addend; -}; - -#endif /* TC_I860 */ - - -struct reloc_std_bytes - { - unsigned char r_address[4]; - unsigned char r_index[3]; - unsigned char r_bits[1]; - }; - -#define RELOC_STD_BITS_PCREL_BIG 0x80 -#define RELOC_STD_BITS_PCREL_LITTLE 0x01 - -#define RELOC_STD_BITS_LENGTH_BIG 0x60 -#define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */ -#define RELOC_STD_BITS_LENGTH_LITTLE 0x06 -#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1 - -#define RELOC_STD_BITS_EXTERN_BIG 0x10 -#define RELOC_STD_BITS_EXTERN_LITTLE 0x08 - -#define RELOC_STD_BITS_BASEREL_BIG 0x08 -#define RELOC_STD_BITS_BASEREL_LITTLE 0x08 - -#define RELOC_STD_BITS_JMPTABLE_BIG 0x04 -#define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04 - -#define RELOC_STD_BITS_RELATIVE_BIG 0x02 -#define RELOC_STD_BITS_RELATIVE_LITTLE 0x02 - -#define RELOC_STD_SIZE 8 /* Bytes per relocation entry */ - -#endif /* USE_EXTENDED_RELOC */ - -#ifndef CUSTOM_RELOC_FORMAT -struct relocation_info -{ - /* Address (within segment) to be relocated. */ - int r_address; - /* The meaning of r_symbolnum depends on r_extern. */ - unsigned int r_symbolnum:24; - /* Nonzero means value is a pc-relative offset - and it should be relocated for changes in its own address - as well as for changes in the symbol or section specified. */ - unsigned int r_pcrel:1; - /* Length (as exponent of 2) of the field to be relocated. - Thus, a value of 2 indicates 1<<2 bytes. */ - unsigned int r_length:2; - /* 1 => relocate with value of symbol. - r_symbolnum is the index of the symbol - in file's the symbol table. - 0 => relocate with the address of a segment. - r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS - (the N_EXT bit may be set also, but signifies nothing). */ - unsigned int r_extern:1; - /* The next three bits are for SunOS shared libraries, and seem to - be undocumented. */ -#ifdef TC_NS32K - unsigned int r_bsr:1; - unsigned int r_disp:2; -#else - unsigned int r_baserel:1; /* Linkage table relative */ - unsigned int r_jmptable:1; /* pc-relative to jump table */ - unsigned int r_relative:1; /* "relative relocation" */ -#endif /* TC_NS32K */ - /* unused */ - unsigned int r_pad:1; /* Padding -- set to zero */ -}; - -#endif /* CUSTOM_RELOC_FORMAT */ - -#endif /* __A_OUT_GNU_H__ */ - -/* end of aout_gnu.h */ diff --git a/contrib/binutils/gas/config/atof-ieee.c b/contrib/binutils/gas/config/atof-ieee.c deleted file mode 100644 index 3ac1f01fd83c..000000000000 --- a/contrib/binutils/gas/config/atof-ieee.c +++ /dev/null @@ -1,696 +0,0 @@ -/* atof_ieee.c - turn a Flonum into an IEEE floating point number - Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 1998 - Free Software Foundation, Inc. - - 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 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. */ - -#include "as.h" - -/* 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) - -/* Length in LittleNums of guard bits. */ -#define GUARD (2) - -static const unsigned long 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, - 0xffffffff, -}; - - -static int bits_left_in_littlenum; -static int littlenums_left; -static LITTLENUM_TYPE *littlenum_pointer; - -static int -next_bits (number_of_bits) - int number_of_bits; -{ - int return_value; - - if (!littlenums_left) - return (0); - if (number_of_bits >= bits_left_in_littlenum) - { - return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; - number_of_bits -= bits_left_in_littlenum; - return_value <<= number_of_bits; - - if (--littlenums_left) - { - bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; - --littlenum_pointer; - return_value |= (*littlenum_pointer >> bits_left_in_littlenum) & mask[number_of_bits]; - } - } - else - { - bits_left_in_littlenum -= number_of_bits; - return_value = mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum); - } - return (return_value); -} - -/* Num had better be less than LITTLENUM_NUMBER_OF_BITS */ -static void -unget_bits (num) - int num; -{ - if (!littlenums_left) - { - ++littlenum_pointer; - ++littlenums_left; - bits_left_in_littlenum = num; - } - else if (bits_left_in_littlenum + num > LITTLENUM_NUMBER_OF_BITS) - { - bits_left_in_littlenum = num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum); - ++littlenum_pointer; - ++littlenums_left; - } - else - bits_left_in_littlenum += num; -} - -static void -make_invalid_floating_point_number (words) - LITTLENUM_TYPE *words; -{ - as_bad ("cannot create floating-point number"); - words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1; /* Zero the leftmost bit */ - words[1] = (LITTLENUM_TYPE) -1; - words[2] = (LITTLENUM_TYPE) -1; - words[3] = (LITTLENUM_TYPE) -1; - words[4] = (LITTLENUM_TYPE) -1; - words[5] = (LITTLENUM_TYPE) -1; -} - -/************************************************************************\ - * Warning: this returns 16-bit LITTLENUMs. It is up to the caller * - * to figure out any alignment problems and to conspire for the * - * bytes/word to be emitted in the right order. Bigendians beware! * - * * -\************************************************************************/ - -/* Note that atof-ieee always has X and P precisions enabled. it is up - to md_atof to filter them out if the target machine does not support - them. */ - -/* Returns pointer past text consumed. */ -char * -atof_ieee (str, what_kind, words) - char *str; /* Text to convert to binary. */ - char 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. */ - static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; - char *return_value; - /* Number of 16-bit words in the format. */ - int precision; - long exponent_bits; - FLONUM_TYPE save_gen_flonum; - - /* We have to save the generic_floating_point_number because it - contains storage allocation about the array of LITTLENUMs where - the value is actually stored. We will allocate our own array of - littlenums below, but have to restore the global one on exit. */ - save_gen_flonum = generic_floating_point_number; - - return_value = str; - generic_floating_point_number.low = bits + MAX_PRECISION; - generic_floating_point_number.high = NULL; - generic_floating_point_number.leader = NULL; - generic_floating_point_number.exponent = 0; - generic_floating_point_number.sign = '\0'; - - /* Use more LittleNums than seems necessary: the highest flonum may - have 15 leading 0 bits, so could be useless. */ - - memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); - - switch (what_kind) - { - case 'f': - case 'F': - case 's': - case 'S': - precision = F_PRECISION; - exponent_bits = 8; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - precision = D_PRECISION; - exponent_bits = 11; - break; - - case 'x': - case 'X': - case 'e': - case 'E': - precision = X_PRECISION; - exponent_bits = 15; - break; - - case 'p': - case 'P': - - precision = P_PRECISION; - exponent_bits = -1; - break; - - default: - make_invalid_floating_point_number (words); - return (NULL); - } - - generic_floating_point_number.high - = generic_floating_point_number.low + precision - 1 + GUARD; - - if (atof_generic (&return_value, ".", EXP_CHARS, - &generic_floating_point_number)) - { - make_invalid_floating_point_number (words); - return (NULL); - } - gen_to_words (words, precision, exponent_bits); - - /* Restore the generic_floating_point_number's storage alloc (and - everything else). */ - generic_floating_point_number = save_gen_flonum; - - return return_value; -} - -/* 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; -{ - int return_value = 0; - - long exponent_1; - long exponent_2; - long exponent_3; - long exponent_4; - int exponent_skippage; - LITTLENUM_TYPE word1; - LITTLENUM_TYPE *lp; - LITTLENUM_TYPE *words_end; - - words_end = words + precision; -#ifdef TC_M68K - if (precision == X_PRECISION) - /* On the m68k the extended precision format has a gap of 16 bits - between the exponent and the mantissa. */ - words_end++; -#endif - - if (generic_floating_point_number.low > generic_floating_point_number.leader) - { - /* 0.0e0 seen. */ - if (generic_floating_point_number.sign == '+') - words[0] = 0x0000; - else - words[0] = 0x8000; - memset (&words[1], '\0', - (words_end - words - 1) * sizeof (LITTLENUM_TYPE)); - return (return_value); - } - - /* NaN: Do the right thing */ - if (generic_floating_point_number.sign == 0) - { - if (precision == F_PRECISION) - { - words[0] = 0x7fff; - words[1] = 0xffff; - } - else if (precision == X_PRECISION) - { -#ifdef TC_M68K - words[0] = 0x7fff; - words[1] = 0; - words[2] = 0xffff; - words[3] = 0xffff; - words[4] = 0xffff; - words[5] = 0xffff; -#else /* ! TC_M68K */ -#ifdef TC_I386 - words[0] = 0xffff; - words[1] = 0xc000; - words[2] = 0; - words[3] = 0; - words[4] = 0; -#else /* ! TC_I386 */ - abort (); -#endif /* ! TC_I386 */ -#endif /* ! TC_M68K */ - } - else - { - words[0] = 0x7fff; - words[1] = 0xffff; - words[2] = 0xffff; - words[3] = 0xffff; - } - return return_value; - } - else if (generic_floating_point_number.sign == 'P') - { - /* +INF: Do the right thing */ - if (precision == F_PRECISION) - { - words[0] = 0x7f80; - words[1] = 0; - } - else if (precision == X_PRECISION) - { -#ifdef TC_M68K - words[0] = 0x7fff; - words[1] = 0; - words[2] = 0; - words[3] = 0; - words[4] = 0; - words[5] = 0; -#else /* ! TC_M68K */ -#ifdef TC_I386 - words[0] = 0x7fff; - words[1] = 0x8000; - words[2] = 0; - words[3] = 0; - words[4] = 0; -#else /* ! TC_I386 */ - abort (); -#endif /* ! TC_I386 */ -#endif /* ! TC_M68K */ - } - else - { - words[0] = 0x7ff0; - words[1] = 0; - words[2] = 0; - words[3] = 0; - } - return (return_value); - } - else if (generic_floating_point_number.sign == 'N') - { - /* Negative INF */ - if (precision == F_PRECISION) - { - words[0] = 0xff80; - words[1] = 0x0; - } - else if (precision == X_PRECISION) - { -#ifdef TC_M68K - words[0] = 0xffff; - words[1] = 0; - words[2] = 0; - words[3] = 0; - words[4] = 0; - words[5] = 0; -#else /* ! TC_M68K */ -#ifdef TC_I386 - words[0] = 0xffff; - words[1] = 0x8000; - words[2] = 0; - words[3] = 0; - words[4] = 0; -#else /* ! TC_I386 */ - abort (); -#endif /* ! TC_I386 */ -#endif /* ! TC_M68K */ - } - else - { - words[0] = 0xfff0; - words[1] = 0x0; - words[2] = 0x0; - words[3] = 0x0; - } - return (return_value); - } - /* - * The floating point formats we support have: - * Bit 15 is sign bit. - * Bits 14:n are excess-whatever exponent. - * Bits n-1:0 (if any) are most significant bits of fraction. - * Bits 15:0 of the next word(s) are the next most significant bits. - * - * So we need: number of bits of exponent, number of bits of - * mantissa. - */ - bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; - littlenum_pointer = generic_floating_point_number.leader; - littlenums_left = (1 - + generic_floating_point_number.leader - - generic_floating_point_number.low); - /* Seek (and forget) 1st significant bit */ - for (exponent_skippage = 0; !next_bits (1); ++exponent_skippage);; - exponent_1 = (generic_floating_point_number.exponent - + generic_floating_point_number.leader - + 1 - - generic_floating_point_number.low); - /* Radix LITTLENUM_RADIX, point just higher than - generic_floating_point_number.leader. */ - exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; - /* Radix 2. */ - exponent_3 = exponent_2 - exponent_skippage; - /* Forget leading zeros, forget 1st bit. */ - exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2); - /* Offset exponent. */ - - lp = words; - - /* Word 1. Sign, exponent and perhaps high bits. */ - word1 = ((generic_floating_point_number.sign == '+') - ? 0 - : (1 << (LITTLENUM_NUMBER_OF_BITS - 1))); - - /* Assume 2's complement integers. */ - if (exponent_4 <= 0) - { - int prec_bits; - int num_bits; - - unget_bits (1); - num_bits = -exponent_4; - prec_bits = LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits); -#ifdef TC_I386 - if (precision == X_PRECISION && exponent_bits == 15) - { - /* On the i386 a denormalized extended precision float is - shifted down by one, effectively decreasing the exponent - bias by one. */ - prec_bits -= 1; - num_bits += 1; - } -#endif - - if (num_bits >= LITTLENUM_NUMBER_OF_BITS - exponent_bits) - { - /* Bigger than one littlenum */ - num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits; - *lp++ = word1; - if (num_bits + exponent_bits + 1 >= precision * LITTLENUM_NUMBER_OF_BITS) - { - /* Exponent overflow */ - make_invalid_floating_point_number (words); - return (return_value); - } -#ifdef TC_M68K - if (precision == X_PRECISION && exponent_bits == 15) - *lp++ = 0; -#endif - while (num_bits >= LITTLENUM_NUMBER_OF_BITS) - { - num_bits -= LITTLENUM_NUMBER_OF_BITS; - *lp++ = 0; - } - if (num_bits) - *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - (num_bits)); - } - else - { - if (precision == X_PRECISION && exponent_bits == 15) - { - *lp++ = word1; -#ifdef TC_M68K - *lp++ = 0; -#endif - *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS - num_bits); - } - else - { - word1 |= next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - (exponent_bits + num_bits)); - *lp++ = word1; - } - } - while (lp < words_end) - *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); - - /* Round the mantissa up, but don't change the number */ - if (next_bits (1)) - { - --lp; - if (prec_bits > LITTLENUM_NUMBER_OF_BITS) - { - int n = 0; - int tmp_bits; - - n = 0; - tmp_bits = prec_bits; - while (tmp_bits > LITTLENUM_NUMBER_OF_BITS) - { - if (lp[n] != (LITTLENUM_TYPE) - 1) - break; - --n; - tmp_bits -= LITTLENUM_NUMBER_OF_BITS; - } - if (tmp_bits > LITTLENUM_NUMBER_OF_BITS || (lp[n] & mask[tmp_bits]) != mask[tmp_bits]) - { - unsigned long carry; - - for (carry = 1; carry && (lp >= words); lp--) - { - carry = *lp + carry; - *lp = carry; - carry >>= LITTLENUM_NUMBER_OF_BITS; - } - } - else - { - /* This is an overflow of the denormal numbers. We - need to forget what we have produced, and instead - generate the smallest normalized number. */ - lp = words; - word1 = ((generic_floating_point_number.sign == '+') - ? 0 - : (1 << (LITTLENUM_NUMBER_OF_BITS - 1))); - word1 |= (1 - << ((LITTLENUM_NUMBER_OF_BITS - 1) - - exponent_bits)); - *lp++ = word1; - while (lp < words_end) - *lp++ = 0; - } - } - else if ((*lp & mask[prec_bits]) != mask[prec_bits]) - *lp += 1; - } - - return return_value; - } - else if ((unsigned long) exponent_4 >= mask[exponent_bits]) - { - /* - * Exponent overflow. Lose immediately. - */ - - /* - * We leave return_value alone: admit we read the - * number, but return a floating exception - * because we can't encode the number. - */ - make_invalid_floating_point_number (words); - return return_value; - } - else - { - word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits)) - | next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits); - } - - *lp++ = word1; - - /* X_PRECISION is special: on the 68k, it has 16 bits of zero in the - middle. Either way, it is then followed by a 1 bit. */ - if (exponent_bits == 15 && precision == X_PRECISION) - { -#ifdef TC_M68K - *lp++ = 0; -#endif - *lp++ = (1 << (LITTLENUM_NUMBER_OF_BITS - 1) - | next_bits (LITTLENUM_NUMBER_OF_BITS - 1)); - } - - /* The rest of the words are just mantissa bits. */ - while (lp < words_end) - *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); - - if (next_bits (1)) - { - unsigned long carry; - /* - * Since the NEXT bit is a 1, round UP the mantissa. - * The cunning design of these hidden-1 floats permits - * us to let the mantissa overflow into the exponent, and - * it 'does the right thing'. However, we lose if the - * highest-order bit of the lowest-order word flips. - * Is that clear? - */ - - /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) - Please allow at least 1 more bit in carry than is in a LITTLENUM. - We need that extra bit to hold a carry during a LITTLENUM carry - propagation. Another extra bit (kept 0) will assure us that we - don't get a sticky sign bit after shifting right, and that - permits us to propagate the carry without any masking of bits. - #endif */ - for (carry = 1, lp--; carry && (lp >= words); lp--) - { - carry = *lp + carry; - *lp = carry; - carry >>= LITTLENUM_NUMBER_OF_BITS; - } - if (precision == X_PRECISION && exponent_bits == 15) - { - /* Extended precision numbers have an explicit integer bit - that we may have to restore. */ - if (lp == words) - { -#ifdef TC_M68K - /* On the m68k there is a gap of 16 bits. We must - explicitly propagate the carry into the exponent. */ - words[0] += words[1]; - words[1] = 0; - lp++; -#endif - /* Put back the integer bit. */ - lp[1] |= 1 << (LITTLENUM_NUMBER_OF_BITS - 1); - } - } - if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) - { - /* We leave return_value alone: admit we read the - * number, but return a floating exception - * because we can't encode the number. - */ - *words &= ~(1 << (LITTLENUM_NUMBER_OF_BITS - 1)); - /* make_invalid_floating_point_number (words); */ - /* return return_value; */ - } - } - return (return_value); -} - -#if 0 /* unused */ -/* This routine is a real kludge. Someone really should do it better, - but I'm too lazy, and I don't understand this stuff all too well - anyway. (JF) */ -static void -int_to_gen (x) - long x; -{ - char buf[20]; - char *bufp; - - sprintf (buf, "%ld", x); - bufp = &buf[0]; - if (atof_generic (&bufp, ".", EXP_CHARS, &generic_floating_point_number)) - as_bad ("Error converting number to floating point (Exponent overflow?)"); -} -#endif - -#ifdef TEST -char * -print_gen (gen) - FLONUM_TYPE *gen; -{ - FLONUM_TYPE f; - LITTLENUM_TYPE arr[10]; - double dv; - float fv; - static char sbuf[40]; - - if (gen) - { - f = generic_floating_point_number; - generic_floating_point_number = *gen; - } - gen_to_words (&arr[0], 4, 11); - memcpy (&dv, &arr[0], sizeof (double)); - sprintf (sbuf, "%x %x %x %x %.14G ", arr[0], arr[1], arr[2], arr[3], dv); - gen_to_words (&arr[0], 2, 8); - memcpy (&fv, &arr[0], sizeof (float)); - sprintf (sbuf + strlen (sbuf), "%x %x %.12g\n", arr[0], arr[1], fv); - - if (gen) - { - generic_floating_point_number = f; - } - - return (sbuf); -} - -#endif - -/* end of atof-ieee.c */ diff --git a/contrib/binutils/gas/config/atof-vax.c b/contrib/binutils/gas/config/atof-vax.c deleted file mode 100644 index 8ba290faca83..000000000000 --- a/contrib/binutils/gas/config/atof-vax.c +++ /dev/null @@ -1,517 +0,0 @@ -/* atof_vax.c - turn a Flonum into a VAX floating point number - Copyright (C) 1987, 1992, 93, 95, 1997 Free Software Foundation, Inc. - - 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 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. */ - -#include "as.h" - -static int atof_vax_sizeof PARAMS ((int)); -static int next_bits PARAMS ((int)); -static void make_invalid_floating_point_number PARAMS ((LITTLENUM_TYPE *)); -static int what_kind_of_float PARAMS ((int, int *, long *)); -static char *atof_vax PARAMS ((char *, int, LITTLENUM_TYPE *)); - -/* Precision in LittleNums. */ -#define MAX_PRECISION (8) -#define H_PRECISION (8) -#define G_PRECISION (4) -#define D_PRECISION (4) -#define F_PRECISION (2) - -/* Length in LittleNums of guard bits. */ -#define GUARD (2) - -int flonum_gen2vax PARAMS ((int format_letter, FLONUM_TYPE * f, - LITTLENUM_TYPE * words)); - -/* Number of chars in flonum type 'letter'. */ -static int -atof_vax_sizeof (letter) - int letter; -{ - int return_value; - - /* - * Permitting uppercase letters is probably a bad idea. - * Please use only lower-cased letters in case the upper-cased - * ones become unsupported! - */ - switch (letter) - { - case 'f': - case 'F': - return_value = 4; - break; - - case 'd': - case 'D': - case 'g': - case 'G': - return_value = 8; - break; - - case 'h': - case 'H': - return_value = 16; - break; - - default: - return_value = 0; - break; - } - return (return_value); -} /* atof_vax_sizeof */ - -static const long 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, - 0xffffffff -}; - - -/* Shared between flonum_gen2vax and next_bits */ -static int bits_left_in_littlenum; -static LITTLENUM_TYPE *littlenum_pointer; -static LITTLENUM_TYPE *littlenum_end; - -static int -next_bits (number_of_bits) - int number_of_bits; -{ - int return_value; - - if (littlenum_pointer < littlenum_end) - return 0; - if (number_of_bits >= bits_left_in_littlenum) - { - return_value = mask[bits_left_in_littlenum] & *littlenum_pointer; - number_of_bits -= bits_left_in_littlenum; - return_value <<= number_of_bits; - bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; - littlenum_pointer--; - if (littlenum_pointer >= littlenum_end) - return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) & mask[number_of_bits]; - } - else - { - bits_left_in_littlenum -= number_of_bits; - return_value = mask[number_of_bits] & ((*littlenum_pointer) >> bits_left_in_littlenum); - } - return (return_value); -} - -static void -make_invalid_floating_point_number (words) - LITTLENUM_TYPE *words; -{ - *words = 0x8000; /* Floating Reserved Operand Code */ -} - -static int /* 0 means letter is OK. */ -what_kind_of_float (letter, precisionP, exponent_bitsP) - int letter; /* In: lowercase please. What kind of float? */ - int *precisionP; /* Number of 16-bit words in the float. */ - long *exponent_bitsP; /* Number of exponent bits. */ -{ - int retval; /* 0: OK. */ - - retval = 0; - switch (letter) - { - case 'f': - *precisionP = F_PRECISION; - *exponent_bitsP = 8; - break; - - case 'd': - *precisionP = D_PRECISION; - *exponent_bitsP = 8; - break; - - case 'g': - *precisionP = G_PRECISION; - *exponent_bitsP = 11; - break; - - case 'h': - *precisionP = H_PRECISION; - *exponent_bitsP = 15; - break; - - default: - retval = 69; - break; - } - return (retval); -} - -/***********************************************************************\ - * * - * Warning: this returns 16-bit LITTLENUMs, because that is * - * what the VAX thinks in. It is up to the caller to figure * - * out any alignment problems and to conspire for the bytes/word * - * to be emitted in the right order. Bigendians beware! * - * * - \***********************************************************************/ - -static char * /* Return pointer past text consumed. */ -atof_vax (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. */ -{ - FLONUM_TYPE f; - LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD]; - /* Extra bits for zeroed low-order bits. */ - /* The 1st MAX_PRECISION are zeroed, */ - /* the last contain flonum bits. */ - char *return_value; - int precision; /* Number of 16-bit words in the format. */ - long exponent_bits; - - return_value = str; - f.low = bits + MAX_PRECISION; - f.high = NULL; - f.leader = NULL; - f.exponent = 0; - f.sign = '\0'; - - if (what_kind_of_float (what_kind, &precision, &exponent_bits)) - { - return_value = NULL; /* We lost. */ - make_invalid_floating_point_number (words); - } - - if (return_value) - { - memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION); - - /* Use more LittleNums than seems */ - /* necessary: the highest flonum may have */ - /* 15 leading 0 bits, so could be useless. */ - f.high = f.low + precision - 1 + GUARD; - - if (atof_generic (&return_value, ".", "eE", &f)) - { - make_invalid_floating_point_number (words); - return_value = NULL; /* we lost */ - } - else - { - if (flonum_gen2vax (what_kind, &f, words)) - { - return_value = NULL; - } - } - } - return (return_value); -} /* atof_vax() */ - -/* - * In: a flonum, a vax floating point format. - * Out: a vax floating-point bit pattern. - */ - -int /* 0: OK. */ -flonum_gen2vax (format_letter, f, words) - char format_letter; /* One of 'd' 'f' 'g' 'h'. */ - FLONUM_TYPE *f; - LITTLENUM_TYPE *words; /* Deliver answer here. */ -{ - LITTLENUM_TYPE *lp; - int precision; - long exponent_bits; - int return_value; /* 0 == OK. */ - - return_value = what_kind_of_float (format_letter, &precision, &exponent_bits); - - if (return_value != 0) - { - make_invalid_floating_point_number (words); - } - else - { - if (f->low > f->leader) - { - /* 0.0e0 seen. */ - memset (words, '\0', sizeof (LITTLENUM_TYPE) * precision); - } - else - { - long exponent_1; - long exponent_2; - long exponent_3; - long exponent_4; - int exponent_skippage; - LITTLENUM_TYPE word1; - - /* JF: Deal with new Nan, +Inf and -Inf codes */ - if (f->sign != '-' && f->sign != '+') - { - make_invalid_floating_point_number (words); - return return_value; - } - /* - * All vaxen floating_point formats (so far) have: - * Bit 15 is sign bit. - * Bits 14:n are excess-whatever exponent. - * Bits n-1:0 (if any) are most significant bits of fraction. - * Bits 15:0 of the next word are the next most significant bits. - * And so on for each other word. - * - * All this to be compatible with a KF11?? (Which is still faster - * than lots of vaxen I can think of, but it also has higher - * maintenance costs ... sigh). - * - * So we need: number of bits of exponent, number of bits of - * mantissa. - */ - -#ifdef NEVER /******* This zeroing seems redundant - Dean 3may86 **********/ - /* - * No matter how few bits we got back from the atof() - * routine, add enough zero littlenums so the rest of the - * code won't run out of "significant" bits in the mantissa. - */ - { - LITTLENUM_TYPE *ltp; - for (ltp = f->leader + 1; - ltp <= f->low + precision; - ltp++) - { - *ltp = 0; - } - } -#endif - - bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; - littlenum_pointer = f->leader; - littlenum_end = f->low; - /* Seek (and forget) 1st significant bit */ - for (exponent_skippage = 0; - !next_bits (1); - exponent_skippage++);; - - exponent_1 = f->exponent + f->leader + 1 - f->low; - /* Radix LITTLENUM_RADIX, point just higher than f->leader. */ - exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; - /* Radix 2. */ - exponent_3 = exponent_2 - exponent_skippage; - /* Forget leading zeros, forget 1st bit. */ - exponent_4 = exponent_3 + (1 << (exponent_bits - 1)); - /* Offset exponent. */ - - if (exponent_4 & ~mask[exponent_bits]) - { - /* - * Exponent overflow. Lose immediately. - */ - - make_invalid_floating_point_number (words); - - /* - * We leave return_value alone: admit we read the - * number, but return a floating exception - * because we can't encode the number. - */ - } - else - { - lp = words; - - /* Word 1. Sign, exponent and perhaps high bits. */ - /* Assume 2's complement integers. */ - word1 = (((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) - | ((f->sign == '+') ? 0 : 0x8000) - | next_bits (15 - exponent_bits)); - *lp++ = word1; - - /* The rest of the words are just mantissa bits. */ - for (; lp < words + precision; lp++) - { - *lp = next_bits (LITTLENUM_NUMBER_OF_BITS); - } - - if (next_bits (1)) - { - /* - * Since the NEXT bit is a 1, round UP the mantissa. - * The cunning design of these hidden-1 floats permits - * us to let the mantissa overflow into the exponent, and - * it 'does the right thing'. However, we lose if the - * highest-order bit of the lowest-order word flips. - * Is that clear? - */ - - unsigned long carry; - - /* - #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) - Please allow at least 1 more bit in carry than is in a LITTLENUM. - We need that extra bit to hold a carry during a LITTLENUM carry - propagation. Another extra bit (kept 0) will assure us that we - don't get a sticky sign bit after shifting right, and that - permits us to propagate the carry without any masking of bits. - #endif - */ - for (carry = 1, lp--; - carry && (lp >= words); - lp--) - { - carry = *lp + carry; - *lp = carry; - carry >>= LITTLENUM_NUMBER_OF_BITS; - } - - if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) - { - make_invalid_floating_point_number (words); - /* - * We leave return_value alone: admit we read the - * number, but return a floating exception - * because we can't encode the number. - */ - } - } /* if (we needed to round up) */ - } /* if (exponent overflow) */ - } /* if (0.0e0) */ - } /* if (float_type was OK) */ - return (return_value); -} /* flonum_gen2vax() */ - - -/* JF this used to be in vax.c but this looks like a better place for it */ - -/* - * md_atof() - * - * In: input_line_pointer->the 1st character of a floating-point - * number. - * 1 letter denoting the type of statement that wants a - * binary floating point number returned. - * Address of where to build floating point literal. - * Assumed to be 'big enough'. - * Address of where to return size of literal (in chars). - * - * Out: Input_line_pointer->of next char after floating number. - * Error message, or 0. - * Floating point literal. - * Number of chars we used for the literal. - */ - -#define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */ - -char * -md_atof (what_statement_type, literalP, sizeP) - int what_statement_type; - char *literalP; - int *sizeP; -{ - LITTLENUM_TYPE words[MAXIMUM_NUMBER_OF_LITTLENUMS]; - register char kind_of_float; - register int number_of_chars; - register LITTLENUM_TYPE *littlenumP; - - switch (what_statement_type) - { - case 'F': /* .float */ - case 'f': /* .ffloat */ - kind_of_float = 'f'; - break; - - case 'D': /* .double */ - case 'd': /* .dfloat */ - kind_of_float = 'd'; - break; - - case 'g': /* .gfloat */ - kind_of_float = 'g'; - break; - - case 'h': /* .hfloat */ - kind_of_float = 'h'; - break; - - default: - kind_of_float = 0; - break; - }; - - if (kind_of_float) - { - register LITTLENUM_TYPE *limit; - - input_line_pointer = atof_vax (input_line_pointer, - kind_of_float, - words); - /* - * The atof_vax() builds up 16-bit numbers. - * Since the assembler may not be running on - * a little-endian machine, be very careful about - * converting words to chars. - */ - number_of_chars = atof_vax_sizeof (kind_of_float); - know (number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof (LITTLENUM_TYPE)); - limit = words + (number_of_chars / sizeof (LITTLENUM_TYPE)); - for (littlenumP = words; littlenumP < limit; littlenumP++) - { - md_number_to_chars (literalP, *littlenumP, sizeof (LITTLENUM_TYPE)); - literalP += sizeof (LITTLENUM_TYPE); - }; - } - else - { - number_of_chars = 0; - }; - - *sizeP = number_of_chars; - return kind_of_float ? 0 : "Bad call to md_atof()"; -} - -/* end of atof-vax.c */ diff --git a/contrib/binutils/gas/config/e-i386coff.c b/contrib/binutils/gas/config/e-i386coff.c deleted file mode 100644 index afed72886acf..000000000000 --- a/contrib/binutils/gas/config/e-i386coff.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "as.h" -#include "emul.h" - -static const char * -i386coff_bfd_name () -{ - abort (); - return NULL; -} - -#define emul_bfd_name i386coff_bfd_name -#define emul_format &coff_format_ops - -#define emul_name "i386coff" -#define emul_struct_name i386coff -#define emul_default_endian 0 -#include "emul-target.h" diff --git a/contrib/binutils/gas/config/e-i386elf.c b/contrib/binutils/gas/config/e-i386elf.c deleted file mode 100644 index a16701e811e1..000000000000 --- a/contrib/binutils/gas/config/e-i386elf.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "as.h" -#include "emul.h" - -static const char * -i386elf_bfd_name () -{ - abort (); - return NULL; -} - -#define emul_bfd_name i386elf_bfd_name -#define emul_format &elf_format_ops - -#define emul_name "i386elf" -#define emul_struct_name i386elf -#define emul_default_endian 0 -#include "emul-target.h" diff --git a/contrib/binutils/gas/config/i386coff.mt b/contrib/binutils/gas/config/i386coff.mt deleted file mode 100644 index efda83365181..000000000000 --- a/contrib/binutils/gas/config/i386coff.mt +++ /dev/null @@ -1 +0,0 @@ -TDEFINES=-DI386COFF diff --git a/contrib/binutils/gas/config/obj-aout.c b/contrib/binutils/gas/config/obj-aout.c deleted file mode 100644 index 7dc894612930..000000000000 --- a/contrib/binutils/gas/config/obj-aout.c +++ /dev/null @@ -1,629 +0,0 @@ -/* a.out object file format - Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996 - Free Software Foundation, Inc. - -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 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. */ - -#include "as.h" -#ifdef BFD_ASSEMBLER -#undef NO_RELOC -#include "aout/aout64.h" -#endif -#include "obstack.h" - -#ifndef BFD_ASSEMBLER -/* 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 */ -}; - -const segT N_TYPE_seg[N_TYPE + 2] = -{ /* N_TYPE == 0x1E = 32-2 */ - SEG_UNKNOWN, /* N_UNDF == 0 */ - SEG_GOOF, - SEG_ABSOLUTE, /* N_ABS == 2 */ - SEG_GOOF, - SEG_TEXT, /* N_TEXT == 4 */ - SEG_GOOF, - SEG_DATA, /* N_DATA == 6 */ - SEG_GOOF, - SEG_BSS, /* N_BSS == 8 */ - 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_GOOF, - 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 obj_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} /* end sentinel */ -}; /* obj_pseudo_table */ - - -#ifdef BFD_ASSEMBLER - -void -obj_aout_frob_symbol (sym, punt) - symbolS *sym; - int *punt; -{ - flagword flags; - asection *sec; - int desc, type, other; - - flags = sym->bsym->flags; - desc = S_GET_DESC (sym); - type = S_GET_TYPE (sym); - other = S_GET_OTHER (sym); - sec = sym->bsym->section; - - /* Only frob simple symbols this way right now. */ - if (! (type & ~ (N_TYPE | N_EXT))) - { - if (type == (N_UNDF | N_EXT) - && sec == &bfd_abs_section) - sym->bsym->section = sec = bfd_und_section_ptr; - - if ((type & N_TYPE) != N_INDR - && (type & N_TYPE) != N_SETA - && (type & N_TYPE) != N_SETT - && (type & N_TYPE) != N_SETD - && (type & N_TYPE) != N_SETB - && type != N_WARNING - && (sec == &bfd_abs_section - || sec == &bfd_und_section)) - return; - if (flags & BSF_EXPORT) - type |= N_EXT; - - switch (type & N_TYPE) - { - case N_SETA: - case N_SETT: - case N_SETD: - case N_SETB: - /* Set the debugging flag for constructor symbols so that - BFD leaves them alone. */ - sym->bsym->flags |= BSF_DEBUGGING; - - /* You can't put a common symbol in a set. The way a set - element works is that the symbol has a definition and a - name, and the linker adds the definition to the set of - that name. That does not work for a common symbol, - because the linker can't tell which common symbol the - user means. FIXME: Using as_bad here may be - inappropriate, since the user may want to force a - particular type without regard to the semantics of sets; - on the other hand, we certainly don't want anybody to be - mislead into thinking that their code will work. */ - if (S_IS_COMMON (sym)) - as_bad ("Attempt to put a common symbol into set %s", - S_GET_NAME (sym)); - /* Similarly, you can't put an undefined symbol in a set. */ - else if (! S_IS_DEFINED (sym)) - as_bad ("Attempt to put an undefined symbol into set %s", - S_GET_NAME (sym)); - - break; - case N_INDR: - /* Put indirect symbols in the indirect section. */ - sym->bsym->section = bfd_ind_section_ptr; - sym->bsym->flags |= BSF_INDIRECT; - if (type & N_EXT) - { - sym->bsym->flags |= BSF_EXPORT; - sym->bsym->flags &=~ BSF_LOCAL; - } - break; - case N_WARNING: - /* Mark warning symbols. */ - sym->bsym->flags |= BSF_WARNING; - break; - } - } - else - { - sym->bsym->flags |= BSF_DEBUGGING; - } - - S_SET_TYPE (sym, type); - - /* Double check weak symbols. */ - if (sym->bsym->flags & BSF_WEAK) - { - if (S_IS_COMMON (sym)) - as_bad ("Symbol `%s' can not be both weak and common", - S_GET_NAME (sym)); - } -} - -void -obj_aout_frob_file () -{ - /* Relocation processing may require knowing the VMAs of the sections. - Since writing to a section will cause the BFD back end to compute the - VMAs, fake it out here.... */ - bfd_byte b = 0; - 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); - } - 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); - } - assert (x == true); -} - -#else - -/* Relocation. */ - -/* - * emit_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; -{ - for (; fixP; fixP = fixP->fx_next) - if (fixP->fx_done == 0) - { - symbolS *sym; - - sym = fixP->fx_addsy; - while (sym->sy_value.X_op == O_symbol - && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym))) - sym = sym->sy_value.X_add_symbol; - fixP->fx_addsy = sym; - - if (! sym->sy_resolved && ! S_IS_DEFINED (sym)) - { - char *file; - unsigned int line; - - if (expr_symbol_where (sym, &file, &line)) - as_bad_where (file, line, "unresolved relocation"); - else - as_bad ("bad relocation: symbol `%s' not in symbol table", - S_GET_NAME (sym)); - } - - tc_aout_fix_to_chars (*where, fixP, segment_address_in_file); - *where += md_reloc_size; - } -} - -#ifndef obj_header_append -/* Aout file generation & utilities */ -void -obj_header_append (where, headers) - char **where; - object_headers *headers; -{ - tc_headers_hook (headers); - -#ifdef CROSS_COMPILE - md_number_to_chars (*where, headers->header.a_info, sizeof (headers->header.a_info)); - *where += sizeof (headers->header.a_info); - md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text)); - *where += sizeof (headers->header.a_text); - md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data)); - *where += sizeof (headers->header.a_data); - md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss)); - *where += sizeof (headers->header.a_bss); - md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms)); - *where += sizeof (headers->header.a_syms); - md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry)); - *where += sizeof (headers->header.a_entry); - md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize)); - *where += sizeof (headers->header.a_trsize); - md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize)); - *where += sizeof (headers->header.a_drsize); - -#else /* CROSS_COMPILE */ - - append (where, (char *) &headers->header, sizeof (headers->header)); -#endif /* CROSS_COMPILE */ - -} -#endif - -void -obj_symbol_to_chars (where, symbolP) - char **where; - symbolS *symbolP; -{ - md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP))); - md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP))); - md_number_to_chars ((char *) &(symbolP->sy_symbol.n_value), S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value)); - - append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type)); -} - -void -obj_emit_symbols (where, symbol_rootP) - char **where; - symbolS *symbol_rootP; -{ - symbolS *symbolP; - - /* Emit all symbols left in the symbol chain. */ - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - /* 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; - - temp = S_GET_NAME (symbolP); - S_SET_OFFSET (symbolP, symbolP->sy_name_offset); - - /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */ - if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP)) - S_SET_EXTERNAL (symbolP); - - /* Adjust the type of a weak symbol. */ - if (S_GET_WEAK (symbolP)) - { - switch (S_GET_TYPE (symbolP)) - { - case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break; - case N_ABS: S_SET_TYPE (symbolP, N_WEAKA); break; - case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break; - case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break; - case N_BSS: S_SET_TYPE (symbolP, N_WEAKB); break; - default: as_bad ("%s: bad type for weak symbol", temp); break; - } - } - - obj_symbol_to_chars (where, symbolP); - S_SET_NAME (symbolP, temp); - } -} - -#endif /* ! BFD_ASSEMBLER */ - -static void -obj_aout_line (ignore) - int ignore; -{ - /* 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; -{ - char *name; - int c; - symbolS *symbolP; - - do - { - name = input_line_pointer; - c = get_symbol_end (); - symbolP = symbol_find_or_make (name); - *input_line_pointer = c; - SKIP_WHITESPACE (); - S_SET_WEAK (symbolP); - if (c == ',') - { - input_line_pointer++; - SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') - c = '\n'; - } - } - while (c == ','); - demand_empty_rest_of_line (); -} - -/* Handle .type. On {Net,Open}BSD, this is used to set the n_other field, - which is then apparently used when doing dynamic linking. Older - versions ogas ignored the .type pseudo-op, so we also ignore it if - we can't parse it. */ - -static void -obj_aout_type (ignore) - int ignore; -{ - char *name; - int c; - symbolS *sym; - - name = input_line_pointer; - c = get_symbol_end (); - sym = symbol_find (name); - *input_line_pointer = c; - if (sym != NULL) - { - SKIP_WHITESPACE (); - if (*input_line_pointer == ',') - { - ++input_line_pointer; - SKIP_WHITESPACE (); - if (*input_line_pointer == '@') - { - ++input_line_pointer; - if (strncmp (input_line_pointer, "object", 6) == 0) - S_SET_OTHER (sym, 1); - else if (strncmp (input_line_pointer, "function", 8) == 0) - S_SET_OTHER (sym, 2); - } - } - } - - /* Ignore everything else on the line. */ - s_ignore (0); -} - -void -obj_read_begin_hook () -{ -} - -#ifndef BFD_ASSEMBLER - -void -obj_crawl_symbol_chain (headers) - object_headers *headers; -{ - symbolS *symbolP; - symbolS **symbolPP; - int symbol_number = 0; - - tc_crawl_symbol_chain (headers); - - symbolPP = &symbol_rootP; /*->last symbol chain link. */ - while ((symbolP = *symbolPP) != NULL) - { - if (symbolP->sy_mri_common) - { - if (S_IS_EXTERNAL (symbolP)) - as_bad ("%s: global symbols not supported in common sections", - S_GET_NAME (symbolP)); - *symbolPP = symbol_next (symbolP); - continue; - } - - if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA)) - { - S_SET_SEGMENT (symbolP, SEG_TEXT); - } /* if pusing data into text */ - - resolve_symbol_value (symbolP, 1); - - /* Skip symbols which were equated to undefined or common - symbols. */ - if (symbolP->sy_value.X_op == O_symbol - && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))) - { - *symbolPP = symbol_next (symbolP); - continue; - } - - /* OK, here is how we decide which symbols go out into the brave - new symtab. Symbols that do are: - - * symbols with no name (stabd's?) - * symbols with debug info in their N_TYPE - - Symbols that don't are: - * symbols that are registers - * symbols with \1 as their 3rd character (numeric labels) - * "local labels" as defined by S_LOCAL_NAME(name) if the -L - switch was passed to gas. - - All other symbols are output. We complain if a deleted - symbol was marked external. */ - - - if (!S_IS_REGISTER (symbolP) - && (!S_GET_NAME (symbolP) - || S_IS_DEBUG (symbolP) - || !S_IS_DEFINED (symbolP) - || S_IS_EXTERNAL (symbolP) - || (S_GET_NAME (symbolP)[0] != '\001' - && (flag_keep_locals || !S_LOCAL_NAME (symbolP))))) - { - symbolP->sy_number = symbol_number++; - - /* The + 1 after strlen account for the \0 at the - end of each string */ - if (!S_IS_STABD (symbolP)) - { - /* Ordinary case. */ - symbolP->sy_name_offset = string_byte_count; - string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; - } - else /* .Stabd case. */ - symbolP->sy_name_offset = 0; - symbolPP = &(symbol_next (symbolP)); - } - else - { - if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP)) - /* 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. */ - - /* 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. - */ - -void -obj_emit_strings (where) - char **where; -{ - symbolS *symbolP; - -#ifdef CROSS_COMPILE - /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ - md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count)); - *where += sizeof (string_byte_count); -#else /* CROSS_COMPILE */ - append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count)); -#endif /* CROSS_COMPILE */ - - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - if (S_GET_NAME (symbolP)) - append (&next_object_file_charP, S_GET_NAME (symbolP), - (unsigned long) (strlen (S_GET_NAME (symbolP)) + 1)); - } /* walk symbol chain */ -} - -#ifndef AOUT_VERSION -#define AOUT_VERSION 0 -#endif - -void -obj_pre_write_hook (headers) - object_headers *headers; -{ - H_SET_DYNAMIC (headers, 0); - H_SET_VERSION (headers, AOUT_VERSION); - H_SET_MACHTYPE (headers, AOUT_MACHTYPE); - tc_aout_pre_write_hook (headers); -} - -void -DEFUN_VOID (s_sect) -{ - /* Strip out the section name */ - char *section_name; - char *section_name_end; - char c; - - unsigned int len; - unsigned int exp; - char *save; - - section_name = input_line_pointer; - c = get_symbol_end (); - section_name_end = input_line_pointer; - - len = section_name_end - section_name; - input_line_pointer++; - save = input_line_pointer; - - SKIP_WHITESPACE (); - if (c == ',') - { - exp = get_absolute_expression (); - } - else if (*input_line_pointer == ',') - { - input_line_pointer++; - exp = get_absolute_expression (); - } - else - { - input_line_pointer = save; - exp = 0; - } - if (exp >= 1000) - { - as_bad ("subsegment index too high"); - } - - if (strcmp (section_name, ".text") == 0) - { - subseg_set (SEG_TEXT, (subsegT) exp); - } - - if (strcmp (section_name, ".data") == 0) - { - if (flag_readonly_data_in_text) - subseg_set (SEG_TEXT, (subsegT) exp + 1000); - else - subseg_set (SEG_DATA, (subsegT) exp); - } - - *section_name_end = c; -} - -#endif /* ! BFD_ASSEMBLER */ - -/* end of obj-aout.c */ diff --git a/contrib/binutils/gas/config/obj-aout.h b/contrib/binutils/gas/config/obj-aout.h deleted file mode 100644 index 339070e093c3..000000000000 --- a/contrib/binutils/gas/config/obj-aout.h +++ /dev/null @@ -1,239 +0,0 @@ -/* obj-aout.h, a.out object file format for gas, the assembler. - Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 1998 - Free Software Foundation, Inc. - - 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 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. */ - -/* Tag to validate a.out object file format processing */ -#define OBJ_AOUT 1 - -#include "targ-cpu.h" - -#ifdef BFD_ASSEMBLER - -#include "bfd/libaout.h" - -#define OUTPUT_FLAVOR bfd_target_aout_flavour - -#else /* ! BFD_ASSEMBLER */ - -#ifndef VMS -#include "aout_gnu.h" /* Needed to define struct nlist. Sigh. */ -#else -#include "a_out.h" -#endif - -#ifndef AOUT_MACHTYPE -#define AOUT_MACHTYPE 0 -#endif /* AOUT_MACHTYPE */ - -extern const short seg_N_TYPE[]; -extern const segT N_TYPE_seg[]; - -#ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE -#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC) -#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */ - -#endif /* ! BFD_ASSEMBLER */ - -/* SYMBOL TABLE */ -/* Symbol table entry data type */ - -typedef struct nlist obj_symbol_type; /* Symbol table entry */ - -/* Symbol table macros and constants */ - -#ifdef BFD_ASSEMBLER - -#define S_SET_OTHER(S,V) (aout_symbol((S)->bsym)->other = (V)) -#define S_SET_TYPE(S,T) (aout_symbol((S)->bsym)->type = (T)) -#define S_SET_DESC(S,D) (aout_symbol((S)->bsym)->desc = (D)) -#define S_GET_OTHER(S) (aout_symbol((S)->bsym)->other) -#define S_GET_TYPE(S) (aout_symbol((S)->bsym)->type) -#define S_GET_DESC(S) (aout_symbol((S)->bsym)->desc) - -asection *text_section, *data_section, *bss_section; - -#define obj_frob_symbol(S,PUNT) obj_aout_frob_symbol (S, &PUNT) -#define obj_frob_file() obj_aout_frob_file () -extern void obj_aout_frob_symbol PARAMS ((struct symbol *, int *)); -extern void obj_aout_frob_file PARAMS ((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 syntaxic 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 */ -#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 */ -#define S_IS_DEFINED(s) \ - (S_GET_TYPE (s) != N_UNDF || S_GET_DESC (s) != 0) - -#define S_IS_COMMON(s) \ - (S_GET_TYPE (s) == N_UNDF && S_GET_VALUE (s) != 0) - -#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER) - -/* 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 */ -#define S_IS_LOCAL(s) \ - ((S_GET_NAME (s) \ - && !S_IS_DEBUG (s) \ - && (strchr (S_GET_NAME (s), '\001') != NULL \ - || strchr (S_GET_NAME (s), '\002') != NULL \ - || (S_LOCAL_NAME(s) && !flag_keep_locals))) \ - || (flag_strip_local_absolute \ - && ! S_IS_EXTERNAL(s) \ - && S_GET_SEGMENT (s) == absolute_section)) -/* 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) - -/* Accessors */ -/* The name of the symbol */ -#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name) -/* The pointer to the string table */ -#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx) -/* The type of the symbol */ -#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE) -/* The numeric value of the segment */ -#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)]) -/* The n_other expression value */ -#define S_GET_OTHER(s) ((s)->sy_symbol.n_other) -/* 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 */ -#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT) -/* The symbol is not external */ -#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT) -/* 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 */ -#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v)) -/* Set the n_type field */ -#define S_SET_TYPE(s,t) ((s)->sy_symbol.n_type = (t)) -/* Set the n_other expression value */ -#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v)) -/* 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 */ - -#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \ - + 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_GET_STRING_SIZE(h)) - -#define H_GET_HEADER_SIZE(h) (EXEC_BYTES_SIZE) -#define H_GET_TEXT_SIZE(h) ((h)->header.a_text) -#define H_GET_DATA_SIZE(h) ((h)->header.a_data) -#define H_GET_BSS_SIZE(h) ((h)->header.a_bss) -#define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize) -#define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize) -#define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms) -#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry) -#define H_GET_STRING_SIZE(h) ((h)->string_table_size) -#define H_GET_LINENO_SIZE(h) (0) - -#define H_GET_DYNAMIC(h) ((h)->header.a_info >> 31) -#define H_GET_VERSION(h) (((h)->header.a_info >> 24) & 0x7f) -#define H_GET_MACHTYPE(h) (((h)->header.a_info >> 16) & 0xff) -#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)))) - -#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)))) - -#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)))) - -#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_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)) -#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * 12) - -#define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v)) -#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) */ - } - -object_headers; - -/* 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)); - -#endif - -#define obj_symbol_new_hook(s) {;} - -#define EMIT_SECTION_SYMBOLS 0 - -#define AOUT_STABS - -/* end of obj-aout.h */ diff --git a/contrib/binutils/gas/config/obj-coff.c b/contrib/binutils/gas/config/obj-coff.c deleted file mode 100644 index a6421bf99b35..000000000000 --- a/contrib/binutils/gas/config/obj-coff.c +++ /dev/null @@ -1,4400 +0,0 @@ -/* coff object file format - Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 97, 1998 - Free Software Foundation, Inc. - - This file is part of GAS. - - 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. - - 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-coff.h" - -#include "as.h" -#include "obstack.h" -#include "subsegs.h" - -/* I think this is probably always correct. */ -#ifndef KEEP_RELOC_INFO -#define KEEP_RELOC_INFO -#endif - -static void obj_coff_bss PARAMS ((int)); -const char *s_get_name PARAMS ((symbolS * s)); -static symbolS *def_symbol_in_progress; - - -/* stack stuff */ -typedef struct - { - unsigned long chunk_size; - unsigned long element_size; - unsigned long size; - char *data; - unsigned long pointer; - } -stack; - -static stack * -stack_init (chunk_size, element_size) - unsigned long chunk_size; - unsigned long element_size; -{ - stack *st; - - st = (stack *) malloc (sizeof (stack)); - if (!st) - return 0; - st->data = malloc (chunk_size); - if (!st->data) - { - free (st); - return 0; - } - st->pointer = 0; - st->size = chunk_size; - st->chunk_size = chunk_size; - st->element_size = element_size; - return st; -} - -#if 0 -/* Not currently used. */ -static void -stack_delete (st) - stack *st; -{ - free (st->data); - free (st); -} -#endif - -static char * -stack_push (st, element) - stack *st; - char *element; -{ - if (st->pointer + st->element_size >= st->size) - { - st->size += st->chunk_size; - if ((st->data = xrealloc (st->data, st->size)) == (char *) 0) - return (char *) 0; - } - memcpy (st->data + st->pointer, element, st->element_size); - st->pointer += st->element_size; - return st->data + st->pointer; -} - -static char * -stack_pop (st) - stack *st; -{ - if (st->pointer < st->element_size) - { - st->pointer = 0; - return (char *) 0; - } - st->pointer -= st->element_size; - return st->data + st->pointer; -} - -/* - * Maintain a list of the tagnames of the structres. - */ - -static struct hash_control *tag_hash; - -static void -tag_init () -{ - tag_hash = hash_new (); -} - -static void -tag_insert (name, symbolP) - const char *name; - symbolS *symbolP; -{ - const char *error_string; - - if ((error_string = hash_jam (tag_hash, name, (char *) symbolP))) - { - as_fatal ("Inserting \"%s\" into structure table failed: %s", - name, error_string); - } -} - -static symbolS * -tag_find (name) - char *name; -{ -#ifdef STRIP_UNDERSCORE - if (*name == '_') - name++; -#endif /* STRIP_UNDERSCORE */ - return (symbolS *) hash_find (tag_hash, name); -} - -static symbolS * -tag_find_or_make (name) - char *name; -{ - symbolS *symbolP; - - if ((symbolP = tag_find (name)) == NULL) - { - symbolP = symbol_new (name, undefined_section, - 0, &zero_address_frag); - - tag_insert (S_GET_NAME (symbolP), symbolP); -#ifdef BFD_ASSEMBLER - symbol_table_insert (symbolP); -#endif - } /* not found */ - - return symbolP; -} - -/* We accept the .bss directive to set the section for backward - compatibility with earlier versions of gas. */ - -static void -obj_coff_bss (ignore) - int ignore; -{ - if (*input_line_pointer == '\n') - subseg_new (".bss", get_absolute_expression ()); - else - s_lcomm (0); -} - -#ifdef BFD_ASSEMBLER - -static void SA_SET_SYM_TAGNDX PARAMS ((symbolS *, symbolS *)); - -#define GET_FILENAME_STRING(X) \ -((char*)(&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1]) - -/* @@ Ick. */ -static segT -fetch_coff_debug_section () -{ - static segT debug_section; - if (!debug_section) - { - CONST asymbol *s; - s = bfd_make_debug_symbol (stdoutput, (char *) 0, 0); - assert (s != 0); - debug_section = s->section; - } - return debug_section; -} - -void -SA_SET_SYM_ENDNDX (sym, val) - symbolS *sym; - symbolS *val; -{ - combined_entry_type *entry, *p; - - entry = &coffsymbol (sym->bsym)->native[1]; - p = coffsymbol (val->bsym)->native; - entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p; - entry->fix_end = 1; -} - -static void -SA_SET_SYM_TAGNDX (sym, val) - symbolS *sym; - symbolS *val; -{ - combined_entry_type *entry, *p; - - entry = &coffsymbol (sym->bsym)->native[1]; - p = coffsymbol (val->bsym)->native; - entry->u.auxent.x_sym.x_tagndx.p = p; - entry->fix_tag = 1; -} - -static int -S_GET_DATA_TYPE (sym) - symbolS *sym; -{ - return coffsymbol (sym->bsym)->native->u.syment.n_type; -} - -int -S_SET_DATA_TYPE (sym, val) - symbolS *sym; - int val; -{ - coffsymbol (sym->bsym)->native->u.syment.n_type = val; - return val; -} - -int -S_GET_STORAGE_CLASS (sym) - symbolS *sym; -{ - return coffsymbol (sym->bsym)->native->u.syment.n_sclass; -} - -int -S_SET_STORAGE_CLASS (sym, val) - symbolS *sym; - int val; -{ - coffsymbol (sym->bsym)->native->u.syment.n_sclass = val; - return val; -} - -/* Merge a debug symbol containing debug information into a normal symbol. */ - -void -c_symbol_merge (debug, normal) - symbolS *debug; - symbolS *normal; -{ - S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); - S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); - - if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) - /* take the most we have */ - S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); - - if (S_GET_NUMBER_AUXILIARY (debug) > 0) - { - /* Move all the auxiliary information. */ - /* @@ How many fields do we want to preserve? Would it make more - sense to pick and choose those we want to copy? Should look - into this further.... [raeburn:19920512.2209EST] */ - alent *linenos; - linenos = coffsymbol (normal->bsym)->lineno; - memcpy ((char *) &coffsymbol (normal->bsym)->native, - (char *) &coffsymbol (debug->bsym)->native, - S_GET_NUMBER_AUXILIARY(debug) * AUXESZ); - coffsymbol (normal->bsym)->lineno = linenos; - } - - /* Move the debug flags. */ - SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); -} - -void -c_dot_file_symbol (filename) - char *filename; -{ - symbolS *symbolP; - - symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag); - - S_SET_STORAGE_CLASS (symbolP, C_FILE); - S_SET_NUMBER_AUXILIARY (symbolP, 1); - - symbolP->bsym->flags = BSF_DEBUGGING; - -#ifndef NO_LISTING - { - extern int listing; - if (listing) - { - listing_source_file (filename); - } - } -#endif - - /* Make sure that the symbol is first on the symbol chain */ - if (symbol_rootP != symbolP) - { - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); - } /* if not first on the list */ -} - -/* Line number handling */ - -struct line_no { - struct line_no *next; - fragS *frag; - alent l; -}; - -int coff_line_base; - -/* Symbol of last function, which we should hang line#s off of. */ -static symbolS *line_fsym; - -#define in_function() (line_fsym != 0) -#define clear_function() (line_fsym = 0) -#define set_function(F) (line_fsym = (F), coff_add_linesym (F)) - - -void -coff_obj_symbol_new_hook (symbolP) - symbolS *symbolP; -{ - char underscore = 0; /* Symbol has leading _ */ - - { - long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type); - char *s = (char *) xmalloc (sz); - memset (s, 0, sz); - coffsymbol (symbolP->bsym)->native = (combined_entry_type *) s; - } - S_SET_DATA_TYPE (symbolP, T_NULL); - S_SET_STORAGE_CLASS (symbolP, 0); - S_SET_NUMBER_AUXILIARY (symbolP, 0); - - if (S_IS_STRING (symbolP)) - SF_SET_STRING (symbolP); - if (!underscore && S_IS_LOCAL (symbolP)) - SF_SET_LOCAL (symbolP); -} - - -/* - * Handle .ln directives. - */ - -static symbolS *current_lineno_sym; -static struct line_no *line_nos; -/* @@ Blindly assume all .ln directives will be in the .text section... */ -int coff_n_line_nos; - -static void -add_lineno (frag, offset, num) - fragS *frag; - int offset; - int num; -{ - struct line_no *new_line = - (struct line_no *) xmalloc (sizeof (struct line_no)); - if (!current_lineno_sym) - { - abort (); - } - new_line->next = line_nos; - new_line->frag = frag; - new_line->l.line_number = num; - new_line->l.u.offset = offset; - line_nos = new_line; - coff_n_line_nos++; -} - -void -coff_add_linesym (sym) - symbolS *sym; -{ - if (line_nos) - { - coffsymbol (current_lineno_sym->bsym)->lineno = (alent *) line_nos; - coff_n_line_nos++; - line_nos = 0; - } - current_lineno_sym = sym; -} - -static void -obj_coff_ln (appline) - int appline; -{ - int l; - - if (! appline && def_symbol_in_progress != NULL) - { - as_warn (".ln pseudo-op inside .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } - - l = get_absolute_expression (); - if (!appline) - { - add_lineno (frag_now, frag_now_fix (), l); - } - - if (appline) - new_logical_line ((char *) NULL, l - 1); - -#ifndef NO_LISTING - { - extern int listing; - - if (listing) - { - if (! appline) - l += coff_line_base - 1; - listing_source_line (l); - } - } -#endif - - demand_empty_rest_of_line (); -} - -/* - * def() - * - * Handle .def directives. - * - * One might ask : why can't we symbol_new if the symbol does not - * already exist and fill it with debug information. Because of - * the C_EFCN special symbol. It would clobber the value of the - * function symbol before we have a chance to notice that it is - * a C_EFCN. And a second reason is that the code is more clear this - * way. (at least I think it is :-). - * - */ - -#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') -#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ - *input_line_pointer == '\t') \ - input_line_pointer++; - -static void -obj_coff_def (what) - int what; -{ - char name_end; /* Char after the end of name */ - char *symbol_name; /* Name of the debug symbol */ - char *symbol_name_copy; /* Temporary copy of the name */ - unsigned int symbol_name_length; - - if (def_symbol_in_progress != NULL) - { - as_warn (".def pseudo-op used inside of .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - SKIP_WHITESPACES (); - - symbol_name = input_line_pointer; -#ifdef STRIP_UNDERSCORE - if (symbol_name[0] == '_' && symbol_name[1] != 0) - symbol_name++; -#endif /* STRIP_UNDERSCORE */ - - name_end = get_symbol_end (); - symbol_name_length = strlen (symbol_name); - symbol_name_copy = xmalloc (symbol_name_length + 1); - strcpy (symbol_name_copy, symbol_name); -#ifdef tc_canonicalize_symbol_name - symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy); -#endif - - /* Initialize the new symbol */ - def_symbol_in_progress = symbol_make (symbol_name_copy); - def_symbol_in_progress->sy_frag = &zero_address_frag; - S_SET_VALUE (def_symbol_in_progress, 0); - - if (S_IS_STRING (def_symbol_in_progress)) - SF_SET_STRING (def_symbol_in_progress); - - *input_line_pointer = name_end; - - demand_empty_rest_of_line (); -} - -unsigned int dim_index; - -static void -obj_coff_endef (ignore) - int ignore; -{ - symbolS *symbolP; - /* DIM BUG FIX sac@cygnus.com */ - dim_index = 0; - if (def_symbol_in_progress == NULL) - { - as_warn (".endef pseudo-op used outside of .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - /* Set the section number according to storage class. */ - switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) - { - case C_STRTAG: - case C_ENTAG: - case C_UNTAG: - SF_SET_TAG (def_symbol_in_progress); - /* intentional fallthrough */ - case C_FILE: - case C_TPDEF: - SF_SET_DEBUG (def_symbol_in_progress); - S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ()); - break; - - case C_EFCN: - SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ - /* intentional fallthrough */ - case C_BLOCK: - SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ - /* intentional fallthrough */ - case C_FCN: - { - CONST char *name; - S_SET_SEGMENT (def_symbol_in_progress, text_section); - - name = bfd_asymbol_name (def_symbol_in_progress->bsym); - if (name[1] == 'b' && name[2] == 'f') - { - if (! in_function ()) - as_warn ("`%s' symbol without preceding function", name); -/* SA_SET_SYM_LNNO (def_symbol_in_progress, 12345);*/ - /* Will need relocating */ - SF_SET_PROCESS (def_symbol_in_progress); - clear_function (); - } - } - break; - -#ifdef C_AUTOARG - case C_AUTOARG: -#endif /* C_AUTOARG */ - case C_AUTO: - case C_REG: - case C_ARG: - case C_REGPARM: - case C_FIELD: - SF_SET_DEBUG (def_symbol_in_progress); - S_SET_SEGMENT (def_symbol_in_progress, absolute_section); - break; - - case C_MOS: - case C_MOE: - case C_MOU: - case C_EOS: - S_SET_SEGMENT (def_symbol_in_progress, absolute_section); - break; - - case C_EXT: - case C_STAT: - case C_LABEL: - /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ - break; - - case C_USTATIC: - case C_EXTDEF: - case C_ULABEL: - as_warn ("unexpected storage class %d", - S_GET_STORAGE_CLASS (def_symbol_in_progress)); - break; - } /* switch on storage class */ - - /* Now that we have built a debug symbol, try to find if we should - merge with an existing symbol or not. If a symbol is C_EFCN or - SEG_ABSOLUTE or untagged SEG_DEBUG it never merges. */ - - /* Two cases for functions. Either debug followed by definition or - definition followed by debug. For definition first, we will - merge the debug symbol into the definition. For debug first, the - lineno entry MUST point to the definition function or else it - will point off into space when obj_crawl_symbol_chain() merges - the debug symbol into the real symbol. Therefor, let's presume - the debug symbol is a real function reference. */ - - /* FIXME-SOON If for some reason the definition label/symbol is - never seen, this will probably leave an undefined symbol at link - time. */ - - if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN - || (!strcmp (bfd_get_section_name (stdoutput, - S_GET_SEGMENT (def_symbol_in_progress)), - "*DEBUG*") - && !SF_GET_TAG (def_symbol_in_progress)) - || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section - || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL) - { - if (def_symbol_in_progress != symbol_lastP) - symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, - &symbol_lastP); - } - else - { - /* This symbol already exists, merge the newly created symbol - into the old one. This is not mandatory. The linker can - handle duplicate symbols correctly. But I guess that it save - a *lot* of space if the assembly file defines a lot of - symbols. [loic] */ - - /* The debug entry (def_symbol_in_progress) is merged into the - previous definition. */ - - c_symbol_merge (def_symbol_in_progress, symbolP); - symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); - - def_symbol_in_progress = symbolP; - - if (SF_GET_FUNCTION (def_symbol_in_progress) - || SF_GET_TAG (def_symbol_in_progress) - || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT) - { - /* For functions, and tags, and static symbols, the symbol - *must* be where the debug symbol appears. Move the - existing symbol to the current place. */ - /* If it already is at the end of the symbol list, do nothing */ - if (def_symbol_in_progress != symbol_lastP) - { - symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); - symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); - } - } - } - - if (SF_GET_TAG (def_symbol_in_progress)) - { - symbolS *oldtag; - - oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress), - DO_NOT_STRIP); - if (oldtag == NULL || ! SF_GET_TAG (oldtag)) - tag_insert (S_GET_NAME (def_symbol_in_progress), - def_symbol_in_progress); - } - - if (SF_GET_FUNCTION (def_symbol_in_progress)) - { - know (sizeof (def_symbol_in_progress) <= sizeof (long)); - set_function (def_symbol_in_progress); - SF_SET_PROCESS (def_symbol_in_progress); - - if (symbolP == NULL) - { - /* That is, if this is the first time we've seen the - function... */ - symbol_table_insert (def_symbol_in_progress); - } /* definition follows debug */ - } /* Create the line number entry pointing to the function being defined */ - - def_symbol_in_progress = NULL; - demand_empty_rest_of_line (); -} - -static void -obj_coff_dim (ignore) - int ignore; -{ - int dim_index; - - if (def_symbol_in_progress == NULL) - { - as_warn (".dim pseudo-op used outside of .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - - for (dim_index = 0; dim_index < DIMNUM; dim_index++) - { - SKIP_WHITESPACES (); - SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, - get_absolute_expression ()); - - switch (*input_line_pointer) - { - case ',': - input_line_pointer++; - break; - - default: - as_warn ("badly formed .dim directive ignored"); - /* intentional fallthrough */ - case '\n': - case ';': - dim_index = DIMNUM; - break; - } - } - - demand_empty_rest_of_line (); -} - -static void -obj_coff_line (ignore) - int ignore; -{ - int this_base; - - if (def_symbol_in_progress == NULL) - { - /* Probably stabs-style line? */ - obj_coff_ln (0); - return; - } - - this_base = get_absolute_expression (); - if (!strcmp (".bf", S_GET_NAME (def_symbol_in_progress))) - coff_line_base = this_base; - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base); - - demand_empty_rest_of_line (); - -#ifndef NO_LISTING - if (strcmp (".bf", S_GET_NAME (def_symbol_in_progress)) == 0) - { - extern int listing; - - if (listing) - listing_source_line ((unsigned int) coff_line_base); - } -#endif -} - -static void -obj_coff_size (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".size pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); - demand_empty_rest_of_line (); -} - -static void -obj_coff_scl (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".scl pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); - demand_empty_rest_of_line (); -} - -static void -obj_coff_tag (ignore) - int ignore; -{ - char *symbol_name; - char name_end; - - if (def_symbol_in_progress == NULL) - { - as_warn (".tag pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - symbol_name = input_line_pointer; - name_end = get_symbol_end (); - -#ifdef tc_canonicalize_symbol_name - symbol_name = tc_canonicalize_symbol_name (symbol_name); -#endif - - /* Assume that the symbol referred to by .tag is always defined. - This was a bad assumption. I've added find_or_make. xoxorich. */ - SA_SET_SYM_TAGNDX (def_symbol_in_progress, - tag_find_or_make (symbol_name)); - if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) - { - as_warn ("tag not found for .tag %s", symbol_name); - } /* not defined */ - - SF_SET_TAGGED (def_symbol_in_progress); - *input_line_pointer = name_end; - - demand_empty_rest_of_line (); -} - -static void -obj_coff_type (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".type pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); - - if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && - S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) - { - SF_SET_FUNCTION (def_symbol_in_progress); - } /* is a function */ - - demand_empty_rest_of_line (); -} - -static void -obj_coff_val (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".val pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - if (is_name_beginner (*input_line_pointer)) - { - char *symbol_name = input_line_pointer; - char name_end = get_symbol_end (); - -#ifdef tc_canonicalize_symbol_name - symbol_name = tc_canonicalize_symbol_name (symbol_name); -#endif - if (!strcmp (symbol_name, ".")) - { - def_symbol_in_progress->sy_frag = frag_now; - S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); - /* If the .val is != from the .def (e.g. statics) */ - } - else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) - { - def_symbol_in_progress->sy_value.X_op = O_symbol; - def_symbol_in_progress->sy_value.X_add_symbol = - symbol_find_or_make (symbol_name); - def_symbol_in_progress->sy_value.X_op_symbol = NULL; - def_symbol_in_progress->sy_value.X_add_number = 0; - - /* If the segment is undefined when the forward reference is - resolved, then copy the segment id from the forward - symbol. */ - SF_SET_GET_SEGMENT (def_symbol_in_progress); - } - /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ - *input_line_pointer = name_end; - } - else - { - S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ()); - } /* if symbol based */ - - demand_empty_rest_of_line (); -} - -void -coff_obj_read_begin_hook () -{ - /* These had better be the same. Usually 18 bytes. */ -#ifndef BFD_HEADERS - know (sizeof (SYMENT) == sizeof (AUXENT)); - know (SYMESZ == AUXESZ); -#endif - tag_init (); -} - - -symbolS *coff_last_function; -static symbolS *coff_last_bf; - -void -coff_frob_symbol (symp, punt) - symbolS *symp; - int *punt; -{ - static symbolS *last_tagP; - static stack *block_stack; - static symbolS *set_end; - symbolS *next_set_end = NULL; - - if (symp == &abs_symbol) - { - *punt = 1; - return; - } - - if (current_lineno_sym) - coff_add_linesym ((symbolS *) 0); - - if (!block_stack) - block_stack = stack_init (512, sizeof (symbolS*)); - - if (!S_IS_DEFINED (symp) && S_GET_STORAGE_CLASS (symp) != C_STAT) - S_SET_STORAGE_CLASS (symp, C_EXT); - - if (!SF_GET_DEBUG (symp)) - { - symbolS *real; - if (!SF_GET_LOCAL (symp) - && !SF_GET_STATICS (symp) - && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP)) - && real != symp) - { - c_symbol_merge (symp, real); - *punt = 1; - } - if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp)) - { - assert (S_GET_VALUE (symp) == 0); - S_SET_EXTERNAL (symp); - } - else if (S_GET_STORAGE_CLASS (symp) == C_NULL) - { - if (S_GET_SEGMENT (symp) == text_section - && symp != seg_info (text_section)->sym) - S_SET_STORAGE_CLASS (symp, C_LABEL); - else - S_SET_STORAGE_CLASS (symp, C_STAT); - } - if (SF_GET_PROCESS (symp)) - { - if (S_GET_STORAGE_CLASS (symp) == C_BLOCK) - { - if (!strcmp (S_GET_NAME (symp), ".bb")) - stack_push (block_stack, (char *) &symp); - else - { - symbolS *begin; - begin = *(symbolS **) stack_pop (block_stack); - if (begin == 0) - as_warn ("mismatched .eb"); - else - next_set_end = begin; - } - } - if (coff_last_function == 0 && SF_GET_FUNCTION (symp)) - { - union internal_auxent *auxp; - coff_last_function = symp; - if (S_GET_NUMBER_AUXILIARY (symp) < 1) - S_SET_NUMBER_AUXILIARY (symp, 1); - auxp = &coffsymbol (symp->bsym)->native[1].u.auxent; - memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0, - sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen)); - } - if (S_GET_STORAGE_CLASS (symp) == C_EFCN) - { - if (coff_last_function == 0) - as_fatal ("C_EFCN symbol out of scope"); - SA_SET_SYM_FSIZE (coff_last_function, - (long) (S_GET_VALUE (symp) - - S_GET_VALUE (coff_last_function))); - next_set_end = coff_last_function; - coff_last_function = 0; - } - } - if (S_IS_EXTERNAL (symp)) - S_SET_STORAGE_CLASS (symp, C_EXT); - else if (SF_GET_LOCAL (symp)) - *punt = 1; - - if (SF_GET_FUNCTION (symp)) - symp->bsym->flags |= BSF_FUNCTION; - - /* more ... */ - } - - if (SF_GET_TAG (symp)) - last_tagP = symp; - else if (S_GET_STORAGE_CLASS (symp) == C_EOS) - next_set_end = last_tagP; - -#ifdef OBJ_XCOFF - /* This is pretty horrible, but we have to set *punt correctly in - order to call SA_SET_SYM_ENDNDX correctly. */ - if (! symp->sy_used_in_reloc - && ((symp->bsym->flags & BSF_SECTION_SYM) != 0 - || (! S_IS_EXTERNAL (symp) - && ! symp->sy_tc.output - && S_GET_STORAGE_CLASS (symp) != C_FILE))) - *punt = 1; -#endif - - if (set_end != (symbolS *) NULL - && ! *punt - && ((symp->bsym->flags & BSF_NOT_AT_END) != 0 - || (S_IS_DEFINED (symp) - && ! S_IS_COMMON (symp) - && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp))))) - { - SA_SET_SYM_ENDNDX (set_end, symp); - set_end = NULL; - } - - if (next_set_end != NULL - && ! *punt) - set_end = next_set_end; - - if (! *punt - && S_GET_STORAGE_CLASS (symp) == C_FCN - && strcmp (S_GET_NAME (symp), ".bf") == 0) - { - if (coff_last_bf != NULL) - SA_SET_SYM_ENDNDX (coff_last_bf, symp); - coff_last_bf = symp; - } - - if (coffsymbol (symp->bsym)->lineno) - { - int i; - struct line_no *lptr; - alent *l; - - lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno; - for (i = 0; lptr; lptr = lptr->next) - i++; - lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno; - - /* We need i entries for line numbers, plus 1 for the first - entry which BFD will override, plus 1 for the last zero - entry (a marker for BFD). */ - l = (alent *) xmalloc ((i + 2) * sizeof (alent)); - coffsymbol (symp->bsym)->lineno = l; - l[i + 1].line_number = 0; - l[i + 1].u.sym = NULL; - for (; i > 0; i--) - { - if (lptr->frag) - lptr->l.u.offset += lptr->frag->fr_address; - l[i] = lptr->l; - lptr = lptr->next; - } - } -} - -void -coff_adjust_section_syms (abfd, sec, x) - bfd *abfd; - asection *sec; - PTR x; -{ - symbolS *secsym; - segment_info_type *seginfo = seg_info (sec); - int nlnno, nrelocs = 0; - - /* RS/6000 gas creates a .debug section manually in ppc_frob_file in - tc-ppc.c. Do not get confused by it. */ - if (seginfo == NULL) - return; - - if (!strcmp (sec->name, ".text")) - nlnno = coff_n_line_nos; - else - nlnno = 0; - { - /* @@ Hope that none of the fixups expand to more than one reloc - entry... */ - fixS *fixp = seginfo->fix_root; - while (fixp) - { - if (! fixp->fx_done) - nrelocs++; - fixp = fixp->fx_next; - } - } - if (bfd_get_section_size_before_reloc (sec) == 0 - && nrelocs == 0 - && nlnno == 0 - && sec != text_section - && sec != data_section - && sec != bss_section) - return; - secsym = section_symbol (sec); - SA_SET_SCN_NRELOC (secsym, nrelocs); - SA_SET_SCN_NLINNO (secsym, nlnno); -} - -void -coff_frob_file_after_relocs () -{ - bfd_map_over_sections (stdoutput, coff_adjust_section_syms, (char*) 0); -} - -/* - * implement the .section pseudo op: - * .section name {, "flags"} - * ^ ^ - * | +--- optional flags: 'b' for bss - * | 'i' for info - * +-- section name 'l' for lib - * 'n' for noload - * 'o' for over - * 'w' for data - * 'd' (apparently m88k for data) - * 'x' for text - * 'r' for read-only data - * But if the argument is not a quoted string, treat it as a - * subsegment number. - */ - -void -obj_coff_section (ignore) - int ignore; -{ - /* Strip out the section name */ - char *section_name; - char c; - char *name; - unsigned int exp; - flagword flags; - asection *sec; - - if (flag_mri) - { - char type; - - s_mri_sect (&type); - return; - } - - section_name = input_line_pointer; - c = get_symbol_end (); - - name = xmalloc (input_line_pointer - section_name + 1); - strcpy (name, section_name); - - *input_line_pointer = c; - - SKIP_WHITESPACE (); - - exp = 0; - flags = SEC_NO_FLAGS; - - if (*input_line_pointer == ',') - { - ++input_line_pointer; - SKIP_WHITESPACE (); - if (*input_line_pointer != '"') - exp = get_absolute_expression (); - else - { - ++input_line_pointer; - while (*input_line_pointer != '"' - && ! is_end_of_line[(unsigned char) *input_line_pointer]) - { - switch (*input_line_pointer) - { - case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break; - case 'n': flags &=~ SEC_LOAD; break; - case 'd': - case 'w': flags &=~ SEC_READONLY; break; - case 'x': flags |= SEC_CODE; break; - case 'r': flags |= SEC_READONLY; break; - - case 'i': /* STYP_INFO */ - case 'l': /* STYP_LIB */ - case 'o': /* STYP_OVER */ - as_warn ("unsupported section attribute '%c'", - *input_line_pointer); - break; - - default: - as_warn("unknown section attribute '%c'", - *input_line_pointer); - break; - } - ++input_line_pointer; - } - if (*input_line_pointer == '"') - ++input_line_pointer; - } - } - - sec = subseg_new (name, (subsegT) exp); - - if (flags != SEC_NO_FLAGS) - { - if (! bfd_set_section_flags (stdoutput, sec, flags)) - as_warn ("error setting flags for \"%s\": %s", - bfd_section_name (stdoutput, sec), - bfd_errmsg (bfd_get_error ())); - } - - demand_empty_rest_of_line (); -} - -void -coff_adjust_symtab () -{ - if (symbol_rootP == NULL - || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) - c_dot_file_symbol ("fake"); -} - -void -coff_frob_section (sec) - segT sec; -{ - segT strsec; - char *p; - fragS *fragp; - bfd_vma size, n_entries, mask; - - /* The COFF back end in BFD requires that all section sizes be - rounded up to multiples of the corresponding section alignments. - Seems kinda silly to me, but that's the way it is. */ - size = bfd_get_section_size_before_reloc (sec); - mask = ((bfd_vma) 1 << (bfd_vma) sec->alignment_power) - 1; - if (size & mask) - { - size = (size + mask) & ~mask; - bfd_set_section_size (stdoutput, sec, size); - } - - /* If the section size is non-zero, the section symbol needs an aux - entry associated with it, indicating the size. We don't know - all the values yet; coff_frob_symbol will fill them in later. */ - if (size != 0 - || sec == text_section - || sec == data_section - || sec == bss_section) - { - symbolS *secsym = section_symbol (sec); - - S_SET_STORAGE_CLASS (secsym, C_STAT); - S_SET_NUMBER_AUXILIARY (secsym, 1); - SF_SET_STATICS (secsym); - SA_SET_SCN_SCNLEN (secsym, size); - } - - /* @@ these should be in a "stabs.h" file, or maybe as.h */ -#ifndef STAB_SECTION_NAME -#define STAB_SECTION_NAME ".stab" -#endif -#ifndef STAB_STRING_SECTION_NAME -#define STAB_STRING_SECTION_NAME ".stabstr" -#endif - if (strcmp (STAB_STRING_SECTION_NAME, sec->name)) - return; - - strsec = sec; - sec = subseg_get (STAB_SECTION_NAME, 0); - /* size is already rounded up, since other section will be listed first */ - size = bfd_get_section_size_before_reloc (strsec); - - n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1; - - /* Find first non-empty frag. It should be large enough. */ - fragp = seg_info (sec)->frchainP->frch_root; - while (fragp && fragp->fr_fix == 0) - fragp = fragp->fr_next; - assert (fragp != 0 && fragp->fr_fix >= 12); - - /* Store the values. */ - p = fragp->fr_literal; - bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6); - bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8); -} - -void -obj_coff_init_stab_section (seg) - segT seg; -{ - char *file; - char *p; - char *stabstr_name; - unsigned int stroff; - - /* Make space for this first symbol. */ - p = frag_more (12); - /* Zero it out. */ - memset (p, 0, 12); - as_where (&file, (unsigned int *) NULL); - stabstr_name = (char *) alloca (strlen (seg->name) + 4); - strcpy (stabstr_name, seg->name); - strcat (stabstr_name, "str"); - stroff = get_stab_string_offset (file, stabstr_name); - know (stroff == 1); - md_number_to_chars (p, stroff, 4); -} - -#ifdef DEBUG -/* for debugging */ -const char * -s_get_name (s) - symbolS *s; -{ - return ((s == NULL) ? "(NULL)" : S_GET_NAME (s)); -} - -void -symbol_dump () -{ - symbolS *symbolP; - - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - printf("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n", - (unsigned long) symbolP, - S_GET_NAME(symbolP), - (long) S_GET_DATA_TYPE(symbolP), - S_GET_STORAGE_CLASS(symbolP), - (int) S_GET_SEGMENT(symbolP)); - } -} - -#endif /* DEBUG */ - -#else /* not BFD_ASSEMBLER */ - -#include "frags.h" -/* This is needed because we include internal bfd things. */ -#include <time.h> - -#include "libbfd.h" -#include "libcoff.h" - -#ifdef TE_PE -#include "coff/pe.h" -#endif - -/* The NOP_OPCODE is for the alignment fill value. Fill with nop so - that we can stick sections together without causing trouble. */ -#ifndef NOP_OPCODE -#define NOP_OPCODE 0x00 -#endif - -/* The zeroes if symbol name is longer than 8 chars */ -#define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v)) - -#define MIN(a,b) ((a) < (b)? (a) : (b)) -/* This vector is used to turn an internal segment into a section # - suitable for insertion into a coff symbol table - */ - -const short seg_N_TYPE[] = -{ /* in: segT out: N_TYPE bits */ - C_ABS_SECTION, - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - C_UNDEF_SECTION, /* SEG_UNKNOWN */ - C_UNDEF_SECTION, /* SEG_GOOF */ - C_UNDEF_SECTION, /* SEG_EXPR */ - C_DEBUG_SECTION, /* SEG_DEBUG */ - C_NTV_SECTION, /* SEG_NTV */ - C_PTV_SECTION, /* SEG_PTV */ - C_REGISTER_SECTION, /* SEG_REGISTER */ -}; - -int function_lineoff = -1; /* Offset in line#s where the last function - started (the odd entry for line #0) */ - -/* structure used to keep the filenames which - are too long around so that we can stick them - into the string table */ -struct filename_list -{ - char *filename; - struct filename_list *next; -}; - -static struct filename_list *filename_list_head; -static struct filename_list *filename_list_tail; - -static symbolS *last_line_symbol; - -/* Add 4 to the real value to get the index and compensate the - negatives. This vector is used by S_GET_SEGMENT to turn a coff - section number into a segment number -*/ -static symbolS *previous_file_symbol; -void c_symbol_merge (); -static int line_base; - -symbolS *c_section_symbol (); -bfd *abfd; - -static void fixup_segment PARAMS ((segment_info_type *segP, - segT this_segment_type)); - - -static void fixup_mdeps PARAMS ((fragS *, - object_headers *, - segT)); - - -static void fill_section PARAMS ((bfd * abfd, - object_headers *, - unsigned long *)); - - -static int c_line_new PARAMS ((symbolS * symbol, long paddr, - int line_number, - fragS * frag)); - - -static void w_symbols PARAMS ((bfd * abfd, char *where, - symbolS * symbol_rootP)); - -static void adjust_stab_section PARAMS ((bfd *abfd, segT seg)); - -static void obj_coff_lcomm PARAMS ((int)); -static void obj_coff_text PARAMS ((int)); -static void obj_coff_data PARAMS ((int)); -static void obj_coff_ident PARAMS ((int)); -void obj_coff_section PARAMS ((int)); - -/* Section stuff - - We allow more than just the standard 3 sections, infact, we allow - 40 sections, (though the usual three have to be there). - - This structure performs the mappings for us: -*/ - - -typedef struct -{ - segT seg_t; - int i; -} seg_info_type; - -static const seg_info_type seg_info_off_by_4[] = -{ - {SEG_PTV, }, - {SEG_NTV, }, - {SEG_DEBUG, }, - {SEG_ABSOLUTE, }, - {SEG_UNKNOWN, }, - {SEG_E0}, {SEG_E1}, {SEG_E2}, {SEG_E3}, {SEG_E4}, - {SEG_E5}, {SEG_E6}, {SEG_E7}, {SEG_E8}, {SEG_E9}, - {SEG_E10},{SEG_E11},{SEG_E12},{SEG_E13},{SEG_E14}, - {SEG_E15},{SEG_E16},{SEG_E17},{SEG_E18},{SEG_E19}, - {SEG_E20},{SEG_E21},{SEG_E22},{SEG_E23},{SEG_E24}, - {SEG_E25},{SEG_E26},{SEG_E27},{SEG_E28},{SEG_E29}, - {SEG_E30},{SEG_E31},{SEG_E32},{SEG_E33},{SEG_E34}, - {SEG_E35},{SEG_E36},{SEG_E37},{SEG_E38},{SEG_E39}, - {(segT)40}, - {(segT)41}, - {(segT)42}, - {(segT)43}, - {(segT)44}, - {(segT)45}, - {(segT)0}, - {(segT)0}, - {(segT)0}, - {SEG_REGISTER} -}; - - - -#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4]) - -static relax_addressT -relax_align (address, alignment) - relax_addressT address; - long alignment; -{ - relax_addressT mask; - relax_addressT new_address; - - mask = ~((~0) << alignment); - new_address = (address + mask) & (~mask); - return (new_address - address); -} - - -segT -s_get_segment (x) - symbolS * x; -{ - return SEG_INFO_FROM_SECTION_NUMBER (x->sy_symbol.ost_entry.n_scnum).seg_t; -} - -/* calculate the size of the frag chain and fill in the section header - to contain all of it, also fill in the addr of the sections */ -static unsigned int -size_section (abfd, idx) - bfd * abfd; - unsigned int idx; -{ - - unsigned int size = 0; - fragS *frag = segment_info[idx].frchainP->frch_root; - while (frag) - { - size = frag->fr_address; - if (frag->fr_address != size) - { - fprintf (stderr, "Out of step\n"); - size = frag->fr_address; - } - - switch (frag->fr_type) - { -#ifdef TC_COFF_SIZEMACHDEP - case rs_machine_dependent: - size += TC_COFF_SIZEMACHDEP (frag); - break; -#endif - case rs_space: - assert (frag->fr_symbol == 0); - case rs_fill: - case rs_org: - size += frag->fr_fix; - size += frag->fr_offset * frag->fr_var; - break; - case rs_align: - case rs_align_code: - { - addressT off; - - size += frag->fr_fix; - off = relax_align (size, frag->fr_offset); - if (frag->fr_subtype != 0 && off > frag->fr_subtype) - off = 0; - size += off; - } - break; - default: - BAD_CASE (frag->fr_type); - break; - } - frag = frag->fr_next; - } - segment_info[idx].scnhdr.s_size = size; - return size; -} - - -static unsigned int -count_entries_in_chain (idx) - unsigned int idx; -{ - unsigned int nrelocs; - fixS *fixup_ptr; - - /* Count the relocations */ - fixup_ptr = segment_info[idx].fix_root; - nrelocs = 0; - while (fixup_ptr != (fixS *) NULL) - { - if (fixup_ptr->fx_done == 0 && TC_COUNT_RELOC (fixup_ptr)) - { -#ifdef TC_A29K - if (fixup_ptr->fx_r_type == RELOC_CONSTH) - nrelocs += 2; - else - nrelocs++; -#else - nrelocs++; -#endif - } - - fixup_ptr = fixup_ptr->fx_next; - } - return nrelocs; -} - -#ifdef TE_AUX - -static int compare_external_relocs PARAMS ((const PTR, const PTR)); - -/* AUX's ld expects relocations to be sorted */ -static int -compare_external_relocs (x, y) - const PTR x; - const PTR y; -{ - struct external_reloc *a = (struct external_reloc *) x; - struct external_reloc *b = (struct external_reloc *) y; - bfd_vma aadr = bfd_getb32 (a->r_vaddr); - bfd_vma badr = bfd_getb32 (b->r_vaddr); - return (aadr < badr ? -1 : badr < aadr ? 1 : 0); -} - -#endif - -/* output all the relocations for a section */ -void -do_relocs_for (abfd, h, file_cursor) - bfd * abfd; - object_headers * h; - unsigned long *file_cursor; -{ - unsigned int nrelocs; - unsigned int idx; - unsigned long reloc_start = *file_cursor; - - for (idx = SEG_E0; idx < SEG_LAST; idx++) - { - if (segment_info[idx].scnhdr.s_name[0]) - { - struct external_reloc *ext_ptr; - struct external_reloc *external_reloc_vec; - unsigned int external_reloc_size; - unsigned int base = segment_info[idx].scnhdr.s_paddr; - fixS *fix_ptr = segment_info[idx].fix_root; - nrelocs = count_entries_in_chain (idx); - - if (nrelocs) - /* Bypass this stuff if no relocs. This also incidentally - avoids a SCO bug, where free(malloc(0)) tends to crash. */ - { - external_reloc_size = nrelocs * RELSZ; - external_reloc_vec = - (struct external_reloc *) malloc (external_reloc_size); - - ext_ptr = external_reloc_vec; - - /* Fill in the internal coff style reloc struct from the - internal fix list. */ - while (fix_ptr) - { - struct internal_reloc intr; - - /* Only output some of the relocations */ - if (fix_ptr->fx_done == 0 && TC_COUNT_RELOC (fix_ptr)) - { -#ifdef TC_RELOC_MANGLE - TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr, - base); - -#else - symbolS *dot; - symbolS *symbol_ptr = fix_ptr->fx_addsy; - - intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr); - intr.r_vaddr = - base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where; - -#ifdef TC_KEEP_FX_OFFSET - intr.r_offset = fix_ptr->fx_offset; -#else - intr.r_offset = 0; -#endif - - while (symbol_ptr->sy_value.X_op == O_symbol - && (! S_IS_DEFINED (symbol_ptr) - || S_IS_COMMON (symbol_ptr))) - { - symbolS *n; - - /* We must avoid looping, as that can occur - with a badly written program. */ - n = symbol_ptr->sy_value.X_add_symbol; - if (n == symbol_ptr) - break; - symbol_ptr = n; - } - - /* Turn the segment of the symbol into an offset. */ - if (symbol_ptr) - { - resolve_symbol_value (symbol_ptr, 1); - if (! symbol_ptr->sy_resolved) - { - char *file; - unsigned int line; - - if (expr_symbol_where (symbol_ptr, &file, &line)) - as_bad_where (file, line, - "unresolved relocation"); - else - as_bad ("bad relocation: symbol `%s' not in symbol table", - S_GET_NAME (symbol_ptr)); - } - dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; - if (dot) - { - intr.r_symndx = dot->sy_number; - } - else - { - intr.r_symndx = symbol_ptr->sy_number; - } - - } - else - { - intr.r_symndx = -1; - } -#endif - - (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); - ext_ptr++; - -#if defined(TC_A29K) - - /* The 29k has a special kludge for the high 16 bit - reloc. Two relocations are emited, R_IHIHALF, - and R_IHCONST. The second one doesn't contain a - symbol, but uses the value for offset. */ - - if (intr.r_type == R_IHIHALF) - { - /* now emit the second bit */ - intr.r_type = R_IHCONST; - intr.r_symndx = fix_ptr->fx_addnumber; - (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); - ext_ptr++; - } -#endif - } - - fix_ptr = fix_ptr->fx_next; - } - -#ifdef TE_AUX - /* Sort the reloc table */ - qsort ((PTR) external_reloc_vec, nrelocs, - sizeof (struct external_reloc), compare_external_relocs); -#endif - - /* Write out the reloc table */ - bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, - abfd); - free (external_reloc_vec); - - /* Fill in section header info. */ - segment_info[idx].scnhdr.s_relptr = *file_cursor; - *file_cursor += external_reloc_size; - segment_info[idx].scnhdr.s_nreloc = nrelocs; - } - else - { - /* No relocs */ - segment_info[idx].scnhdr.s_relptr = 0; - } - } - } - /* Set relocation_size field in file headers */ - H_SET_RELOCATION_SIZE (h, *file_cursor - reloc_start, 0); -} - - -/* run through a frag chain and write out the data to go with it, fill - in the scnhdrs with the info on the file postions -*/ -static void -fill_section (abfd, h, file_cursor) - bfd * abfd; - object_headers *h; - unsigned long *file_cursor; -{ - - unsigned int i; - unsigned int paddr = 0; - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - unsigned int offset = 0; - struct internal_scnhdr *s = &(segment_info[i].scnhdr); - - PROGRESS (1); - - if (s->s_name[0]) - { - fragS *frag = segment_info[i].frchainP->frch_root; - char *buffer; - - if (s->s_size == 0) - s->s_scnptr = 0; - else - { - buffer = xmalloc (s->s_size); - s->s_scnptr = *file_cursor; - } - know (s->s_paddr == paddr); - - if (strcmp (s->s_name, ".text") == 0) - s->s_flags |= STYP_TEXT; - else if (strcmp (s->s_name, ".data") == 0) - s->s_flags |= STYP_DATA; - else if (strcmp (s->s_name, ".bss") == 0) - { - s->s_scnptr = 0; - s->s_flags |= STYP_BSS; - - /* @@ Should make the i386 and a29k coff targets define - COFF_NOLOAD_PROBLEM, and have only one test here. */ -#ifndef TC_I386 -#ifndef TC_A29K -#ifndef COFF_NOLOAD_PROBLEM - /* Apparently the SVR3 linker (and exec syscall) and UDI - mondfe progrem are confused by noload sections. */ - s->s_flags |= STYP_NOLOAD; -#endif -#endif -#endif - } - else if (strcmp (s->s_name, ".lit") == 0) - s->s_flags = STYP_LIT | STYP_TEXT; - else if (strcmp (s->s_name, ".init") == 0) - s->s_flags |= STYP_TEXT; - else if (strcmp (s->s_name, ".fini") == 0) - s->s_flags |= STYP_TEXT; - else if (strncmp (s->s_name, ".comment", 8) == 0) - s->s_flags |= STYP_INFO; - - while (frag) - { - unsigned int fill_size; - switch (frag->fr_type) - { - case rs_machine_dependent: - if (frag->fr_fix) - { - memcpy (buffer + frag->fr_address, - frag->fr_literal, - (unsigned int) frag->fr_fix); - offset += frag->fr_fix; - } - - break; - case rs_space: - assert (frag->fr_symbol == 0); - case rs_fill: - case rs_align: - case rs_align_code: - case rs_org: - if (frag->fr_fix) - { - memcpy (buffer + frag->fr_address, - frag->fr_literal, - (unsigned int) frag->fr_fix); - offset += frag->fr_fix; - } - - fill_size = frag->fr_var; - if (fill_size && frag->fr_offset > 0) - { - unsigned int count; - unsigned int off = frag->fr_fix; - for (count = frag->fr_offset; count; count--) - { - if (fill_size + frag->fr_address + off <= s->s_size) - { - memcpy (buffer + frag->fr_address + off, - frag->fr_literal + frag->fr_fix, - fill_size); - off += fill_size; - offset += fill_size; - } - } - } - break; - case rs_broken_word: - break; - default: - abort (); - } - frag = frag->fr_next; - } - - if (s->s_size != 0) - { - if (s->s_scnptr != 0) - { - bfd_write (buffer, s->s_size, 1, abfd); - *file_cursor += s->s_size; - } - free (buffer); - } - paddr += s->s_size; - } - } -} - -/* Coff file generation & utilities */ - -static void -coff_header_append (abfd, h) - bfd * abfd; - object_headers * h; -{ - unsigned int i; - char buffer[1000]; - char buffero[1000]; -#ifdef COFF_LONG_SECTION_NAMES - unsigned long string_size = 4; -#endif - - bfd_seek (abfd, 0, 0); - -#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER - H_SET_MAGIC_NUMBER (h, COFF_MAGIC); - H_SET_VERSION_STAMP (h, 0); - H_SET_ENTRY_POINT (h, 0); - H_SET_TEXT_START (h, segment_info[SEG_E0].frchainP->frch_root->fr_address); - H_SET_DATA_START (h, segment_info[SEG_E1].frchainP->frch_root->fr_address); - H_SET_SIZEOF_OPTIONAL_HEADER (h, bfd_coff_swap_aouthdr_out(abfd, &h->aouthdr, - buffero)); -#else /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ - H_SET_SIZEOF_OPTIONAL_HEADER (h, 0); -#endif /* defined (OBJ_COFF_OMIT_OPTIONAL_HEADER) */ - - i = bfd_coff_swap_filehdr_out (abfd, &h->filehdr, buffer); - - bfd_write (buffer, i, 1, abfd); - bfd_write (buffero, H_GET_SIZEOF_OPTIONAL_HEADER (h), 1, abfd); - - for (i = SEG_E0; i < SEG_LAST; i++) - { - if (segment_info[i].scnhdr.s_name[0]) - { - unsigned int size; - -#ifdef COFF_LONG_SECTION_NAMES - /* Support long section names as found in PE. This code - must coordinate with that in write_object_file and - w_strings. */ - if (strlen (segment_info[i].name) > SCNNMLEN) - { - memset (segment_info[i].scnhdr.s_name, 0, SCNNMLEN); - sprintf (segment_info[i].scnhdr.s_name, "/%lu", string_size); - string_size += strlen (segment_info[i].name) + 1; - } -#endif - - size = bfd_coff_swap_scnhdr_out (abfd, - &(segment_info[i].scnhdr), - buffer); - if (size == 0) - as_bad ("bfd_coff_swap_scnhdr_out failed"); - bfd_write (buffer, size, 1, abfd); - } - } -} - - -char * -symbol_to_chars (abfd, where, symbolP) - bfd * abfd; - char *where; - symbolS * symbolP; -{ - unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux; - unsigned int i; - valueT val; - - /* Turn any symbols with register attributes into abs symbols */ - if (S_GET_SEGMENT (symbolP) == reg_section) - { - S_SET_SEGMENT (symbolP, absolute_section); - } - /* At the same time, relocate all symbols to their output value */ - -#ifndef TE_PE - val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr - + S_GET_VALUE (symbolP)); -#else - val = S_GET_VALUE (symbolP); -#endif - - S_SET_VALUE (symbolP, val); - - symbolP->sy_symbol.ost_entry.n_value = val; - - where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry, - where); - - for (i = 0; i < numaux; i++) - { - where += bfd_coff_swap_aux_out (abfd, - &symbolP->sy_symbol.ost_auxent[i], - S_GET_DATA_TYPE (symbolP), - S_GET_STORAGE_CLASS (symbolP), - i, numaux, where); - } - return where; - -} - -void -coff_obj_symbol_new_hook (symbolP) - symbolS *symbolP; -{ - char underscore = 0; /* Symbol has leading _ */ - - /* Effective symbol */ - /* Store the pointer in the offset. */ - S_SET_ZEROES (symbolP, 0L); - S_SET_DATA_TYPE (symbolP, T_NULL); - S_SET_STORAGE_CLASS (symbolP, 0); - S_SET_NUMBER_AUXILIARY (symbolP, 0); - /* Additional information */ - symbolP->sy_symbol.ost_flags = 0; - /* Auxiliary entries */ - memset ((char *) &symbolP->sy_symbol.ost_auxent[0], 0, AUXESZ); - - if (S_IS_STRING (symbolP)) - SF_SET_STRING (symbolP); - if (!underscore && S_IS_LOCAL (symbolP)) - SF_SET_LOCAL (symbolP); -} - -/* - * Handle .ln directives. - */ - -static void -obj_coff_ln (appline) - int appline; -{ - int l; - - if (! appline && def_symbol_in_progress != NULL) - { - as_warn (".ln pseudo-op inside .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } /* wrong context */ - - l = get_absolute_expression (); - c_line_new (0, frag_now_fix (), l, frag_now); - - if (appline) - new_logical_line ((char *) NULL, l - 1); - -#ifndef NO_LISTING - { - extern int listing; - - if (listing) - { - if (! appline) - l += line_base - 1; - listing_source_line ((unsigned int) l); - } - - } -#endif - demand_empty_rest_of_line (); -} - -/* - * def() - * - * Handle .def directives. - * - * One might ask : why can't we symbol_new if the symbol does not - * already exist and fill it with debug information. Because of - * the C_EFCN special symbol. It would clobber the value of the - * function symbol before we have a chance to notice that it is - * a C_EFCN. And a second reason is that the code is more clear this - * way. (at least I think it is :-). - * - */ - -#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';') -#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \ - *input_line_pointer == '\t') \ - input_line_pointer++; - -static void -obj_coff_def (what) - int what; -{ - char name_end; /* Char after the end of name */ - char *symbol_name; /* Name of the debug symbol */ - char *symbol_name_copy; /* Temporary copy of the name */ - unsigned int symbol_name_length; - - if (def_symbol_in_progress != NULL) - { - as_warn (".def pseudo-op used inside of .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - SKIP_WHITESPACES (); - - def_symbol_in_progress = (symbolS *) obstack_alloc (¬es, sizeof (*def_symbol_in_progress)); - memset (def_symbol_in_progress, 0, sizeof (*def_symbol_in_progress)); - - symbol_name = input_line_pointer; - name_end = get_symbol_end (); - symbol_name_length = strlen (symbol_name); - symbol_name_copy = xmalloc (symbol_name_length + 1); - strcpy (symbol_name_copy, symbol_name); -#ifdef tc_canonicalize_symbol_name - symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy); -#endif - - /* Initialize the new symbol */ -#ifdef STRIP_UNDERSCORE - S_SET_NAME (def_symbol_in_progress, (*symbol_name_copy == '_' - ? symbol_name_copy + 1 - : symbol_name_copy)); -#else /* STRIP_UNDERSCORE */ - S_SET_NAME (def_symbol_in_progress, symbol_name_copy); -#endif /* STRIP_UNDERSCORE */ - /* free(symbol_name_copy); */ - def_symbol_in_progress->sy_name_offset = (unsigned long) ~0; - def_symbol_in_progress->sy_number = ~0; - def_symbol_in_progress->sy_frag = &zero_address_frag; - S_SET_VALUE (def_symbol_in_progress, 0); - - if (S_IS_STRING (def_symbol_in_progress)) - SF_SET_STRING (def_symbol_in_progress); - - *input_line_pointer = name_end; - - demand_empty_rest_of_line (); -} - -unsigned int dim_index; - - -static void -obj_coff_endef (ignore) - int ignore; -{ - symbolS *symbolP = 0; - /* DIM BUG FIX sac@cygnus.com */ - dim_index = 0; - if (def_symbol_in_progress == NULL) - { - as_warn (".endef pseudo-op used outside of .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - /* Set the section number according to storage class. */ - switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) - { - case C_STRTAG: - case C_ENTAG: - case C_UNTAG: - SF_SET_TAG (def_symbol_in_progress); - /* intentional fallthrough */ - case C_FILE: - case C_TPDEF: - SF_SET_DEBUG (def_symbol_in_progress); - S_SET_SEGMENT (def_symbol_in_progress, SEG_DEBUG); - break; - - case C_EFCN: - SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ - /* intentional fallthrough */ - case C_BLOCK: - SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */ - /* intentional fallthrough */ - case C_FCN: - S_SET_SEGMENT (def_symbol_in_progress, SEG_E0); - - if (strcmp (S_GET_NAME (def_symbol_in_progress), ".bf") == 0) - { /* .bf */ - if (function_lineoff < 0) - { - fprintf (stderr, "`.bf' symbol without preceding function\n"); - } /* missing function symbol */ - SA_GET_SYM_LNNOPTR (last_line_symbol) = function_lineoff; - - SF_SET_PROCESS (last_line_symbol); - SF_SET_ADJ_LNNOPTR (last_line_symbol); - SF_SET_PROCESS (def_symbol_in_progress); - function_lineoff = -1; - } - /* Value is always set to . */ - def_symbol_in_progress->sy_frag = frag_now; - S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); - break; - -#ifdef C_AUTOARG - case C_AUTOARG: -#endif /* C_AUTOARG */ - case C_AUTO: - case C_REG: - case C_MOS: - case C_MOE: - case C_MOU: - case C_ARG: - case C_REGPARM: - case C_FIELD: - case C_EOS: - SF_SET_DEBUG (def_symbol_in_progress); - S_SET_SEGMENT (def_symbol_in_progress, absolute_section); - break; - - case C_EXT: - case C_STAT: - case C_LABEL: - /* Valid but set somewhere else (s_comm, s_lcomm, colon) */ - break; - - case C_USTATIC: - case C_EXTDEF: - case C_ULABEL: - as_warn ("unexpected storage class %d", S_GET_STORAGE_CLASS (def_symbol_in_progress)); - break; - } /* switch on storage class */ - - /* Now that we have built a debug symbol, try to find if we should - merge with an existing symbol or not. If a symbol is C_EFCN or - absolute_section or untagged SEG_DEBUG it never merges. We also - don't merge labels, which are in a different namespace, nor - symbols which have not yet been defined since they are typically - unique, nor do we merge tags with non-tags. */ - - /* Two cases for functions. Either debug followed by definition or - definition followed by debug. For definition first, we will - merge the debug symbol into the definition. For debug first, the - lineno entry MUST point to the definition function or else it - will point off into space when crawl_symbols() merges the debug - symbol into the real symbol. Therefor, let's presume the debug - symbol is a real function reference. */ - - /* FIXME-SOON If for some reason the definition label/symbol is - never seen, this will probably leave an undefined symbol at link - time. */ - - if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN - || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL - || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG - && !SF_GET_TAG (def_symbol_in_progress)) - || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section - || def_symbol_in_progress->sy_value.X_op != O_constant - || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL - || (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))) - { - symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, - &symbol_lastP); - } - else - { - /* This symbol already exists, merge the newly created symbol - into the old one. This is not mandatory. The linker can - handle duplicate symbols correctly. But I guess that it save - a *lot* of space if the assembly file defines a lot of - symbols. [loic] */ - - /* The debug entry (def_symbol_in_progress) is merged into the - previous definition. */ - - c_symbol_merge (def_symbol_in_progress, symbolP); - /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */ - def_symbol_in_progress = symbolP; - - if (SF_GET_FUNCTION (def_symbol_in_progress) - || SF_GET_TAG (def_symbol_in_progress) - || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT) - { - /* For functions, and tags, and static symbols, the symbol - *must* be where the debug symbol appears. Move the - existing symbol to the current place. */ - /* If it already is at the end of the symbol list, do nothing */ - if (def_symbol_in_progress != symbol_lastP) - { - symbol_remove (def_symbol_in_progress, &symbol_rootP, - &symbol_lastP); - symbol_append (def_symbol_in_progress, symbol_lastP, - &symbol_rootP, &symbol_lastP); - } /* if not already in place */ - } /* if function */ - } /* normal or mergable */ - - if (SF_GET_TAG (def_symbol_in_progress)) - { - symbolS *oldtag; - - oldtag = symbol_find_base (S_GET_NAME (def_symbol_in_progress), - DO_NOT_STRIP); - if (oldtag == NULL || ! SF_GET_TAG (oldtag)) - tag_insert (S_GET_NAME (def_symbol_in_progress), - def_symbol_in_progress); - } - - if (SF_GET_FUNCTION (def_symbol_in_progress)) - { - know (sizeof (def_symbol_in_progress) <= sizeof (long)); - function_lineoff - = c_line_new (def_symbol_in_progress, 0, 0, &zero_address_frag); - - SF_SET_PROCESS (def_symbol_in_progress); - - if (symbolP == NULL) - { - /* That is, if this is the first time we've seen the - function... */ - symbol_table_insert (def_symbol_in_progress); - } /* definition follows debug */ - } /* Create the line number entry pointing to the function being defined */ - - def_symbol_in_progress = NULL; - demand_empty_rest_of_line (); -} - -static void -obj_coff_dim (ignore) - int ignore; -{ - int dim_index; - - if (def_symbol_in_progress == NULL) - { - as_warn (".dim pseudo-op used outside of .def/.endef: ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - - for (dim_index = 0; dim_index < DIMNUM; dim_index++) - { - SKIP_WHITESPACES (); - SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index, - get_absolute_expression ()); - - switch (*input_line_pointer) - { - case ',': - input_line_pointer++; - break; - - default: - as_warn ("badly formed .dim directive ignored"); - /* intentional fallthrough */ - case '\n': - case ';': - dim_index = DIMNUM; - break; - } - } - - demand_empty_rest_of_line (); -} - -static void -obj_coff_line (ignore) - int ignore; -{ - int this_base; - const char *name; - - if (def_symbol_in_progress == NULL) - { - obj_coff_ln (0); - return; - } - - name = S_GET_NAME (def_symbol_in_progress); - this_base = get_absolute_expression (); - - /* Only .bf symbols indicate the use of a new base line number; the - line numbers associated with .ef, .bb, .eb are relative to the - start of the containing function. */ - if (!strcmp (".bf", name)) - { -#if 0 /* XXX Can we ever have line numbers going backwards? */ - if (this_base > line_base) -#endif - { - line_base = this_base; - } - -#ifndef NO_LISTING - { - extern int listing; - if (listing) - { - listing_source_line ((unsigned int) line_base); - } - } -#endif - } - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - SA_SET_SYM_LNNO (def_symbol_in_progress, this_base); - - demand_empty_rest_of_line (); -} - -static void -obj_coff_size (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".size pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ()); - demand_empty_rest_of_line (); -} - -static void -obj_coff_scl (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".scl pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ()); - demand_empty_rest_of_line (); -} - -static void -obj_coff_tag (ignore) - int ignore; -{ - char *symbol_name; - char name_end; - - if (def_symbol_in_progress == NULL) - { - as_warn (".tag pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } - - S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1); - symbol_name = input_line_pointer; - name_end = get_symbol_end (); -#ifdef tc_canonicalize_symbol_name - symbol_name = tc_canonicalize_symbol_name (symbol_name); -#endif - - /* Assume that the symbol referred to by .tag is always defined. - This was a bad assumption. I've added find_or_make. xoxorich. */ - SA_SET_SYM_TAGNDX (def_symbol_in_progress, - (long) tag_find_or_make (symbol_name)); - if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L) - { - as_warn ("tag not found for .tag %s", symbol_name); - } /* not defined */ - - SF_SET_TAGGED (def_symbol_in_progress); - *input_line_pointer = name_end; - - demand_empty_rest_of_line (); -} - -static void -obj_coff_type (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".type pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ()); - - if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) && - S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF) - { - SF_SET_FUNCTION (def_symbol_in_progress); - } /* is a function */ - - demand_empty_rest_of_line (); -} - -static void -obj_coff_val (ignore) - int ignore; -{ - if (def_symbol_in_progress == NULL) - { - as_warn (".val pseudo-op used outside of .def/.endef ignored."); - demand_empty_rest_of_line (); - return; - } /* if not inside .def/.endef */ - - if (is_name_beginner (*input_line_pointer)) - { - char *symbol_name = input_line_pointer; - char name_end = get_symbol_end (); - -#ifdef tc_canonicalize_symbol_name - symbol_name = tc_canonicalize_symbol_name (symbol_name); -#endif - - if (!strcmp (symbol_name, ".")) - { - def_symbol_in_progress->sy_frag = frag_now; - S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); - /* If the .val is != from the .def (e.g. statics) */ - } - else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name)) - { - def_symbol_in_progress->sy_value.X_op = O_symbol; - def_symbol_in_progress->sy_value.X_add_symbol = - symbol_find_or_make (symbol_name); - def_symbol_in_progress->sy_value.X_op_symbol = NULL; - def_symbol_in_progress->sy_value.X_add_number = 0; - - /* If the segment is undefined when the forward reference is - resolved, then copy the segment id from the forward - symbol. */ - SF_SET_GET_SEGMENT (def_symbol_in_progress); - - /* FIXME: gcc can generate address expressions - here in unusual cases (search for "obscure" - in sdbout.c). We just ignore the offset - here, thus generating incorrect debugging - information. We ignore the rest of the - line just below. */ - } - /* Otherwise, it is the name of a non debug symbol and - its value will be calculated later. */ - *input_line_pointer = name_end; - - /* FIXME: this is to avoid an error message in the - FIXME case mentioned just above. */ - while (! is_end_of_line[(unsigned char) *input_line_pointer]) - ++input_line_pointer; - } - else - { - S_SET_VALUE (def_symbol_in_progress, - (valueT) get_absolute_expression ()); - } /* if symbol based */ - - demand_empty_rest_of_line (); -} - -#ifdef TE_PE - -/* Handle the .linkonce pseudo-op. This is parsed by s_linkonce in - read.c, which then calls this object file format specific routine. */ - -void -obj_coff_pe_handle_link_once (type) - enum linkonce_type type; -{ - seg_info (now_seg)->scnhdr.s_flags |= IMAGE_SCN_LNK_COMDAT; - - /* We store the type in the seg_info structure, and use it to set up - the auxiliary entry for the section symbol in c_section_symbol. */ - seg_info (now_seg)->linkonce = type; -} - -#endif /* TE_PE */ - -void -coff_obj_read_begin_hook () -{ - /* These had better be the same. Usually 18 bytes. */ -#ifndef BFD_HEADERS - know (sizeof (SYMENT) == sizeof (AUXENT)); - know (SYMESZ == AUXESZ); -#endif - tag_init (); -} - -/* This function runs through the symbol table and puts all the - externals onto another chain */ - -/* The chain of globals. */ -symbolS *symbol_globalP; -symbolS *symbol_global_lastP; - -/* The chain of externals */ -symbolS *symbol_externP; -symbolS *symbol_extern_lastP; - -stack *block_stack; -symbolS *last_functionP; -static symbolS *last_bfP; -symbolS *last_tagP; - -static unsigned int -yank_symbols () -{ - symbolS *symbolP; - unsigned int symbol_number = 0; - unsigned int last_file_symno = 0; - - struct filename_list *filename_list_scan = filename_list_head; - - for (symbolP = symbol_rootP; - symbolP; - symbolP = symbolP ? symbol_next (symbolP) : symbol_rootP) - { - if (symbolP->sy_mri_common) - { - if (S_GET_STORAGE_CLASS (symbolP) == C_EXT) - as_bad ("%s: global symbols not supported in common sections", - S_GET_NAME (symbolP)); - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - continue; - } - - if (!SF_GET_DEBUG (symbolP)) - { - /* Debug symbols do not need all this rubbish */ - symbolS *real_symbolP; - - /* L* and C_EFCN symbols never merge. */ - if (!SF_GET_LOCAL (symbolP) - && !SF_GET_STATICS (symbolP) - && S_GET_STORAGE_CLASS (symbolP) != C_LABEL - && symbolP->sy_value.X_op == O_constant - && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP)) - && real_symbolP != symbolP) - { - /* FIXME-SOON: where do dups come from? - Maybe tag references before definitions? xoxorich. */ - /* Move the debug data from the debug symbol to the - real symbol. Do NOT do the oposite (i.e. move from - real symbol to debug symbol and remove real symbol from the - list.) Because some pointers refer to the real symbol - whereas no pointers refer to the debug symbol. */ - c_symbol_merge (symbolP, real_symbolP); - /* Replace the current symbol by the real one */ - /* The symbols will never be the last or the first - because : 1st symbol is .file and 3 last symbols are - .text, .data, .bss */ - symbol_remove (real_symbolP, &symbol_rootP, &symbol_lastP); - symbol_insert (real_symbolP, symbolP, &symbol_rootP, &symbol_lastP); - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - symbolP = real_symbolP; - } /* if not local but dup'd */ - - if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_E1)) - { - S_SET_SEGMENT (symbolP, SEG_E0); - } /* push data into text */ - - resolve_symbol_value (symbolP, 1); - - if (S_GET_STORAGE_CLASS (symbolP) == C_NULL) - { - if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP)) - { - S_SET_EXTERNAL (symbolP); - } - else if (S_GET_SEGMENT (symbolP) == SEG_E0) - { - S_SET_STORAGE_CLASS (symbolP, C_LABEL); - } - else - { - S_SET_STORAGE_CLASS (symbolP, C_STAT); - } - } - - /* Mainly to speed up if not -g */ - if (SF_GET_PROCESS (symbolP)) - { - /* Handle the nested blocks auxiliary info. */ - if (S_GET_STORAGE_CLASS (symbolP) == C_BLOCK) - { - if (!strcmp (S_GET_NAME (symbolP), ".bb")) - stack_push (block_stack, (char *) &symbolP); - else - { /* .eb */ - register symbolS *begin_symbolP; - begin_symbolP = *(symbolS **) stack_pop (block_stack); - if (begin_symbolP == (symbolS *) 0) - as_warn ("mismatched .eb"); - else - SA_SET_SYM_ENDNDX (begin_symbolP, symbol_number + 2); - } - } - /* If we are able to identify the type of a function, and we - are out of a function (last_functionP == 0) then, the - function symbol will be associated with an auxiliary - entry. */ - if (last_functionP == (symbolS *) 0 && - SF_GET_FUNCTION (symbolP)) - { - last_functionP = symbolP; - - if (S_GET_NUMBER_AUXILIARY (symbolP) < 1) - { - S_SET_NUMBER_AUXILIARY (symbolP, 1); - } /* make it at least 1 */ - - /* Clobber possible stale .dim information. */ -#if 0 - /* Iffed out by steve - this fries the lnnoptr info too */ - bzero (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen, - sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen)); -#endif - } - if (S_GET_STORAGE_CLASS (symbolP) == C_FCN) - { - if (strcmp (S_GET_NAME (symbolP), ".bf") == 0) - { - if (last_bfP != NULL) - SA_SET_SYM_ENDNDX (last_bfP, symbol_number); - last_bfP = symbolP; - } - } - else if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN) - { - /* I don't even know if this is needed for sdb. But - the standard assembler generates it, so... */ - if (last_functionP == (symbolS *) 0) - as_fatal ("C_EFCN symbol out of scope"); - SA_SET_SYM_FSIZE (last_functionP, - (long) (S_GET_VALUE (symbolP) - - S_GET_VALUE (last_functionP))); - SA_SET_SYM_ENDNDX (last_functionP, symbol_number); - last_functionP = (symbolS *) 0; - } - } - } - else if (SF_GET_TAG (symbolP)) - { - /* First descriptor of a structure must point to - the first slot after the structure description. */ - last_tagP = symbolP; - - } - else if (S_GET_STORAGE_CLASS (symbolP) == C_EOS) - { - /* +2 take in account the current symbol */ - SA_SET_SYM_ENDNDX (last_tagP, symbol_number + 2); - } - else if (S_GET_STORAGE_CLASS (symbolP) == C_FILE) - { - /* If the filename was too long to fit in the - auxent, put it in the string table */ - if (SA_GET_FILE_FNAME_ZEROS (symbolP) == 0 - && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0) - { - SA_SET_FILE_FNAME_OFFSET (symbolP, string_byte_count); - string_byte_count += strlen (filename_list_scan->filename) + 1; - filename_list_scan = filename_list_scan->next; - } - if (S_GET_VALUE (symbolP)) - { - S_SET_VALUE (symbolP, last_file_symno); - last_file_symno = symbol_number; - } /* no one points at the first .file symbol */ - } /* if debug or tag or eos or file */ - -#ifdef tc_frob_coff_symbol - tc_frob_coff_symbol (symbolP); -#endif - - /* We must put the external symbols apart. The loader - does not bomb if we do not. But the references in - the endndx field for a .bb symbol are not corrected - if an external symbol is removed between .bb and .be. - I.e in the following case : - [20] .bb endndx = 22 - [21] foo external - [22] .be - ld will move the symbol 21 to the end of the list but - endndx will still be 22 instead of 21. */ - - - if (SF_GET_LOCAL (symbolP)) - { - /* remove C_EFCN and LOCAL (L...) symbols */ - /* next pointer remains valid */ - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - - } - else if (symbolP->sy_value.X_op == O_symbol - && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP))) - { - /* Skip symbols which were equated to undefined or common - symbols. */ - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - } - else if (!S_IS_DEFINED (symbolP) - && !S_IS_DEBUG (symbolP) - && !SF_GET_STATICS (symbolP) && - S_GET_STORAGE_CLASS (symbolP) == C_EXT) - { /* C_EXT && !SF_GET_FUNCTION(symbolP)) */ - /* if external, Remove from the list */ - symbolS *hold = symbol_previous (symbolP); - - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - symbol_clear_list_pointers (symbolP); - symbol_append (symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP); - symbolP = hold; - } - else if (! S_IS_DEBUG (symbolP) - && ! SF_GET_STATICS (symbolP) - && ! SF_GET_FUNCTION (symbolP) - && S_GET_STORAGE_CLASS (symbolP) == C_EXT) - { - symbolS *hold = symbol_previous (symbolP); - - /* The O'Reilly COFF book says that defined global symbols - come at the end of the symbol table, just before - undefined global symbols. */ - - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - symbol_clear_list_pointers (symbolP); - symbol_append (symbolP, symbol_global_lastP, &symbol_globalP, - &symbol_global_lastP); - symbolP = hold; - } - else - { - if (SF_GET_STRING (symbolP)) - { - symbolP->sy_name_offset = string_byte_count; - string_byte_count += strlen (S_GET_NAME (symbolP)) + 1; - } - else - { - symbolP->sy_name_offset = 0; - } /* fix "long" names */ - - symbolP->sy_number = symbol_number; - symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP); - } /* if local symbol */ - } /* traverse the symbol list */ - return symbol_number; - -} - - -static unsigned int -glue_symbols (head, tail) - symbolS **head; - symbolS **tail; -{ - unsigned int symbol_number = 0; - - while (*head != NULL) - { - symbolS *tmp = *head; - - /* append */ - symbol_remove (tmp, head, tail); - symbol_append (tmp, symbol_lastP, &symbol_rootP, &symbol_lastP); - - /* and process */ - if (SF_GET_STRING (tmp)) - { - tmp->sy_name_offset = string_byte_count; - string_byte_count += strlen (S_GET_NAME (tmp)) + 1; - } - else - { - tmp->sy_name_offset = 0; - } /* fix "long" names */ - - tmp->sy_number = symbol_number; - symbol_number += 1 + S_GET_NUMBER_AUXILIARY (tmp); - } /* append the entire extern chain */ - - return symbol_number; -} - -static unsigned int -tie_tags () -{ - unsigned int symbol_number = 0; - symbolS *symbolP; - - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - symbolP->sy_number = symbol_number; - - if (SF_GET_TAGGED (symbolP)) - { - SA_SET_SYM_TAGNDX - (symbolP, - ((symbolS *) SA_GET_SYM_TAGNDX (symbolP))->sy_number); - } - - symbol_number += 1 + S_GET_NUMBER_AUXILIARY (symbolP); - } - - return symbol_number; -} - -static void -crawl_symbols (h, abfd) - object_headers *h; - bfd * abfd; -{ - unsigned int i; - - /* Initialize the stack used to keep track of the matching .bb .be */ - - block_stack = stack_init (512, sizeof (symbolS *)); - - /* The symbol list should be ordered according to the following sequence - * order : - * . .file symbol - * . debug entries for functions - * . fake symbols for the sections, including .text .data and .bss - * . defined symbols - * . undefined symbols - * But this is not mandatory. The only important point is to put the - * undefined symbols at the end of the list. - */ - - /* Is there a .file symbol ? If not insert one at the beginning. */ - if (symbol_rootP == NULL - || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE) - { - c_dot_file_symbol ("fake"); - } - - /* - * Build up static symbols for the sections, they are filled in later - */ - - - for (i = SEG_E0; i < SEG_LAST; i++) - if (segment_info[i].scnhdr.s_name[0]) - segment_info[i].dot = c_section_symbol (segment_info[i].name, - i - SEG_E0 + 1); - - /* Take all the externals out and put them into another chain */ - H_SET_SYMBOL_TABLE_SIZE (h, yank_symbols ()); - /* Take the externals and glue them onto the end.*/ - H_SET_SYMBOL_TABLE_SIZE (h, - (H_GET_SYMBOL_COUNT (h) - + glue_symbols (&symbol_globalP, - &symbol_global_lastP) - + glue_symbols (&symbol_externP, - &symbol_extern_lastP))); - - H_SET_SYMBOL_TABLE_SIZE (h, tie_tags ()); - know (symbol_globalP == NULL); - know (symbol_global_lastP == NULL); - know (symbol_externP == NULL); - know (symbol_extern_lastP == NULL); -} - -/* - * Find strings by crawling along symbol table chain. - */ - -void -w_strings (where) - char *where; -{ - symbolS *symbolP; - struct filename_list *filename_list_scan = filename_list_head; - - /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */ - md_number_to_chars (where, (valueT) string_byte_count, 4); - where += 4; - -#ifdef COFF_LONG_SECTION_NAMES - /* Support long section names as found in PE. This code must - coordinate with that in coff_header_append and write_object_file. */ - { - unsigned int i; - - for (i = SEG_E0; i < SEG_LAST; i++) - { - if (segment_info[i].scnhdr.s_name[0] - && strlen (segment_info[i].name) > SCNNMLEN) - { - unsigned int size; - - size = strlen (segment_info[i].name) + 1; - memcpy (where, segment_info[i].name, size); - where += size; - } - } - } -#endif /* COFF_LONG_SECTION_NAMES */ - - for (symbolP = symbol_rootP; - symbolP; - symbolP = symbol_next (symbolP)) - { - unsigned int size; - - if (SF_GET_STRING (symbolP)) - { - size = strlen (S_GET_NAME (symbolP)) + 1; - memcpy (where, S_GET_NAME (symbolP), size); - where += size; - } - if (S_GET_STORAGE_CLASS (symbolP) == C_FILE - && SA_GET_FILE_FNAME_ZEROS (symbolP) == 0 - && SA_GET_FILE_FNAME_OFFSET (symbolP) != 0) - { - size = strlen (filename_list_scan->filename) + 1; - memcpy (where, filename_list_scan->filename, size); - filename_list_scan = filename_list_scan ->next; - where += size; - } - } -} - -static void -do_linenos_for (abfd, h, file_cursor) - bfd * abfd; - object_headers * h; - unsigned long *file_cursor; -{ - unsigned int idx; - unsigned long start = *file_cursor; - - for (idx = SEG_E0; idx < SEG_LAST; idx++) - { - segment_info_type *s = segment_info + idx; - - - if (s->scnhdr.s_nlnno != 0) - { - struct lineno_list *line_ptr; - - struct external_lineno *buffer = - (struct external_lineno *) xmalloc (s->scnhdr.s_nlnno * LINESZ); - - struct external_lineno *dst = buffer; - - /* Run through the table we've built and turn it into its external - form, take this chance to remove duplicates */ - - for (line_ptr = s->lineno_list_head; - line_ptr != (struct lineno_list *) NULL; - line_ptr = line_ptr->next) - { - - if (line_ptr->line.l_lnno == 0) - { - /* Turn a pointer to a symbol into the symbols' index */ - line_ptr->line.l_addr.l_symndx = - ((symbolS *) line_ptr->line.l_addr.l_symndx)->sy_number; - } - else - { - line_ptr->line.l_addr.l_paddr += ((struct frag *) (line_ptr->frag))->fr_address; - } - - - (void) bfd_coff_swap_lineno_out (abfd, &(line_ptr->line), dst); - dst++; - - } - - s->scnhdr.s_lnnoptr = *file_cursor; - - bfd_write (buffer, 1, s->scnhdr.s_nlnno * LINESZ, abfd); - free (buffer); - - *file_cursor += s->scnhdr.s_nlnno * LINESZ; - } - } - H_SET_LINENO_SIZE (h, *file_cursor - start); -} - - -/* Now we run through the list of frag chains in a segment and - make all the subsegment frags appear at the end of the - list, as if the seg 0 was extra long */ - -static void -remove_subsegs () -{ - unsigned int i; - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - frchainS *head = segment_info[i].frchainP; - fragS dummy; - fragS *prev_frag = &dummy; - - while (head && head->frch_seg == i) - { - prev_frag->fr_next = head->frch_root; - prev_frag = head->frch_last; - head = head->frch_next; - } - prev_frag->fr_next = 0; - } -} - -unsigned long machine; -int coff_flags; -extern void -write_object_file () -{ - int i; - const char *name; - struct frchain *frchain_ptr; - - object_headers headers; - unsigned long file_cursor; - bfd *abfd; - unsigned int addr; - abfd = bfd_openw (out_file_name, TARGET_FORMAT); - - - if (abfd == 0) - { - as_perror ("FATAL: Can't create %s", out_file_name); - exit (EXIT_FAILURE); - } - bfd_set_format (abfd, bfd_object); - bfd_set_arch_mach (abfd, BFD_ARCH, machine); - - string_byte_count = 4; - - for (frchain_ptr = frchain_root; - frchain_ptr != (struct frchain *) NULL; - frchain_ptr = frchain_ptr->frch_next) - { - /* Run through all the sub-segments and align them up. Also - close any open frags. We tack a .fill onto the end of the - frag chain so that any .align's size can be worked by looking - at the next frag. */ - - subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); -#ifndef SUB_SEGMENT_ALIGN -#define SUB_SEGMENT_ALIGN(SEG) 1 -#endif -#ifdef md_do_align - md_do_align (SUB_SEGMENT_ALIGN (now_seg), (char *) NULL, 0, 0, - alignment_done); -#endif - frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE, 0); -#ifdef md_do_align - alignment_done: -#endif - frag_wane (frag_now); - frag_now->fr_fix = 0; - know (frag_now->fr_next == NULL); - } - - - remove_subsegs (); - - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - relax_segment (segment_info[i].frchainP->frch_root, i); - } - - H_SET_NUMBER_OF_SECTIONS (&headers, 0); - - /* Find out how big the sections are, and set the addresses. */ - addr = 0; - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - long size; - - segment_info[i].scnhdr.s_paddr = addr; - segment_info[i].scnhdr.s_vaddr = addr; - - if (segment_info[i].scnhdr.s_name[0]) - { - H_SET_NUMBER_OF_SECTIONS (&headers, - H_GET_NUMBER_OF_SECTIONS (&headers) + 1); - -#ifdef COFF_LONG_SECTION_NAMES - /* Support long section names as found in PE. This code - must coordinate with that in coff_header_append and - w_strings. */ - { - unsigned int len; - - len = strlen (segment_info[i].name); - if (len > SCNNMLEN) - string_byte_count += len + 1; - } -#endif /* COFF_LONG_SECTION_NAMES */ - } - - size = size_section (abfd, (unsigned int) i); - addr += size; - - /* I think the section alignment is only used on the i960; the - i960 needs it, and it should do no harm on other targets. */ -#ifdef ALIGNMENT_IN_S_FLAGS - segment_info[i].scnhdr.s_flags |= (section_alignment[i] & 0xF) << 8; -#else - segment_info[i].scnhdr.s_align = 1 << section_alignment[i]; -#endif - - if (i == SEG_E0) - H_SET_TEXT_SIZE (&headers, size); - else if (i == SEG_E1) - H_SET_DATA_SIZE (&headers, size); - else if (i == SEG_E2) - H_SET_BSS_SIZE (&headers, size); - } - - /* Turn the gas native symbol table shape into a coff symbol table */ - crawl_symbols (&headers, abfd); - - if (string_byte_count == 4) - string_byte_count = 0; - - H_SET_STRING_SIZE (&headers, string_byte_count); - -#ifdef tc_frob_file - tc_frob_file (); -#endif - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - fixup_mdeps (segment_info[i].frchainP->frch_root, &headers, i); - fixup_segment (&segment_info[i], i); - } - - /* Look for ".stab" segments and fill in their initial symbols - correctly. */ - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - name = segment_info[i].name; - - if (name != NULL - && strncmp (".stab", name, 5) == 0 - && strncmp (".stabstr", name, 8) != 0) - adjust_stab_section (abfd, i); - } - - file_cursor = H_GET_TEXT_FILE_OFFSET (&headers); - - bfd_seek (abfd, (file_ptr) file_cursor, 0); - - /* Plant the data */ - - fill_section (abfd, &headers, &file_cursor); - - do_relocs_for (abfd, &headers, &file_cursor); - - do_linenos_for (abfd, &headers, &file_cursor); - - H_SET_FILE_MAGIC_NUMBER (&headers, COFF_MAGIC); -#ifndef OBJ_COFF_OMIT_TIMESTAMP - H_SET_TIME_STAMP (&headers, (long)time((time_t *)0)); -#else - H_SET_TIME_STAMP (&headers, 0); -#endif -#ifdef TC_COFF_SET_MACHINE - TC_COFF_SET_MACHINE (&headers); -#endif - -#ifndef COFF_FLAGS -#define COFF_FLAGS 0 -#endif - -#ifdef KEEP_RELOC_INFO - H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) | - COFF_FLAGS | coff_flags)); -#else - H_SET_FLAGS (&headers, ((H_GET_LINENO_SIZE(&headers) ? 0 : F_LNNO) | - (H_GET_RELOCATION_SIZE(&headers) ? 0 : F_RELFLG) | - COFF_FLAGS | coff_flags)); -#endif - - { - unsigned int symtable_size = H_GET_SYMBOL_TABLE_SIZE (&headers); - char *buffer1 = xmalloc (symtable_size + string_byte_count + 1); - - H_SET_SYMBOL_TABLE_POINTER (&headers, bfd_tell (abfd)); - w_symbols (abfd, buffer1, symbol_rootP); - if (string_byte_count > 0) - w_strings (buffer1 + symtable_size); - bfd_write (buffer1, 1, symtable_size + string_byte_count, abfd); - free (buffer1); - } - - coff_header_append (abfd, &headers); -#if 0 - /* Recent changes to write need this, but where it should - go is up to Ken.. */ - if (bfd_close_all_done (abfd) == false) - as_fatal ("Can't close %s: %s", out_file_name, - bfd_errmsg (bfd_get_error ())); -#else - { - extern bfd *stdoutput; - stdoutput = abfd; - } -#endif - -} - -/* Add a new segment. This is called from subseg_new via the - obj_new_segment macro. */ - -segT -obj_coff_add_segment (name) - const char *name; -{ - unsigned int i; - -#ifndef COFF_LONG_SECTION_NAMES - char buf[SCNNMLEN + 1]; - - strncpy (buf, name, SCNNMLEN); - buf[SCNNMLEN] = '\0'; - name = buf; -#endif - - for (i = SEG_E0; i < SEG_LAST && segment_info[i].scnhdr.s_name[0]; i++) - if (strcmp (name, segment_info[i].name) == 0) - return (segT) i; - - if (i == SEG_LAST) - { - as_bad ("Too many new sections; can't add \"%s\"", name); - return now_seg; - } - - /* Add a new section. */ - strncpy (segment_info[i].scnhdr.s_name, name, - sizeof (segment_info[i].scnhdr.s_name)); - segment_info[i].scnhdr.s_flags = STYP_REG; - segment_info[i].name = xstrdup (name); - - return (segT) i; -} - -/* - * implement the .section pseudo op: - * .section name {, "flags"} - * ^ ^ - * | +--- optional flags: 'b' for bss - * | 'i' for info - * +-- section name 'l' for lib - * 'n' for noload - * 'o' for over - * 'w' for data - * 'd' (apparently m88k for data) - * 'x' for text - * 'r' for read-only data - * But if the argument is not a quoted string, treat it as a - * subsegment number. - */ - -void -obj_coff_section (ignore) - int ignore; -{ - /* Strip out the section name */ - char *section_name, *name; - char c; - unsigned int exp; - long flags; - - if (flag_mri) - { - char type; - - s_mri_sect (&type); - flags = 0; - if (type == 'C') - flags = STYP_TEXT; - else if (type == 'D') - flags = STYP_DATA; - segment_info[now_seg].scnhdr.s_flags |= flags; - - return; - } - - section_name = input_line_pointer; - c = get_symbol_end (); - - name = xmalloc (input_line_pointer - section_name + 1); - strcpy (name, section_name); - - *input_line_pointer = c; - - exp = 0; - flags = 0; - - SKIP_WHITESPACE (); - if (*input_line_pointer == ',') - { - ++input_line_pointer; - SKIP_WHITESPACE (); - - if (*input_line_pointer != '"') - exp = get_absolute_expression (); - else - { - ++input_line_pointer; - while (*input_line_pointer != '"' - && ! is_end_of_line[(unsigned char) *input_line_pointer]) - { - switch (*input_line_pointer) - { - case 'b': flags |= STYP_BSS; break; - case 'i': flags |= STYP_INFO; break; - case 'l': flags |= STYP_LIB; break; - case 'n': flags |= STYP_NOLOAD; break; - case 'o': flags |= STYP_OVER; break; - case 'd': - case 'w': flags |= STYP_DATA; break; - case 'x': flags |= STYP_TEXT; break; - case 'r': flags |= STYP_LIT; break; - default: - as_warn("unknown section attribute '%c'", - *input_line_pointer); - break; - } - ++input_line_pointer; - } - if (*input_line_pointer == '"') - ++input_line_pointer; - } - } - - subseg_new (name, (subsegT) exp); - - segment_info[now_seg].scnhdr.s_flags |= flags; - - demand_empty_rest_of_line (); -} - - -static void -obj_coff_text (ignore) - int ignore; -{ - subseg_new (".text", get_absolute_expression ()); -} - - -static void -obj_coff_data (ignore) - int ignore; -{ - if (flag_readonly_data_in_text) - subseg_new (".text", get_absolute_expression () + 1000); - else - subseg_new (".data", get_absolute_expression ()); -} - -static void -obj_coff_ident (ignore) - int ignore; -{ - segT current_seg = now_seg; /* save current seg */ - subsegT current_subseg = now_subseg; - subseg_new (".comment", 0); /* .comment seg */ - stringer (1); /* read string */ - subseg_set (current_seg, current_subseg); /* restore current seg */ -} - -void -c_symbol_merge (debug, normal) - symbolS *debug; - symbolS *normal; -{ - S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug)); - S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug)); - - if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal)) - { - S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug)); - } /* take the most we have */ - - if (S_GET_NUMBER_AUXILIARY (debug) > 0) - { - memcpy ((char *) &normal->sy_symbol.ost_auxent[0], - (char *) &debug->sy_symbol.ost_auxent[0], - (unsigned int) (S_GET_NUMBER_AUXILIARY (debug) * AUXESZ)); - } /* Move all the auxiliary information */ - - /* Move the debug flags. */ - SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug)); -} /* c_symbol_merge() */ - -static int -c_line_new (symbol, paddr, line_number, frag) - symbolS * symbol; - long paddr; - int line_number; - fragS * frag; -{ - struct lineno_list *new_line = - (struct lineno_list *) xmalloc (sizeof (struct lineno_list)); - - segment_info_type *s = segment_info + now_seg; - new_line->line.l_lnno = line_number; - - if (line_number == 0) - { - last_line_symbol = symbol; - new_line->line.l_addr.l_symndx = (long) symbol; - } - else - { - new_line->line.l_addr.l_paddr = paddr; - } - - new_line->frag = (char *) frag; - new_line->next = (struct lineno_list *) NULL; - - - if (s->lineno_list_head == (struct lineno_list *) NULL) - { - s->lineno_list_head = new_line; - } - else - { - s->lineno_list_tail->next = new_line; - } - s->lineno_list_tail = new_line; - return LINESZ * s->scnhdr.s_nlnno++; -} - -void -c_dot_file_symbol (filename) - char *filename; -{ - symbolS *symbolP; - - symbolP = symbol_new (".file", - SEG_DEBUG, - 0, - &zero_address_frag); - - S_SET_STORAGE_CLASS (symbolP, C_FILE); - S_SET_NUMBER_AUXILIARY (symbolP, 1); - - if (strlen (filename) > FILNMLEN) - { - /* Filename is too long to fit into an auxent, - we stick it into the string table instead. We keep - a linked list of the filenames we find so we can emit - them later.*/ - struct filename_list *f = ((struct filename_list *) - xmalloc (sizeof (struct filename_list))); - - f->filename = filename; - f->next = 0; - - SA_SET_FILE_FNAME_ZEROS (symbolP, 0); - SA_SET_FILE_FNAME_OFFSET (symbolP, 1); - - if (filename_list_tail) - filename_list_tail->next = f; - else - filename_list_head = f; - filename_list_tail = f; - } - else - { - SA_SET_FILE_FNAME (symbolP, filename); - } -#ifndef NO_LISTING - { - extern int listing; - if (listing) - { - listing_source_file (filename); - } - - } - -#endif - SF_SET_DEBUG (symbolP); - S_SET_VALUE (symbolP, (valueT) previous_file_symbol); - - previous_file_symbol = symbolP; - - /* Make sure that the symbol is first on the symbol chain */ - if (symbol_rootP != symbolP) - { - symbol_remove (symbolP, &symbol_rootP, &symbol_lastP); - symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP); - } -} /* c_dot_file_symbol() */ - -/* - * Build a 'section static' symbol. - */ - -symbolS * -c_section_symbol (name, idx) - char *name; - int idx; -{ - symbolS *symbolP; - - symbolP = symbol_new (name, idx, - 0, - &zero_address_frag); - - S_SET_STORAGE_CLASS (symbolP, C_STAT); - S_SET_NUMBER_AUXILIARY (symbolP, 1); - - SF_SET_STATICS (symbolP); - -#ifdef TE_DELTA - /* manfred@s-direktnet.de: section symbols *must* have the LOCAL bit cleared, - which is set by the new definition of LOCAL_LABEL in tc-m68k.h. */ - SF_CLEAR_LOCAL (symbolP); -#endif -#ifdef TE_PE - /* If the .linkonce pseudo-op was used for this section, we must - store the information in the auxiliary entry for the section - symbol. */ - if (segment_info[idx].linkonce != LINKONCE_UNSET) - { - int type; - - switch (segment_info[idx].linkonce) - { - default: - abort (); - case LINKONCE_DISCARD: - type = IMAGE_COMDAT_SELECT_ANY; - break; - case LINKONCE_ONE_ONLY: - type = IMAGE_COMDAT_SELECT_NODUPLICATES; - break; - case LINKONCE_SAME_SIZE: - type = IMAGE_COMDAT_SELECT_SAME_SIZE; - break; - case LINKONCE_SAME_CONTENTS: - type = IMAGE_COMDAT_SELECT_EXACT_MATCH; - break; - } - - SYM_AUXENT (symbolP)->x_scn.x_comdat = type; - } -#endif /* TE_PE */ - - return symbolP; -} /* c_section_symbol() */ - -static void -w_symbols (abfd, where, symbol_rootP) - bfd * abfd; - char *where; - symbolS * symbol_rootP; -{ - symbolS *symbolP; - unsigned int i; - - /* First fill in those values we have only just worked out */ - for (i = SEG_E0; i < SEG_LAST; i++) - { - symbolP = segment_info[i].dot; - if (symbolP) - { - SA_SET_SCN_SCNLEN (symbolP, segment_info[i].scnhdr.s_size); - SA_SET_SCN_NRELOC (symbolP, segment_info[i].scnhdr.s_nreloc); - SA_SET_SCN_NLINNO (symbolP, segment_info[i].scnhdr.s_nlnno); - } - } - - /* - * Emit all symbols left in the symbol chain. - */ - for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) - { - /* 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; - - /* We can't fix the lnnoptr field in yank_symbols with the other - adjustments, because we have to wait until we know where they - go in the file. */ - if (SF_GET_ADJ_LNNOPTR (symbolP)) - { - SA_GET_SYM_LNNOPTR (symbolP) += - segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_lnnoptr; - } - - tc_coff_symbol_emit_hook (symbolP); - - temp = S_GET_NAME (symbolP); - if (SF_GET_STRING (symbolP)) - { - S_SET_OFFSET (symbolP, symbolP->sy_name_offset); - S_SET_ZEROES (symbolP, 0); - } - else - { - memset (symbolP->sy_symbol.ost_entry.n_name, 0, SYMNMLEN); - strncpy (symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN); - } - where = symbol_to_chars (abfd, where, symbolP); - S_SET_NAME (symbolP, temp); - } - -} /* w_symbols() */ - -static void -obj_coff_lcomm (ignore) - int ignore; -{ - s_lcomm(0); - return; -#if 0 - char *name; - char c; - int temp; - char *p; - - symbolS *symbolP; - - name = input_line_pointer; - - c = get_symbol_end (); - p = input_line_pointer; - *p = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - as_bad ("Expected comma after name"); - ignore_rest_of_line (); - return; - } - if (*input_line_pointer == '\n') - { - as_bad ("Missing size expression"); - return; - } - input_line_pointer++; - if ((temp = get_absolute_expression ()) < 0) - { - as_warn ("lcomm length (%d.) <0! Ignored.", temp); - ignore_rest_of_line (); - return; - } - *p = 0; - - symbolP = symbol_find_or_make(name); - - if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN && - S_GET_VALUE(symbolP) == 0) - { - if (! need_pass_2) - { - char *p; - segT current_seg = now_seg; /* save current seg */ - subsegT current_subseg = now_subseg; - - subseg_set (SEG_E2, 1); - symbolP->sy_frag = frag_now; - p = frag_var(rs_org, 1, 1, (relax_substateT)0, symbolP, - (offsetT) temp, (char *) 0); - *p = 0; - subseg_set (current_seg, current_subseg); /* restore current seg */ - S_SET_SEGMENT(symbolP, SEG_E2); - S_SET_STORAGE_CLASS(symbolP, C_STAT); - } - } - else - as_bad("Symbol %s already defined", name); - - demand_empty_rest_of_line(); -#endif -} - -static void -fixup_mdeps (frags, h, this_segment) - fragS * frags; - object_headers * h; - segT this_segment; -{ - subseg_change (this_segment, 0); - while (frags) - { - switch (frags->fr_type) - { - case rs_align: - case rs_align_code: - case rs_org: -#ifdef HANDLE_ALIGN - HANDLE_ALIGN (frags); -#endif - frags->fr_type = rs_fill; - frags->fr_offset = - ((frags->fr_next->fr_address - frags->fr_address - frags->fr_fix) - / frags->fr_var); - break; - case rs_machine_dependent: - md_convert_frag (h, this_segment, frags); - frag_wane (frags); - break; - default: - ; - } - frags = frags->fr_next; - } -} - -#if 1 - -#ifndef TC_FORCE_RELOCATION -#define TC_FORCE_RELOCATION(fix) 0 -#endif - -static void -fixup_segment (segP, this_segment_type) - segment_info_type * segP; - segT this_segment_type; -{ - register fixS * fixP; - register symbolS *add_symbolP; - register symbolS *sub_symbolP; - long add_number; - register int size; - register char *place; - register long where; - register char pcrel; - register fragS *fragP; - register segT add_symbol_segment = absolute_section; - - for (fixP = segP->fix_root; fixP; fixP = fixP->fx_next) - { - fragP = fixP->fx_frag; - know (fragP); - where = fixP->fx_where; - place = fragP->fr_literal + where; - size = fixP->fx_size; - add_symbolP = fixP->fx_addsy; - sub_symbolP = fixP->fx_subsy; - add_number = fixP->fx_offset; - pcrel = fixP->fx_pcrel; - - /* We want function-relative stabs to work on systems which - may use a relaxing linker; thus we must handle the sym1-sym2 - fixups function-relative stabs generates. - - Of course, if you actually enable relaxing in the linker, the - line and block scoping information is going to be incorrect - in some cases. The only way to really fix this is to support - a reloc involving the difference of two symbols. */ - if (linkrelax - && (!sub_symbolP || pcrel)) - continue; - -#ifdef TC_I960 - if (fixP->fx_tcbit && SF_GET_CALLNAME (add_symbolP)) - { - /* Relocation should be done via the associated 'bal' entry - point symbol. */ - - if (!SF_GET_BALNAME (tc_get_bal_of_call (add_symbolP))) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - "No 'bal' entry point for leafproc %s", - S_GET_NAME (add_symbolP)); - continue; - } - fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP); - } -#endif - - /* Make sure the symbols have been resolved; this may not have - happened if these are expression symbols. */ - if (add_symbolP != NULL && ! add_symbolP->sy_resolved) - resolve_symbol_value (add_symbolP, 1); - - if (add_symbolP != NULL) - { - /* If this fixup is against a symbol which has been equated - to another symbol, convert it to the other symbol. */ - if (add_symbolP->sy_value.X_op == O_symbol - && (! S_IS_DEFINED (add_symbolP) - || S_IS_COMMON (add_symbolP))) - { - while (add_symbolP->sy_value.X_op == O_symbol - && (! S_IS_DEFINED (add_symbolP) - || S_IS_COMMON (add_symbolP))) - { - symbolS *n; - - /* We must avoid looping, as that can occur with a - badly written program. */ - n = add_symbolP->sy_value.X_add_symbol; - if (n == add_symbolP) - break; - add_number += add_symbolP->sy_value.X_add_number; - add_symbolP = n; - } - fixP->fx_addsy = add_symbolP; - fixP->fx_offset = add_number; - } - } - - if (sub_symbolP != NULL && ! sub_symbolP->sy_resolved) - resolve_symbol_value (sub_symbolP, 1); - - if (add_symbolP != NULL - && add_symbolP->sy_mri_common) - { - know (add_symbolP->sy_value.X_op == O_symbol); - add_number += S_GET_VALUE (add_symbolP); - fixP->fx_offset = add_number; - add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol; - } - - if (add_symbolP) - { - add_symbol_segment = S_GET_SEGMENT (add_symbolP); - } /* if there is an addend */ - - if (sub_symbolP) - { - if (add_symbolP == NULL || add_symbol_segment == absolute_section) - { - if (add_symbolP != NULL) - { - add_number += S_GET_VALUE (add_symbolP); - add_symbolP = NULL; - fixP->fx_addsy = NULL; - } - - /* It's just -sym. */ - if (S_GET_SEGMENT (sub_symbolP) == absolute_section) - { - add_number -= S_GET_VALUE (sub_symbolP); - fixP->fx_subsy = 0; - fixP->fx_done = 1; - } - else - { -#ifndef TC_M68K - as_bad_where (fixP->fx_file, fixP->fx_line, - "Negative of non-absolute symbol %s", - S_GET_NAME (sub_symbolP)); -#endif - add_number -= S_GET_VALUE (sub_symbolP); - } /* not absolute */ - - /* if sub_symbol is in the same segment that add_symbol - and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */ - } - else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment - && SEG_NORMAL (add_symbol_segment)) - { - /* Difference of 2 symbols from same segment. Can't - make difference of 2 undefineds: 'value' means - something different for N_UNDF. */ -#ifdef TC_I960 - /* Makes no sense to use the difference of 2 arbitrary symbols - as the target of a call instruction. */ - if (fixP->fx_tcbit) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - "callj to difference of 2 symbols"); - } -#endif /* TC_I960 */ - add_number += S_GET_VALUE (add_symbolP) - - S_GET_VALUE (sub_symbolP); - add_symbolP = NULL; - - if (!TC_FORCE_RELOCATION (fixP)) - { - fixP->fx_addsy = NULL; - fixP->fx_subsy = NULL; - fixP->fx_done = 1; -#ifdef TC_M68K /* is this right? */ - pcrel = 0; - fixP->fx_pcrel = 0; -#endif - } - } - else - { - /* Different segments in subtraction. */ - know (!(S_IS_EXTERNAL (sub_symbolP) && (S_GET_SEGMENT (sub_symbolP) == absolute_section))); - - if ((S_GET_SEGMENT (sub_symbolP) == absolute_section)) - { - add_number -= S_GET_VALUE (sub_symbolP); - } -#ifdef DIFF_EXPR_OK - else if (S_GET_SEGMENT (sub_symbolP) == this_segment_type -#if 0 /* Okay for 68k, at least... */ - && !pcrel -#endif - ) - { - /* Make it pc-relative. */ - add_number += (md_pcrel_from (fixP) - - S_GET_VALUE (sub_symbolP)); - pcrel = 1; - fixP->fx_pcrel = 1; - sub_symbolP = 0; - fixP->fx_subsy = 0; - } -#endif - else - { - as_bad_where (fixP->fx_file, fixP->fx_line, - "Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %ld.", - segment_name (S_GET_SEGMENT (sub_symbolP)), - S_GET_NAME (sub_symbolP), - (long) (fragP->fr_address + where)); - } /* if absolute */ - } - } /* if sub_symbolP */ - - if (add_symbolP) - { - if (add_symbol_segment == this_segment_type && pcrel) - { - /* - * This fixup was made when the symbol's segment was - * SEG_UNKNOWN, but it is now in the local segment. - * So we know how to do the address without relocation. - */ -#ifdef TC_I960 - /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal', - * in which cases it modifies *fixP as appropriate. In the case - * of a 'calls', no further work is required, and *fixP has been - * set up to make the rest of the code below a no-op. - */ - reloc_callj (fixP); -#endif /* TC_I960 */ - - add_number += S_GET_VALUE (add_symbolP); - add_number -= md_pcrel_from (fixP); - - /* We used to do - add_number -= segP->scnhdr.s_vaddr; - if defined (TC_I386) || defined (TE_LYNX). I now - think that was an error propagated from the case when - we are going to emit the relocation. If we are not - going to emit the relocation, then we just want to - set add_number to the difference between the symbols. - This is a case that would only arise when there is a - PC relative reference from a section other than .text - to a symbol defined in the same section, and the - reference is not relaxed. Since jump instructions on - the i386 are relaxed, this could only arise with a - call instruction. */ - - pcrel = 0; /* Lie. Don't want further pcrel processing. */ - if (!TC_FORCE_RELOCATION (fixP)) - { - fixP->fx_addsy = NULL; - fixP->fx_done = 1; - } - } - else - { - switch (add_symbol_segment) - { - case absolute_section: -#ifdef TC_I960 - reloc_callj (fixP); /* See comment about reloc_callj() above*/ -#endif /* TC_I960 */ - add_number += S_GET_VALUE (add_symbolP); - add_symbolP = NULL; - - if (!TC_FORCE_RELOCATION (fixP)) - { - fixP->fx_addsy = NULL; - fixP->fx_done = 1; - } - break; - default: - - -#if defined(TC_A29K) || (defined(TE_PE) && defined(TC_I386)) || defined(TC_M88K) - /* This really should be handled in the linker, but - backward compatibility forbids. */ - add_number += S_GET_VALUE (add_symbolP); -#else - add_number += S_GET_VALUE (add_symbolP) + - segment_info[S_GET_SEGMENT (add_symbolP)].scnhdr.s_paddr; -#endif - break; - - case SEG_UNKNOWN: -#ifdef TC_I960 - if ((int) fixP->fx_bit_fixP == 13) - { - /* This is a COBR instruction. They have only a - * 13-bit displacement and are only to be used - * for local branches: flag as error, don't generate - * relocation. - */ - as_bad_where (fixP->fx_file, fixP->fx_line, - "can't use COBR format with external label"); - fixP->fx_addsy = NULL; - fixP->fx_done = 1; - continue; - } /* COBR */ -#endif /* TC_I960 */ -#if ((defined (TC_I386) || defined (TE_LYNX) || defined (TE_AUX)) && !defined(TE_PE)) || defined (COFF_COMMON_ADDEND) - /* 386 COFF uses a peculiar format in which the - value of a common symbol is stored in the .text - segment (I've checked this on SVR3.2 and SCO - 3.2.2) Ian Taylor <ian@cygnus.com>. */ - /* This is also true for 68k COFF on sysv machines - (Checked on Motorola sysv68 R3V6 and R3V7.1, and also on - UNIX System V/M68000, Release 1.0 from ATT/Bell Labs) - Philippe De Muyter <phdm@info.ucl.ac.be>. */ - if (S_IS_COMMON (add_symbolP)) - add_number += S_GET_VALUE (add_symbolP); -#endif - break; - - - } /* switch on symbol seg */ - } /* if not in local seg */ - } /* if there was a + symbol */ - - if (pcrel) - { -#if !defined(TC_M88K) && !(defined(TE_PE) && defined(TC_I386)) && !defined(TC_A29K) - /* This adjustment is not correct on the m88k, for which the - linker does all the computation. */ - add_number -= md_pcrel_from (fixP); -#endif - if (add_symbolP == 0) - { - fixP->fx_addsy = &abs_symbol; - } /* if there's an add_symbol */ -#if defined (TC_I386) || defined (TE_LYNX) || defined (TC_I960) || defined (TC_M68K) - /* On the 386 we must adjust by the segment vaddr as well. - Ian Taylor. - - I changed the i960 to work this way as well. This is - compatible with the current GNU linker behaviour. I do - not know what other i960 COFF assemblers do. This is not - a common case: normally, only assembler code will contain - a PC relative reloc, and only branches which do not - originate in the .text section will have a non-zero - address. - - I changed the m68k to work this way as well. This will - break existing PC relative relocs from sections which do - not start at address 0, but it will make ld -r work. - Ian Taylor, 4 Oct 96. */ - - add_number -= segP->scnhdr.s_vaddr; -#endif - } /* if pcrel */ - - if (!fixP->fx_bit_fixP && ! fixP->fx_no_overflow) - { -#ifndef TC_M88K - /* The m88k uses the offset field of the reloc to get around - this problem. */ - if ((size == 1 - && ((add_number & ~0xFF) - || (fixP->fx_signed && (add_number & 0x80))) - && ((add_number & ~0xFF) != (-1 & ~0xFF) - || (add_number & 0x80) == 0)) - || (size == 2 - && ((add_number & ~0xFFFF) - || (fixP->fx_signed && (add_number & 0x8000))) - && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF) - || (add_number & 0x8000) == 0))) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - "Value of %ld too large for field of %d bytes at 0x%lx", - (long) add_number, size, - (unsigned long) (fragP->fr_address + where)); - } -#endif -#ifdef WARN_SIGNED_OVERFLOW_WORD - /* Warn if a .word value is too large when treated as a - signed number. We already know it is not too negative. - This is to catch over-large switches generated by gcc on - the 68k. */ - if (!flag_signed_overflow_ok - && size == 2 - && add_number > 0x7fff) - as_bad_where (fixP->fx_file, fixP->fx_line, - "Signed .word overflow; switch may be too large; %ld at 0x%lx", - (long) add_number, - (unsigned long) (fragP->fr_address + where)); -#endif - } /* not a bit fix */ - /* Once this fix has been applied, we don't have to output - anything nothing more need be done. */ -#ifdef MD_APPLY_FIX3 - md_apply_fix3 (fixP, (valueT *) &add_number, this_segment_type); -#else - md_apply_fix (fixP, add_number); -#endif - } /* For each fixS in this segment. */ -} /* fixup_segment() */ - -#endif - -/* The first entry in a .stab section is special. */ - -void -obj_coff_init_stab_section (seg) - segT seg; -{ - char *file; - char *p; - char *stabstr_name; - unsigned int stroff; - - /* Make space for this first symbol. */ - p = frag_more (12); - /* Zero it out. */ - memset (p, 0, 12); - as_where (&file, (unsigned int *) NULL); - stabstr_name = (char *) alloca (strlen (segment_info[seg].name) + 4); - strcpy (stabstr_name, segment_info[seg].name); - strcat (stabstr_name, "str"); - stroff = get_stab_string_offset (file, stabstr_name); - know (stroff == 1); - md_number_to_chars (p, stroff, 4); -} - -/* Fill in the counts in the first entry in a .stab section. */ - -static void -adjust_stab_section(abfd, seg) - bfd *abfd; - segT seg; -{ - segT stabstrseg = SEG_UNKNOWN; - const char *secname, *name2; - char *name; - char *p = NULL; - int i, strsz = 0, nsyms; - fragS *frag = segment_info[seg].frchainP->frch_root; - - /* Look for the associated string table section. */ - - secname = segment_info[seg].name; - name = (char *) alloca (strlen (secname) + 4); - strcpy (name, secname); - strcat (name, "str"); - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - name2 = segment_info[i].name; - if (name2 != NULL && strncmp(name2, name, 8) == 0) - { - stabstrseg = i; - break; - } - } - - /* If we found the section, get its size. */ - if (stabstrseg != SEG_UNKNOWN) - strsz = size_section (abfd, stabstrseg); - - nsyms = size_section (abfd, seg) / 12 - 1; - - /* Look for the first frag of sufficient size for the initial stab - symbol, and collect a pointer to it. */ - while (frag && frag->fr_fix < 12) - frag = frag->fr_next; - assert (frag != 0); - p = frag->fr_literal; - assert (p != 0); - - /* Write in the number of stab symbols and the size of the string - table. */ - bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); - bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); -} - -#endif /* not BFD_ASSEMBLER */ - -const pseudo_typeS obj_pseudo_table[] = -{ - {"def", obj_coff_def, 0}, - {"dim", obj_coff_dim, 0}, - {"endef", obj_coff_endef, 0}, - {"line", obj_coff_line, 0}, - {"ln", obj_coff_ln, 0}, - {"appline", obj_coff_ln, 1}, - {"scl", obj_coff_scl, 0}, - {"size", obj_coff_size, 0}, - {"tag", obj_coff_tag, 0}, - {"type", obj_coff_type, 0}, - {"val", obj_coff_val, 0}, - {"section", obj_coff_section, 0}, - {"sect", obj_coff_section, 0}, - /* FIXME: We ignore the MRI short attribute. */ - {"section.s", obj_coff_section, 0}, - {"sect.s", obj_coff_section, 0}, - /* We accept the .bss directive for backward compatibility with - earlier versions of gas. */ - {"bss", obj_coff_bss, 0}, -#ifndef BFD_ASSEMBLER - {"use", obj_coff_section, 0}, - {"text", obj_coff_text, 0}, - {"data", obj_coff_data, 0}, - {"lcomm", obj_coff_lcomm, 0}, - {"ident", obj_coff_ident, 0}, -#else - {"optim", s_ignore, 0}, /* For sun386i cc (?) */ - {"ident", s_ignore, 0}, /* we don't yet handle this. */ -#endif - {"version", s_ignore, 0}, - {"ABORT", s_abort, 0}, -#ifdef TC_M88K - /* The m88k uses sdef instead of def. */ - {"sdef", obj_coff_def, 0}, -#endif - {NULL} /* end sentinel */ -}; /* obj_pseudo_table */ - -#ifdef BFD_ASSEMBLER - -/* Support for a COFF emulation. */ - -static void -coff_pop_insert () -{ - pop_insert (obj_pseudo_table); -} - -static int -coff_sec_sym_ok_for_reloc (sec) - asection *sec; -{ - return 0; -} - -static void -no_func () -{ - abort (); -} - -const struct format_ops coff_format_ops = -{ - bfd_target_coff_flavour, - 0, - 1, - coff_frob_symbol, - no_func, - coff_frob_file_after_relocs, - 0, 0, - 0, 0, - 0, -#if 0 - obj_generate_asm_lineno, -#else - no_func, -#endif -#if 0 - obj_stab, -#else - no_func, -#endif - coff_sec_sym_ok_for_reloc, - coff_pop_insert, -#if 0 - obj_set_ext, -#else - no_func, -#endif - coff_obj_read_begin_hook, - coff_obj_symbol_new_hook, -}; - -#endif diff --git a/contrib/binutils/gas/config/obj-coff.h b/contrib/binutils/gas/config/obj-coff.h deleted file mode 100644 index f796461770b6..000000000000 --- a/contrib/binutils/gas/config/obj-coff.h +++ /dev/null @@ -1,816 +0,0 @@ -/* coff object file format - Copyright (C) 1989, 90, 91, 92, 94, 95, 96, 97, 1998 - Free Software Foundation, Inc. - - This file is part of GAS. - - 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. - - 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. */ - -#ifndef OBJ_FORMAT_H -#define OBJ_FORMAT_H - -#define OBJ_COFF 1 - -#ifndef BFD_ASSEMBLER - -#define WORKING_DOT_WORD -#define WARN_SIGNED_OVERFLOW_WORD -#define OBJ_COFF_OMIT_OPTIONAL_HEADER -#define BFD_HEADERS -#define BFD - -#endif - -#include "targ-cpu.h" - -#include "bfd.h" - -/* This internal_lineno crap is to stop namespace pollution from the - bfd internal coff headerfile. */ -#define internal_lineno bfd_internal_lineno -#include "coff/internal.h" -#undef internal_lineno - -/* CPU-specific setup: */ - -#ifdef TC_ARM -#include "coff/arm.h" -#ifndef TARGET_FORMAT -#define TARGET_FORMAT "coff-arm" -#endif -#endif - -#ifdef TC_PPC -#ifdef TE_PE -#include "coff/powerpc.h" -#else -#include "coff/rs6000.h" -#endif -#endif - -#ifdef TC_SPARC -#include "coff/sparc.h" -#endif - -#ifdef TC_I386 -#include "coff/i386.h" - -#ifdef TE_PE -#define TARGET_FORMAT "pe-i386" -#endif - -#ifndef TARGET_FORMAT -#define TARGET_FORMAT "coff-i386" -#endif -#endif - -#ifdef TC_M68K -#include "coff/m68k.h" -#ifndef TARGET_FORMAT -#define TARGET_FORMAT "coff-m68k" -#endif -#endif - -#ifdef TC_A29K -#include "coff/a29k.h" -#define TARGET_FORMAT "coff-a29k-big" -#endif - -#ifdef TC_I960 -#include "coff/i960.h" -#define TARGET_FORMAT "coff-Intel-little" -#endif - -#ifdef TC_Z8K -#include "coff/z8k.h" -#define TARGET_FORMAT "coff-z8k" -#endif - -#ifdef TC_H8300 -#include "coff/h8300.h" -#define TARGET_FORMAT "coff-h8300" -#endif - -#ifdef TC_H8500 -#include "coff/h8500.h" -#define TARGET_FORMAT "coff-h8500" -#endif - -#ifdef TC_SH -#include "coff/sh.h" -#define TARGET_FORMAT \ - (shl \ - ? (sh_small ? "coff-shl-small" : "coff-shl") \ - : (sh_small ? "coff-sh-small" : "coff-sh")) -#endif - -#ifdef TC_M88K -#include "coff/m88k.h" -#define TARGET_FORMAT "coff-m88kbcs" -#endif - -#ifdef TC_W65 -#include "coff/w65.h" -#define TARGET_FORMAT "coff-w65" -#endif - -#ifdef TC_TIC30 -#include "coff/tic30.h" -#define TARGET_FORMAT "coff-tic30" -#endif - - -/* Targets may also set this. Also, if BFD_ASSEMBLER is defined, this - will already have been defined. */ -#undef SYMBOLS_NEED_BACKPOINTERS -#define SYMBOLS_NEED_BACKPOINTERS 1 - -#ifndef OBJ_COFF_MAX_AUXENTRIES -#define OBJ_COFF_MAX_AUXENTRIES 1 -#endif /* OBJ_COFF_MAX_AUXENTRIES */ - -extern void coff_obj_symbol_new_hook PARAMS ((struct symbol *)); -#define obj_symbol_new_hook coff_obj_symbol_new_hook - -extern void coff_obj_read_begin_hook PARAMS ((void)); -#define obj_read_begin_hook coff_obj_read_begin_hook - -/* *********************************************************************** - - This file really contains two implementations of the COFF back end. - They are in the process of being merged, but this is only a - preliminary, mechanical merging. Many definitions that are - identical between the two are still found in both versions. - - The first version, with BFD_ASSEMBLER defined, uses high-level BFD - interfaces and data structures. The second version, with - BFD_ASSEMBLER not defined, also uses BFD, but mostly for swapping - data structures and for doing the actual I/O. The latter defines - the preprocessor symbols BFD and BFD_HEADERS. Try not to let this - confuse you. - - These two are in the process of being merged, and eventually the - BFD_ASSEMBLER version should take over completely. Release timing - issues and namespace problems convinced me to merge the two - together in this fashion, a little sooner than I would have liked. - The real merge should be much better done by the time the next - release comes out. - - For now, the structure of this file is: - <common> - #ifdef BFD_ASSEMBLER - <one version> - #else - <other version> - #endif - <common> - Unfortunately, the common portions are very small at the moment, - and many declarations or definitions are duplicated. The structure - of obj-coff.c is similar. - - See doc/internals.texi for a brief discussion of the history, if - you care. - - Ken Raeburn, 5 May 1994 - - *********************************************************************** */ - -#ifdef BFD_ASSEMBLER - -#include "bfd/libcoff.h" - -#define OUTPUT_FLAVOR bfd_target_coff_flavour - -/* SYMBOL TABLE */ - -/* Alter the field names, for now, until we've fixed up the other - references to use the new name. */ -#ifdef TC_I960 -#define TC_SYMFIELD_TYPE struct symbol * -#define sy_tc bal -#endif - -#define OBJ_SYMFIELD_TYPE unsigned long -#define sy_obj sy_flags - -#define SYM_AUXENT(S) (&coffsymbol ((S)->bsym)->native[1].u.auxent) - -#define DO_NOT_STRIP 0 - -extern void obj_coff_section PARAMS ((int)); - -/* The number of auxiliary entries */ -#define S_GET_NUMBER_AUXILIARY(s) (coffsymbol((s)->bsym)->native->u.syment.n_numaux) -/* The number of auxiliary entries */ -#define S_SET_NUMBER_AUXILIARY(s,v) (S_GET_NUMBER_AUXILIARY (s) = (v)) - -/* True if a symbol name is in the string table, i.e. its length is > 8. */ -#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0) - -extern int S_SET_DATA_TYPE PARAMS ((struct symbol *, int)); -extern int S_SET_STORAGE_CLASS PARAMS ((struct symbol *, int)); -extern int S_GET_STORAGE_CLASS PARAMS ((struct symbol *)); -extern void SA_SET_SYM_ENDNDX PARAMS ((struct symbol *, struct symbol *)); - -/* Auxiliary entry macros. SA_ stands for symbol auxiliary */ -/* Omit the tv related fields */ -/* Accessors */ - -#define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l) -#define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno) -#define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size) -#define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize) -#define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr) -#define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx) -#define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]) -#define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname) -#define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen) -#define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc) -#define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno) - -#define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v)) -#define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v)) -#define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v)) -#define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v)) -#define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v)) -#define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN) -#define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v)) -#define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v)) -#define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v)) - -/* - * Internal use only definitions. SF_ stands for symbol flags. - * - * These values can be assigned to sy_symbol.ost_flags field of a symbolS. - * - * You'll break i960 if you shift the SYSPROC bits anywhere else. for - * more on the balname/callname hack, see tc-i960.h. b.out is done - * differently. - */ - -#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */ -#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ -#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */ -#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */ -#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */ - -#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */ - -#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */ -#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */ -#define SF_STRING (0x00004000) /* Symbol name length > 8 */ -#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */ - -#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */ - -#define SF_FUNCTION (0x00010000) /* The symbol is a function */ -#define SF_PROCESS (0x00020000) /* Process symbol before write */ -#define SF_TAGGED (0x00040000) /* Is associated with a tag */ -#define SF_TAG (0x00080000) /* Is a tag */ -#define SF_DEBUG (0x00100000) /* Is in debug or abs section */ -#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */ -/* All other bits are unused. */ - -/* Accessors */ -#define SF_GET(s) ((s)->sy_flags) -#define SF_GET_DEBUG(s) ((s)->bsym->flags & BSF_DEBUGGING) -#define SF_SET_DEBUG(s) ((s)->bsym->flags |= BSF_DEBUGGING) -#define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK) -#define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK) -#define SF_GET_FILE(s) (SF_GET (s) & SF_FILE) -#define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS) -#define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED) -#define SF_GET_STRING(s) (SF_GET (s) & SF_STRING) -#define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL) -#define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION) -#define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS) -#define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED) -#define SF_GET_TAG(s) (SF_GET (s) & SF_TAG) -#define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT) -#define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */ -#define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */ -#define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */ -#define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */ -#define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */ - -/* Modifiers */ -#define SF_SET(s,v) (SF_GET (s) = (v)) -#define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK)) -#define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK)) -#define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE) -#define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS) -#define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED) -#define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING) -#define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL) -#define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL) -#define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION) -#define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS) -#define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED) -#define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG) -#define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT) -#define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */ -#define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */ -#define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */ -#define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */ -#define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */ - -/* -------------- Line number handling ------- */ -extern int text_lineno_number; -extern int coff_line_base; -extern int coff_n_line_nos; - -#define obj_emit_lineno(WHERE,LINE,FILE_START) abort () -extern void coff_add_linesym PARAMS ((struct symbol *)); - - -void c_dot_file_symbol PARAMS ((char *filename)); -#define obj_app_file c_dot_file_symbol - -extern void coff_frob_symbol PARAMS ((struct symbol *, int *)); -extern void coff_adjust_symtab PARAMS ((void)); -extern void coff_frob_section PARAMS ((segT)); -extern void coff_adjust_section_syms PARAMS ((bfd *, asection *, PTR)); -extern void coff_frob_file_after_relocs PARAMS ((void)); -#define obj_frob_symbol(S,P) coff_frob_symbol(S,&P) -#define obj_adjust_symtab() coff_adjust_symtab() -#define obj_frob_section(S) coff_frob_section (S) -#define obj_frob_file_after_relocs() coff_frob_file_after_relocs () - -extern struct symbol *coff_last_function; - -/* Forward the segment of a forwarded symbol, handle assignments that - just copy symbol values, etc. */ -#ifndef TE_I386AIX -#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \ - (SF_GET_GET_SEGMENT (dest) \ - ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \ - : 0) -#else -#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \ - (SF_GET_GET_SEGMENT (dest) && S_GET_SEGMENT (dest) == SEG_UNKNOWN \ - ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \ - : 0) -#endif - -/* sanity check */ - -#ifdef TC_I960 -#ifndef C_LEAFSTAT -hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it. -#endif /* no C_LEAFSTAT */ -#endif /* TC_I960 */ - -#else /* not BFD_ASSEMBLER */ - -#ifdef TC_A29K -/* Allow translate from aout relocs to coff relocs */ -#define NO_RELOC 20 -#define RELOC_32 1 -#define RELOC_8 2 -#define RELOC_CONST 3 -#define RELOC_CONSTH 4 -#define RELOC_JUMPTARG 5 -#define RELOC_BASE22 6 -#define RELOC_HI22 7 -#define RELOC_LO10 8 -#define RELOC_BASE13 9 -#define RELOC_WDISP22 10 -#define RELOC_WDISP30 11 -#endif - -extern const segT N_TYPE_seg[]; - -/* Magic number of paged executable. */ -#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 0x8300 - - -/* SYMBOL TABLE */ - -/* Symbol table entry data type */ - -typedef struct -{ - /* Basic symbol */ - struct internal_syment ost_entry; - /* Auxiliary entry. */ - union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; - /* obj_coff internal use only flags */ - unsigned int ost_flags; -} obj_symbol_type; - -#ifndef DO_NOT_STRIP -#define DO_NOT_STRIP 0 -#endif -/* Symbol table macros and constants */ - -/* Possible and usefull section number in symbol table - * The values of TEXT, DATA and BSS may not be portable. - */ - -#define C_ABS_SECTION N_ABS -#define C_UNDEF_SECTION N_UNDEF -#define C_DEBUG_SECTION N_DEBUG -#define C_NTV_SECTION N_TV -#define C_PTV_SECTION P_TV -#define C_REGISTER_SECTION 50 - -/* - * Macros to extract information from a symbol table entry. - * This syntaxic 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 */ -#define S_IS_EXTERNAL(s) ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION) -/* True if symbol has been defined, ie : - section > 0 (DATA, TEXT or BSS) - section == 0 and value > 0 (external bss symbol) */ -#define S_IS_DEFINED(s) \ - ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION \ - || ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION \ - && S_GET_VALUE (s) > 0) \ - || ((s)->sy_symbol.ost_entry.n_scnum == C_ABS_SECTION)) -/* True if a debug special symbol entry */ -#define S_IS_DEBUG(s) ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION) -/* True if a symbol is local symbol name */ -/* A symbol name whose name includes ^A is a gas internal pseudo symbol */ -#define S_IS_LOCAL(s) \ - ((s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION \ - || (S_LOCAL_NAME(s) && ! flag_keep_locals && ! S_IS_DEBUG (s)) \ - || strchr (S_GET_NAME (s), '\001') != NULL \ - || strchr (S_GET_NAME (s), '\002') != NULL \ - || (flag_strip_local_absolute \ - && !S_IS_EXTERNAL(s) \ - && (s)->sy_symbol.ost_entry.n_scnum == C_ABS_SECTION)) -/* True if a symbol is not defined in this file */ -#define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \ - && S_GET_VALUE (s) == 0) -/* - * True if a symbol can be multiply defined (bss symbols have this def - * though it is bad practice) - */ -#define S_IS_COMMON(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 \ - && S_GET_VALUE (s) != 0) -/* True if a symbol name is in the string table, i.e. its length is > 8. */ -#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0) - -/* Accessors */ -/* The name of the symbol */ -#define S_GET_NAME(s) ((char*)(s)->sy_symbol.ost_entry.n_offset) -/* The pointer to the string table */ -#define S_GET_OFFSET(s) ((s)->sy_symbol.ost_entry.n_offset) -/* The numeric value of the segment */ -#define S_GET_SEGMENT(s) s_get_segment(s) -/* The data type */ -#define S_GET_DATA_TYPE(s) ((s)->sy_symbol.ost_entry.n_type) -/* The storage class */ -#define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass) -/* The number of auxiliary entries */ -#define S_GET_NUMBER_AUXILIARY(s) ((s)->sy_symbol.ost_entry.n_numaux) - -/* Modifiers */ -/* Set the name of the symbol */ -#define S_SET_NAME(s,v) ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v)) -/* Set the offset of the symbol */ -#define S_SET_OFFSET(s,v) ((s)->sy_symbol.ost_entry.n_offset = (v)) -/* The numeric value of the segment */ -#define S_SET_SEGMENT(s,v) ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v)) -/* The data type */ -#define S_SET_DATA_TYPE(s,v) ((s)->sy_symbol.ost_entry.n_type = (v)) -/* The storage class */ -#define S_SET_STORAGE_CLASS(s,v) ((s)->sy_symbol.ost_entry.n_sclass = (v)) -/* The number of auxiliary entries */ -#define S_SET_NUMBER_AUXILIARY(s,v) ((s)->sy_symbol.ost_entry.n_numaux = (v)) - -/* Additional modifiers */ -/* The symbol is external (does not mean undefined) */ -#define S_SET_EXTERNAL(s) { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); } - -/* Auxiliary entry macros. SA_ stands for symbol auxiliary */ -/* Omit the tv related fields */ -/* Accessors */ -#define SYM_AUXENT(S) (&(S)->sy_symbol.ost_auxent[0]) - -#define SA_GET_SYM_TAGNDX(s) (SYM_AUXENT (s)->x_sym.x_tagndx.l) -#define SA_GET_SYM_LNNO(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno) -#define SA_GET_SYM_SIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size) -#define SA_GET_SYM_FSIZE(s) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize) -#define SA_GET_SYM_LNNOPTR(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr) -#define SA_GET_SYM_ENDNDX(s) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l) -#define SA_GET_SYM_DIMEN(s,i) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]) -#define SA_GET_FILE_FNAME(s) (SYM_AUXENT (s)->x_file.x_fname) -#define SA_GET_FILE_FNAME_OFFSET(s) (SYM_AUXENT (s)->x_file.x_n.x_offset) -#define SA_GET_FILE_FNAME_ZEROS(s) (SYM_AUXENT (s)->x_file.x_n.x_zeroes) -#define SA_GET_SCN_SCNLEN(s) (SYM_AUXENT (s)->x_scn.x_scnlen) -#define SA_GET_SCN_NRELOC(s) (SYM_AUXENT (s)->x_scn.x_nreloc) -#define SA_GET_SCN_NLINNO(s) (SYM_AUXENT (s)->x_scn.x_nlinno) - -/* Modifiers */ -#define SA_SET_SYM_TAGNDX(s,v) (SYM_AUXENT (s)->x_sym.x_tagndx.l=(v)) -#define SA_SET_SYM_LNNO(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_lnno=(v)) -#define SA_SET_SYM_SIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_lnsz.x_size=(v)) -#define SA_SET_SYM_FSIZE(s,v) (SYM_AUXENT (s)->x_sym.x_misc.x_fsize=(v)) -#define SA_SET_SYM_LNNOPTR(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_lnnoptr=(v)) -#define SA_SET_SYM_ENDNDX(s,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_fcn.x_endndx.l=(v)) -#define SA_SET_SYM_DIMEN(s,i,v) (SYM_AUXENT (s)->x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v)) -#define SA_SET_FILE_FNAME(s,v) strncpy(SYM_AUXENT (s)->x_file.x_fname,(v),FILNMLEN) -#define SA_SET_FILE_FNAME_OFFSET(s,v) (SYM_AUXENT (s)->x_file.x_n.x_offset=(v)) -#define SA_SET_FILE_FNAME_ZEROS(s,v) (SYM_AUXENT (s)->x_file.x_n.x_zeroes=(v)) -#define SA_SET_SCN_SCNLEN(s,v) (SYM_AUXENT (s)->x_scn.x_scnlen=(v)) -#define SA_SET_SCN_NRELOC(s,v) (SYM_AUXENT (s)->x_scn.x_nreloc=(v)) -#define SA_SET_SCN_NLINNO(s,v) (SYM_AUXENT (s)->x_scn.x_nlinno=(v)) - -/* - * Internal use only definitions. SF_ stands for symbol flags. - * - * These values can be assigned to sy_symbol.ost_flags field of a symbolS. - * - * You'll break i960 if you shift the SYSPROC bits anywhere else. for - * more on the balname/callname hack, see tc-i960.h. b.out is done - * differently. - */ - -#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */ -#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */ -#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */ -#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */ -#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */ - -#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */ - -#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */ -#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */ -#define SF_STRING (0x00004000) /* Symbol name length > 8 */ -#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */ - -#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */ - -#define SF_FUNCTION (0x00010000) /* The symbol is a function */ -#define SF_PROCESS (0x00020000) /* Process symbol before write */ -#define SF_TAGGED (0x00040000) /* Is associated with a tag */ -#define SF_TAG (0x00080000) /* Is a tag */ -#define SF_DEBUG (0x00100000) /* Is in debug or abs section */ -#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */ -#define SF_ADJ_LNNOPTR (0x00400000) /* Has a lnnoptr */ -/* All other bits are unused. */ - -/* Accessors */ -#define SF_GET(s) ((s)->sy_symbol.ost_flags) -#define SF_GET_NORMAL_FIELD(s) (SF_GET (s) & SF_NORMAL_MASK) -#define SF_GET_DEBUG_FIELD(s) (SF_GET (s) & SF_DEBUG_MASK) -#define SF_GET_FILE(s) (SF_GET (s) & SF_FILE) -#define SF_GET_STATICS(s) (SF_GET (s) & SF_STATICS) -#define SF_GET_DEFINED(s) (SF_GET (s) & SF_DEFINED) -#define SF_GET_STRING(s) (SF_GET (s) & SF_STRING) -#define SF_GET_LOCAL(s) (SF_GET (s) & SF_LOCAL) -#define SF_GET_FUNCTION(s) (SF_GET (s) & SF_FUNCTION) -#define SF_GET_PROCESS(s) (SF_GET (s) & SF_PROCESS) -#define SF_GET_DEBUG(s) (SF_GET (s) & SF_DEBUG) -#define SF_GET_TAGGED(s) (SF_GET (s) & SF_TAGGED) -#define SF_GET_TAG(s) (SF_GET (s) & SF_TAG) -#define SF_GET_GET_SEGMENT(s) (SF_GET (s) & SF_GET_SEGMENT) -#define SF_GET_ADJ_LNNOPTR(s) (SF_GET (s) & SF_ADJ_LNNOPTR) -#define SF_GET_I960(s) (SF_GET (s) & SF_I960_MASK) /* used by i960 */ -#define SF_GET_BALNAME(s) (SF_GET (s) & SF_BALNAME) /* used by i960 */ -#define SF_GET_CALLNAME(s) (SF_GET (s) & SF_CALLNAME) /* used by i960 */ -#define SF_GET_IS_SYSPROC(s) (SF_GET (s) & SF_IS_SYSPROC) /* used by i960 */ -#define SF_GET_SYSPROC(s) (SF_GET (s) & SF_SYSPROC) /* used by i960 */ - -/* Modifiers */ -#define SF_SET(s,v) (SF_GET (s) = (v)) -#define SF_SET_NORMAL_FIELD(s,v)(SF_GET (s) |= ((v) & SF_NORMAL_MASK)) -#define SF_SET_DEBUG_FIELD(s,v) (SF_GET (s) |= ((v) & SF_DEBUG_MASK)) -#define SF_SET_FILE(s) (SF_GET (s) |= SF_FILE) -#define SF_SET_STATICS(s) (SF_GET (s) |= SF_STATICS) -#define SF_SET_DEFINED(s) (SF_GET (s) |= SF_DEFINED) -#define SF_SET_STRING(s) (SF_GET (s) |= SF_STRING) -#define SF_SET_LOCAL(s) (SF_GET (s) |= SF_LOCAL) -#define SF_CLEAR_LOCAL(s) (SF_GET (s) &= ~SF_LOCAL) -#define SF_SET_FUNCTION(s) (SF_GET (s) |= SF_FUNCTION) -#define SF_SET_PROCESS(s) (SF_GET (s) |= SF_PROCESS) -#define SF_SET_DEBUG(s) (SF_GET (s) |= SF_DEBUG) -#define SF_SET_TAGGED(s) (SF_GET (s) |= SF_TAGGED) -#define SF_SET_TAG(s) (SF_GET (s) |= SF_TAG) -#define SF_SET_GET_SEGMENT(s) (SF_GET (s) |= SF_GET_SEGMENT) -#define SF_SET_ADJ_LNNOPTR(s) (SF_GET (s) |= SF_ADJ_LNNOPTR) -#define SF_SET_I960(s,v) (SF_GET (s) |= ((v) & SF_I960_MASK)) /* used by i960 */ -#define SF_SET_BALNAME(s) (SF_GET (s) |= SF_BALNAME) /* used by i960 */ -#define SF_SET_CALLNAME(s) (SF_GET (s) |= SF_CALLNAME) /* used by i960 */ -#define SF_SET_IS_SYSPROC(s) (SF_GET (s) |= SF_IS_SYSPROC) /* used by i960 */ -#define SF_SET_SYSPROC(s,v) (SF_GET (s) |= ((v) & SF_SYSPROC)) /* used by i960 */ - -/* File header macro and type definition */ - -/* - * File position calculators. Beware to use them when all the - * appropriate fields are set in the header. - */ - -#ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER -#define OBJ_COFF_AOUTHDRSZ (0) -#else -#define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ) -#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ - -#define H_GET_FILE_SIZE(h) \ - (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ - H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ - H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ - H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \ - H_GET_SYMBOL_TABLE_SIZE(h) + \ - (h)->string_table_size) -#define H_GET_TEXT_FILE_OFFSET(h) \ - (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ - H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ) -#define H_GET_DATA_FILE_OFFSET(h) \ - (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ - H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ - H_GET_TEXT_SIZE(h)) -#define H_GET_BSS_FILE_OFFSET(h) 0 -#define H_GET_RELOCATION_FILE_OFFSET(h) \ - (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ - H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ - H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h)) -#define H_GET_LINENO_FILE_OFFSET(h) \ - (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ - H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ - H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ - H_GET_RELOCATION_SIZE(h)) -#define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \ - (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \ - H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \ - H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \ - H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h)) - -/* Accessors */ -/* aouthdr */ -#define H_GET_MAGIC_NUMBER(h) ((h)->aouthdr.magic) -#define H_GET_VERSION_STAMP(h) ((h)->aouthdr.vstamp) -#define H_GET_TEXT_SIZE(h) ((h)->aouthdr.tsize) -#define H_GET_DATA_SIZE(h) ((h)->aouthdr.dsize) -#define H_GET_BSS_SIZE(h) ((h)->aouthdr.bsize) -#define H_GET_ENTRY_POINT(h) ((h)->aouthdr.entry) -#define H_GET_TEXT_START(h) ((h)->aouthdr.text_start) -#define H_GET_DATA_START(h) ((h)->aouthdr.data_start) -/* filehdr */ -#define H_GET_FILE_MAGIC_NUMBER(h) ((h)->filehdr.f_magic) -#define H_GET_NUMBER_OF_SECTIONS(h) ((h)->filehdr.f_nscns) -#define H_GET_TIME_STAMP(h) ((h)->filehdr.f_timdat) -#define H_GET_SYMBOL_TABLE_POINTER(h) ((h)->filehdr.f_symptr) -#define H_GET_SYMBOL_COUNT(h) ((h)->filehdr.f_nsyms) -#define H_GET_SYMBOL_TABLE_SIZE(h) (H_GET_SYMBOL_COUNT(h) * SYMESZ) -#define H_GET_SIZEOF_OPTIONAL_HEADER(h) ((h)->filehdr.f_opthdr) -#define H_GET_FLAGS(h) ((h)->filehdr.f_flags) -/* Extra fields to achieve bsd a.out compatibility and for convenience */ -#define H_GET_RELOCATION_SIZE(h) ((h)->relocation_size) -#define H_GET_STRING_SIZE(h) ((h)->string_table_size) -#define H_GET_LINENO_SIZE(h) ((h)->lineno_size) - -#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER -#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ - + sizeof(AOUTHDR)\ - + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) -#else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ -#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \ - + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)) -#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */ - -#define H_GET_TEXT_RELOCATION_SIZE(h) (text_section_header.s_nreloc * RELSZ) -#define H_GET_DATA_RELOCATION_SIZE(h) (data_section_header.s_nreloc * RELSZ) - -/* Modifiers */ -/* aouthdr */ -#define H_SET_MAGIC_NUMBER(h,v) ((h)->aouthdr.magic = (v)) -#define H_SET_VERSION_STAMP(h,v) ((h)->aouthdr.vstamp = (v)) -#define H_SET_TEXT_SIZE(h,v) ((h)->aouthdr.tsize = (v)) -#define H_SET_DATA_SIZE(h,v) ((h)->aouthdr.dsize = (v)) -#define H_SET_BSS_SIZE(h,v) ((h)->aouthdr.bsize = (v)) -#define H_SET_ENTRY_POINT(h,v) ((h)->aouthdr.entry = (v)) -#define H_SET_TEXT_START(h,v) ((h)->aouthdr.text_start = (v)) -#define H_SET_DATA_START(h,v) ((h)->aouthdr.data_start = (v)) -/* filehdr */ -#define H_SET_FILE_MAGIC_NUMBER(h,v) ((h)->filehdr.f_magic = (v)) -#define H_SET_NUMBER_OF_SECTIONS(h,v) ((h)->filehdr.f_nscns = (v)) -#define H_SET_TIME_STAMP(h,v) ((h)->filehdr.f_timdat = (v)) -#define H_SET_SYMBOL_TABLE_POINTER(h,v) ((h)->filehdr.f_symptr = (v)) -#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->filehdr.f_nsyms = (v)) -#define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v)) -#define H_SET_FLAGS(h,v) ((h)->filehdr.f_flags = (v)) -/* Extra fields to achieve bsd a.out compatibility and for convinience */ -#define H_SET_RELOCATION_SIZE(h,t,d) ((h)->relocation_size = (t)+(d)) -#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v)) -#define H_SET_LINENO_SIZE(h,v) ((h)->lineno_size = (v)) - -/* Segment flipping */ - -typedef struct -{ - struct internal_aouthdr aouthdr; /* a.out header */ - struct internal_filehdr filehdr; /* File header, not machine dep. */ - long string_table_size; /* names + '\0' + sizeof(int) */ - long relocation_size; /* Cumulated size of relocation - information for all sections in - bytes. */ - long lineno_size; /* Size of the line number information - table in bytes */ -} object_headers; - - - -struct lineno_list -{ - struct bfd_internal_lineno line; - char *frag; /* Frag to which the line number is related */ - struct lineno_list *next; /* Forward chain pointer */ -}; - - - - -#define obj_segment_name(i) (segment_info[(int) (i)].scnhdr.s_name) - -#define obj_add_segment(s) obj_coff_add_segment (s) - -extern segT obj_coff_add_segment PARAMS ((const char *)); - -extern void obj_coff_section PARAMS ((int)); - -extern void c_dot_file_symbol PARAMS ((char *filename)); -#define obj_app_file c_dot_file_symbol -extern void obj_extra_stuff PARAMS ((object_headers * headers)); - -extern segT s_get_segment PARAMS ((struct symbol * ptr)); - -extern void c_section_header PARAMS ((struct internal_scnhdr * header, - char *name, - long core_address, - long size, - long data_ptr, - long reloc_ptr, - long lineno_ptr, - long reloc_number, - long lineno_number, - long alignment)); - -#ifndef tc_coff_symbol_emit_hook -void tc_coff_symbol_emit_hook PARAMS ((struct symbol *)); -#endif - -/* sanity check */ - -#ifdef TC_I960 -#ifndef C_LEAFSTAT -hey ! Where is the C_LEAFSTAT definition ? i960 - coff support is depending on it. -#endif /* no C_LEAFSTAT */ -#endif /* TC_I960 */ -extern struct internal_scnhdr data_section_header; -extern struct internal_scnhdr text_section_header; - -/* Forward the segment of a forwarded symbol. */ -#define OBJ_COPY_SYMBOL_ATTRIBUTES(dest,src) \ - (SF_GET_GET_SEGMENT (dest) \ - ? (S_SET_SEGMENT (dest, S_GET_SEGMENT (src)), 0) \ - : 0) - -#ifdef TE_PE -#define obj_handle_link_once(t) obj_coff_pe_handle_link_once (t) -extern void obj_coff_pe_handle_link_once (); -#endif - -#endif /* not BFD_ASSEMBLER */ - -/* In COFF, if a symbol is defined using .def/.val SYM/.endef, it's OK - to redefine the symbol later on. This can happen if C symbols use - a prefix, and a symbol is defined both with and without the prefix, - as in start/_start/__start in gcc/libgcc1-test.c. */ -#define RESOLVE_SYMBOL_REDEFINITION(sym) \ -(SF_GET_GET_SEGMENT (sym) \ - ? (sym->sy_frag = frag_now, \ - S_SET_VALUE (sym, frag_now_fix ()), \ - S_SET_SEGMENT (sym, now_seg), \ - 0) \ - : 0) - -/* Stabs in a coff file go into their own section. */ -#define SEPARATE_STAB_SECTIONS 1 - -/* We need 12 bytes at the start of the section to hold some initial - information. */ -extern void obj_coff_init_stab_section PARAMS ((segT)); -#define INIT_STAB_SECTION(seg) obj_coff_init_stab_section (seg) - -#endif /* OBJ_FORMAT_H */ diff --git a/contrib/binutils/gas/config/obj-ecoff.c b/contrib/binutils/gas/config/obj-ecoff.c deleted file mode 100644 index 27194a094d43..000000000000 --- a/contrib/binutils/gas/config/obj-ecoff.c +++ /dev/null @@ -1,305 +0,0 @@ -/* ECOFF object file format. - Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc. - Contributed by Cygnus Support. - This file was put together by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GAS. - - 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. - - 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-ecoff.h" -#include "as.h" -#include "coff/internal.h" -#include "bfd/libcoff.h" -#include "bfd/libecoff.h" - -/* Almost all of the ECOFF support is actually in ecoff.c in the main - 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)); - -/* 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 }, - { "weakext", ecoff_directive_weakext, 0 }, - - /* 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 } -}; - -/* Swap out the symbols and debugging information for BFD. */ - -void -ecoff_frob_file () -{ - const struct ecoff_debug_swap * const debug_swap - = &ecoff_backend (stdoutput)->debug_swap; - bfd_vma addr; - asection *sec; - HDRR *hdr; - char *buf; - char *set; - - /* Set the section VMA values. We force the .sdata and .sbss - sections to the end to ensure that their VMA addresses are close - together so that the GP register can address both of them. We - put the .bss section after the .sbss section. - - Also, for the Alpha, we must sort the sections, to make sure they - appear in the output file in the correct order. (Actually, maybe - this is a job for BFD. But the VMAs computed would be out of - whack if we computed them given our initial, random ordering. - It's possible that that wouldn't break things; I could do some - experimenting sometime and find out. - - This output ordering of sections is magic, on the Alpha, at - least. The .lita section must come before .lit8 and .lit4, - otherwise the OSF/1 linker may silently trash the .lit{4,8} - section contents. Also, .text must preceed .rdata. These differ - from the order described in some parts of the DEC OSF/1 Assembly - Language Programmer's Guide, but that order doesn't seem to work - with their linker. - - I don't know if section ordering on the MIPS is important. */ - - static const char *const names[] = { - /* text segment */ - ".text", ".rdata", ".init", ".fini", - /* data segment */ - ".data", ".lita", ".lit8", ".lit4", ".sdata", ".got", - /* bss segment */ - ".sbss", ".bss", - }; -#define n_names (sizeof (names) / sizeof (names[0])) - - addr = 0; - { - /* Sections that match names, order to be straightened out later. */ - asection *secs[n_names]; - /* Linked list of sections with non-matching names. Random ordering. */ - asection *other_sections = 0; - /* Pointer to next section, since we're destroying the original - ordering. */ - asection *next; - - int i; - - for (i = 0; i < n_names; i++) - secs[i] = 0; - for (sec = stdoutput->sections; sec != (asection *) NULL; sec = next) - { - next = sec->next; - for (i = 0; i < n_names; i++) - if (!strcmp (sec->name, names[i])) - { - secs[i] = sec; - break; - } - if (i == n_names) - { - bfd_set_section_vma (stdoutput, sec, addr); - addr += bfd_section_size (stdoutput, sec); - sec->next = other_sections; - other_sections = sec; - } - } - for (i = 0; i < n_names; i++) - if (secs[i]) - { - sec = secs[i]; - bfd_set_section_vma (stdoutput, sec, addr); - addr += bfd_section_size (stdoutput, sec); - } - for (i = n_names - 1; i >= 0; i--) - if (secs[i]) - { - sec = secs[i]; - sec->next = other_sections; - other_sections = sec; - } - stdoutput->sections = other_sections; - } - - /* Build the ECOFF debugging information. */ - assert (ecoff_data (stdoutput) != 0); - hdr = &ecoff_data (stdoutput)->debug_info.symbolic_header; - ecoff_build_debug (hdr, &buf, debug_swap); - - /* Finish up the ecoff_tdata structure. */ - set = buf; -#define SET(ptr, count, type, size) \ - if (hdr->count == 0) \ - ecoff_data (stdoutput)->debug_info.ptr = (type) NULL; \ - else \ - { \ - ecoff_data (stdoutput)->debug_info.ptr = (type) set; \ - set += hdr->count * size; \ - } - - 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_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); - -#undef SET - - /* Fill in the register masks. */ - { - unsigned long gprmask = 0; - unsigned long fprmask = 0; - unsigned long *cprmask = NULL; - -#ifdef TC_MIPS - /* Fill in the MIPS register masks. It's probably not worth - setting up a generic interface for this. */ - gprmask = mips_gprmask; - cprmask = mips_cprmask; -#endif - -#ifdef TC_ALPHA - alpha_frob_ecoff_data (); - - if (! bfd_ecoff_set_gp_value (stdoutput, alpha_gp_value)) - as_fatal ("Can't set GP value"); - - gprmask = alpha_gprmask; - fprmask = alpha_fprmask; -#endif - - if (! bfd_ecoff_set_regmasks (stdoutput, gprmask, fprmask, cprmask)) - as_fatal ("Can't set register masks"); - } -} - -/* This is called by the ECOFF code to set the external information - for a symbol. We just pass it on to BFD, which expects the swapped - information to be stored in the native field of the symbol. */ - -void -obj_ecoff_set_ext (sym, ext) - symbolS *sym; - EXTR *ext; -{ - const struct ecoff_debug_swap * const debug_swap - = &ecoff_backend (stdoutput)->debug_swap; - ecoff_symbol_type *esym; - - know (bfd_asymbol_flavour (sym->bsym) == bfd_target_ecoff_flavour); - esym = ecoffsymbol (sym->bsym); - esym->local = false; - esym->native = xmalloc (debug_swap->external_ext_size); - (*debug_swap->swap_ext_out) (stdoutput, ext, esym->native); -} - -static int -ecoff_sec_sym_ok_for_reloc (sec) - asection *sec; -{ - return 1; -} - -static void -obj_ecoff_frob_symbol (sym, puntp) - symbolS *sym; - int *puntp; -{ - ecoff_frob_symbol (sym); -} - -static void -ecoff_pop_insert () -{ - pop_insert (obj_pseudo_table); -} - -const struct format_ops ecoff_format_ops = -{ - bfd_target_ecoff_flavour, - 0, - 1, - obj_ecoff_frob_symbol, - ecoff_frob_file, - 0, - 0, 0, - 0, 0, - 0, - ecoff_generate_asm_lineno, - ecoff_stab, - ecoff_sec_sym_ok_for_reloc, - ecoff_pop_insert, - ecoff_set_ext, - ecoff_read_begin_hook, - ecoff_symbol_new_hook, -}; diff --git a/contrib/binutils/gas/config/obj-ecoff.h b/contrib/binutils/gas/config/obj-ecoff.h deleted file mode 100644 index 0192afe4dc5c..000000000000 --- a/contrib/binutils/gas/config/obj-ecoff.h +++ /dev/null @@ -1,70 +0,0 @@ -/* ECOFF object file format header file. - Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc. - Contributed by Cygnus Support. - Written by Ian Lance Taylor <ian@cygnus.com>. - - This file is part of GAS. - - 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. - - 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_ECOFF 1 - -/* Use the generic ECOFF debugging code. */ -#define ECOFF_DEBUGGING 1 - -#define OUTPUT_FLAVOR bfd_target_ecoff_flavour - -#include "targ-cpu.h" - -#include "ecoff.h" - -/* For each gas symbol we keep track of which file it came from, of - whether we have generated an ECOFF symbol for it, and whether the - symbols is undefined (this last is needed to distinguish a .extern - symbols from a .comm symbol). */ - -#define TARGET_SYMBOL_FIELDS \ - struct efdr *ecoff_file; \ - struct localsym *ecoff_symbol; \ - valueT ecoff_extern_size; - -/* Modify the ECOFF symbol. */ -#define obj_frob_symbol(symp, punt) ecoff_frob_symbol (symp) - -/* 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. */ -#define obj_read_begin_hook ecoff_read_begin_hook -#define obj_symbol_new_hook ecoff_symbol_new_hook - -/* Record file switches in the ECOFF symbol table. */ -#define obj_app_file(name) ecoff_new_file (name) - -/* At the moment we don't want to do any stabs processing in read.c. */ -#define OBJ_PROCESS_STAB(seg, what, string, type, other, desc) \ - ecoff_stab ((seg), (what), (string), (type), (other), (desc)) - -#define OBJ_GENERATE_ASM_LINENO(filename, lineno) \ - ecoff_generate_asm_lineno ((filename), (lineno)) - -#define EMIT_SECTION_SYMBOLS 0 -#define obj_sec_sym_ok_for_reloc(SEC) 1 - -#define obj_ecoff_set_ext ecoff_set_ext -extern void obj_ecoff_set_ext PARAMS ((struct symbol *, EXTR *)); diff --git a/contrib/binutils/gas/config/obj-elf.c b/contrib/binutils/gas/config/obj-elf.c deleted file mode 100644 index b8201f5e45b2..000000000000 --- a/contrib/binutils/gas/config/obj-elf.c +++ /dev/null @@ -1,1642 +0,0 @@ -/* ELF object file format - Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. - - 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 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. */ - -#define OBJ_HEADER "obj-elf.h" -#include "as.h" -#include "subsegs.h" -#include "obstack.h" - -#ifndef ECOFF_DEBUGGING -#define ECOFF_DEBUGGING 0 -#else -#define NEED_ECOFF_DEBUG -#endif - -#ifdef NEED_ECOFF_DEBUG -#include "ecoff.h" -#endif - -#ifdef TC_ALPHA -#include "elf/alpha.h" -#endif - -#ifdef TC_MIPS -#include "elf/mips.h" -#endif - -#ifdef TC_PPC -#include "elf/ppc.h" -#endif - -static bfd_vma elf_s_get_size PARAMS ((symbolS *)); -static void elf_s_set_size PARAMS ((symbolS *, bfd_vma)); -static bfd_vma elf_s_get_align PARAMS ((symbolS *)); -static void elf_s_set_align PARAMS ((symbolS *, bfd_vma)); -static void elf_copy_symbol_attributes PARAMS ((symbolS *, symbolS *)); -static int elf_sec_sym_ok_for_reloc PARAMS ((asection *)); -static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR)); - -#ifdef NEED_ECOFF_DEBUG -static boolean elf_get_extr PARAMS ((asymbol *, EXTR *)); -static void elf_set_index PARAMS ((asymbol *, bfd_size_type)); -#endif - -static void obj_elf_line PARAMS ((int)); -void obj_elf_version PARAMS ((int)); -static void obj_elf_size PARAMS ((int)); -static void obj_elf_type PARAMS ((int)); -static void obj_elf_ident PARAMS ((int)); -static void obj_elf_weak PARAMS ((int)); -static void obj_elf_local PARAMS ((int)); -static void obj_elf_common PARAMS ((int)); -static void obj_elf_symver PARAMS ((int)); -static void obj_elf_data PARAMS ((int)); -static void obj_elf_text PARAMS ((int)); -static void obj_elf_subsection PARAMS ((int)); - -static const pseudo_typeS elf_pseudo_table[] = -{ - {"comm", obj_elf_common, 0}, - {"ident", obj_elf_ident, 0}, - {"local", obj_elf_local, 0}, - {"previous", obj_elf_previous, 0}, - {"section", obj_elf_section, 0}, - {"section.s", obj_elf_section, 0}, - {"sect", obj_elf_section, 0}, - {"sect.s", obj_elf_section, 0}, - {"size", obj_elf_size, 0}, - {"type", obj_elf_type, 0}, - {"version", obj_elf_version, 0}, - {"weak", obj_elf_weak, 0}, - - /* These are used for stabs-in-elf configurations. */ - {"line", obj_elf_line, 0}, - - /* This is a GNU extension to handle symbol versions. */ - {"symver", obj_elf_symver, 0}, - - /* A GNU extension to change subsection only. */ - {"subsection", obj_elf_subsection, 0}, - - /* These are used for dwarf. */ - {"2byte", cons, 2}, - {"4byte", cons, 4}, - {"8byte", cons, 8}, - - /* We need to trap the section changing calls to handle .previous. */ - {"data", obj_elf_data, 0}, - {"text", obj_elf_text, 0}, - - /* End sentinel. */ - {NULL}, -}; - -static const pseudo_typeS ecoff_debug_pseudo_table[] = -{ -#ifdef NEED_ECOFF_DEBUG - /* COFF style debugging information for ECOFF. .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 }, - { "tag", ecoff_directive_tag, 0 }, - { "val", ecoff_directive_val, 0 }, - - /* COFF debugging requires pseudo-ops .size and .type, but ELF - already has meanings for those. We use .esize and .etype - instead. These are only generated by gcc anyhow. */ - { "esize", ecoff_directive_size, 0 }, - { "etype", ecoff_directive_type, 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 }, - - /* These are used on Irix. I don't know how to implement them. */ - { "alias", s_ignore, 0 }, - { "bgnb", s_ignore, 0 }, - { "endb", s_ignore, 0 }, - { "lab", s_ignore, 0 }, - { "noalias", s_ignore, 0 }, - { "verstamp", s_ignore, 0 }, - { "vreg", s_ignore, 0 }, -#endif - - {NULL} /* end sentinel */ -}; - -#undef NO_RELOC -#include "aout/aout64.h" - -/* This is called when the assembler starts. */ - -void -elf_begin () -{ - /* Add symbols for the known sections to the symbol table. */ - symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput, - TEXT_SECTION_NAME))); - symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput, - DATA_SECTION_NAME))); - symbol_table_insert (section_symbol (bfd_get_section_by_name (stdoutput, - BSS_SECTION_NAME))); -} - -void -elf_pop_insert () -{ - pop_insert (elf_pseudo_table); - if (ECOFF_DEBUGGING) - pop_insert (ecoff_debug_pseudo_table); -} - -static bfd_vma -elf_s_get_size (sym) - symbolS *sym; -{ - return S_GET_SIZE (sym); -} - -static void -elf_s_set_size (sym, sz) - symbolS *sym; - bfd_vma sz; -{ - S_SET_SIZE (sym, sz); -} - -static bfd_vma -elf_s_get_align (sym) - symbolS *sym; -{ - return S_GET_ALIGN (sym); -} - -static void -elf_s_set_align (sym, align) - symbolS *sym; - bfd_vma align; -{ - S_SET_ALIGN (sym, align); -} - -static void -elf_copy_symbol_attributes (dest, src) - symbolS *dest, *src; -{ - OBJ_COPY_SYMBOL_ATTRIBUTES (dest, src); -} - -static int -elf_sec_sym_ok_for_reloc (sec) - asection *sec; -{ - return obj_sec_sym_ok_for_reloc (sec); -} - -void -elf_file_symbol (s) - char *s; -{ - symbolS *sym; - - sym = symbol_new (s, absolute_section, (valueT) 0, (struct frag *) 0); - sym->sy_frag = &zero_address_frag; - sym->bsym->flags |= BSF_FILE; - - if (symbol_rootP != sym) - { - symbol_remove (sym, &symbol_rootP, &symbol_lastP); - symbol_insert (sym, symbol_rootP, &symbol_rootP, &symbol_lastP); -#ifdef DEBUG - verify_symbol_chain (symbol_rootP, symbol_lastP); -#endif - } - -#ifdef NEED_ECOFF_DEBUG - ecoff_new_file (s); -#endif -} - -static void -obj_elf_common (ignore) - int ignore; -{ - char *name; - char c; - char *p; - int temp, size; - symbolS *symbolP; - int have_align; - - name = input_line_pointer; - c = get_symbol_end (); - /* just after name is now '\0' */ - p = input_line_pointer; - *p = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - as_bad ("Expected comma after symbol-name"); - ignore_rest_of_line (); - return; - } - input_line_pointer++; /* skip ',' */ - if ((temp = get_absolute_expression ()) < 0) - { - as_bad (".COMMon length (%d.) <0! Ignored.", temp); - ignore_rest_of_line (); - return; - } - size = temp; - *p = 0; - symbolP = symbol_find_or_make (name); - *p = c; - if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) - { - as_bad ("Ignoring attempt to re-define symbol"); - ignore_rest_of_line (); - return; - } - if (S_GET_VALUE (symbolP) != 0) - { - if (S_GET_VALUE (symbolP) != size) - { - as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.", - S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); - } - } - know (symbolP->sy_frag == &zero_address_frag); - if (*input_line_pointer != ',') - have_align = 0; - else - { - have_align = 1; - input_line_pointer++; - SKIP_WHITESPACE (); - } - if (! have_align || *input_line_pointer != '"') - { - if (! have_align) - temp = 0; - else - { - temp = get_absolute_expression (); - if (temp < 0) - { - temp = 0; - as_warn ("Common alignment negative; 0 assumed"); - } - } - if (symbolP->local) - { - segT old_sec; - int old_subsec; - char *pfrag; - int align; - - /* allocate_bss: */ - old_sec = now_seg; - old_subsec = now_subseg; - if (temp) - { - /* convert to a power of 2 alignment */ - for (align = 0; (temp & 1) == 0; temp >>= 1, ++align); - if (temp != 1) - { - as_bad ("Common alignment not a power of 2"); - ignore_rest_of_line (); - return; - } - } - else - align = 0; - record_alignment (bss_section, align); - subseg_set (bss_section, 0); - if (align) - frag_align (align, 0, 0); - if (S_GET_SEGMENT (symbolP) == bss_section) - symbolP->sy_frag->fr_symbol = 0; - symbolP->sy_frag = frag_now; - pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, - (offsetT) size, (char *) 0); - *pfrag = 0; - S_SET_SIZE (symbolP, size); - S_SET_SEGMENT (symbolP, bss_section); - S_CLEAR_EXTERNAL (symbolP); - subseg_set (old_sec, old_subsec); - } - else - { - allocate_common: - S_SET_VALUE (symbolP, (valueT) size); - S_SET_ALIGN (symbolP, temp); - S_SET_EXTERNAL (symbolP); - S_SET_SEGMENT (symbolP, bfd_com_section_ptr); - } - } - else - { - input_line_pointer++; - /* @@ Some use the dot, some don't. Can we get some consistency?? */ - if (*input_line_pointer == '.') - input_line_pointer++; - /* @@ Some say data, some say bss. */ - if (strncmp (input_line_pointer, "bss\"", 4) - && strncmp (input_line_pointer, "data\"", 5)) - { - while (*--input_line_pointer != '"') - ; - input_line_pointer--; - goto bad_common_segment; - } - while (*input_line_pointer++ != '"') - ; - goto allocate_common; - } - - symbolP->bsym->flags |= BSF_OBJECT; - - demand_empty_rest_of_line (); - return; - - { - bad_common_segment: - p = input_line_pointer; - while (*p && *p != '\n') - p++; - c = *p; - *p = '\0'; - as_bad ("bad .common segment %s", input_line_pointer + 1); - *p = c; - input_line_pointer = p; - ignore_rest_of_line (); - return; - } -} - -static void -obj_elf_local (ignore) - int ignore; -{ - char *name; - int c; - symbolS *symbolP; - - do - { - name = input_line_pointer; - c = get_symbol_end (); - symbolP = symbol_find_or_make (name); - *input_line_pointer = c; - SKIP_WHITESPACE (); - S_CLEAR_EXTERNAL (symbolP); - symbolP->local = 1; - if (c == ',') - { - input_line_pointer++; - SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') - c = '\n'; - } - } - while (c == ','); - demand_empty_rest_of_line (); -} - -static void -obj_elf_weak (ignore) - int ignore; -{ - char *name; - int c; - symbolS *symbolP; - - do - { - name = input_line_pointer; - c = get_symbol_end (); - symbolP = symbol_find_or_make (name); - *input_line_pointer = c; - SKIP_WHITESPACE (); - S_SET_WEAK (symbolP); - symbolP->local = 1; - if (c == ',') - { - input_line_pointer++; - SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') - c = '\n'; - } - } - while (c == ','); - demand_empty_rest_of_line (); -} - -static segT previous_section; -static int previous_subsection; - -/* Handle the .section pseudo-op. This code supports two different - syntaxes. - - The first is found on Solaris, and looks like - .section ".sec1",#alloc,#execinstr,#write - Here the names after '#' are the SHF_* flags to turn on for the - section. I'm not sure how it determines the SHT_* type (BFD - doesn't really give us control over the type, anyhow). - - The second format is found on UnixWare, and probably most SVR4 - machines, and looks like - .section .sec1,"a",@progbits - The quoted string may contain any combination of a, w, x, and - represents the SHF_* flags to turn on for the section. The string - beginning with '@' can be progbits or nobits. There should be - other possibilities, but I don't know what they are. In any case, - BFD doesn't really let us set the section type. */ - -/* Certain named sections have particular defined types, listed on p. - 4-19 of the ABI. */ -struct special_section -{ - const char *name; - int type; - int attributes; -}; - -static struct special_section special_sections[] = -{ - { ".bss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, - { ".comment", SHT_PROGBITS, 0 }, - { ".data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, - { ".data1", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, - { ".debug", SHT_PROGBITS, 0 }, - { ".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, - { ".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, - { ".line", SHT_PROGBITS, 0 }, - { ".note", SHT_NOTE, 0 }, - { ".rodata", SHT_PROGBITS, SHF_ALLOC }, - { ".rodata1", SHT_PROGBITS, SHF_ALLOC }, - { ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR }, - -#ifdef ELF_TC_SPECIAL_SECTIONS - ELF_TC_SPECIAL_SECTIONS -#endif - -#if 0 - /* The following section names are special, but they can not - reasonably appear in assembler code. Some of the attributes are - processor dependent. */ - { ".dynamic", SHT_DYNAMIC, SHF_ALLOC /* + SHF_WRITE */ }, - { ".dynstr", SHT_STRTAB, SHF_ALLOC }, - { ".dynsym", SHT_DYNSYM, SHF_ALLOC }, - { ".got", SHT_PROGBITS, 0 }, - { ".hash", SHT_HASH, SHF_ALLOC }, - { ".interp", SHT_PROGBITS, /* SHF_ALLOC */ }, - { ".plt", SHT_PROGBITS, 0 }, - { ".shstrtab",SHT_STRTAB, 0 }, - { ".strtab", SHT_STRTAB, /* SHF_ALLOC */ }, - { ".symtab", SHT_SYMTAB, /* SHF_ALLOC */ }, -#endif - - { NULL, 0, 0 } -}; - -void -obj_elf_section (xxx) - int xxx; -{ - char *string; - int new_sec; - segT sec; - int type, attr; - int i; - flagword flags; - symbolS *secsym; - -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - if (flag_mri) - { - char mri_type; - - previous_section = now_seg; - previous_subsection = now_subseg; - - s_mri_sect (&mri_type); - -#ifdef md_elf_section_change_hook - md_elf_section_change_hook (); -#endif - - return; - } - - /* Get name of section. */ - SKIP_WHITESPACE (); - if (*input_line_pointer == '"') - { - string = demand_copy_C_string (&xxx); - if (string == NULL) - { - ignore_rest_of_line (); - return; - } - } - else - { - char *p = input_line_pointer; - char c; - while (0 == strchr ("\n\t,; ", *p)) - p++; - if (p == input_line_pointer) - { - as_warn ("Missing section name"); - ignore_rest_of_line (); - return; - } - c = *p; - *p = 0; - string = xmalloc ((unsigned long) (p - input_line_pointer + 1)); - strcpy (string, input_line_pointer); - *p = c; - input_line_pointer = p; - } - - /* Switch to the section, creating it if necessary. */ - previous_section = now_seg; - previous_subsection = now_subseg; - - new_sec = bfd_get_section_by_name (stdoutput, string) == NULL; - sec = subseg_new (string, 0); - - /* If this section already existed, we don't bother to change the - flag values. */ - if (! new_sec) - { - while (! is_end_of_line[(unsigned char) *input_line_pointer]) - ++input_line_pointer; - ++input_line_pointer; - -#ifdef md_elf_section_change_hook - md_elf_section_change_hook (); -#endif - - return; - } - - SKIP_WHITESPACE (); - - type = SHT_NULL; - attr = 0; - - if (*input_line_pointer == ',') - { - /* Skip the comma. */ - ++input_line_pointer; - - SKIP_WHITESPACE (); - - if (*input_line_pointer == '"') - { - /* Pick up a string with a combination of a, w, x. */ - ++input_line_pointer; - while (*input_line_pointer != '"') - { - switch (*input_line_pointer) - { - case 'a': - attr |= SHF_ALLOC; - break; - case 'w': - attr |= SHF_WRITE; - break; - case 'x': - attr |= SHF_EXECINSTR; - break; - default: - { - char *bad_msg = "Bad .section directive: want a,w,x in string"; -#ifdef md_elf_section_letter - int md_attr = md_elf_section_letter (*input_line_pointer, &bad_msg); - if (md_attr) - attr |= md_attr; - else -#endif - { - as_warn (bad_msg); - ignore_rest_of_line (); - return; - } - } - } - ++input_line_pointer; - } - - /* Skip the closing quote. */ - ++input_line_pointer; - - SKIP_WHITESPACE (); - if (*input_line_pointer == ',') - { - ++input_line_pointer; - SKIP_WHITESPACE (); - if (*input_line_pointer == '@') - { - ++input_line_pointer; - if (strncmp (input_line_pointer, "progbits", - sizeof "progbits" - 1) == 0) - { - type = SHT_PROGBITS; - input_line_pointer += sizeof "progbits" - 1; - } - else if (strncmp (input_line_pointer, "nobits", - sizeof "nobits" - 1) == 0) - { - type = SHT_NOBITS; - input_line_pointer += sizeof "nobits" - 1; - } - else - { -#ifdef md_elf_section_type - int md_type = md_elf_section_type (&input_line_pointer); - if (md_type) - type = md_type; - else -#endif - { - as_warn ("Unrecognized section type"); - ignore_rest_of_line (); - } - } - } - } - } - else - { - do - { - SKIP_WHITESPACE (); - if (*input_line_pointer != '#') - { - as_warn ("Bad .section directive - character following name is not '#'"); - ignore_rest_of_line (); - return; - } - ++input_line_pointer; - if (strncmp (input_line_pointer, "write", - sizeof "write" - 1) == 0) - { - attr |= SHF_WRITE; - input_line_pointer += sizeof "write" - 1; - } - else if (strncmp (input_line_pointer, "alloc", - sizeof "alloc" - 1) == 0) - { - attr |= SHF_ALLOC; - input_line_pointer += sizeof "alloc" - 1; - } - else if (strncmp (input_line_pointer, "execinstr", - sizeof "execinstr" - 1) == 0) - { - attr |= SHF_EXECINSTR; - input_line_pointer += sizeof "execinstr" - 1; - } - else - { -#ifdef md_elf_section_word - int md_attr = md_elf_section_word (&input_line_pointer); - if (md_attr) - attr |= md_attr; - else -#endif - { - as_warn ("Unrecognized section attribute"); - ignore_rest_of_line (); - return; - } - } - SKIP_WHITESPACE (); - } - while (*input_line_pointer++ == ','); - --input_line_pointer; - } - } - - /* See if this is one of the special sections. */ - for (i = 0; special_sections[i].name != NULL; i++) - { - if (string[1] == special_sections[i].name[1] - && strcmp (string, special_sections[i].name) == 0) - { - if (type == SHT_NULL) - type = special_sections[i].type; - else if (type != special_sections[i].type) - as_warn ("Setting incorrect section type for %s", string); - - if ((attr &~ special_sections[i].attributes) != 0) - { - /* As a GNU extension, we permit a .note section to be - allocatable. If the linker sees an allocateable - .note section, it will create a PT_NOTE segment in - the output file. */ - if (strcmp (string, ".note") != 0 - || attr != SHF_ALLOC) - as_warn ("Setting incorrect section attributes for %s", - string); - } - attr |= special_sections[i].attributes; - - break; - } - } - - flags = (SEC_RELOC - | ((attr & SHF_WRITE) ? 0 : SEC_READONLY) - | ((attr & SHF_ALLOC) ? SEC_ALLOC : 0) - | (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0) - | ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)); - if (special_sections[i].name == NULL) - { - if (type == SHT_PROGBITS) - flags |= SEC_ALLOC | SEC_LOAD; - else if (type == SHT_NOBITS) - { - flags |= SEC_ALLOC; - flags &=~ SEC_LOAD; - } - -#ifdef md_elf_section_flags - flags = md_elf_section_flags (flags, attr, type); -#endif - } - - /* Prevent SEC_HAS_CONTENTS from being inadvertently set. */ - if (type == SHT_NOBITS) - seg_info (sec)->bss = 1; - - bfd_set_section_flags (stdoutput, sec, flags); - - /* Add a symbol for this section to the symbol table. */ - secsym = symbol_find (string); - if (secsym != NULL) - secsym->bsym = sec->symbol; - else - symbol_table_insert (section_symbol (sec)); - -#ifdef md_elf_section_change_hook - md_elf_section_change_hook (); -#endif - - demand_empty_rest_of_line (); -} - -/* Change to the .data section. */ - -static void -obj_elf_data (i) - int i; -{ -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - previous_section = now_seg; - previous_subsection = now_subseg; - s_data (i); - -#ifdef md_elf_section_change_hook - md_elf_section_change_hook (); -#endif -} - -/* Change to the .text section. */ - -static void -obj_elf_text (i) - int i; -{ -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - previous_section = now_seg; - previous_subsection = now_subseg; - s_text (i); - -#ifdef md_elf_section_change_hook - md_elf_section_change_hook (); -#endif -} - -static void -obj_elf_subsection (ignore) - int ignore; -{ - register int temp; - -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - previous_section = now_seg; - previous_subsection = now_subseg; - - temp = get_absolute_expression (); - subseg_set (now_seg, (subsegT) temp); - demand_empty_rest_of_line (); - -#ifdef md_elf_section_change_hook - md_elf_section_change_hook (); -#endif -} - -/* This can be called from the processor backends if they change - sections. */ - -void -obj_elf_section_change_hook () -{ - previous_section = now_seg; - previous_subsection = now_subseg; -} - -void -obj_elf_previous (ignore) - int ignore; -{ - if (previous_section == 0) - { - as_bad (".previous without corresponding .section; ignored"); - return; - } - -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - subseg_set (previous_section, previous_subsection); - previous_section = 0; - -#ifdef md_elf_section_change_hook - md_elf_section_change_hook (); -#endif -} - -static void -obj_elf_line (ignore) - int ignore; -{ - /* 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 (); -} - -/* This handle the .symver pseudo-op, which is used to specify a - symbol version. The syntax is ``.symver NAME,SYMVERNAME''. - SYMVERNAME may contain ELF_VER_CHR ('@') characters. This - pseudo-op causes the assembler to emit a symbol named SYMVERNAME - with the same value as the symbol NAME. */ - -static void -obj_elf_symver (ignore) - int ignore; -{ - char *name; - char c; - symbolS *sym; - - name = input_line_pointer; - c = get_symbol_end (); - - sym = symbol_find_or_make (name); - - *input_line_pointer = c; - - if (sym->sy_obj.versioned_name != NULL) - { - as_bad ("multiple .symver directives for symbol `%s'", - S_GET_NAME (sym)); - ignore_rest_of_line (); - return; - } - - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - as_bad ("expected comma after name in .symver"); - ignore_rest_of_line (); - return; - } - - ++input_line_pointer; - name = input_line_pointer; - while (1) - { - c = get_symbol_end (); - if (c != ELF_VER_CHR) - break; - *input_line_pointer++ = c; - } - - sym->sy_obj.versioned_name = xstrdup (name); - - *input_line_pointer = c; - - if (strchr (sym->sy_obj.versioned_name, ELF_VER_CHR) == NULL) - { - as_bad ("missing version name in `%s' for symbol `%s'", - sym->sy_obj.versioned_name, S_GET_NAME (sym)); - ignore_rest_of_line (); - return; - } - - demand_empty_rest_of_line (); -} - -void -obj_read_begin_hook () -{ -#ifdef NEED_ECOFF_DEBUG - if (ECOFF_DEBUGGING) - ecoff_read_begin_hook (); -#endif -} - -void -obj_symbol_new_hook (symbolP) - symbolS *symbolP; -{ - symbolP->sy_obj.size = NULL; - symbolP->sy_obj.versioned_name = NULL; - -#ifdef NEED_ECOFF_DEBUG - if (ECOFF_DEBUGGING) - ecoff_symbol_new_hook (symbolP); -#endif -} - -void -obj_elf_version (ignore) - int ignore; -{ - char *name; - unsigned int c; - char ch; - char *p; - asection *seg = now_seg; - subsegT subseg = now_subseg; - Elf_Internal_Note i_note; - Elf_External_Note e_note; - asection *note_secp = (asection *) NULL; - int i, len; - - SKIP_WHITESPACE (); - if (*input_line_pointer == '\"') - { - ++input_line_pointer; /* -> 1st char of string. */ - name = input_line_pointer; - - while (is_a_char (c = next_char_of_string ())) - ; - c = *input_line_pointer; - *input_line_pointer = '\0'; - *(input_line_pointer - 1) = '\0'; - *input_line_pointer = c; - - /* create the .note section */ - - note_secp = subseg_new (".note", 0); - bfd_set_section_flags (stdoutput, - note_secp, - SEC_HAS_CONTENTS | SEC_READONLY); - - /* process the version string */ - - len = strlen (name); - - i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */ - i_note.descsz = 0; /* no description */ - i_note.type = NT_VERSION; - p = frag_more (sizeof (e_note.namesz)); - md_number_to_chars (p, (valueT) i_note.namesz, 4); - p = frag_more (sizeof (e_note.descsz)); - md_number_to_chars (p, (valueT) i_note.descsz, 4); - p = frag_more (sizeof (e_note.type)); - md_number_to_chars (p, (valueT) i_note.type, 4); - - for (i = 0; i < len; i++) - { - ch = *(name + i); - { - FRAG_APPEND_1_CHAR (ch); - } - } - frag_align (2, 0, 0); - - subseg_set (seg, subseg); - } - else - { - as_bad ("Expected quoted string"); - } - demand_empty_rest_of_line (); -} - -static void -obj_elf_size (ignore) - int ignore; -{ - char *name = input_line_pointer; - char c = get_symbol_end (); - char *p; - expressionS exp; - symbolS *sym; - - p = input_line_pointer; - *p = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - *p = 0; - as_bad ("expected comma after name `%s' in .size directive", name); - *p = c; - ignore_rest_of_line (); - return; - } - input_line_pointer++; - expression (&exp); - if (exp.X_op == O_absent) - { - as_bad ("missing expression in .size directive"); - exp.X_op = O_constant; - exp.X_add_number = 0; - } - *p = 0; - sym = symbol_find_or_make (name); - *p = c; - if (exp.X_op == O_constant) - S_SET_SIZE (sym, exp.X_add_number); - else - { - sym->sy_obj.size = (expressionS *) xmalloc (sizeof (expressionS)); - *sym->sy_obj.size = exp; - } - demand_empty_rest_of_line (); -} - -/* Handle the ELF .type pseudo-op. This sets the type of a symbol. - There are three syntaxes. The first (used on Solaris) is - .type SYM,#function - The second (used on UnixWare) is - .type SYM,@function - The third (reportedly to be used on Irix 6.0) is - .type SYM STT_FUNC - */ - -static void -obj_elf_type (ignore) - int ignore; -{ - char *name; - char c; - int type; - const char *typename; - symbolS *sym; - - name = input_line_pointer; - c = get_symbol_end (); - sym = symbol_find_or_make (name); - *input_line_pointer = c; - - SKIP_WHITESPACE (); - if (*input_line_pointer == ',') - ++input_line_pointer; - - SKIP_WHITESPACE (); - if (*input_line_pointer == '#' || *input_line_pointer == '@') - ++input_line_pointer; - - typename = input_line_pointer; - c = get_symbol_end (); - - type = 0; - if (strcmp (typename, "function") == 0 - || strcmp (typename, "STT_FUNC") == 0) - type = BSF_FUNCTION; - else if (strcmp (typename, "object") == 0 - || strcmp (typename, "STT_OBJECT") == 0) - type = BSF_OBJECT; - else - as_bad ("ignoring unrecognized symbol type \"%s\"", typename); - - *input_line_pointer = c; - - sym->bsym->flags |= type; - - demand_empty_rest_of_line (); -} - -static void -obj_elf_ident (ignore) - int ignore; -{ - static segT comment_section; - segT old_section = now_seg; - int old_subsection = now_subseg; - - if (!comment_section) - { - char *p; - comment_section = subseg_new (".comment", 0); - bfd_set_section_flags (stdoutput, comment_section, - SEC_READONLY | SEC_HAS_CONTENTS); - p = frag_more (1); - *p = 0; - } - else - subseg_set (comment_section, 0); - stringer (1); - subseg_set (old_section, old_subsection); -} - -#ifdef INIT_STAB_SECTION - -/* The first entry in a .stabs section is special. */ - -void -obj_elf_init_stab_section (seg) - segT seg; -{ - char *file; - char *p; - char *stabstr_name; - unsigned int stroff; - - /* Force the section to align to a longword boundary. Without this, - UnixWare ar crashes. */ - bfd_set_section_alignment (stdoutput, seg, 2); - - /* Make space for this first symbol. */ - p = frag_more (12); - /* Zero it out. */ - memset (p, 0, 12); - as_where (&file, (unsigned int *) NULL); - stabstr_name = (char *) alloca (strlen (segment_name (seg)) + 4); - strcpy (stabstr_name, segment_name (seg)); - strcat (stabstr_name, "str"); - stroff = get_stab_string_offset (file, stabstr_name); - know (stroff == 1); - md_number_to_chars (p, stroff, 4); - seg_info (seg)->stabu.p = p; -} - -#endif - -/* 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; -{ - char *name; - asection *strsec; - char *p; - int strsz, nsyms; - - if (strncmp (".stab", sec->name, 5)) - return; - if (!strcmp ("str", sec->name + strlen (sec->name) - 3)) - return; - - name = (char *) alloca (strlen (sec->name) + 4); - strcpy (name, sec->name); - strcat (name, "str"); - strsec = bfd_get_section_by_name (abfd, name); - if (strsec) - strsz = bfd_section_size (abfd, strsec); - else - strsz = 0; - nsyms = bfd_section_size (abfd, sec) / 12 - 1; - - p = seg_info (sec)->stabu.p; - assert (p != 0); - - bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); - bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8); -} - -#ifdef NEED_ECOFF_DEBUG - -/* This function is called by the ECOFF code. It is supposed to - record the external symbol information so that the backend can - write it out correctly. The ELF backend doesn't actually handle - this at the moment, so we do it ourselves. We save the information - in the symbol. */ - -void -elf_ecoff_set_ext (sym, ext) - symbolS *sym; - struct ecoff_extr *ext; -{ - sym->bsym->udata.p = (PTR) ext; -} - -/* This function is called by bfd_ecoff_debug_externals. It is - supposed to *EXT to the external symbol information, and return - whether the symbol should be used at all. */ - -static boolean -elf_get_extr (sym, ext) - asymbol *sym; - EXTR *ext; -{ - if (sym->udata.p == NULL) - return false; - *ext = *(EXTR *) sym->udata.p; - return true; -} - -/* This function is called by bfd_ecoff_debug_externals. It has - nothing to do for ELF. */ - -/*ARGSUSED*/ -static void -elf_set_index (sym, indx) - asymbol *sym; - bfd_size_type indx; -{ -} - -#endif /* NEED_ECOFF_DEBUG */ - -void -elf_frob_symbol (symp, puntp) - symbolS *symp; - int *puntp; -{ -#ifdef NEED_ECOFF_DEBUG - if (ECOFF_DEBUGGING) - ecoff_frob_symbol (symp); -#endif - - if (symp->sy_obj.size != NULL) - { - switch (symp->sy_obj.size->X_op) - { - case O_subtract: - S_SET_SIZE (symp, - (S_GET_VALUE (symp->sy_obj.size->X_add_symbol) - + symp->sy_obj.size->X_add_number - - S_GET_VALUE (symp->sy_obj.size->X_op_symbol))); - break; - case O_constant: - S_SET_SIZE (symp, - (S_GET_VALUE (symp->sy_obj.size->X_add_symbol) - + symp->sy_obj.size->X_add_number)); - break; - default: - as_bad (".size expression too complicated to fix up"); - break; - } - free (symp->sy_obj.size); - symp->sy_obj.size = NULL; - } - - if (symp->sy_obj.versioned_name != NULL) - { - /* This symbol was given a new name with the .symver directive. - - If this is an external reference, just rename the symbol to - include the version string. This will make the relocs be - against the correct versioned symbol. - - If this is a definition, add an alias. FIXME: Using an alias - will permit the debugging information to refer to the right - symbol. However, it's not clear whether it is the best - approach. */ - - if (! S_IS_DEFINED (symp)) - { - char *p; - - /* Verify that the name isn't using the @@ syntax--this is - reserved for definitions of the default version to link - against. */ - p = strchr (symp->sy_obj.versioned_name, ELF_VER_CHR); - know (p != NULL); - if (p[1] == ELF_VER_CHR) - { - as_bad ("invalid attempt to declare external version name as default in symbol `%s'", - symp->sy_obj.versioned_name); - *puntp = true; - } - S_SET_NAME (symp, symp->sy_obj.versioned_name); - } - else - { - symbolS *symp2; - - /* FIXME: Creating a new symbol here is risky. We're in the - final loop over the symbol table. We can get away with - it only because the symbol goes to the end of the list, - where the loop will still see it. It would probably be - better to do this in obj_frob_file_before_adjust. */ - - symp2 = symbol_find_or_make (symp->sy_obj.versioned_name); - - /* Now we act as though we saw symp2 = sym. */ - - S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp)); - - /* Subtracting out the frag address here is a hack because - we are in the middle of the final loop. */ - S_SET_VALUE (symp2, S_GET_VALUE (symp) - symp->sy_frag->fr_address); - - symp2->sy_frag = symp->sy_frag; - - /* This will copy over the size information. */ - copy_symbol_attributes (symp2, symp); - - if (S_IS_WEAK (symp)) - S_SET_WEAK (symp2); - - if (S_IS_EXTERNAL (symp)) - S_SET_EXTERNAL (symp2); - } - } - - /* Double check weak symbols. */ - if (symp->bsym->flags & BSF_WEAK) - { - if (S_IS_COMMON (symp)) - as_bad ("Symbol `%s' can not be both weak and common", - S_GET_NAME (symp)); - } - -#ifdef TC_MIPS - /* The Irix 5 and 6 assemblers set the type of any common symbol and - any undefined non-function symbol to STT_OBJECT. We try to be - compatible, since newer Irix 5 and 6 linkers care. However, we - only set undefined symbols to be STT_OBJECT if we are on Irix, - because that is the only time gcc will generate the necessary - .global directives to mark functions. */ - - if (S_IS_COMMON (symp)) - symp->bsym->flags |= BSF_OBJECT; - - if (strstr (TARGET_OS, "irix") != NULL - && (! S_IS_DEFINED (symp) && ((symp->bsym->flags & BSF_FUNCTION) == 0))) - symp->bsym->flags |= BSF_OBJECT; -#endif - -#ifdef TC_PPC - /* Frob the PowerPC, so that the symbol always has object type - if it is not some other type. VxWorks needs this. */ - if ((symp->bsym->flags & (BSF_FUNCTION | BSF_FILE | BSF_SECTION_SYM)) == 0 - && S_IS_DEFINED (symp)) - symp->bsym->flags |= BSF_OBJECT; -#endif -} - -void -elf_frob_file () -{ - bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0); - -#ifdef elf_tc_final_processing - elf_tc_final_processing (); -#endif -} - -/* It is required that we let write_relocs have the opportunity to - optimize away fixups before output has begun, since it is possible - to eliminate all fixups for a section and thus we never should - have generated the relocation section. */ - -void -elf_frob_file_after_relocs () -{ -#ifdef NEED_ECOFF_DEBUG - if (ECOFF_DEBUGGING) - /* Generate the ECOFF debugging information. */ - { - const struct ecoff_debug_swap *debug_swap; - struct ecoff_debug_info debug; - char *buf; - asection *sec; - - debug_swap - = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap; - know (debug_swap != (const struct ecoff_debug_swap *) NULL); - ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap); - - /* Set up the pointers in debug. */ -#define SET(ptr, offset, type) \ - debug.ptr = (type) (buf + debug.symbolic_header.offset) - - SET (line, cbLineOffset, unsigned char *); - SET (external_dnr, cbDnOffset, PTR); - SET (external_pdr, cbPdOffset, PTR); - SET (external_sym, cbSymOffset, PTR); - SET (external_opt, cbOptOffset, PTR); - SET (external_aux, cbAuxOffset, union aux_ext *); - SET (ss, cbSsOffset, char *); - SET (external_fdr, cbFdOffset, PTR); - SET (external_rfd, cbRfdOffset, PTR); - /* ssext and external_ext are set up just below. */ - -#undef SET - - /* Set up the external symbols. */ - debug.ssext = debug.ssext_end = NULL; - debug.external_ext = debug.external_ext_end = NULL; - if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true, - elf_get_extr, elf_set_index)) - as_fatal ("Failed to set up debugging information: %s", - bfd_errmsg (bfd_get_error ())); - - sec = bfd_get_section_by_name (stdoutput, ".mdebug"); - assert (sec != NULL); - - know (stdoutput->output_has_begun == false); - - /* We set the size of the section, call bfd_set_section_contents - to force the ELF backend to allocate a file position, and then - write out the data. FIXME: Is this really the best way to do - this? */ - sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap); - - if (! bfd_set_section_contents (stdoutput, sec, (PTR) NULL, - (file_ptr) 0, (bfd_size_type) 0)) - as_fatal ("Can't start writing .mdebug section: %s", - bfd_errmsg (bfd_get_error ())); - - know (stdoutput->output_has_begun == true); - know (sec->filepos != 0); - - if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap, - sec->filepos)) - as_fatal ("Could not write .mdebug section: %s", - bfd_errmsg (bfd_get_error ())); - } -#endif /* NEED_ECOFF_DEBUG */ -} - -#ifdef SCO_ELF - -/* Heavily plagarized from obj_elf_version. The idea is to emit the - SCO specific identifier in the .notes section to satisfy the SCO - linker. - - This looks more complicated than it really is. As opposed to the - "obvious" solution, this should handle the cross dev cases - correctly. (i.e, hosting on a 64 bit big endian processor, but - generating SCO Elf code) Efficiency isn't a concern, as there - should be exactly one of these sections per object module. - - SCO OpenServer 5 identifies it's ELF modules with a standard ELF - .note section. - - int_32 namesz = 4 ; Name size - int_32 descsz = 12 ; Descriptive information - int_32 type = 1 ; - char name[4] = "SCO" ; Originator name ALWAYS SCO + NULL - int_32 version = (major ver # << 16) | version of tools ; - int_32 source = (tool_id << 16 ) | 1 ; - int_32 info = 0 ; These are set by the SCO tools, but we - don't know enough about the source - environment to set them. SCO ld currently - ignores them, and recommends we set them - to zero. */ - -#define SCO_MAJOR_VERSION 0x1 -#define SCO_MINOR_VERSION 0x1 - -void -sco_id () -{ - - char *name; - unsigned int c; - char ch; - char *p; - asection *seg = now_seg; - subsegT subseg = now_subseg; - Elf_Internal_Note i_note; - Elf_External_Note e_note; - asection *note_secp = (asection *) NULL; - int i, len; - - /* create the .note section */ - - note_secp = subseg_new (".note", 0); - bfd_set_section_flags (stdoutput, - note_secp, - SEC_HAS_CONTENTS | SEC_READONLY); - - /* process the version string */ - - i_note.namesz = 4; - i_note.descsz = 12; /* 12 descriptive bytes */ - i_note.type = NT_VERSION; /* Contains a version string */ - - p = frag_more (sizeof (i_note.namesz)); - md_number_to_chars (p, (valueT) i_note.namesz, 4); - - p = frag_more (sizeof (i_note.descsz)); - md_number_to_chars (p, (valueT) i_note.descsz, 4); - - p = frag_more (sizeof (i_note.type)); - md_number_to_chars (p, (valueT) i_note.type, 4); - - p = frag_more (4); - strcpy (p, "SCO"); - - /* Note: this is the version number of the ELF we're representing */ - p = frag_more (4); - md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4); - - /* Here, we pick a magic number for ourselves (yes, I "registered" - it with SCO. The bottom bit shows that we are compat with the - SCO ABI. */ - p = frag_more (4); - md_number_to_chars (p, 0x4c520000 | 0x0001, 4); - - /* If we knew (or cared) what the source language options were, we'd - fill them in here. SCO has given us permission to ignore these - and just set them to zero. */ - p = frag_more (4); - md_number_to_chars (p, 0x0000, 4); - - frag_align (2, 0, 0); - - /* We probably can't restore the current segment, for there likely - isn't one yet... */ - if (seg && subseg) - subseg_set (seg, subseg); - -} - -#endif /* SCO_ELF */ - -const struct format_ops elf_format_ops = -{ - bfd_target_elf_flavour, - 0, - 1, - elf_frob_symbol, - elf_frob_file, - elf_frob_file_after_relocs, - elf_s_get_size, elf_s_set_size, - elf_s_get_align, elf_s_set_align, - elf_copy_symbol_attributes, -#ifdef NEED_ECOFF_DEBUG - ecoff_generate_asm_lineno, - ecoff_stab, -#else - 0, - 0, /* process_stab */ -#endif - elf_sec_sym_ok_for_reloc, - elf_pop_insert, -#ifdef NEED_ECOFF_DEBUG - elf_ecoff_set_ext, -#else - 0, -#endif - obj_read_begin_hook, - obj_symbol_new_hook, -}; diff --git a/contrib/binutils/gas/config/obj-elf.h b/contrib/binutils/gas/config/obj-elf.h deleted file mode 100644 index ff6579048057..000000000000 --- a/contrib/binutils/gas/config/obj-elf.h +++ /dev/null @@ -1,186 +0,0 @@ -/* ELF object file format. - Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. - - 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 1, 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. - - 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. */ - - -/* HP PA-RISC support was contributed by the Center for Software Science - at the University of Utah. */ - -#ifndef _OBJ_ELF_H -#define _OBJ_ELF_H - -#define OBJ_ELF 1 - -#define OUTPUT_FLAVOR bfd_target_elf_flavour - -#include <bfd.h> - -#define BYTES_IN_WORD 4 /* for now */ -#include "bfd/elf-bfd.h" - -/* Additional information we keep for each symbol. */ - -/* FIXME: For some reason, this structure is needed both here and in - obj-multi.h. */ -#ifndef OBJ_SYMFIELD_TYPE -struct elf_obj_sy -{ - /* Use this to keep track of .size expressions that involve - differences that we can't compute yet. */ - expressionS *size; - - /* The name specified by the .symver directive. */ - char *versioned_name; -}; -#endif - -#define OBJ_SYMFIELD_TYPE struct elf_obj_sy - -/* Symbol fields used by the ELF back end. */ -#define ELF_TARGET_SYMBOL_FIELDS int local:1; - -/* Don't change this; change ELF_TARGET_SYMBOL_FIELDS instead. */ -#define TARGET_SYMBOL_FIELDS ELF_TARGET_SYMBOL_FIELDS - -#include "targ-cpu.h" - -#ifndef FALSE -#define FALSE 0 -#define TRUE !FALSE -#endif - -#define obj_begin() elf_begin () -extern void elf_begin PARAMS ((void)); - -/* should be conditional on address size! */ -#define elf_symbol(asymbol) ((elf_symbol_type *)(&(asymbol)->the_bfd)) - -#define S_GET_SIZE(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_size) -#define S_SET_SIZE(S,V) \ - (elf_symbol((S)->bsym)->internal_elf_sym.st_size = (V)) - -#define S_GET_ALIGN(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_value) -#define S_SET_ALIGN(S,V) \ - (elf_symbol ((S)->bsym)->internal_elf_sym.st_value = (V)) - -#define S_GET_OTHER(S) (elf_symbol ((S)->bsym)->internal_elf_sym.st_other) -#define S_SET_OTHER(S,V) \ - (elf_symbol ((S)->bsym)->internal_elf_sym.st_other = (V)) - -extern asection *gdb_section; - -#define obj_frob_file elf_frob_file -extern void elf_frob_file PARAMS ((void)); - -#define obj_frob_file_after_relocs elf_frob_file_after_relocs -extern void elf_frob_file_after_relocs PARAMS ((void)); - -#define obj_app_file elf_file_symbol -extern void elf_file_symbol PARAMS ((char *)); - -extern void obj_elf_section_change_hook PARAMS ((void)); - -extern void obj_elf_section PARAMS ((int)); -extern void obj_elf_previous PARAMS ((int)); -extern void obj_elf_version PARAMS ((int)); - -/* BFD wants to write the udata field, which is a no-no for the - globally defined sections. */ -#define obj_sec_sym_ok_for_reloc(SEC) ((SEC)->owner != 0) - -/* When setting one symbol equal to another, by default we probably - want them to have the same "size", whatever it means in the current - context. */ -#define OBJ_COPY_SYMBOL_ATTRIBUTES(DEST,SRC) \ -do \ - { \ - if ((SRC)->sy_obj.size) \ - { \ - if ((DEST)->sy_obj.size == NULL) \ - (DEST)->sy_obj.size = \ - (expressionS *) xmalloc (sizeof (expressionS)); \ - *(DEST)->sy_obj.size = *(SRC)->sy_obj.size; \ - } \ - else \ - { \ - if ((DEST)->sy_obj.size != NULL) \ - free ((DEST)->sy_obj.size); \ - (DEST)->sy_obj.size = NULL; \ - } \ - S_SET_SIZE ((DEST), S_GET_SIZE (SRC)); \ - S_SET_OTHER ((DEST), S_GET_OTHER (SRC)); \ - } \ -while (0) - -/* Stabs go in a separate section. */ -#define SEPARATE_STAB_SECTIONS 1 - -/* We need 12 bytes at the start of the section to hold some initial - information. */ -extern void obj_elf_init_stab_section PARAMS ((segT)); -#define INIT_STAB_SECTION(seg) obj_elf_init_stab_section (seg) - -/* For now, always set ECOFF_DEBUGGING for an Alpha target. */ -#ifdef TC_ALPHA -#define ECOFF_DEBUGGING 1 -#endif - -/* For now, always set ECOFF_DEBUGGING for a MIPS target. */ -#ifdef TC_MIPS -#define ECOFF_DEBUGGING 1 -#endif - -#if ECOFF_DEBUGGING - -/* If we are generating ECOFF debugging information, we need some - additional fields for each symbol. */ -#undef TARGET_SYMBOL_FIELDS -#define TARGET_SYMBOL_FIELDS \ - ELF_TARGET_SYMBOL_FIELDS \ - struct efdr *ecoff_file; \ - struct localsym *ecoff_symbol; \ - valueT ecoff_extern_size; - -/* We smuggle stabs in ECOFF rather than using a separate section. - The Irix linker can not handle a separate stabs section. */ -#undef SEPARATE_STAB_SECTIONS -#undef INIT_STAB_SECTION -#define OBJ_PROCESS_STAB(seg, what, string, type, other, desc) \ - ecoff_stab ((seg), (what), (string), (type), (other), (desc)) - -#define OBJ_GENERATE_ASM_LINENO(filename, lineno) \ - ecoff_generate_asm_lineno ((filename), (lineno)) - -#endif /* ECOFF_DEBUGGING */ - -extern void elf_frob_symbol PARAMS ((struct symbol *, int *)); -#define obj_frob_symbol(symp, punt) elf_frob_symbol (symp, &punt) - -extern void elf_pop_insert PARAMS ((void)); -#define obj_pop_insert() elf_pop_insert() - -#ifndef OBJ_MAYBE_ELF -#define obj_ecoff_set_ext elf_ecoff_set_ext -#ifdef ANSI_PROTOTYPES -struct ecoff_extr; -#endif -extern void elf_ecoff_set_ext PARAMS ((struct symbol *, struct ecoff_extr *)); -#endif - -#endif /* _OBJ_ELF_H */ diff --git a/contrib/binutils/gas/config/obj-generic.c b/contrib/binutils/gas/config/obj-generic.c deleted file mode 100644 index 69fc3d1dbf96..000000000000 --- a/contrib/binutils/gas/config/obj-generic.c +++ /dev/null @@ -1,41 +0,0 @@ -/* This file is obj-generic.c and is intended to be a template for - object format specific source files. - - Copyright (C) 1987-1992 Free Software Foundation, Inc. - - 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 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. */ - -/* Chars that can be used to separate mant from exp in floating point nums */ -char EXP_CHARS[] = "eE"; - -/* Chars that mean this number is a floating point constant */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ -char FLT_CHARS[] = "rRsSfFdDxXpP"; - -/* These chars start a comment anywhere in a source file (except inside - another comment */ -const char comment_chars[] = "#"; - -/* - * Local Variables: - * comment-column: 0 - * fill-column: 131 - * End: - */ - -/* end of obj-generic.c */ diff --git a/contrib/binutils/gas/config/obj-generic.h b/contrib/binutils/gas/config/obj-generic.h deleted file mode 100644 index dc18e4397034..000000000000 --- a/contrib/binutils/gas/config/obj-generic.h +++ /dev/null @@ -1,80 +0,0 @@ -/* This file is obj-generic.h - Copyright (C) 1987-1992 Free Software Foundation, Inc. - - 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 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. */ - -/* - * This file is obj-generic.h and is intended to be a template for - * object format specific header files. - */ - -/* define an obj specific macro off which target cpu back ends may key. */ -#define OBJ_GENERIC 1 - -/* include whatever target cpu is appropriate. */ -#include "targ-cpu.h" - -/* - * SYMBOLS - */ - -/* - * If your object format needs to reorder symbols, define this. When - * defined, symbols are kept on a doubly linked list and functions are - * made available for push, insert, append, and delete. If not defined, - * symbols are kept on a singly linked list, only the append and clear - * facilities are available, and they are macros. - */ - -/* #define SYMBOLS_NEED_PACKPOINTERS */ - -/* */ -typedef struct - { - void *nothing; - } - -obj_symbol_type; /* should be the format's symbol structure */ - -typedef void *object_headers; - -/* symbols have names */ -#define S_GET_NAME(s) ("foo") /* get the name of a symbolP */ -#define S_SET_NAME(s,v) ; -/* symbols have segments */ -#define S_GET_SEGMENT(s) (SEG_UNKNOWN) -#define S_SET_SEGMENT(s,v) ; -/* symbols may be external */ -#define S_IS_EXTERNAL(s) (0) -#define S_SET_EXTERNAL(s) ; - -/* symbols may or may not be defined */ -#define S_IS_DEFINED(s) (0) - - -#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0) /* your magic number */ - -#define OBJ_EMIT_LINENO(a,b,c) /* must be *something*. This no-op's it out. */ - -/* - * Local Variables: - * comment-column: 0 - * fill-column: 131 - * End: - */ - -/* end of obj-generic.h */ diff --git a/contrib/binutils/gas/config/obj-ieee.c b/contrib/binutils/gas/config/obj-ieee.c deleted file mode 100644 index 42e4b1f8951a..000000000000 --- a/contrib/binutils/gas/config/obj-ieee.c +++ /dev/null @@ -1,627 +0,0 @@ -/* obj-format for ieee-695 records. - Copyright (C) 1991, 92, 93, 94, 95, 1997 Free Software Foundation, Inc. - - 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 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. */ - - -/* - created by - - steve chamberlain steve@cygnus.com - */ - -/* - this will hopefully become the port through which bfd and gas talk, - for the moment, only ieee is known to work well. - */ - -#include "bfd.h" -#include "as.h" -#include "subsegs.h" -#include "output-file.h" -#include "frags.h" - -bfd *abfd; - -/* How many addresses does the .align take? */ -static relax_addressT -relax_align (address, alignment) - register relax_addressT address; /* Address now. */ - register long alignment; /* Alignment (binary). */ -{ - relax_addressT mask; - relax_addressT new_address; - - mask = ~((~0) << alignment); - new_address = (address + mask) & (~mask); - return (new_address - address); -} /* relax_align() */ - -/* calculate the size of the frag chain and create a bfd section - to contain all of it */ -static void -DEFUN (size_section, (abfd, idx), - bfd * abfd AND - unsigned int idx) -{ - asection *sec; - unsigned int size = 0; - fragS *frag = segment_info[idx].frag_root; - while (frag) - { - if (frag->fr_address != size) - { - printf ("Out of step\n"); - size = frag->fr_address; - } - size += frag->fr_fix; - switch (frag->fr_type) - { - case rs_fill: - case rs_org: - size += frag->fr_offset * frag->fr_var; - break; - case rs_align: - case rs_align_code: - { - addressT off; - - off = relax_align (size, frag->fr_offset); - if (frag->fr_subtype != 0 && off > frag->fr_subtype) - off = 0; - size += off; - } - } - frag = frag->fr_next; - } - if (size) - { - char *name = segment_info[idx].name; - if (name == (char *) NULL) - { - name = ".data"; - } - segment_info[idx].user_stuff = (char *) (sec = bfd_make_section (abfd, name)); - /* Make it output through itself */ - sec->output_section = sec; - sec->flags |= SEC_HAS_CONTENTS; - bfd_set_section_size (abfd, sec, size); - } -} - -/* run through a frag chain and write out the data to go with it */ -static void -DEFUN (fill_section, (abfd, idx), - bfd * abfd AND - unsigned int idx) -{ - asection *sec = segment_info[idx].user_stuff; - if (sec) - { - fragS *frag = segment_info[idx].frag_root; - unsigned int offset = 0; - while (frag) - { - unsigned int fill_size; - unsigned int count; - switch (frag->fr_type) - { - case rs_fill: - case rs_align: - case rs_org: - if (frag->fr_fix) - { - bfd_set_section_contents (abfd, - sec, - frag->fr_literal, - frag->fr_address, - frag->fr_fix); - } - offset += frag->fr_fix; - fill_size = frag->fr_var; - if (fill_size) - { - unsigned int off = frag->fr_fix; - for (count = frag->fr_offset; count; count--) - { - bfd_set_section_contents (abfd, sec, - frag->fr_literal + - frag->fr_fix, - frag->fr_address + off, - fill_size); - off += fill_size; - } - } - break; - default: - abort (); - } - frag = frag->fr_next; - } - } -} - -/* Count the relocations in a chain */ - -static unsigned int -DEFUN (count_entries_in_chain, (idx), - unsigned int idx) -{ - unsigned int nrelocs; - fixS *fixup_ptr; - - /* Count the relocations */ - fixup_ptr = segment_info[idx].fix_root; - nrelocs = 0; - while (fixup_ptr != (fixS *) NULL) - { - fixup_ptr = fixup_ptr->fx_next; - nrelocs++; - } - return nrelocs; -} - -/* output all the relocations for a section */ -void -DEFUN (do_relocs_for, (idx), - unsigned int idx) -{ - unsigned int nrelocs; - arelent **reloc_ptr_vector; - arelent *reloc_vector; - asymbol **ptrs; - asection *section = (asection *) (segment_info[idx].user_stuff); - unsigned int i; - fixS *from; - if (section) - { - nrelocs = count_entries_in_chain (idx); - - reloc_ptr_vector = (arelent **) malloc ((nrelocs + 1) * sizeof (arelent *)); - reloc_vector = (arelent *) malloc (nrelocs * sizeof (arelent)); - ptrs = (asymbol **) malloc (nrelocs * sizeof (asymbol *)); - from = segment_info[idx].fix_root; - for (i = 0; i < nrelocs; i++) - { - arelent *to = reloc_vector + i; - asymbol *s; - reloc_ptr_vector[i] = to; - to->howto = (reloc_howto_type *) (from->fx_r_type); - -#if 0 /* We can't represent complicated things in a reloc yet */ - if (from->fx_addsy == 0 || from->fx_subsy != 0) abort(); -#endif - - s = &(from->fx_addsy->sy_symbol.sy); - to->address = ((char *) (from->fx_frag->fr_address + - from->fx_where)) - - ((char *) (&(from->fx_frag->fr_literal))); - to->addend = from->fx_offset; - /* If we know the symbol which we want to relocate to, turn - this reloaction into a section relative. - - If this relocation is pcrelative, and we know the - destination, we still want to keep the relocation - since - the linker might relax some of the bytes, but it stops - being pc relative and turns into an absolute relocation. */ - if (s) - { - if ((s->flags & BSF_UNDEFINED) == 0) - { - to->section = s->section; - - /* We can refer directly to the value field here, - rather than using S_GET_VALUE, because this is - only called after do_symbols, which sets up the - value field. */ - to->addend += s->value; - - to->sym_ptr_ptr = 0; - if (to->howto->pcrel_offset) - { - /* This is a pcrel relocation, the addend should be adjusted */ - to->addend -= to->address + 1; - } - } - else - { - to->section = 0; - *ptrs = &(from->fx_addsy->sy_symbol.sy); - to->sym_ptr_ptr = ptrs; - - if (to->howto->pcrel_offset) - { - /* This is a pcrel relocation, the addend should be adjusted */ - to->addend -= to->address - 1; - } - } - - } - else - { - to->section = 0; - } - - ptrs++; - from = from->fx_next; - } - - /* attatch to the section */ - section->orelocation = reloc_ptr_vector; - section->reloc_count = nrelocs; - section->flags |= SEC_LOAD; - } -} - -/* do the symbols.. */ -static void -DEFUN (do_symbols, (abfd), - bfd * abfd) -{ - extern symbolS *symbol_rootP; - symbolS *ptr; - asymbol **symbol_ptr_vec; - asymbol *symbol_vec; - unsigned int count = 0; - unsigned int index; - - - for (ptr = symbol_rootP; - ptr != (symbolS *) NULL; - ptr = ptr->sy_next) - { - if (SEG_NORMAL (ptr->sy_symbol.seg)) - { - ptr->sy_symbol.sy.section = - (asection *) (segment_info[ptr->sy_symbol.seg].user_stuff); - S_SET_VALUE (ptr, S_GET_VALUE (ptr) + ptr->sy_frag->fr_address); - if (ptr->sy_symbol.sy.flags == 0) - { - ptr->sy_symbol.sy.flags = BSF_LOCAL; - } - } - else - { - switch (ptr->sy_symbol.seg) - { - case SEG_ABSOLUTE: - ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE; - ptr->sy_symbol.sy.section = 0; - break; - case SEG_UNKNOWN: - ptr->sy_symbol.sy.flags = BSF_UNDEFINED; - ptr->sy_symbol.sy.section = 0; - break; - default: - abort (); - } - } - ptr->sy_symbol.sy.value = S_GET_VALUE (ptr); - count++; - } - symbol_ptr_vec = (asymbol **) malloc ((count + 1) * sizeof (asymbol *)); - - index = 0; - for (ptr = symbol_rootP; - ptr != (symbolS *) NULL; - ptr = ptr->sy_next) - { - symbol_ptr_vec[index] = &(ptr->sy_symbol.sy); - index++; - } - symbol_ptr_vec[index] = 0; - abfd->outsymbols = symbol_ptr_vec; - abfd->symcount = count; -} - -/* The generic as->bfd converter. Other backends may have special case - code */ - -void -DEFUN_VOID (bfd_as_write_hook) -{ - int i; - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - size_section (abfd, i); - } - - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - fill_section (abfd, i); - - do_symbols (abfd); - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - do_relocs_for (i); - -} - -S_SET_SEGMENT (x, y) - symbolS *x; - int y; -{ - x->sy_symbol.seg = y; -} - -S_IS_DEFINED (x) - symbolS *x; -{ - if (SEG_NORMAL (x->sy_symbol.seg)) - { - return 1; - } - switch (x->sy_symbol.seg) - { - case SEG_UNKNOWN: - return 0; - default: - abort (); - } -} - -S_IS_EXTERNAL (x) -{ - abort (); -} - -S_GET_DESC (x) -{ - abort (); -} - -S_GET_SEGMENT (x) - symbolS *x; -{ - return x->sy_symbol.seg; -} - -S_SET_EXTERNAL (x) - symbolS *x; -{ - x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT; -} - -S_SET_NAME (x, y) - symbolS *x; - char *y; -{ - x->sy_symbol.sy.name = y; -} - -S_GET_OTHER (x) -{ - abort (); -} - -S_IS_DEBUG (x) -{ - abort (); -} - -#ifndef segment_name -char * -segment_name () -{ - abort (); -} -#endif - -void -obj_read_begin_hook () -{ -} - -static void -obj_ieee_section (ignore) - int ignore; -{ - extern char *input_line_pointer; - extern char is_end_of_line[]; - char *p = input_line_pointer; - char *s = p; - int i; - /* Look up the name, if it doesn't exist, make it */ - while (*p && *p != ' ' && *p != ',' && !is_end_of_line[*p]) - { - p++; - } - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - if (segment_info[i].hadone) - { - if (strncmp (segment_info[i].name, s, p - s) == 0) - { - goto ok; - - } - } - else - break; - } - if (i == SEG_UNKNOWN) - { - as_bad ("too many sections"); - return; - } - - segment_info[i].hadone = 1; - segment_info[i].name = malloc (p - s + 1); - memcpy (segment_info[i].name, s, p - s); - segment_info[i].name[p - s] = 0; -ok: - subseg_set (i, 0); - while (!is_end_of_line[*p]) - p++; - input_line_pointer = p; - -} - - -void cons (); -void s_ignore (); - - -void s_globl (); -const pseudo_typeS obj_pseudo_table[] = -{ - {"section", obj_ieee_section, 0}, - {"data.b", cons, 1}, - {"data.w", cons, 2}, - {"data.l", cons, 4}, - {"export", s_globl, 0}, - {"option", s_ignore, 0}, - {"end", s_ignore, 0}, - {"import", s_ignore, 0}, - {"sdata", stringer, 0}, - 0, - -}; - - - -void -obj_symbol_new_hook (symbolP) - symbolS *symbolP; -{ - symbolP->sy_symbol.sy.the_bfd = abfd; -} - - - - - -#if 1 -extern void -DEFUN_VOID (write_object_file) -{ - int i; - struct frchain *frchain_ptr; - struct frag *frag_ptr; - - abfd = bfd_openw (out_file_name, "ieee"); - - if (abfd == 0) - { - as_perror ("FATAL: Can't create %s", out_file_name); - exit (EXIT_FAILURE); - } - bfd_set_format (abfd, bfd_object); - bfd_set_arch_mach (abfd, bfd_arch_h8300, 0); - subseg_set (1, 0); - subseg_set (2, 0); - subseg_set (3, 0); - for (frchain_ptr = frchain_root; - frchain_ptr != (struct frchain *) NULL; - frchain_ptr = frchain_ptr->frch_next) - { - /* Run through all the sub-segments and align them up. Also close any - open frags. We tack a .fill onto the end of the frag chain so - that any .align's size can be worked by looking at the next - frag. */ - - subseg_set (frchain_ptr->frch_seg, frchain_ptr->frch_subseg); -#ifndef SUB_SEGMENT_ALIGN -#define SUB_SEGMENT_ALIGN(SEG) 2 -#endif - frag_align (SUB_SEGMENT_ALIGN (now_seg), 0, 0); - frag_wane (frag_now); - frag_now->fr_fix = 0; - know (frag_now->fr_next == NULL); - } - - /* Now build one big frag chain for each segment, linked through - fr_next. */ - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - - fragS **prev_frag_ptr_ptr; - struct frchain *next_frchain_ptr; - - /* struct frag **head_ptr = segment_info[i].frag_root;*/ - - segment_info[i].frag_root = segment_info[i].frchainP->frch_root; -#if 0 - /* Im not sure what this is for */ - for (frchain_ptr = segment_info[i].frchainP->frch_root; - frchain_ptr != (struct frchain *) NULL; - frchain_ptr = frchain_ptr->frch_next) - { - *head_ptr = frchain_ptr; - head_ptr = &frchain_ptr->next; - } - - -#endif - } - - for (i = SEG_E0; i < SEG_UNKNOWN; i++) - { - relax_segment (segment_info[i].frag_root, i); - } - - /* Now the addresses of the frags are correct within the segment */ - - bfd_as_write_hook (); - bfd_close (abfd); -} - -#endif - -H_SET_TEXT_SIZE (a, b) -{ - abort (); -} - -H_GET_TEXT_SIZE () -{ - abort (); -} - -H_SET_BSS_SIZE () -{ - abort (); -} - -H_SET_STRING_SIZE () -{ - abort (); -} - -H_SET_RELOCATION_SIZE () -{ - abort (); -} - -H_SET_MAGIC_NUMBER () -{ - abort (); -} - -H_GET_FILE_SIZE () -{ - abort (); -} - -H_GET_TEXT_RELOCATION_SIZE () -{ - abort (); -} - -/* end of obj-ieee.c */ diff --git a/contrib/binutils/gas/config/obj-ieee.h b/contrib/binutils/gas/config/obj-ieee.h deleted file mode 100644 index 4a0f126ebe43..000000000000 --- a/contrib/binutils/gas/config/obj-ieee.h +++ /dev/null @@ -1,50 +0,0 @@ -/* This file is obj-ieee.h - - Copyright (C) 1987-1992 Free Software Foundation, Inc. - - 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 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. */ - -#define BFD 1 - -#include <bfd.h> - -typedef struct -{ - asymbol sy; - int seg; -} - -obj_symbol_type; - -#define S_GET_NAME(s) (((s)->sy_symbol.sy.name)) - -typedef struct - { - int x; - } - -object_headers; - -#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 1 - - -int lineno_rootP; - - -#define IEEE_STYLE - -/* end of obj-ieee.h */ diff --git a/contrib/binutils/gas/config/obj-multi.c b/contrib/binutils/gas/config/obj-multi.c deleted file mode 100644 index d115093aff38..000000000000 --- a/contrib/binutils/gas/config/obj-multi.c +++ /dev/null @@ -1,4 +0,0 @@ -/* foo */ - -#include "as.h" - diff --git a/contrib/binutils/gas/config/obj-multi.h b/contrib/binutils/gas/config/obj-multi.h deleted file mode 100644 index fe8d98d0d6e8..000000000000 --- a/contrib/binutils/gas/config/obj-multi.h +++ /dev/null @@ -1,50 +0,0 @@ -/* hi */ - -#include "emul.h" -#include "targ-cpu.h" - -#define OUTPUT_FLAVOR (this_format->flavor) -#define obj_frob_symbol(S,P) (this_format->frob_symbol)(S,&(P)) -#define obj_frob_file (this_format->frob_file) -#define obj_frob_file_after_relocs (this_format->frob_file_after_relocs) -#define obj_ecoff_set_ext (this_format->ecoff_set_ext) -#define obj_pop_insert (this_format->pop_insert) -#define obj_read_begin_hook() (this_format->read_begin_hook?this_format->read_begin_hook():(void)0) -#define obj_symbol_new_hook (this_format->symbol_new_hook) -#define obj_sec_sym_ok_for_reloc (this_format->sec_sym_ok_for_reloc) -#define S_GET_SIZE (this_format->s_get_size) -#define S_SET_SIZE (this_format->s_set_size) -#define S_GET_ALIGN (this_format->s_get_align) -#define S_SET_ALIGN (this_format->s_set_align) -#define OBJ_COPY_SYMBOL_ATTRIBUTES (this_format->copy_symbol_attributes) -#define OBJ_PROCESS_STAB (this_format->process_stab) - -#if defined (OBJ_MAYBE_ECOFF) || (defined (OBJ_MAYBE_ELF) && defined (TC_MIPS)) -#define ECOFF_DEBUGGING 1 -#endif - -/* FIXME: What's the story here? Why do we have to define - OBJ_SYMFIELD_TYPE both here and in obj-elf.h? */ -#ifdef OBJ_MAYBE_ELF -struct elf_obj_sy -{ - expressionS *size; - char *versioned_name; -}; -#define OBJ_SYMFIELD_TYPE struct elf_obj_sy -#define ELF_TARGET_SYMBOL_FIELDS int local:1; -#else -#define ELF_TARGET_SYMBOL_FIELDS -#endif - -#ifdef ECOFF_DEBUGGING -struct efdr; -struct localsym; -#define ECOFF_DEBUG_TARGET_SYMBOL_FIELDS struct efdr *ecoff_file; struct localsym *ecoff_symbol; valueT ecoff_extern_size; -#else -#define ECOFF_DEBUG_TARGET_SYMBOL_FIELDS -#endif - -#define TARGET_SYMBOL_FIELDS \ - ELF_TARGET_SYMBOL_FIELDS \ - ECOFF_DEBUG_TARGET_SYMBOL_FIELDS diff --git a/contrib/binutils/gas/config/sco5.mt b/contrib/binutils/gas/config/sco5.mt deleted file mode 100644 index 8879320c4e1e..000000000000 --- a/contrib/binutils/gas/config/sco5.mt +++ /dev/null @@ -1 +0,0 @@ -TDEFINES=-DSCO_ELF diff --git a/contrib/binutils/gas/config/tc-alpha.c b/contrib/binutils/gas/config/tc-alpha.c deleted file mode 100644 index 4c4da6c0981b..000000000000 --- a/contrib/binutils/gas/config/tc-alpha.c +++ /dev/null @@ -1,4532 +0,0 @@ -/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU. - Copyright (C) 1989, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. - Contributed by Carnegie Mellon University, 1993. - Written by Alessandro Forin, based on earlier gas-1.38 target CPU files. - Modified by Ken Raeburn for gas-2.x and ECOFF support. - Modified by Richard Henderson for ELF support. - Modified by Klaus K"ampf for EVAX (openVMS/Alpha) support. - - 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 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. */ - -/* - * 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" - -#include "opcode/alpha.h" - -#ifdef OBJ_ELF -#include "elf/alpha.h" -#endif - -#include <ctype.h> - - -/* Local types */ - -#define MAX_INSN_FIXUPS 2 -#define MAX_INSN_ARGS 5 - -struct alpha_fixup -{ - expressionS exp; - bfd_reloc_code_real_type reloc; -}; - -struct alpha_insn -{ - unsigned insn; - int nfixups; - struct alpha_fixup fixups[MAX_INSN_FIXUPS]; -}; - -enum alpha_macro_arg -{ - MACRO_EOA = 1, MACRO_IR, MACRO_PIR, MACRO_CPIR, MACRO_FPR, MACRO_EXP -}; - -struct alpha_macro -{ - const char *name; - void (*emit) PARAMS ((const expressionS *, int, const PTR)); - const PTR arg; - enum alpha_macro_arg argsets[16]; -}; - -/* Two extra symbols we want to see in our input. This is a blatent - misuse of the expressionS.X_op field. */ - -#define O_pregister (O_max+1) /* O_register, but in parentheses */ -#define O_cpregister (O_pregister+1) /* + a leading comma */ - -/* Macros for extracting the type and number of encoded register tokens */ - -#define is_ir_num(x) (((x) & 32) == 0) -#define is_fpr_num(x) (((x) & 32) != 0) -#define regno(x) ((x) & 31) - -/* Something odd inherited from the old assembler */ - -#define note_gpreg(R) (alpha_gprmask |= (1 << (R))) -#define note_fpreg(R) (alpha_fprmask |= (1 << (R))) - -/* Predicates for 16- and 32-bit ranges */ -/* XXX: The non-shift version appears to trigger a compiler bug when - cross-assembling from x86 w/ gcc 2.7.2. */ - -#if 1 -#define range_signed_16(x) \ - (((offsetT)(x) >> 15) == 0 || ((offsetT)(x) >> 15) == -1) -#define range_signed_32(x) \ - (((offsetT)(x) >> 31) == 0 || ((offsetT)(x) >> 31) == -1) -#else -#define range_signed_16(x) ((offsetT)(x) >= -(offsetT)0x8000 && \ - (offsetT)(x) <= (offsetT)0x7FFF) -#define range_signed_32(x) ((offsetT)(x) >= -(offsetT)0x80000000 && \ - (offsetT)(x) <= (offsetT)0x7FFFFFFF) -#endif - -/* Macros for sign extending from 16- and 32-bits. */ -/* XXX: The cast macros will work on all the systems that I care about, - but really a predicate should be found to use the non-cast forms. */ - -#if 1 -#define sign_extend_16(x) ((short)(x)) -#define sign_extend_32(x) ((int)(x)) -#else -#define sign_extend_16(x) ((offsetT)(((x) & 0xFFFF) ^ 0x8000) - 0x8000) -#define sign_extend_32(x) ((offsetT)(((x) & 0xFFFFFFFF) \ - ^ 0x80000000) - 0x80000000) -#endif - -/* Macros to build tokens */ - -#define set_tok_reg(t, r) (memset(&(t), 0, sizeof(t)), \ - (t).X_op = O_register, \ - (t).X_add_number = (r)) -#define set_tok_preg(t, r) (memset(&(t), 0, sizeof(t)), \ - (t).X_op = O_pregister, \ - (t).X_add_number = (r)) -#define set_tok_cpreg(t, r) (memset(&(t), 0, sizeof(t)), \ - (t).X_op = O_cpregister, \ - (t).X_add_number = (r)) -#define set_tok_freg(t, r) (memset(&(t), 0, sizeof(t)), \ - (t).X_op = O_register, \ - (t).X_add_number = (r)+32) -#define set_tok_sym(t, s, a) (memset(&(t), 0, sizeof(t)), \ - (t).X_op = O_symbol, \ - (t).X_add_symbol = (s), \ - (t).X_add_number = (a)) -#define set_tok_const(t, n) (memset(&(t), 0, sizeof(t)), \ - (t).X_op = O_constant, \ - (t).X_add_number = (n)) - - -/* Prototypes for all local functions */ - -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 *)); -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 int 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)); -#endif -#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) -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)); -#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 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. */ - -/* These are exported to relaxing code, even though we don't do any - relaxing on this processor currently. */ -int md_short_jump_size = 4; -int md_long_jump_size = 4; - -/* Characters which always start a comment. */ -const char comment_chars[] = "#"; - -/* Characters which start a comment at the beginning of a line. */ -const char line_comment_chars[] = "#"; - -/* Characters which may be used to separate multiple commands on a - single line. */ -const char line_separator_chars[] = ";"; - -/* Characters which are used to indicate an exponent in a floating - point number. */ -const char EXP_CHARS[] = "eE"; - -/* Characters which mean that a number is a floating point constant, - as in 0d1.0. */ -#if 0 -const char FLT_CHARS[] = "dD"; -#else -/* XXX: Do all of these really get used on the alpha?? */ -char FLT_CHARS[] = "rRsSfFdDxXpP"; -#endif - -#ifdef OBJ_EVAX -const char *md_shortopts = "Fm:g+1h:HG:"; -#else -const char *md_shortopts = "Fm:gG:"; -#endif - -struct option md_longopts[] = { -#define OPTION_32ADDR (OPTION_MD_BASE) - { "32addr", no_argument, NULL, OPTION_32ADDR }, -#define OPTION_RELAX (OPTION_32ADDR+1) - { "relax", no_argument, NULL, OPTION_RELAX }, - { NULL, no_argument, NULL, 0 } -}; - -size_t md_longopts_size = sizeof(md_longopts); - - -#ifdef OBJ_EVAX -#define AXP_REG_R0 0 -#define AXP_REG_R16 16 -#define AXP_REG_R17 17 -#undef AXP_REG_T9 -#define AXP_REG_T9 22 -#undef AXP_REG_T10 -#define AXP_REG_T10 23 -#undef AXP_REG_T11 -#define AXP_REG_T11 24 -#undef AXP_REG_T12 -#define AXP_REG_T12 25 -#define AXP_REG_AI 25 -#undef AXP_REG_FP -#define AXP_REG_FP 29 - -#undef AXP_REG_GP -#define AXP_REG_GP AXP_REG_PV -#endif /* OBJ_EVAX */ - -/* The cpu for which we are generating code */ -static unsigned alpha_target = AXP_OPCODE_BASE; -static const char *alpha_target_name = "<all>"; - -/* The hash table of instruction opcodes */ -static struct hash_control *alpha_opcode_hash; - -/* The hash table of macro opcodes */ -static struct hash_control *alpha_macro_hash; - -#ifdef OBJ_ECOFF -/* The $gp relocation symbol */ -static symbolS *alpha_gp_symbol; - -/* XXX: what is this, and why is it exported? */ -valueT alpha_gp_value; -#endif - -/* The current $gp register */ -static int alpha_gp_register = AXP_REG_GP; - -/* A table of the register symbols */ -static symbolS *alpha_register_table[64]; - -/* Constant sections, or sections of constants */ -#ifdef OBJ_ECOFF -static segT alpha_lita_section; -static segT alpha_lit4_section; -#endif -#ifdef OBJ_EVAX -static segT alpha_link_section; -static segT alpha_ctors_section; -static segT alpha_dtors_section; -#endif -static segT alpha_lit8_section; - -/* Symbols referring to said sections. */ -#ifdef OBJ_ECOFF -static symbolS *alpha_lita_symbol; -static symbolS *alpha_lit4_symbol; -#endif -#ifdef OBJ_EVAX -static symbolS *alpha_link_symbol; -static symbolS *alpha_ctors_symbol; -static symbolS *alpha_dtors_symbol; -#endif -static symbolS *alpha_lit8_symbol; - -/* Literal for .litX+0x8000 within .lita */ -#ifdef OBJ_ECOFF -static offsetT alpha_lit4_literal; -static offsetT alpha_lit8_literal; -#endif - -/* Is the assembler not allowed to use $at? */ -static int alpha_noat_on = 0; - -/* Are macros enabled? */ -static int alpha_macros_on = 1; - -/* Are floats disabled? */ -static int alpha_nofloats_on = 0; - -/* Are addresses 32 bit? */ -static int alpha_addr32_on = 0; - -/* Symbol labelling the current insn. When the Alpha gas sees - foo: - .quad 0 - and the section happens to not be on an eight byte boundary, it - will align both the symbol and the .quad to an eight byte boundary. */ -static symbolS *alpha_insn_label; - -/* Whether we should automatically align data generation pseudo-ops. - .align 0 will turn this off. */ -static int alpha_auto_align_on = 1; - -/* The known current alignment of the current section. */ -static int alpha_current_align; - -/* These are exported to ECOFF code. */ -unsigned long alpha_gprmask, alpha_fprmask; - -/* Whether the debugging option was seen. */ -static int alpha_debug; - -/* Don't fully resolve relocations, allowing code movement in the linker. */ -static int alpha_flag_relax; - -/* What value to give to bfd_set_gp_size. */ -static int g_switch_value = 8; - -#ifdef OBJ_EVAX -/* Collect information about current procedure here. */ -static struct { - symbolS *symbol; /* proc pdesc symbol */ - int pdsckind; - int framereg; /* register for frame pointer */ - int framesize; /* size of frame */ - int rsa_offset; - int ra_save; - int fp_save; - long imask; - long fmask; - int type; - int prologue; -} alpha_evax_proc; - -static int alpha_flag_hash_long_names = 0; /* -+ */ -static int alpha_flag_show_after_trunc = 0; /* -H */ - -/* If the -+ switch is given, then a hash is appended to any name that is - * longer than 64 characters, else longer symbol names are truncated. - */ - -#endif - -/* A table of CPU names and opcode sets. */ - -static const struct cpu_type -{ - const char *name; - unsigned flags; -} cpu_types[] = -{ - /* Ad hoc convention: cpu number gets palcode, process code doesn't. - This supports usage under DU 4.0b that does ".arch ev4", and - usage in MILO that does -m21064. Probably something more - specific like -m21064-pal should be used, but oh well. */ - - { "21064", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, - { "21064a", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, - { "21066", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, - { "21068", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, - { "21164", AXP_OPCODE_BASE|AXP_OPCODE_EV5 }, - /* Do we have CIX extension here? */ - { "21164a", AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX }, - /* Still same PALcodes? */ - { "21164pc", (AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX - |AXP_OPCODE_MAX) }, - /* All new PALcodes? Extras? */ - { "21264", (AXP_OPCODE_BASE|AXP_OPCODE_BWX - |AXP_OPCODE_CIX|AXP_OPCODE_MAX) }, - - { "ev4", AXP_OPCODE_BASE }, - { "ev45", AXP_OPCODE_BASE }, - { "lca45", AXP_OPCODE_BASE }, - { "ev5", AXP_OPCODE_BASE }, - { "ev56", AXP_OPCODE_BASE|AXP_OPCODE_BWX }, - { "pca56", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX }, - { "ev6", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_CIX|AXP_OPCODE_MAX }, - - { "all", AXP_OPCODE_BASE }, - { 0 } -}; - -/* The macro table */ - -static const struct alpha_macro alpha_macros[] = { -/* Load/Store macros */ - { "lda", emit_lda, NULL, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldah", emit_ldah, NULL, - { MACRO_IR, MACRO_EXP, MACRO_EOA } }, - - { "ldl", emit_ir_load, "ldl", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldl_l", emit_ir_load, "ldl_l", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldq", emit_ir_load, "ldq", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldq_l", emit_ir_load, "ldq_l", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldq_u", emit_ir_load, "ldq_u", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldf", emit_loadstore, "ldf", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "ldg", emit_loadstore, "ldg", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "lds", emit_loadstore, "lds", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "ldt", emit_loadstore, "ldt", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - - { "ldb", emit_ldX, (PTR)0, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldbu", emit_ldXu, (PTR)0, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldw", emit_ldX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ldwu", emit_ldXu, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - - { "uldw", emit_uldX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldwu", emit_uldXu, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldl", emit_uldX, (PTR)2, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldlu", emit_uldXu, (PTR)2, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "uldq", emit_uldXu, (PTR)3, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - - { "ldgp", emit_ldgp, NULL, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } }, - - { "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 0 - { "ldif" emit_ldiq, NULL, - { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "ldid" emit_ldiq, NULL, - { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "ldig" emit_ldiq, NULL, - { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "ldis" emit_ldiq, NULL, - { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "ldit" emit_ldiq, NULL, - { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, -#endif - - { "stl", emit_loadstore, "stl", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stl_c", emit_loadstore, "stl_c", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stq", emit_loadstore, "stq", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stq_c", emit_loadstore, "stq_c", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stq_u", emit_loadstore, "stq_u", - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stf", emit_loadstore, "stf", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "stg", emit_loadstore, "stg", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "sts", emit_loadstore, "sts", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - { "stt", emit_loadstore, "stt", - { MACRO_FPR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_FPR, MACRO_EXP, MACRO_EOA } }, - - { "stb", emit_stX, (PTR)0, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "stw", emit_stX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustw", emit_ustX, (PTR)1, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustl", emit_ustX, (PTR)2, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - { "ustq", emit_ustX, (PTR)3, - { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA, - MACRO_IR, MACRO_EXP, MACRO_EOA } }, - -/* Arithmetic macros */ -#if 0 - { "absl" emit_absl, 1, { IR } }, - { "absl" emit_absl, 2, { IR, IR } }, - { "absl" emit_absl, 2, { EXP, IR } }, - { "absq" emit_absq, 1, { IR } }, - { "absq" emit_absq, 2, { IR, IR } }, - { "absq" emit_absq, 2, { EXP, IR } }, -#endif - - { "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 */ } }, - - { "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 */ } }, - - { "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 } }, -}; - -static const int alpha_num_macros - = sizeof(alpha_macros) / sizeof(*alpha_macros); - -/* 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 () -{ - unsigned int i; - - /* 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". */ - } - - 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, (PTR)&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 ("<GP value>", 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; - - sec = subseg_new(".mdebug", (subsegT)0); - bfd_set_section_flags(stdoutput, sec, SEC_HAS_CONTENTS|SEC_READONLY); - bfd_set_section_alignment(stdoutput, sec, 3); - -#ifdef ERIC_neverdef - sec = subseg_new(".reginfo", (subsegT)0); - /* The ABI says this section should be loaded so that the running - program can access it. */ - bfd_set_section_flags(stdoutput, sec, - SEC_ALLOC|SEC_LOAD|SEC_READONLY|SEC_DATA); - bfd_set_section_alignement(stdoutput, sec, 3); -#endif - } -#endif /* OBJ_ELF */ - - subseg_set(text_section, 0); -} - -/* The public interface to the instruction assembler. */ - -void -md_assemble (str) - char *str; -{ - char opname[32]; /* current maximum is 13 */ - expressionS tok[MAX_INSN_ARGS]; - int ntok, opnamelen, trunclen; - - /* split off the opcode */ - opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/48"); - 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) - { - 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; -{ - 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 PARAMS ((int, char *, int *)); - -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) - { - /* 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 (c, arg) - 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; - - default: - return 0; - } - - return 1; -} - -/* Print a description of the command-line options that we accept. */ - -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\ --m21064 | -m21066 | -m21164 | -m21164a\n\ --mev4 | -mev45 | -mev5 | -mev56 | -mall\n\ - specify variant of Alpha architecture\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 (fixP) - fixS *fixP; -{ - valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; - switch (fixP->fx_r_type) - { - case BFD_RELOC_ALPHA_GPDISP: - case BFD_RELOC_ALPHA_GPDISP_HI16: - case BFD_RELOC_ALPHA_GPDISP_LO16: - return addr; - default: - return fixP->fx_size + 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. */ - -int -md_apply_fix (fixP, valueP) - fixS *fixP; - valueT *valueP; -{ - char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; - valueT value = *valueP; - unsigned image, size; - - switch (fixP->fx_r_type) - { - /* The GPDISP relocations are processed internally with a symbol - referring to the current function; 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; - assert (next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16); - - 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 (absolute_section); - 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 1; - -#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; -#endif -#ifdef OBJ_ELF - case BFD_RELOC_GPREL32: - return 1; -#endif - - 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 1; - - 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 1; - -#ifdef OBJ_ECOFF - case BFD_RELOC_ALPHA_LITERAL: - md_number_to_chars (fixpos, value, 2); - return 1; - - case BFD_RELOC_ALPHA_LITUSE: - return 1; -#endif -#ifdef OBJ_ELF - case BFD_RELOC_ALPHA_ELF_LITERAL: - case BFD_RELOC_ALPHA_LITUSE: - return 1; -#endif -#ifdef OBJ_EVAX - case BFD_RELOC_ALPHA_LINKAGE: - case BFD_RELOC_ALPHA_CODEADDR: - return 1; -#endif - - 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 < 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 - && fixP->fx_addsy->bsym->section != 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 1; - 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; - return 0; -} - -/* - * Look for a register name in the given symbol. - */ - -symbolS * -md_undefined_symbol(name) - 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; - /* FALLTHRU */ - - case 'r': - if (!isdigit(*++name)) - break; - /* FALLTHRU */ - - 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 == 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 () -{ - 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 (sym) - 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 a assembly time. */ - -int -alpha_force_relocation (f) - 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: -#ifdef OBJ_ECOFF - case BFD_RELOC_ALPHA_LITERAL: -#endif -#ifdef OBJ_ELF - case BFD_RELOC_ALPHA_ELF_LITERAL: -#endif - case BFD_RELOC_ALPHA_LITUSE: - case BFD_RELOC_GPREL32: -#ifdef OBJ_EVAX - case BFD_RELOC_ALPHA_LINKAGE: - case BFD_RELOC_ALPHA_CODEADDR: -#endif - return 1; - - case BFD_RELOC_23_PCREL_S2: - case BFD_RELOC_32: - case BFD_RELOC_64: - case BFD_RELOC_ALPHA_HINT: - return 0; - - default: - assert((int)f->fx_r_type < 0 && -(int)f->fx_r_type < alpha_num_operands); - return 0; - } -} - -/* Return true if we can partially resolve a relocation now. */ - -int -alpha_fix_adjustable (f) - fixS *f; -{ -#ifdef OBJ_ELF - /* Prevent all adjustments to global symbols */ - if (S_IS_EXTERN (f->fx_addsy)) - return 0; -#endif - - /* 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; - -#ifdef OBJ_ECOFF - case BFD_RELOC_ALPHA_LITERAL: -#endif -#ifdef OBJ_ELF - case BFD_RELOC_ALPHA_ELF_LITERAL: -#endif -#ifdef OBJ_EVAX - case BFD_RELOC_ALPHA_LINKAGE: - case BFD_RELOC_ALPHA_CODEADDR: -#endif - return 1; - - case BFD_RELOC_ALPHA_LITUSE: - return 0; - - case BFD_RELOC_GPREL32: - case BFD_RELOC_23_PCREL_S2: - case BFD_RELOC_32: - case BFD_RELOC_64: - case BFD_RELOC_ALPHA_HINT: - return 1; - - default: - assert ((int)f->fx_r_type < 0 - && - (int)f->fx_r_type < alpha_num_operands); - return 1; - } - /*NOTREACHED*/ -} - -/* Generate the BFD reloc to be stuck in the object file from the - fixup used internally in the assembler. */ - -arelent * -tc_gen_reloc (sec, fixp) - asection *sec; - fixS *fixp; -{ - arelent *reloc; - - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; - reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - - /* 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); - - 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; - } - - 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); - -#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; -#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_COMMON(fixp->fx_addsy)) - reloc->addend -= fixp->fx_addsy->bsym->value; -#endif - } - - return reloc; -} - -/* 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. - - Only called as a part of processing the ECOFF .frame directive. */ - -int -tc_get_register (frame) - int frame; -{ - int framereg = AXP_REG_SP; - - SKIP_WHITESPACE (); - if (*input_line_pointer == '$') - { - char *s = input_line_pointer; - char c = get_symbol_end (); - symbolS *sym = md_undefined_symbol (s); - - *strchr(s, '\0') = c; - if (sym && (framereg = S_GET_VALUE (sym)) <= 31) - goto found; - } - as_warn ("frame reg expected, using $%d.", framereg); - -found: - note_gpreg (framereg); - return framereg; -} - -/* 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 () -{ - if (alpha_debug != 0 - && ! ecoff_debugging_seen) - flag_keep_locals = 1; -} - -#endif /* OBJ_ECOFF */ - -/* Parse the arguments to an opcode. */ - -static int -tokenize_arguments (str, tok, ntok) - char *str; - expressionS tok[]; - int ntok; -{ - expressionS *end_tok = tok + ntok; - char *old_input_line_pointer; - int saw_comma = 0, saw_arg = 0; - - memset (tok, 0, sizeof (*tok) * ntok); - - /* Save and restore input_line_pointer around this function */ - old_input_line_pointer = input_line_pointer; - input_line_pointer = str; - - while (tok < end_tok && *input_line_pointer) - { - SKIP_WHITESPACE (); - switch (*input_line_pointer) - { - case '\0': - goto fini; - - case ',': - ++input_line_pointer; - if (saw_comma || !saw_arg) - goto err; - saw_comma = 1; - break; - - case '(': - { - char *hold = input_line_pointer++; - - /* 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; - } - - /* ... then fall through to plain expression */ - input_line_pointer = hold; - } - - default: - if (saw_arg && !saw_comma) - goto err; - expression (tok); - if (tok->X_op == O_illegal || tok->X_op == O_absent) - goto err; - - saw_comma = 0; - saw_arg = 1; - ++tok; - break; - } - } - -fini: - if (saw_comma) - goto err; - input_line_pointer = old_input_line_pointer; - return ntok - (end_tok - tok); - -err: - input_line_pointer = old_input_line_pointer; - return -1; -} - -/* Search forward through all variants of an opcode looking for a - syntax match. */ - -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; -{ - const struct alpha_opcode *opcode = first_opcode; - int ntok = *pntok; - int got_cpu_match = 0; - - do - { - 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; - - for (opidx = opcode->operands; *opidx; ++opidx) - { - const struct alpha_operand *operand = &alpha_operands[*opidx]; - - /* only take input from real operands */ - if (operand->flags & AXP_OPERAND_FAKE) - continue; - - /* 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; - } - 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 < 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; - - 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; - 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; - 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; - 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; - - 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: - goto match_failed; - } - ++tokidx; - break; - - match_failed: - while (*arg != MACRO_EOA) - ++arg; - tokidx = 0; - break; - } - ++arg; - } - } - while (++macro-alpha_macros < 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) - { - const char *err = - "operand out of range (%s not between %d and %d)"; - char buf[sizeof (val) * 3 + 2]; - - sprint_value(buf, val); - if (file) - as_warn_where(file, line, err, buf, min, max); - else - as_warn(err, buf, min, max); - } - } - - if (operand->insert) - { - const char *errmsg = NULL; - - insn = (*operand->insert) (insn, val, &errmsg); - if (errmsg) - as_warn (errmsg); - } - else - insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift); - - return insn; -} - -/* - * Turn an opcode description and a set of arguments into - * an instruction and a fixup. - */ - -static void -assemble_insn(opcode, tok, ntok, insn) - const struct alpha_opcode *opcode; - const expressionS *tok; - int ntok; - struct alpha_insn *insn; -{ - const unsigned char *argidx; - unsigned image; - int tokidx = 0; - - memset (insn, 0, sizeof (*insn)); - image = opcode->opcode; - - for (argidx = opcode->operands; *argidx; ++argidx) - { - const struct alpha_operand *operand = &alpha_operands[*argidx]; - const expressionS *t; - - if (operand->flags & AXP_OPERAND_FAKE) - { - /* fake operands take no value and generate no fixup */ - image = insert_operand(image, operand, 0, NULL, 0); - continue; - } - - if (tokidx >= ntok) - { - switch (operand->flags & AXP_OPERAND_OPTIONAL_MASK) - { - case AXP_OPERAND_DEFAULT_FIRST: - t = &tok[0]; - break; - case AXP_OPERAND_DEFAULT_SECOND: - t = &tok[1]; - break; - case AXP_OPERAND_DEFAULT_ZERO: - { - static const expressionS zero_exp = { 0, 0, 0, O_constant, 1 }; - t = &zero_exp; - } - break; - default: - abort(); - } - } - else - t = &tok[tokidx++]; - - switch (t->X_op) - { - case O_register: - case O_pregister: - case O_cpregister: - image = insert_operand(image, operand, regno(t->X_add_number), - NULL, 0); - break; - - case O_constant: - image = insert_operand(image, operand, t->X_add_number, NULL, 0); - break; - - default: - { - struct alpha_fixup *fixup; - - if (insn->nfixups >= MAX_INSN_FIXUPS) - as_fatal("too many fixups"); - - fixup = &insn->fixups[insn->nfixups++]; - - fixup->exp = *t; - fixup->reloc = operand->default_reloc; - } - break; - } - } - - insn->insn = image; -} - -/* - * Actually output an instruction with its fixup. - */ - -static void -emit_insn (insn) - struct alpha_insn *insn; -{ - char *f; - int i; - - /* 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; - - /* Write out the instruction. */ - f = frag_more (4); - md_number_to_chars (f, insn->insn, 4); - - /* Apply the fixups in order */ - for (i = 0; i < insn->nfixups; ++i) - { - struct alpha_fixup *fixup = &insn->fixups[i]; - int size, pcrel; - fixS *fixP; - - /* Some fixups are only used internally and so have no howto */ - if ((int)fixup->reloc < 0) - size = 4, pcrel = 0; -#ifdef OBJ_ELF - /* These relocation types are only used internally. */ - else if (fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16 - || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16) - { - size = 2, pcrel = 0; - } -#endif - else - { - reloc_howto_type *reloc_howto - = bfd_reloc_type_lookup (stdoutput, fixup->reloc); - assert (reloc_howto); - - size = bfd_get_reloc_size (reloc_howto); - pcrel = reloc_howto->pc_relative; - } - assert (size >= 1 && size <= 4); - - fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size, - &fixup->exp, pcrel, fixup->reloc); - - /* Turn off complaints that the addend is too large for some fixups */ - switch (fixup->reloc) - { - case BFD_RELOC_ALPHA_GPDISP_LO16: -#ifdef OBJ_ECOFF - case BFD_RELOC_ALPHA_LITERAL: -#endif -#ifdef OBJ_ELF - case BFD_RELOC_ALPHA_ELF_LITERAL: -#endif - case BFD_RELOC_GPREL32: - fixP->fx_no_overflow = 1; - break; - default: - break; - } - } -} - -/* 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. */ - -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; - - /* 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); - 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); -} - -/* Given an opcode name and a pre-tokenized set of arguments, take the - opcode all the way through emission. */ - -static void -assemble_tokens (opname, tok, ntok, local_macros_on) - const char *opname; - const expressionS *tok; - int ntok; - int local_macros_on; -{ - int found_something = 0; - const struct alpha_opcode *opcode; - const struct alpha_macro *macro; - int cpumatch = 1; - - /* search macros */ - 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); - 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 ldX_op[] = { "ldb", "ldw", "ldll", "ldq" }; -static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL }; - -/* Implement the ldgp macro. */ - -static void -emit_ldgp (tok, ntok, unused) - const expressionS *tok; - int ntok; - const PTR unused; -{ -#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; - - /* We're going to need this symbol in md_apply_fix(). */ - (void) section_symbol (absolute_section); - -#ifdef OBJ_ECOFF - if (regno (tok[2].X_add_number) == AXP_REG_PV) - ecoff_set_gp_prolog_size (0); -#endif - - newtok[0] = tok[0]; - set_tok_const (newtok[1], 0); - newtok[2] = tok[2]; - - assemble_tokens_to_insn ("ldah", newtok, 3, &insn); - - addend = tok[1]; - -#ifdef OBJ_ECOFF - assert (addend.X_op == O_constant); - addend.X_op = O_symbol; - addend.X_add_symbol = alpha_gp_symbol; -#endif - - insn.nfixups = 1; - insn.fixups[0].exp = addend; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16; - - emit_insn (&insn); - - set_tok_preg (newtok[2], tok[0].X_add_number); - - assemble_tokens_to_insn ("lda", newtok, 3, &insn); - -#ifdef OBJ_ECOFF - addend.X_add_number += 4; -#endif - - insn.nfixups = 1; - insn.fixups[0].exp = addend; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16; - - emit_insn (&insn); -#endif /* OBJ_ECOFF || OBJ_ELF */ -} - -#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. */ - -valueT -add_to_link_pool (basesym, sym, addend) - 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; - - offset = -basesym->sy_obj; - - /* @@ 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 (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; - } - } - } - - /* Not found in 16bit signed range. */ - - subseg_set (alpha_link_section, 0); - p = frag_more (8); - memset (p, 0, 8); - - fix_new (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0, - BFD_RELOC_64); - - subseg_set (current_section, current_subsec); - seginfo->literal_pool_size += 8; - return offset; -} - -#endif /* OBJ_EVAX */ - -/* Load a (partial) expression into a target register. - - 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. - - 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. - - Finally, the return value is true if the calling macro may emit a - LITUSE reloc if otherwise appropriate. */ - -static int -load_expression (targreg, exp, pbasereg, poffset) - int targreg; - const expressionS *exp; - int *pbasereg; - expressionS *poffset; -{ - int 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"); - - /* emit "ldq r, lit(gp)" */ - - 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"); - - 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); - - assemble_tokens_to_insn ("ldq", newtok, 3, &insn); - - assert (insn.nfixups == 1); - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL; -#endif /* OBJ_ECOFF */ -#ifdef OBJ_ELF - /* emit "ldq r, gotoff(gp)" */ - - 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"); - - set_tok_reg (newtok[0], AXP_REG_AT); - } - else - set_tok_reg (newtok[0], targreg); - - /* 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); - } - - set_tok_preg (newtok[2], alpha_gp_register); - - assemble_tokens_to_insn ("ldq", newtok, 3, &insn); - - assert (insn.nfixups == 1); - insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL; -#endif /* OBJ_ELF */ -#ifdef OBJ_EVAX - offsetT link; - - /* Find symbol or symbol pointer in link section. */ - - 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_insn(&insn); - -#ifndef OBJ_EVAX - emit_lituse = 1; - - if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO) - { - /* emit "addq r, base, r" */ - - set_tok_reg (newtok[1], basereg); - set_tok_reg (newtok[2], targreg); - assemble_tokens ("addq", newtok, 3, 0); - } -#endif - - basereg = targreg; - } - break; - - case O_constant: - break; - - case O_subtract: - /* Assume that this difference expression will be resolved to an - absolute value and that that value will fit in 16 bits. */ - - set_tok_reg (newtok[0], targreg); - newtok[1] = *exp; - set_tok_preg (newtok[2], basereg); - assemble_tokens ("lda", newtok, 3, 0); - - if (poffset) - set_tok_const (*poffset, 0); - return 0; - - case O_big: - as_bad ("%s number invalid; zero assumed", - exp->X_add_number > 0 ? "bignum" : "floating point"); - addend = 0; - break; - - default: - abort(); - } - - if (!range_signed_32 (addend)) - { - offsetT lit; - - /* 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) - { - 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); - - 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 - - emit_insn (&insn); - - /* emit "ldq litreg, lit(litreg)" */ - - 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); - if (insn.nfixups > 0) - { - memmove (&insn.fixups[1], &insn.fixups[0], - sizeof(struct alpha_fixup) * insn.nfixups); - } - insn.nfixups++; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE; - insn.fixups[0].exp.X_op = O_constant; - insn.fixups[0].exp.X_add_number = 1; - 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 - { - 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) - { - /* emit "ldah r, extra(r) */ - set_tok_const (newtok[1], extra); - assemble_tokens ("ldah", newtok, 3, 0); - set_tok_preg (newtok[2], basereg = targreg); - } - - 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); - } - - 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; -} - -/* The lda macro differs from the lda instruction in that it handles - most simple expressions, particualrly symbol address loads and - large constants. */ - -static void -emit_lda (tok, ntok, unused) - const expressionS *tok; - int ntok; - const PTR unused; -{ - int basereg; - - 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); -} - -/* The ldah macro differs from the ldah instruction in that it has $31 - as an implied base register. */ - -static void -emit_ldah (tok, ntok, unused) - const expressionS *tok; - int ntok; - const PTR unused; -{ - 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); -} - -/* 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_ir_load (tok, ntok, opname) - const expressionS *tok; - int ntok; - const PTR opname; -{ - int basereg, lituse; - 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]); - - newtok[0] = tok[0]; - set_tok_preg (newtok[2], basereg); - - assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn); - - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - if (insn.nfixups > 0) - { - memmove (&insn.fixups[1], &insn.fixups[0], - sizeof(struct alpha_fixup) * insn.nfixups); - } - insn.nfixups++; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE; - insn.fixups[0].exp.X_op = O_constant; - insn.fixups[0].exp.X_add_number = 1; - } - - emit_insn (&insn); -} - -/* Handle fp register loads, and both integer and fp register stores. - Again, we handle simple expressions. */ - -static void -emit_loadstore (tok, ntok, opname) - const expressionS *tok; - int ntok; - const PTR opname; -{ - int basereg, lituse; - 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; - - 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"); - - lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]); - } - else - { - newtok[1] = tok[1]; - lituse = 0; - } - - newtok[0] = tok[0]; - set_tok_preg (newtok[2], basereg); - - assemble_tokens_to_insn ((const char *)opname, newtok, 3, &insn); - - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - if (insn.nfixups > 0) - { - memmove (&insn.fixups[1], &insn.fixups[0], - sizeof(struct alpha_fixup) * insn.nfixups); - } - insn.nfixups++; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE; - insn.fixups[0].exp.X_op = O_constant; - insn.fixups[0].exp.X_add_number = 1; - } - - emit_insn (&insn); -} - -/* Load a half-word or byte as an unsigned value. */ - -static void -emit_ldXu (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - if (alpha_target & AXP_OPCODE_BWX) - emit_ir_load (tok, ntok, ldXu_op[(long)vlgsize]); - else - { - expressionS newtok[3]; - - if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); - - /* 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 targ, 0($at)" */ - - newtok[0] = tok[0]; - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("ldq_u", newtok, 3, 1); - - /* emit "extXl targ, $at, targ" */ - - set_tok_reg (newtok[1], AXP_REG_AT); - newtok[2] = newtok[0]; - assemble_tokens (extXl_op[(long)vlgsize], newtok, 3, 1); - } -} - -/* Load a half-word or byte as a signed value. */ - -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); -} - -/* Load an integral value from an unaligned address as an unsigned - value. */ - -static void -emit_uldXu (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - long lgsize = (long)vlgsize; - expressionS newtok[3]; - - if (alpha_noat_on) - as_bad ("macro requires $at register while noat in effect"); - - /* 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); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("ldq_u", newtok, 3, 1); - - /* 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); - - /* 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); - - /* 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); - - /* 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); -} - -/* 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. */ - -static void -emit_uldX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - emit_uldXu (tok, ntok, vlgsize); - assemble_tokens (sextX_op[(long)vlgsize], tok, 1, 1); -} - -/* Implement the ldil macro. */ - -static void -emit_ldil (tok, ntok, unused) - const expressionS *tok; - int ntok; - const PTR unused; -{ - expressionS newtok[2]; - - memcpy (newtok, tok, sizeof(newtok)); - newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number); - - assemble_tokens ("lda", newtok, ntok, 1); -} - -/* Store a half-word or byte. */ - -static void -emit_stX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - int lgsize = (int)(long)vlgsize; - - if (alpha_target & AXP_OPCODE_BWX) - emit_loadstore (tok, ntok, stX_op[lgsize]); - else - { - expressionS newtok[3]; - - if (alpha_noat_on) - as_bad("macro requires $at register while noat in effect"); - - /* 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); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("ldq_u", newtok, 3, 1); - - /* emit "insXl src, $at, $t10" */ - - newtok[0] = tok[0]; - set_tok_reg (newtok[1], AXP_REG_AT); - set_tok_reg (newtok[2], AXP_REG_T10); - assemble_tokens (insXl_op[lgsize], newtok, 3, 1); - - /* 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 "or $t9, $t10, $t9" */ - - set_tok_reg (newtok[1], AXP_REG_T10); - assemble_tokens ("or", newtok, 3, 1); - - /* emit "stq_u $t9, 0($at) */ - - set_tok_const (newtok[1], 0); - set_tok_preg (newtok[2], AXP_REG_AT); - assemble_tokens ("stq_u", newtok, 3, 1); - } -} - -/* Store an integer to an unaligned address. */ - -static void -emit_ustX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - 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)" */ - - 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); - - /* 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); - - /* 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); - - /* emit "insXh src, $at, $t12" */ - - set_tok_reg (newtok[2], AXP_REG_T12); - assemble_tokens (insXh_op[lgsize], newtok, 3, 1); - - /* 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 "mskXh $t10, $at, $t10" */ - - set_tok_reg (newtok[0], AXP_REG_T10); - newtok[2] = newtok[0]; - assemble_tokens (mskXh_op[lgsize], newtok, 3, 1); - - /* 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); - - /* 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); - - /* 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); - - /* 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); -} - -/* Sign extend a half-word or byte. The 32-bit sign extend is - implemented as "addl $31, $r, $t" in the opcode table. */ - -static void -emit_sextX (tok, ntok, vlgsize) - const expressionS *tok; - int ntok; - const PTR vlgsize; -{ - 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); - } -} - -/* Implement the division and modulus macros. */ - -#ifdef OBJ_EVAX - -/* Make register usage like in normal procedure call. - Don't clobber PV and RA. */ - -static void -emit_division (tok, ntok, symname) - const expressionS *tok; - int ntok; - const PTR symname; -{ - /* 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. - */ - - int xr, yr, rr; - symbolS *sym; - expressionS newtok[3]; - - xr = regno (tok[0].X_add_number); - yr = regno (tok[1].X_add_number); - - if (ntok < 3) - rr = xr; - else - rr = regno (tok[2].X_add_number); - - /* 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"); - - set_tok_reg (newtok[0], AXP_REG_R16); - set_tok_reg (newtok[1], AXP_REG_AT); - assemble_tokens ("mov", newtok, 2, 1); - - set_tok_reg (newtok[0], AXP_REG_R17); - set_tok_reg (newtok[1], AXP_REG_R16); - assemble_tokens ("mov", newtok, 2, 1); - - set_tok_reg (newtok[0], AXP_REG_AT); - set_tok_reg (newtok[1], AXP_REG_R17); - assemble_tokens ("mov", newtok, 2, 1); - } - 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); - } - - 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); - } - - 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); - } - } - - sym = symbol_find_or_make ((const char *)symname); - - set_tok_reg (newtok[0], AXP_REG_AT); - set_tok_sym (newtok[1], sym, 0); - assemble_tokens ("lda", newtok, 2, 1); - - /* 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); - - /* 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); - } -} - -#else /* !OBJ_EVAX */ - -static void -emit_division (tok, ntok, symname) - const expressionS *tok; - int ntok; - const PTR symname; -{ - /* 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 xr, yr, rr; - symbolS *sym; - expressionS newtok[3]; - - xr = regno (tok[0].X_add_number); - yr = regno (tok[1].X_add_number); - - if (ntok < 3) - rr = xr; - else - rr = regno (tok[2].X_add_number); - - sym = symbol_find_or_make ((const char *)symname); - - /* 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"); - - set_tok_reg (newtok[0], AXP_REG_T10); - set_tok_reg (newtok[1], AXP_REG_AT); - assemble_tokens ("mov", newtok, 2, 1); - - set_tok_reg (newtok[0], AXP_REG_T11); - set_tok_reg (newtok[1], AXP_REG_T10); - assemble_tokens ("mov", newtok, 2, 1); - - 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 (tok, ntok, vopname) - const expressionS *tok; - int ntok; - const PTR vopname; -{ - const char *opname = (const char *) vopname; - struct alpha_insn insn; - expressionS newtok[3]; - int r, tokidx = 0, lituse = 0; - - if (tokidx < ntok && tok[tokidx].X_op == O_register) - r = regno (tok[tokidx++].X_add_number); - else - r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA; - - set_tok_reg (newtok[0], r); - - 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.<sym> */ -#else - else - { - int basereg = alpha_gp_register; - lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL); - } -#endif - - set_tok_cpreg (newtok[1], r); - -#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); - - /* add the LITUSE fixup */ - if (lituse) - { - assert (insn.nfixups < MAX_INSN_FIXUPS); - if (insn.nfixups > 0) - { - memmove (&insn.fixups[1], &insn.fixups[0], - sizeof(struct alpha_fixup) * insn.nfixups); - } - insn.nfixups++; - insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITUSE; - insn.fixups[0].exp.X_op = O_constant; - insn.fixups[0].exp.X_add_number = 3; - } - - emit_insn (&insn); -} - -/* 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; -{ - 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); - else - r = AXP_REG_ZERO; - - set_tok_reg (newtok[0], r); - - 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; - - set_tok_cpreg (newtok[1], r); - - if (tokidx < ntok) - newtok[2] = tok[tokidx]; - else - set_tok_const (newtok[2], strcmp(opname, "ret") == 0); - - assemble_tokens (opname, newtok, 3, 0); -} - -/* 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_text (i); - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} - -/* Handle the .data pseudo-op. This is like the usual one, but it - clears alpha_insn_label and restores auto alignment. */ - -static void -s_alpha_data (i) - int i; -{ - s_data (i); - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} - -#if defined (OBJ_ECOFF) || defined (OBJ_EVAX) - -/* Handle the OSF/1 and openVMS .comm pseudo quirks. - openVMS constructs a section for every common symbol. */ - -static void -s_alpha_comm (ignore) - int ignore; -{ - 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 (); - - /* just after name is now '\0' */ - p = input_line_pointer; - *p = c; - - SKIP_WHITESPACE (); - - /* 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) - { - as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp); - ignore_rest_of_line (); - return; - } - - *p = 0; - symbolP = symbol_find_or_make (name); - *p = c; - -#ifdef OBJ_EVAX - /* Make a section for the common symbol. */ - new_seg = subseg_new (xstrdup (name), 0); -#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 - { -#ifdef OBJ_EVAX - subseg_set (new_seg, 0); - p = frag_more (temp); - new_seg->flags |= SEC_IS_COMMON; - if (! S_IS_DEFINED (symbolP)) - symbolP->bsym->section = new_seg; -#else - S_SET_VALUE (symbolP, (valueT) temp); -#endif - S_SET_EXTERNAL (symbolP); - } - -#ifdef OBJ_EVAX - subseg_set (current_section, current_subsec); -#endif - - know (symbolP->sy_frag == &zero_address_frag); - - demand_empty_rest_of_line (); -} - -#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 void -s_alpha_rdata (ignore) - int ignore; -{ - 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; -} - -#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 -s_alpha_sdata (ignore) - int ignore; -{ - 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; -} -#endif - -#ifdef OBJ_ELF - -/* Handle the .section pseudo-op. This is like the usual one, but it - clears alpha_insn_label and restores auto alignment. */ - -static void -s_alpha_section (ignore) - int ignore; -{ - obj_elf_section (ignore); - - alpha_insn_label = NULL; - alpha_auto_align_on = 1; - alpha_current_align = 0; -} - -#endif - -#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; -} - - -/* .prologue */ - -static void -s_alpha_prologue (ignore) - int ignore; -{ - demand_empty_rest_of_line (); - - return; -} - - -/* Parse .ent directives. */ - -static void -s_alpha_ent (ignore) - int ignore; -{ - 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->bsym->flags |= BSF_FUNCTION; - alpha_evax_proc.symbol = symbol; - - demand_empty_rest_of_line (); - return; -} - - -/* Parse .frame <framreg>,<framesize>,RA,<rsa_offset> directives. */ - -static void -s_alpha_frame (ignore) - int ignore; -{ - 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 (); - - return; -} - -static void -s_alpha_pdesc (ignore) - int ignore; -{ - 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; - } - - alpha_evax_proc.symbol->sy_obj = (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. */ - alpha_evax_proc.symbol->bsym->udata.p = (PTR)entry_sym->bsym; - - SKIP_WHITESPACE (); - if (*input_line_pointer++ != ',') - { - as_warn ("No comma after .pdesc <entryname>"); - 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 - - frag_align (3, 0, 0); - p = frag_more (16); - fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0); - fixp->fx_done = 1; - seginfo->literal_pool_size += 16; - - *p = alpha_evax_proc.pdsckind - | ((alpha_evax_proc.framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0); - *(p+1) = PDSC_S_M_NATIVE - | PDSC_S_M_NO_JACKET; - - switch (alpha_evax_proc.pdsckind) - { - case PDSC_S_K_KIND_NULL: - *(p+2) = 0; - *(p+3) = 0; - break; - case PDSC_S_K_KIND_FP_REGISTER: - *(p+2) = alpha_evax_proc.fp_save; - *(p+3) = alpha_evax_proc.ra_save; - break; - case PDSC_S_K_KIND_FP_STACK: - md_number_to_chars (p+2, (valueT)alpha_evax_proc.rsa_offset, 2); - break; - default: /* impossible */ - break; - } - - *(p+4) = 0; - *(p+5) = alpha_evax_proc.type & 0x0f; - - /* Signature offset. */ - md_number_to_chars (p+6, (valueT)0, 2); - - fix_new_exp (frag_now, p-frag_now->fr_literal+8, 8, &exp, 0, BFD_RELOC_64); - - if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_NULL) - return; - - /* Add dummy fix to make add_to_link_pool work. */ - p = frag_more (8); - fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0); - fixp->fx_done = 1; - seginfo->literal_pool_size += 8; - - /* pdesc+16: Size. */ - md_number_to_chars (p, (valueT)alpha_evax_proc.framesize, 4); - - md_number_to_chars (p+4, (valueT)0, 2); - - /* Entry length. */ - md_number_to_chars (p+6, alpha_evax_proc.prologue, 2); - - if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_FP_REGISTER) - return; - - /* Add dummy fix to make add_to_link_pool work. */ - p = frag_more (8); - fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0); - fixp->fx_done = 1; - seginfo->literal_pool_size += 8; - - /* pdesc+24: register masks. */ - - md_number_to_chars (p, alpha_evax_proc.imask, 4); - md_number_to_chars (p+4, alpha_evax_proc.fmask, 4); - - return; -} - - -/* Support for crash debug on vms. */ - -static void -s_alpha_name (ignore) - int ignore; -{ - register char *p; - expressionS exp; - segment_info_type *seginfo = seg_info (alpha_link_section); - - if (now_seg != alpha_link_section) - { - as_bad (".name directive not in link (.link) section"); - demand_empty_rest_of_line (); - return; - } - - expression (&exp); - if (exp.X_op != O_symbol) - { - as_warn (".name directive has no symbol"); - demand_empty_rest_of_line (); - return; - } - - demand_empty_rest_of_line (); - -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - frag_align (3, 0, 0); - p = frag_more (8); - seginfo->literal_pool_size += 8; - - fix_new_exp (frag_now, p-frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64); - - return; -} - - -static void -s_alpha_linkage (ignore) - int ignore; -{ - expressionS exp; - char *p; - -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - expression (&exp); - if (exp.X_op != O_symbol) - { - as_fatal ("No symbol after .linkage"); - } - else - { - p = frag_more (LKP_S_K_SIZE); - memset (p, 0, LKP_S_K_SIZE); - fix_new_exp (frag_now, p - frag_now->fr_literal, LKP_S_K_SIZE, &exp, 0,\ - BFD_RELOC_ALPHA_LINKAGE); - } - demand_empty_rest_of_line (); - - return; -} - - -static void -s_alpha_code_address (ignore) - int ignore; -{ - expressionS exp; - char *p; - -#ifdef md_flush_pending_output - md_flush_pending_output (); -#endif - - expression (&exp); - if (exp.X_op != O_symbol) - { - as_fatal ("No symbol after .code_address"); - } - else - { - p = frag_more (8); - memset (p, 0, 8); - fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0,\ - BFD_RELOC_ALPHA_CODEADDR); - } - demand_empty_rest_of_line (); - - return; -} - - -static void -s_alpha_fp_save (ignore) - int ignore; -{ - - alpha_evax_proc.fp_save = tc_get_register (1); - - demand_empty_rest_of_line (); - return; -} - - -static void -s_alpha_mask (ignore) - int ignore; -{ - long val; - - if (get_absolute_expression_and_terminator (&val) != ',') - { - as_warn ("Bad .mask directive"); - --input_line_pointer; - } - else - { - alpha_evax_proc.imask = val; - (void)get_absolute_expression (); - } - demand_empty_rest_of_line (); - - return; -} - - -static void -s_alpha_fmask (ignore) - int ignore; -{ - long val; - - if (get_absolute_expression_and_terminator (&val) != ',') - { - as_warn ("Bad .fmask directive"); - --input_line_pointer; - } - else - { - alpha_evax_proc.fmask = val; - (void) get_absolute_expression (); - } - demand_empty_rest_of_line (); - - return; -} - -static void -s_alpha_end (ignore) - int ignore; -{ - char c; - - c = get_symbol_end (); - *input_line_pointer = c; - demand_empty_rest_of_line (); - alpha_evax_proc.symbol = 0; - - return; -} - - -static void -s_alpha_file (ignore) - int ignore; -{ - symbolS *s; - int length; - static char case_hack[32]; - - extern char *demand_copy_string PARAMS ((int *lenP)); - - sprintf (case_hack, "<CASE:%01d%01d>", - alpha_flag_hash_long_names, alpha_flag_show_after_trunc); - - s = symbol_find_or_make (case_hack); - s->bsym->flags |= BSF_FILE; - - get_absolute_expression (); - s = symbol_find_or_make (demand_copy_string (&length)); - s->bsym->flags |= BSF_FILE; - demand_empty_rest_of_line (); - - return; -} -#endif /* OBJ_EVAX */ - -/* Handle the .gprel32 pseudo op. */ - -static void -s_alpha_gprel32 (ignore) - int ignore; -{ - expressionS e; - char *p; - - SKIP_WHITESPACE (); - expression (&e); - -#ifdef OBJ_ELF - switch (e.X_op) - { - case O_constant: - e.X_add_symbol = section_symbol(absolute_section); - e.X_op = O_symbol; - /* FALLTHRU */ - case O_symbol: - break; - default: - abort(); - } -#else -#ifdef OBJ_ECOFF - switch (e.X_op) - { - case O_constant: - e.X_add_symbol = section_symbol (absolute_section); - /* fall through */ - case O_symbol: - e.X_op = O_subtract; - e.X_op_symbol = alpha_gp_symbol; - break; - default: - abort (); - } -#endif -#endif - - 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; - - p = frag_more (4); - memset (p, 0, 4); - fix_new_exp (frag_now, p-frag_now->fr_literal, 4, - &e, 0, BFD_RELOC_GPREL32); -} - -/* Handle floating point allocation pseudo-ops. This is like the - generic vresion, but it makes sure the current label, if any, is - correctly aligned. */ - -static void -s_alpha_float_cons (type) - int type; -{ - int log_size; - - switch (type) - { - default: - case 'f': - case 'F': - log_size = 2; - break; - - case 'd': - case 'D': - case 'G': - log_size = 3; - break; - - case 'x': - case 'X': - case 'p': - case 'P': - log_size = 4; - break; - } - - if (alpha_auto_align_on && alpha_current_align < log_size) - alpha_align (log_size, (char *) NULL, alpha_insn_label, 0); - if (alpha_current_align > log_size) - alpha_current_align = log_size; - alpha_insn_label = NULL; - - float_cons (type); -} - -/* Handle the .proc pseudo op. We don't really do much with it except - parse it. */ - -static void -s_alpha_proc (is_static) - int is_static; -{ - char *name; - char c; - char *p; - symbolS *symbolP; - int temp; - - /* Takes ".proc name,nargs" */ - SKIP_WHITESPACE (); - name = input_line_pointer; - c = get_symbol_end (); - p = input_line_pointer; - symbolP = symbol_find_or_make (name); - *p = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - *p = 0; - as_warn ("Expected comma after name \"%s\"", name); - *p = c; - temp = 0; - ignore_rest_of_line (); - } - else - { - input_line_pointer++; - temp = get_absolute_expression (); - } - /* symbolP->sy_other = (signed char) temp; */ - as_warn ("unhandled: .proc %s,%d", name, temp); - demand_empty_rest_of_line (); -} - -/* Handle the .set pseudo op. This is used to turn on and off most of - the assembler features. */ - -static void -s_alpha_set (x) - int x; -{ - char *name, ch, *s; - int yesno = 1; - - SKIP_WHITESPACE (); - name = input_line_pointer; - ch = get_symbol_end (); - - s = name; - if (s[0] == 'n' && s[1] == 'o') - { - yesno = 0; - s += 2; - } - if (!strcmp ("reorder", s)) - /* ignore */ ; - else if (!strcmp ("at", s)) - alpha_noat_on = !yesno; - else if (!strcmp ("macro", s)) - alpha_macros_on = yesno; - else if (!strcmp ("move", s)) - /* ignore */ ; - else if (!strcmp ("volatile", s)) - /* ignore */ ; - else - as_warn ("Tried to .set unrecognized mode `%s'", name); - - *input_line_pointer = ch; - demand_empty_rest_of_line (); -} - -/* Handle the .base pseudo op. This changes the assembler's notion of - the $gp register. */ - -static void -s_alpha_base (ignore) - int ignore; -{ -#if 0 - if (first_32bit_quadrant) - { - /* not fatal, but it might not work in the end */ - as_warn ("File overrides no-base-register option."); - first_32bit_quadrant = 0; - } -#endif - - SKIP_WHITESPACE (); - if (*input_line_pointer == '$') - { /* $rNN form */ - input_line_pointer++; - if (*input_line_pointer == 'r') - input_line_pointer++; - } - - alpha_gp_register = get_absolute_expression (); - if (alpha_gp_register < 0 || alpha_gp_register > 31) - { - alpha_gp_register = AXP_REG_GP; - as_warn ("Bad base register, using $%d.", alpha_gp_register); - } - - demand_empty_rest_of_line (); -} - -/* Handle the .align pseudo-op. This aligns to a power of two. It - also adjusts any current instruction label. We treat this the same - way the MIPS port does: .align 0 turns off auto alignment. */ - -static void -s_alpha_align (ignore) - int ignore; -{ - int align; - char fill, *pfill; - long max_alignment = 15; - - align = get_absolute_expression (); - if (align > max_alignment) - { - align = max_alignment; - as_bad ("Alignment too large: %d. assumed", align); - } - else if (align < 0) - { - as_warn ("Alignment negative: 0 assumed"); - align = 0; - } - - if (*input_line_pointer == ',') - { - input_line_pointer++; - fill = get_absolute_expression (); - pfill = &fill; - } - else - pfill = NULL; - - if (align != 0) - { - alpha_auto_align_on = 1; - alpha_align (align, pfill, alpha_insn_label, 1); - } - else - { - alpha_auto_align_on = 0; - } - - demand_empty_rest_of_line (); -} - -/* Hook the normal string processor to reset known alignment. */ - -static void -s_alpha_stringer (terminate) - int terminate; -{ - alpha_current_align = 0; - alpha_insn_label = NULL; - stringer (terminate); -} - -/* Hook the normal space processing to reset known alignment. */ - -static void -s_alpha_space (ignore) - int ignore; -{ - alpha_current_align = 0; - alpha_insn_label = NULL; - s_space (ignore); -} - -/* Hook into cons for auto-alignment. */ - -void -alpha_cons_align (size) - int size; -{ - int log_size; - - log_size = 0; - while ((size >>= 1) != 0) - ++log_size; - - if (alpha_auto_align_on && alpha_current_align < log_size) - alpha_align (log_size, (char *) NULL, alpha_insn_label, 0); - if (alpha_current_align > log_size) - alpha_current_align = log_size; - alpha_insn_label = NULL; -} - -/* Here come the .uword, .ulong, and .uquad explicitly unaligned - pseudos. We just turn off auto-alignment and call down to cons. */ - -static void -s_alpha_ucons (bytes) - int bytes; -{ - int hold = alpha_auto_align_on; - alpha_auto_align_on = 0; - cons (bytes); - alpha_auto_align_on = hold; -} - -/* Switch the working cpu type. */ - -static void -s_alpha_arch (ignored) - int ignored; -{ - char *name, ch; - const struct cpu_type *p; - - SKIP_WHITESPACE (); - name = input_line_pointer; - ch = get_symbol_end (); - - for (p = cpu_types; p->name; ++p) - if (strcmp(name, p->name) == 0) - { - alpha_target_name = p->name, alpha_target = p->flags; - goto found; - } - as_warn("Unknown CPU identifier `%s'", name); - -found: - *input_line_pointer = ch; - demand_empty_rest_of_line (); -} - - - -#ifdef DEBUG1 -/* print token expression with alpha specific extension. */ - -static void -alpha_print_token(f, exp) - FILE *f; - const expressionS *exp; -{ - switch (exp->X_op) - { - case O_cpregister: - putc (',', f); - /* FALLTHRU */ - case O_pregister: - putc ('(', f); - { - expressionS nexp = *exp; - nexp.X_op = O_register; - print_expr (f, &nexp); - } - putc (')', f); - break; - default: - print_expr (f, exp); - break; - } - return; -} -#endif - -/* The target specific pseudo-ops which we support. */ - -const pseudo_typeS md_pseudo_table[] = -{ -#ifdef OBJ_ECOFF - {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */ - {"rdata", s_alpha_rdata, 0}, -#endif - {"text", s_alpha_text, 0}, - {"data", s_alpha_data, 0}, -#ifdef OBJ_ECOFF - {"sdata", s_alpha_sdata, 0}, -#endif -#ifdef OBJ_ELF - {"section", s_alpha_section, 0}, - {"section.s", s_alpha_section, 0}, - {"sect", s_alpha_section, 0}, - {"sect.s", s_alpha_section, 0}, -#endif -#ifdef OBJ_EVAX - { "pdesc", s_alpha_pdesc, 0}, - { "name", s_alpha_name, 0}, - { "linkage", s_alpha_linkage, 0}, - { "code_address", s_alpha_code_address, 0}, - { "ent", s_alpha_ent, 0}, - { "frame", s_alpha_frame, 0}, - { "fp_save", s_alpha_fp_save, 0}, - { "mask", s_alpha_mask, 0}, - { "fmask", s_alpha_fmask, 0}, - { "end", s_alpha_end, 0}, - { "file", s_alpha_file, 0}, - { "rdata", s_alpha_section, 1}, - { "comm", s_alpha_comm, 0}, - { "link", s_alpha_section, 3}, - { "ctors", s_alpha_section, 4}, - { "dtors", s_alpha_section, 5}, -#endif - {"gprel32", s_alpha_gprel32, 0}, - {"t_floating", s_alpha_float_cons, 'd'}, - {"s_floating", s_alpha_float_cons, 'f'}, - {"f_floating", s_alpha_float_cons, 'F'}, - {"g_floating", s_alpha_float_cons, 'G'}, - {"d_floating", s_alpha_float_cons, 'D'}, - - {"proc", s_alpha_proc, 0}, - {"aproc", s_alpha_proc, 1}, - {"set", s_alpha_set, 0}, - {"reguse", s_ignore, 0}, - {"livereg", s_ignore, 0}, - {"base", s_alpha_base, 0}, /*??*/ - {"option", s_ignore, 0}, - {"prologue", s_ignore, 0}, - {"aent", s_ignore, 0}, - {"ugen", s_ignore, 0}, - {"eflag", s_ignore, 0}, - - {"align", s_alpha_align, 0}, - {"double", s_alpha_float_cons, 'd'}, - {"float", s_alpha_float_cons, 'f'}, - {"single", s_alpha_float_cons, 'f'}, - {"ascii", s_alpha_stringer, 0}, - {"asciz", s_alpha_stringer, 1}, - {"string", s_alpha_stringer, 1}, - {"space", s_alpha_space, 0}, - {"skip", s_alpha_space, 0}, - {"zero", s_alpha_space, 0}, - -/* Unaligned data pseudos. */ - {"uword", s_alpha_ucons, 2}, - {"ulong", s_alpha_ucons, 4}, - {"uquad", s_alpha_ucons, 8}, - -#ifdef OBJ_ELF -/* Dwarf wants these versions of unaligned. */ - {"2byte", s_alpha_ucons, 2}, - {"4byte", s_alpha_ucons, 4}, - {"8byte", s_alpha_ucons, 8}, -#endif - -/* We don't do any optimizing, so we can safely ignore these. */ - {"noalias", s_ignore, 0}, - {"alias", s_ignore, 0}, - - {"arch", s_alpha_arch, 0}, - - {NULL, 0, 0}, -}; - - -/* Build a BFD section with its flags set appropriately for the .lita, - .lit8, or .lit4 sections. */ - -static void -create_literal_section (name, secp, symp) - const char *name; - segT *secp; - symbolS **symp; -{ - segT current_section = now_seg; - int current_subsec = now_subseg; - segT new_sec; - - *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); - - S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec)); -} - -#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 (sec) - asection *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 () -{ - 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); -#if 0 - /* These were disabled before -- should we use them? */ - maybe_set_gp (sdata); - maybe_set_gp (lit8_sec); - maybe_set_gp (lit4_sec); -#endif - -/* @@ 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 */ - -/* 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. */ - -static void -alpha_align (n, pfill, label, force) - int n; - char *pfill; - symbolS *label; - int force; -{ - if (alpha_current_align >= n) - return; - - if (pfill == NULL) - { - if (n > 2 - && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) - { - static char const unop[4] = { 0x00, 0x00, 0xe0, 0x2f }; - static char const nopunop[8] = { - 0x1f, 0x04, 0xff, 0x47, - 0x00, 0x00, 0xe0, 0x2f - }; - - /* First, make sure we're on a four-byte boundary, in case - someone has been putting .byte values into the text - section. The DEC assembler silently fills with unaligned - no-op instructions. This will zero-fill, then nop-fill - with proper alignment. */ - if (alpha_current_align < 2) - frag_align (2, 0, 0); - if (alpha_current_align < 3) - frag_align_pattern (3, unop, sizeof unop, 0); - if (n > 3) - frag_align_pattern (n, nopunop, sizeof nopunop, 0); - } - else - frag_align (n, 0, 0); - } - else - frag_align (n, *pfill, 0); - - alpha_current_align = n; - - if (label != NULL) - { - assert (S_GET_SEGMENT (label) == now_seg); - label->sy_frag = frag_now; - S_SET_VALUE (label, (valueT) frag_now_fix ()); - } - - record_alignment(now_seg, n); - - /* ??? if alpha_flag_relax && force && elf, record the requested alignment - in a reloc for the linker to see. */ -} - -/* 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. */ -#define md_atof vax_md_atof -#include "config/atof-vax.c" diff --git a/contrib/binutils/gas/config/tc-alpha.h b/contrib/binutils/gas/config/tc-alpha.h deleted file mode 100644 index bdc8ec155e73..000000000000 --- a/contrib/binutils/gas/config/tc-alpha.h +++ /dev/null @@ -1,92 +0,0 @@ -/* This file is tc-alpha.h - Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. - Written by Ken Raeburn <raeburn@cygnus.com>. - - 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 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. */ - -#define TC_ALPHA - -#define TARGET_BYTES_BIG_ENDIAN 0 - -#define TARGET_ARCH bfd_arch_alpha - -#define TARGET_FORMAT (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ - ? "ecoff-littlealpha" \ - : OUTPUT_FLAVOR == bfd_target_elf_flavour \ - ? "elf64-alpha" \ - : OUTPUT_FLAVOR == bfd_target_evax_flavour \ - ? "evax-alpha" \ - : "unknown-format") - -#define NEED_LITERAL_POOL -#define TC_HANDLES_FX_DONE -#define REPEAT_CONS_EXPRESSIONS - -extern int alpha_force_relocation PARAMS ((struct fix *)); -extern int alpha_fix_adjustable PARAMS ((struct fix *)); - -extern unsigned long alpha_gprmask, alpha_fprmask; -extern valueT alpha_gp_value; - -#define TC_FORCE_RELOCATION(FIXP) alpha_force_relocation (FIXP) -#define tc_fix_adjustable(FIXP) alpha_fix_adjustable (FIXP) -#define RELOC_REQUIRES_SYMBOL - -#define md_convert_frag(b,s,f) as_fatal ("alpha convert_frag\n") -#define md_create_long_jump(p,f,t,fr,s) as_fatal("alpha_create_long_jump") -#define md_create_short_jump(p,f,t,fr,s) as_fatal("alpha_create_short_jump") -#define md_estimate_size_before_relax(f,s) \ - (as_fatal("estimate_size_before_relax called"),1) -#define md_operand(x) - -#ifdef OBJ_EVAX - -/* This field keeps the symbols position in the link section. */ -#define OBJ_SYMFIELD_TYPE valueT - -#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP) \ - fix_new_exp (FRAG, OFF, (int)LEN, EXP, 0, \ - LEN == 2 ? BFD_RELOC_16 \ - : LEN == 4 ? BFD_RELOC_32 \ - : LEN == 8 ? BFD_RELOC_64 \ - : BFD_RELOC_ALPHA_LINKAGE); -#endif - -#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)); - -#define tc_frob_label(sym) alpha_define_label (sym) -extern void alpha_define_label PARAMS ((struct symbol *)); - -#define md_cons_align(nbytes) alpha_cons_align (nbytes) -extern void alpha_cons_align PARAMS ((int)); - -#ifdef OBJ_ECOFF -#define tc_frob_file_before_adjust() alpha_frob_file_before_adjust () -extern void alpha_frob_file_before_adjust PARAMS ((void)); -#endif - -#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ - -#ifdef OBJ_ELF -#define ELF_TC_SPECIAL_SECTIONS \ - { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL }, \ - { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_ALPHA_GPREL }, -#endif diff --git a/contrib/binutils/gas/config/tc-arc.c b/contrib/binutils/gas/config/tc-arc.c deleted file mode 100644 index 6fed5c64e72a..000000000000 --- a/contrib/binutils/gas/config/tc-arc.c +++ /dev/null @@ -1,1481 +0,0 @@ -/* tc-arc.c -- Assembler for the ARC - Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. - Contributed by Doug Evans (dje@cygnus.com). - - 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 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. */ - -#include <stdio.h> -#include <ctype.h> -#include "as.h" -#include "subsegs.h" -#include "opcode/arc.h" -#include "elf/arc.h" - -extern int arc_get_mach PARAMS ((char *)); - -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_cpu PARAMS ((int)); -/*static void arc_rename PARAMS ((int));*/ -static int get_arc_exp_reloc_type PARAMS ((int, int, expressionS *, - expressionS *)); - -const pseudo_typeS md_pseudo_table[] = -{ - { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */ - { "common", arc_common, 0 }, -/*{ "hword", cons, 2 }, - already exists */ - { "word", cons, 4 }, -/*{ "xword", cons, 8 },*/ - { "cpu", arc_cpu, 0 }, -/*{ "rename", arc_rename, 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[] = "#;"; - -/* 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 */ -/* 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 started like this one will always - work if '/' isn't otherwise defined. */ -const char line_comment_chars[] = "#"; - -const char line_separator_chars[] = ""; - -/* 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 */ -const char FLT_CHARS[] = "rRsSfFdD"; - -/* Byte order. */ -extern int target_big_endian; -const char *arc_target_format = DEFAULT_TARGET_FORMAT; -static int byte_order = DEFAULT_BYTE_ORDER; - -/* One of bfd_mach_arc_xxx. */ -static int arc_mach_type = bfd_mach_arc_base; - -/* Non-zero if the cpu type has been explicitly specified. */ -static int mach_type_specified_p = 0; - -/* Non-zero if opcode tables have been initialized. - A .cpu command must appear before any instructions. */ -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) - {"EB", no_argument, NULL, OPTION_EB}, -#define OPTION_EL (OPTION_MD_BASE + 1) - {"EL", no_argument, NULL, OPTION_EL}, - { NULL, no_argument, NULL, 0 } -}; -size_t md_longopts_size = sizeof (md_longopts); - -/* - * md_parse_option - * - * Invocation line includes a switch not recognized by the base assembler. - * See if it's a processor-specific option. - */ - -int -md_parse_option (c, arg) - int c; - char *arg; -{ - switch (c) - { - case OPTION_EB: - byte_order = BIG_ENDIAN; - arc_target_format = "elf32-bigarc"; - break; - case OPTION_EL: - byte_order = LITTLE_ENDIAN; - arc_target_format = "elf32-littlearc"; - break; - default: - return 0; - } - return 1; -} - -void -md_show_usage (stream) - FILE *stream; -{ - fprintf (stream, "\ -ARC options:\n\ --EB generate big endian output\n\ --EL generate little endian output\n"); -} - -/* 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. - Opcode selection is defered until later because we might see a .cpu - command. */ - -void -md_begin () -{ - /* The endianness can be chosen "at the factory". */ - target_big_endian = byte_order == BIG_ENDIAN; - - if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type)) - as_warn ("could not set architecture and machine"); - - /* Assume the base cpu. This call is necessary because we need to - initialize `arc_operand_map' which may be needed before we see the - first insn. */ - arc_opcode_init_tables (arc_get_opcode_mach (bfd_mach_arc_base, - target_big_endian)); -} - -/* Initialize the various opcode and operand tables. - MACH is one of bfd_mach_arc_xxx. */ - -static void -init_opcode_tables (mach) - int mach; -{ - register unsigned int i; - char *last; - - if ((arc_suffix_hash = hash_new ()) == NULL) - as_fatal ("virtual memory exhausted"); - - if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach)) - as_warn ("could not set architecture and machine"); - - /* This initializes a few things in arc-opc.c that we need. - This must be called before the various arc_xxx_supported fns. */ - arc_opcode_init_tables (arc_get_opcode_mach (mach, target_big_endian)); - - /* Only put the first entry of each equivalently named suffix in the - table. */ - last = ""; - for (i = 0; i < arc_suffixes_count; i++) - { - if (! arc_opval_supported (&arc_suffixes[i])) - continue; - if (strcmp (arc_suffixes[i].name, last) != 0) - hash_insert (arc_suffix_hash, arc_suffixes[i].name, (PTR) (arc_suffixes + i)); - last = arc_suffixes[i].name; - } - - /* Since registers don't have a prefix, we put them in the symbol table so - they can't be used as symbols. This also simplifies argument parsing as - we can let gas parse registers for us. The recorded register number is - the index in `arc_reg_names'. */ - for (i = 0; i < arc_reg_names_count; i++) - { - if (! arc_opval_supported (&arc_reg_names[i])) - continue; - /* Use symbol_create here instead of symbol_new so we don't try to - output registers into the object file's symbol table. */ - symbol_table_insert (symbol_create (arc_reg_names[i].name, reg_section, - i, &zero_address_frag)); - } - - /* Tell `s_cpu' it's too late. */ - cpu_tables_init_p = 1; -} - -/* Insert an operand value into an instruction. - 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; -{ - if (operand->bits != 32) - { - long min, max; - offsetT test; - - if ((operand->flags & ARC_OPERAND_SIGNED) != 0) - { - if ((operand->flags & ARC_OPERAND_SIGNOPT) != 0) - max = (1 << operand->bits) - 1; - else - max = (1 << (operand->bits - 1)) - 1; - min = - (1 << (operand->bits - 1)); - } - else - { - max = (1 << operand->bits) - 1; - min = 0; - } - - if ((operand->flags & ARC_OPERAND_NEGATIVE) != 0) - test = - val; - else - test = val; - - if (test < (offsetT) min || test > (offsetT) max) - { - const char *err = - "operand out of range (%s not between %ld and %ld)"; - char buf[100]; - - sprint_value (buf, test); - if (file == (char *) NULL) - as_warn (err, buf, min, max); - else - as_warn_where (file, line, err, buf, min, max); - } - } - - if (operand->insert) - { - const char *errmsg; - - errmsg = NULL; - insn = (*operand->insert) (insn, operand, mods, reg, (long) val, &errmsg); - if (errmsg != (const char *) NULL) - as_warn (errmsg); - } - else - insn |= (((long) val & ((1 << operand->bits) - 1)) - << operand->shift); - - return insn; -} - -/* 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 - that would screw up references to ``.''. */ - -struct arc_fixup -{ - /* index into `arc_operands' */ - int opindex; - expressionS exp; -}; - -#define MAX_FIXUPS 5 - -#define MAX_SUFFIXES 5 - -/* This routine is called for each instruction to be assembled. */ - -void -md_assemble (str) - char *str; -{ - const struct arc_opcode *opcode; - char *start; - arc_insn insn; - static int init_tables_p = 0; - - /* Opcode table initialization is deferred until here because we have to - wait for a possible .cpu 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. */ - - opcode = arc_opcode_lookup_asm (str); - - /* Keep looking until we find a match. */ - - start = str; - for ( ; opcode != NULL; opcode = ARC_OPCODE_NEXT_ASM (opcode)) - { - int past_opcode_p, fc, num_suffixes; - 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; - 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; - - /* 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 == '%') - { - /* Handle '+' specially as we want to allow "ld r0,[sp-4]". */ - /* ??? The syntax has changed to [sp,-4]. */ - if (0 && *syn == '+' && *str == '-') - { - /* Skip over syn's +, but leave str's - alone. - That makes the case identical to "ld r0,[sp+-4]". */ - ++syn; - } - else 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[*syn]].flags)) - { - mods |= arc_operands[arc_operand_map[*syn]].flags & ARC_MOD_BITS; - ++syn; - } - operand = arc_operands + arc_operand_map[*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 we get an error, go on to try the next insn. */ - if (errmsg) - break; - } - ++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,*suffix_end; - - 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 && isalpha (*t); ++t) - continue; - c = *t; - *t = '\0'; - suf = hash_find (arc_suffix_hash, s); - *t = c; - 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. */ - 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; - 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 c; - 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 (*str == '\0') - break; -#if 0 - /* Is this a syntax character? Eg: is there a '[' present when - there shouldn't be? */ - if (!isalnum (*str) - /* '.' as in ".LLC0" */ - && *str != '.' - /* '_' as in "_print" */ - && *str != '_' - /* '-' as in "[fp,-4]" */ - && *str != '-' - /* '%' as in "%ia(_func)" */ - && *str != '%') - break; -#endif - - /* 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 = arc_reg_names + exp.X_add_number; - } - else - { - /* We need to generate a fixup for this expression. */ - if (fc >= MAX_FIXUPS) - as_fatal ("too many fixups"); - fixups[fc].exp = exp; - - /* If this is a register constant (IE: one whose - register value gets stored as 61-63) then this - must be a limm. We don't support shimm relocs. */ - /* ??? This bit could use some cleaning up. - Referencing the format chars like this goes - against style. */ -#define IS_REG_OPERAND(o) ((o) == 'a' || (o) == 'b' || (o) == 'c') - if (IS_REG_OPERAND (*syn)) - { - const char *junk; - - fixups[fc].opindex = arc_operand_map['L']; - limm_reloc_p = 1; - /* 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[*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 0 - if (errmsg != (const char *) NULL) - as_warn (errmsg); -#endif - /* FIXME: We want to try shimm insns for limm ones. But if - the constant won't fit, we must go on to try the next - possibility. Where do we issue warnings for constants - that are too big then? At present, we'll flag the insn - as unrecognizable! Maybe have the "bad instruction" - error message include our `errmsg'? */ - if (errmsg != (const char *) NULL) - 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 (*str != '\0') - 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; - int need_cc_nop_p = 0; - - 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) - 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) - as_warn ("conditional branch follows set of flags"); - prev_insn_needs_cc_nop_p = 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); - } - 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); - } - - /* 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_fix. - - 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) - { - op_type = fixups[i].opindex; - /* FIXME: can we add this data to the operand table? */ - if (op_type == arc_operand_map['L']) - 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); - } - - /* All done. */ - return; - } - - /* Try the next entry. */ - } - - as_bad ("bad instruction `%s'", start); -} - -/* ??? This was copied from tc-sparc.c, I think. Is it necessary? */ - -static void -arc_common (ignore) - int ignore; -{ - char *name; - char c; - char *p; - int temp, size; - symbolS *symbolP; - - name = input_line_pointer; - c = get_symbol_end (); - /* just after name is now '\0' */ - p = input_line_pointer; - *p = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - as_bad ("expected comma after symbol-name"); - ignore_rest_of_line (); - return; - } - input_line_pointer++; /* skip ',' */ - if ((temp = get_absolute_expression ()) < 0) - { - as_bad (".COMMon length (%d.) <0! Ignored.", temp); - ignore_rest_of_line (); - return; - } - size = temp; - *p = 0; - symbolP = symbol_find_or_make (name); - *p = c; - if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) - { - as_bad ("ignoring attempt to re-define symbol"); - ignore_rest_of_line (); - return; - } - if (S_GET_VALUE (symbolP) != 0) - { - if (S_GET_VALUE (symbolP) != size) - { - as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.", - S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); - } - } - assert (symbolP->sy_frag == &zero_address_frag); - if (*input_line_pointer != ',') - { - as_bad ("expected comma after common length"); - ignore_rest_of_line (); - return; - } - input_line_pointer++; - SKIP_WHITESPACE (); - if (*input_line_pointer != '"') - { - temp = get_absolute_expression (); - if (temp < 0) - { - temp = 0; - as_warn ("Common alignment negative; 0 assumed"); - } - if (symbolP->local) - { - segT old_sec; - int old_subsec; - char *p; - int align; - - allocate_bss: - old_sec = now_seg; - old_subsec = now_subseg; - align = temp; - record_alignment (bss_section, align); - subseg_set (bss_section, 0); - if (align) - frag_align (align, 0, 0); - if (S_GET_SEGMENT (symbolP) == bss_section) - symbolP->sy_frag->fr_symbol = 0; - symbolP->sy_frag = frag_now; - p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, - (offsetT) size, (char *) 0); - *p = 0; - S_SET_SEGMENT (symbolP, bss_section); - S_CLEAR_EXTERNAL (symbolP); - subseg_set (old_sec, old_subsec); - } - else - { - allocate_common: - S_SET_VALUE (symbolP, (valueT) size); - S_SET_ALIGN (symbolP, temp); - S_SET_EXTERNAL (symbolP); - S_SET_SEGMENT (symbolP, bfd_com_section_ptr); - } - } - else - { - input_line_pointer++; - /* ??? Some say data, some say bss. */ - if (strncmp (input_line_pointer, ".bss\"", 5) - && strncmp (input_line_pointer, ".data\"", 6)) - { - input_line_pointer--; - goto bad_common_segment; - } - while (*input_line_pointer++ != '"') - ; - goto allocate_common; - } - demand_empty_rest_of_line (); - return; - - { - bad_common_segment: - p = input_line_pointer; - while (*p && *p != '\n') - p++; - c = *p; - *p = '\0'; - as_bad ("bad .common segment %s", input_line_pointer + 1); - *p = c; - input_line_pointer = p; - ignore_rest_of_line (); - return; - } -} - -/* Select the cpu we're assembling for. */ - -static void -arc_cpu (ignore) - int ignore; -{ - int mach; - char c; - char *cpu; - - /* If an instruction has already been seen, it's too late. */ - if (cpu_tables_init_p) - { - as_bad (".cpu command must appear before any instructions"); - ignore_rest_of_line (); - return; - } - - cpu = input_line_pointer; - c = get_symbol_end (); - mach = arc_get_mach (cpu); - *input_line_pointer = c; - if (mach == -1) - goto bad_cpu; - - demand_empty_rest_of_line (); - - /* The cpu may have been selected on the command line. - The choices must match. */ - /* ??? This was a command line option early on. It's gone now, but - leave this in. */ - if (mach_type_specified_p && mach != arc_mach_type) - as_bad (".cpu conflicts with previous value"); - else - { - arc_mach_type = mach; - mach_type_specified_p = 1; - if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach)) - as_warn ("could not set architecture and machine"); - } - return; - - bad_cpu: - as_bad ("bad .cpu op"); - ignore_rest_of_line (); -} - -#if 0 -/* The .rename pseudo-op. This is used by gcc to implement - -mmangle-cpu-libgcc. */ - -static void -arc_rename (ignore) - int ignore; -{ - char *name,*new; - char c; - symbolS *sym; - int len; - - name = input_line_pointer; - c = get_symbol_end (); - sym = symbol_find_or_make (name); - *input_line_pointer = c; - - if (*input_line_pointer != ',') - { - as_bad ("missing rename string"); - ignore_rest_of_line (); - return; - } - ++input_line_pointer; - SKIP_WHITESPACE (); - - name = input_line_pointer; - c = get_symbol_end (); - if (*name == '\0') - { - *input_line_pointer = c; - as_bad ("invalid symbol to rename to"); - ignore_rest_of_line (); - return; - } - new = (char *) xmalloc (strlen (name) + 1); - strcpy (new, name); - *input_line_pointer = c; - sym->sy_tc.real_name = new; - - demand_empty_rest_of_line (); -} -#endif - -/* 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 - -char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; -{ - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - char *atof_ieee (); - - switch (type) - { - case 'f': - case 'F': - prec = 2; - break; - - case 'd': - 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--;) - { - md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - - return NULL; -} - -/* 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; -{ - if (target_big_endian) - number_to_chars_bigendian (buf, val, n); - else - number_to_chars_littleendian (buf, val, n); -} - -/* Round up a section size to the appropriate boundary. */ - -valueT -md_section_align (segment, size) - segT segment; - valueT size; -{ - int align = bfd_get_section_alignment (stdoutput, segment); - - return ((size + (1 << align) - 1) & (-1 << align)); -} - -/* We don't have any form of relaxing. */ - -int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp; - asection *seg; -{ - abort (); -} - -/* Convert a machine dependent frag. We never generate these. */ - -void -md_convert_frag (abfd, sec, fragp) - bfd *abfd; - asection *sec; - fragS *fragp; -{ - abort (); -} - -/* Parse an operand that is machine-specific. - - The ARC has a special %-op to adjust addresses so they're usable in - branches. The "st" is short for the STatus register. - ??? Later expand this to take a flags value too. - - ??? We can't create new expression types so we map the %-op's onto the - existing syntax. This means that the user could use the chosen syntax - to achieve the same effect. Perhaps put a special cookie in X_add_number - to mark the expression as special. */ - -void -md_operand (expressionP) - expressionS *expressionP; -{ - char *p = input_line_pointer; - - if (*p == '%' && strncmp (p, "%st(", 4) == 0) - { - input_line_pointer += 4; - expression (expressionP); - if (*input_line_pointer != ')') - { - as_bad ("missing ')' in %-op"); - return; - } - ++input_line_pointer; - if (expressionP->X_op == O_symbol - && expressionP->X_add_number == 0 - /* I think this test is unnecessary but just as a sanity check... */ - && expressionP->X_op_symbol == NULL) - { - expressionS two; - - expressionP->X_op = O_right_shift; - two.X_op = O_constant; - two.X_add_symbol = two.X_op_symbol = NULL; - two.X_add_number = 2; - expressionP->X_op_symbol = make_expr_symbol (&two); - } - /* allow %st(sym1-sym2) */ - else if (expressionP->X_op == O_subtract - && expressionP->X_add_symbol != NULL - && expressionP->X_op_symbol != NULL - && 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; - two.X_add_symbol = two.X_op_symbol = NULL; - two.X_add_number = 2; - expressionP->X_op_symbol = make_expr_symbol (&two); - } - else - { - as_bad ("expression too complex for %%st"); - return; - } - } -} - -/* We have no need to default values of symbols. - We could catch register names here, but that is handled by inserting - them all in the symbol table to begin with. */ - -symbolS * -md_undefined_symbol (name) - char *name; -{ - return 0; -} - -/* Functions concerning expressions. */ - -/* Parse a .byte, .word, etc. expression. - - Values for the status register are specified with %st(label). - `label' will be right shifted by 2. */ - -void -arc_parse_cons_expression (exp, nbytes) - expressionS *exp; - int nbytes; -{ - expr (0, exp); -} - -/* Record a fixup for a cons expression. */ - -void -arc_cons_fix_new (frag, where, nbytes, exp) - fragS *frag; - int where; - int nbytes; - expressionS *exp; -{ - if (nbytes == 4) - { - int reloc_type; - expressionS exptmp; - - /* This may be a special ARC reloc (eg: %st()). */ - reloc_type = get_arc_exp_reloc_type (1, BFD_RELOC_32, exp, &exptmp); - fix_new_exp (frag, where, nbytes, &exptmp, 0, reloc_type); - } - else - { - fix_new_exp (frag, where, nbytes, exp, 0, - nbytes == 2 ? BFD_RELOC_16 - : nbytes == 8 ? BFD_RELOC_64 - : BFD_RELOC_32); - } -} - -/* Functions concerning relocs. */ - -/* The location from which a PC relative jump should be calculated, - given a PC relative reloc. */ - -long -md_pcrel_from (fixP) - fixS *fixP; -{ - if (fixP->fx_addsy != (symbolS *) NULL - && ! S_IS_DEFINED (fixP->fx_addsy)) - { - /* The symbol is undefined. Let the linker figure it out. */ - return 0; - } - - /* 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. Similarily 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 - plus the operand index. Here we undo that to recover the operand - index. At this point all symbol values should be fully resolved, - and we attempt to completely resolve the reloc. If we can not do - that, we determine the correct reloc code and put it back in the fixup. */ - -int -md_apply_fix3 (fixP, valueP, seg) - fixS *fixP; - valueT *valueP; - segT seg; -{ - /*char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;*/ - valueT value; - - /* FIXME FIXME FIXME: The value we are passed in *valueP includes - the symbol values. Since we are using BFD_ASSEMBLER, if we are - doing this relocation the code in write.c is going to call - bfd_perform_relocation, which is also going to use the symbol - value. That means that if the reloc is fully resolved we want to - use *valueP since bfd_perform_relocation is not being used. - However, if the reloc is not fully resolved we do not want to use - *valueP, and must use fx_offset instead. However, if the reloc - is PC relative, we do want to use *valueP since it includes the - result of md_pcrel_from. This is confusing. */ - - if (fixP->fx_addsy == (symbolS *) NULL) - { - value = *valueP; - fixP->fx_done = 1; - } - else if (fixP->fx_pcrel) - { - value = *valueP; - /* ELF relocations are against symbols. - If this symbol is in a different section then we need to leave it for - the linker to deal with. Unfortunately, md_pcrel_from can't tell, - so we have to undo it's effects here. */ - if (S_IS_DEFINED (fixP->fx_addsy) - && S_GET_SEGMENT (fixP->fx_addsy) != seg) - value += md_pcrel_from (fixP); - } - else - { - value = fixP->fx_offset; - if (fixP->fx_subsy != (symbolS *) NULL) - { - if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section) - value -= S_GET_VALUE (fixP->fx_subsy); - else - { - /* We can't actually support subtracting a symbol. */ - as_bad_where (fixP->fx_file, fixP->fx_line, - "expression too complex"); - } - } - } - - if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) - { - int opindex; - const struct arc_operand *operand; - char *where; - arc_insn insn; - - opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; - - operand = &arc_operands[opindex]; - - /* Fetch the instruction, insert the fully resolved operand - value, and stuff the instruction back again. */ - where = fixP->fx_frag->fr_literal + fixP->fx_where; - if (target_big_endian) - insn = bfd_getb32 ((unsigned char *) where); - else - insn = bfd_getl32 ((unsigned char *) where); - insn = arc_insert_operand (insn, operand, -1, NULL, (offsetT) value, - fixP->fx_file, fixP->fx_line); - if (target_big_endian) - bfd_putb32 ((bfd_vma) insn, (unsigned char *) where); - else - bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); - - if (fixP->fx_done) - { - /* Nothing else to do here. */ - return 1; - } - - /* Determine a BFD reloc value based on the operand information. - We are only prepared to turn a few of the operands into relocs. - !!! Note that we can't handle limm values here. Since we're using - implicit addends the addend must be inserted into the instruction, - however, the opcode insertion routines currently do nothing with - limm values. */ - if (operand->fmt == 'B') - { - assert ((operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0 - && operand->bits == 20 - && operand->shift == 7); - fixP->fx_r_type = BFD_RELOC_ARC_B22_PCREL; - } - else if (0 && operand->fmt == 'J') - { - assert ((operand->flags & ARC_OPERAND_ABSOLUTE_BRANCH) != 0 - && operand->bits == 24 - && operand->shift == 32); - fixP->fx_r_type = BFD_RELOC_ARC_B26; - } - else if (0 && operand->fmt == 'L') - { - assert ((operand->flags & ARC_OPERAND_LIMM) != 0 - && operand->bits == 32 - && operand->shift == 32); - fixP->fx_r_type = BFD_RELOC_32; - } - else - { - as_bad_where (fixP->fx_file, fixP->fx_line, - "unresolved expression that must be resolved"); - fixP->fx_done = 1; - return 1; - } - } - else - { - switch (fixP->fx_r_type) - { - case BFD_RELOC_8: - md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, - value, 1); - break; - case BFD_RELOC_16: - md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, - value, 2); - break; - case BFD_RELOC_32: - md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, - value, 4); - break; -#if 0 - case BFD_RELOC_64: - md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, - value, 8); - break; -#endif - case BFD_RELOC_ARC_B26: - /* If !fixP->fx_done then `value' is an implicit addend. - We must shift it right by 2 in this case as well because the - linker performs the relocation and then adds this in (as opposed - to adding this in and then shifting right by 2). */ - value >>= 2; - md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, - value, 4); - break; - default: - abort (); - } - } - - fixP->fx_addnumber = value; - - return 1; -} - -/* Translate internal representation of relocation info to BFD target - format. */ - -arelent * -tc_gen_reloc (section, fixP) - asection *section; - fixS *fixP; -{ - arelent *reloc; - - reloc = (arelent *) xmalloc (sizeof (arelent)); - - reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym; - 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, - "internal error: can't export reloc type %d (`%s')", - fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type)); - return NULL; - } - - assert (!fixP->fx_pcrel == !reloc->howto->pc_relative); - - reloc->addend = fixP->fx_addnumber; - - return reloc; -} - -/* Frobbers. */ - -#if 0 -/* Set the real name if the .rename pseudo-op was used. - Return 1 if the symbol should not be included in the symbol table. */ - -int -arc_frob_symbol (sym) - symbolS *sym; -{ - if (sym->sy_tc.real_name != (char *) NULL) - S_SET_NAME (sym, sym->sy_tc.real_name); - - return 0; -} -#endif diff --git a/contrib/binutils/gas/config/tc-arc.h b/contrib/binutils/gas/config/tc-arc.h deleted file mode 100644 index 6a95ff4b614d..000000000000 --- a/contrib/binutils/gas/config/tc-arc.h +++ /dev/null @@ -1,71 +0,0 @@ -/* tc-arc.h - Macros and type defines for the ARC. - Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc. - Contributed by Doug Evans (dje@cygnus.com). - - 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 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. */ - -#define TC_ARC 1 - -#define TARGET_BYTES_BIG_ENDIAN 0 - -#define LOCAL_LABELS_FB 1 - -#define TARGET_ARCH bfd_arch_arc - -#define LITTLE_ENDIAN 1234 -#define BIG_ENDIAN 4321 - -/* 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 - -#define WORKING_DOT_WORD - -#define LISTING_HEADER "ARC GAS " - -#define TC_HANDLES_FX_DONE - -#define MD_APPLY_FIX3 - -/* The ARC needs to parse reloc specifiers in .word. */ - -extern void arc_parse_cons_expression (); -#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ -arc_parse_cons_expression (EXP, NBYTES) - -extern void arc_cons_fix_new (); -#define TC_CONS_FIX_NEW(FRAG, WHERE, NBYTES, EXP) \ -arc_cons_fix_new (FRAG, WHERE, NBYTES, EXP) - -#if 0 -/* Extra stuff that we need to keep track of for each symbol. */ -struct arc_tc_sy -{ - /* The real name, if the symbol was renamed. */ - char *real_name; -}; - -#define TC_SYMFIELD_TYPE struct arc_tc_sy - -/* Finish up the symbol. */ -extern int arc_frob_symbol PARAMS ((struct symbol *)); -#define tc_frob_symbol(sym, punt) punt = arc_frob_symbol (sym) -#endif diff --git a/contrib/binutils/gas/config/tc-generic.c b/contrib/binutils/gas/config/tc-generic.c deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/contrib/binutils/gas/config/tc-generic.c +++ /dev/null diff --git a/contrib/binutils/gas/config/tc-generic.h b/contrib/binutils/gas/config/tc-generic.h deleted file mode 100644 index 72df02031651..000000000000 --- a/contrib/binutils/gas/config/tc-generic.h +++ /dev/null @@ -1,39 +0,0 @@ -/* This file is tc-generic.h - - Copyright (C) 1987, 91, 92, 95, 1997 Free Software Foundation, Inc. - - 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 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. */ - -/* - * This file is tc-generic.h and is intended to be a template for target cpu - * specific header files. It is my intent that this file compile. It is also - * my intent that this file grow into something that can be used as both a - * template for porting, and a stub for testing. xoxorich. - */ - -#define TC_GENERIC 1 - -#define TARGET_BYTES_BIG_ENDIAN 0 - -/* - * Local Variables: - * comment-column: 0 - * fill-column: 131 - * End: - */ - -/* end of tc-generic.h */ diff --git a/contrib/binutils/gas/config/tc-i386.c b/contrib/binutils/gas/config/tc-i386.c deleted file mode 100644 index cc173eceb3e7..000000000000 --- a/contrib/binutils/gas/config/tc-i386.c +++ /dev/null @@ -1,3257 +0,0 @@ -/* i386.c -- Assemble code for the Intel 80386 - Copyright (C) 1989, 91, 92, 93, 94, 95, 96, 97, 1998 - Free Software Foundation. - - 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 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. */ - -/* - Intel 80386 machine specific gas. - Written by Eliot Dresselhaus (eliot@mgm.mit.edu). - Bugs & suggestions are completely welcome. This is free software. - Please help us make it better. - */ - -#include <ctype.h> - -#include "as.h" -#include "subsegs.h" - -#include "obstack.h" -#include "opcode/i386.h" - -#ifndef TC_RELOC -#define TC_RELOC(X,Y) (Y) -#endif - -static unsigned long mode_from_disp_size PARAMS ((unsigned long)); -static int fits_in_signed_byte PARAMS ((long)); -static int fits_in_unsigned_byte PARAMS ((long)); -static int fits_in_unsigned_word PARAMS ((long)); -static int fits_in_signed_word PARAMS ((long)); -static int smallest_imm_type PARAMS ((long)); -static void set_16bit_code_flag PARAMS ((int)); -#ifdef BFD_ASSEMBLER -static bfd_reloc_code_real_type reloc - PARAMS ((int, int, bfd_reloc_code_real_type)); -#endif - -/* 'md_assemble ()' gathers together information and puts it into a - i386_insn. */ - -struct _i386_insn - { - /* TM holds the template for the insn were currently assembling. */ - template tm; - /* SUFFIX holds the opcode suffix (e.g. 'l' for 'movl') if given. */ - char suffix; - /* Operands are coded with OPERANDS, TYPES, DISPS, IMMS, and REGS. */ - - /* OPERANDS gives the number of given operands. */ - unsigned int operands; - - /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number - of given register, displacement, memory operands and immediate - operands. */ - unsigned int reg_operands, disp_operands, mem_operands, imm_operands; - - /* TYPES [i] is the type (see above #defines) which tells us how to - search through DISPS [i] & IMMS [i] & REGS [i] for the required - operand. */ - unsigned int types[MAX_OPERANDS]; - - /* Displacements (if given) for each operand. */ - expressionS *disps[MAX_OPERANDS]; - - /* Relocation type for operand */ -#ifdef BFD_ASSEMBLER - enum bfd_reloc_code_real disp_reloc[MAX_OPERANDS]; -#else - int disp_reloc[MAX_OPERANDS]; -#endif - - /* Immediate operands (if given) for each operand. */ - expressionS *imms[MAX_OPERANDS]; - - /* Register operands (if given) for each operand. */ - reg_entry *regs[MAX_OPERANDS]; - - /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode - the base index byte below. */ - reg_entry *base_reg; - reg_entry *index_reg; - unsigned int log2_scale_factor; - - /* SEG gives the seg_entry of this insn. It is equal to zero unless - an explicit segment override is given. */ - const seg_entry *seg; /* segment for memory operands (if given) */ - - /* PREFIX holds all the given prefix opcodes (usually null). - PREFIXES is the size of PREFIX. */ - /* richfix: really unsigned? */ - unsigned char prefix[MAX_PREFIXES]; - unsigned int prefixes; - - /* RM and BI are the modrm byte and the base index byte where the - addressing modes of this insn are encoded. */ - - modrm_byte rm; - base_index_byte bi; - }; - -typedef struct _i386_insn i386_insn; - -/* This array holds the chars that always start a comment. If the - pre-processor is disabled, these aren't very useful */ -#if defined (TE_I386AIX) || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) -const char comment_chars[] = "#/"; -#else -const char comment_chars[] = "#"; -#endif - -/* 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 */ -/* 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 started like this one will always work if - '/' isn't otherwise defined. */ -#if defined (TE_I386AIX) || defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) -const char line_comment_chars[] = ""; -#else -const char line_comment_chars[] = "/"; -#endif -const char line_separator_chars[] = ""; - -/* 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 */ -const char FLT_CHARS[] = "fFdDxX"; - -/* tables for lexical analysis */ -static char opcode_chars[256]; -static char register_chars[256]; -static char operand_chars[256]; -static char space_chars[256]; -static char identifier_chars[256]; -static char digit_chars[256]; - -/* lexical macros */ -#define is_opcode_char(x) (opcode_chars[(unsigned char) x]) -#define is_operand_char(x) (operand_chars[(unsigned char) x]) -#define is_register_char(x) (register_chars[(unsigned char) x]) -#define is_space_char(x) (space_chars[(unsigned char) x]) -#define is_identifier_char(x) (identifier_chars[(unsigned char) x]) -#define is_digit_char(x) (digit_chars[(unsigned char) x]) - -/* put here all non-digit non-letter charcters that may occur in an operand */ -static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:[@]"; - -static char *ordinal_names[] = {"first", "second", "third"}; /* for printfs */ - -/* md_assemble() always leaves the strings it's passed unaltered. To - effect this we maintain a stack of saved characters that we've smashed - with '\0's (indicating end of strings for various sub-fields of the - assembler instruction). */ -static char save_stack[32]; -static char *save_stack_p; /* stack pointer */ -#define END_STRING_AND_SAVE(s) *save_stack_p++ = *s; *s = '\0' -#define RESTORE_END_STRING(s) *s = *--save_stack_p - -/* The instruction we're assembling. */ -static i386_insn i; - -/* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */ -static expressionS disp_expressions[2], im_expressions[2]; - -/* pointers to ebp & esp entries in reg_hash hash table */ -static reg_entry *ebp, *esp; - -static int this_operand; /* current operand we are working on */ - -static int flag_do_long_jump; /* FIXME what does this do? */ - -static int flag_16bit_code; /* 1 if we're writing 16-bit code, 0 if 32-bit */ - -/* Interface to relax_segment. - There are 2 relax states for 386 jump insns: one for conditional & - one for unconditional jumps. This is because the these two types - of jumps add different sizes to frags when we're figuring out what - sort of jump to choose to reach a given label. */ - -/* types */ -#define COND_JUMP 1 /* conditional jump */ -#define UNCOND_JUMP 2 /* unconditional jump */ -/* sizes */ -#define BYTE 0 -#define WORD 1 -#define DWORD 2 -#define UNKNOWN_SIZE 3 - -#ifndef INLINE -#ifdef __GNUC__ -#define INLINE __inline__ -#else -#define INLINE -#endif -#endif - -#define ENCODE_RELAX_STATE(type,size) \ - ((relax_substateT)((type<<2) | (size))) -#define SIZE_FROM_RELAX_STATE(s) \ - ( (((s) & 0x3) == BYTE ? 1 : (((s) & 0x3) == WORD ? 2 : 4)) ) - -const relax_typeS md_relax_table[] = -{ -/* The fields are: - 1) most positive reach of this state, - 2) most negative reach of this state, - 3) how many bytes this mode will add to the size of the current frag - 4) which index into the table to try if we can't fit into this one. - */ - {1, 1, 0, 0}, - {1, 1, 0, 0}, - {1, 1, 0, 0}, - {1, 1, 0, 0}, - - /* For now we don't use word displacement jumps; they may be - untrustworthy. */ - {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, DWORD)}, - /* word conditionals add 3 bytes to frag: - 2 opcode prefix; 1 displacement bytes */ - {32767 + 2, -32768 + 2, 3, ENCODE_RELAX_STATE (COND_JUMP, DWORD)}, - /* dword conditionals adds 4 bytes to frag: - 1 opcode prefix; 3 displacement bytes */ - {0, 0, 4, 0}, - {1, 1, 0, 0}, - - {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, DWORD)}, - /* word jmp adds 2 bytes to frag: - 1 opcode prefix; 1 displacement bytes */ - {32767 + 2, -32768 + 2, 2, ENCODE_RELAX_STATE (UNCOND_JUMP, DWORD)}, - /* dword jmp adds 3 bytes to frag: - 0 opcode prefix; 3 displacement bytes */ - {0, 0, 3, 0}, - {1, 1, 0, 0}, - -}; - - -void -i386_align_code (fragP, count) - fragS *fragP; - int count; -{ - /* Various efficient no-op patterns for aligning code labels. */ - /* Note: Don't try to assemble the instructions in the comments. */ - /* 0L and 0w are not legal */ - static const char f32_1[] = - {0x90}; /* nop */ - static const char f32_2[] = - {0x89,0xf6}; /* movl %esi,%esi */ - static const char f32_3[] = - {0x8d,0x76,0x00}; /* leal 0(%esi),%esi */ - static const char f32_4[] = - {0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const char f32_5[] = - {0x90, /* nop */ - 0x8d,0x74,0x26,0x00}; /* leal 0(%esi,1),%esi */ - static const char f32_6[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00}; /* leal 0L(%esi),%esi */ - static const char f32_7[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const char f32_8[] = - {0x90, /* nop */ - 0x8d,0xb4,0x26,0x00,0x00,0x00,0x00}; /* leal 0L(%esi,1),%esi */ - static const char f32_9[] = - {0x89,0xf6, /* movl %esi,%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_10[] = - {0x8d,0x76,0x00, /* leal 0(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_11[] = - {0x8d,0x74,0x26,0x00, /* leal 0(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_12[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbf,0x00,0x00,0x00,0x00}; /* leal 0L(%edi),%edi */ - static const char f32_13[] = - {0x8d,0xb6,0x00,0x00,0x00,0x00, /* leal 0L(%esi),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_14[] = - {0x8d,0xb4,0x26,0x00,0x00,0x00,0x00, /* leal 0L(%esi,1),%esi */ - 0x8d,0xbc,0x27,0x00,0x00,0x00,0x00}; /* leal 0L(%edi,1),%edi */ - static const char f32_15[] = - {0xeb,0x0d,0x90,0x90,0x90,0x90,0x90, /* jmp .+15; lotsa nops */ - 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90}; - static const char f16_4[] = - {0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const char f16_5[] = - {0x90, /* nop */ - 0x8d,0xb4,0x00,0x00}; /* lea 0w(%si),%si */ - static const char f16_6[] = - {0x89,0xf6, /* mov %si,%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char f16_7[] = - {0x8d,0x74,0x00, /* lea 0(%si),%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char f16_8[] = - {0x8d,0xb4,0x00,0x00, /* lea 0w(%si),%si */ - 0x8d,0xbd,0x00,0x00}; /* lea 0w(%di),%di */ - static const char *const f32_patt[] = { - f32_1, f32_2, f32_3, f32_4, f32_5, f32_6, f32_7, f32_8, - f32_9, f32_10, f32_11, f32_12, f32_13, f32_14, f32_15 - }; - static const char *const f16_patt[] = { - f32_1, f32_2, f32_3, f16_4, f16_5, f16_6, f16_7, f16_8, - f32_15, f32_15, f32_15, f32_15, f32_15, f32_15, f32_15 - }; - - if (count > 0 && count <= 15) - { - if (flag_16bit_code) - { - memcpy(fragP->fr_literal + fragP->fr_fix, - f16_patt[count - 1], count); - if (count > 8) /* adjust jump offset */ - fragP->fr_literal[fragP->fr_fix + 1] = count - 2; - } - else - memcpy(fragP->fr_literal + fragP->fr_fix, - f32_patt[count - 1], count); - fragP->fr_var = count; - } -} - -static char *output_invalid PARAMS ((int c)); -static int i386_operand PARAMS ((char *operand_string)); -static reg_entry *parse_register PARAMS ((char *reg_string)); -#ifndef I386COFF -static void s_bss PARAMS ((int)); -#endif - -symbolS *GOT_symbol; /* Pre-defined "__GLOBAL_OFFSET_TABLE" */ - -static INLINE unsigned long -mode_from_disp_size (t) - unsigned long t; -{ - return (t & Disp8) ? 1 : (t & Disp32) ? 2 : 0; -} - -#if 0 -/* Not used. */ -/* convert opcode suffix ('b' 'w' 'l' typically) into type specifier */ - -static INLINE unsigned long -opcode_suffix_to_type (s) - unsigned long s; -{ - return (s == BYTE_OPCODE_SUFFIX - ? Byte : (s == WORD_OPCODE_SUFFIX - ? Word : DWord)); -} /* opcode_suffix_to_type() */ -#endif - -static INLINE int -fits_in_signed_byte (num) - long num; -{ - return (num >= -128) && (num <= 127); -} /* fits_in_signed_byte() */ - -static INLINE int -fits_in_unsigned_byte (num) - long num; -{ - return (num & 0xff) == num; -} /* fits_in_unsigned_byte() */ - -static INLINE int -fits_in_unsigned_word (num) - long num; -{ - return (num & 0xffff) == num; -} /* fits_in_unsigned_word() */ - -static INLINE int -fits_in_signed_word (num) - long num; -{ - return (-32768 <= num) && (num <= 32767); -} /* fits_in_signed_word() */ - -static int -smallest_imm_type (num) - long num; -{ -#if 0 - /* This code is disabled because all the Imm1 forms in the opcode table - are slower on the i486, and they're the versions with the implicitly - specified single-position displacement, which has another syntax if - you really want to use that form. If you really prefer to have the - one-byte-shorter Imm1 form despite these problems, re-enable this - code. */ - if (num == 1) - return Imm1 | Imm8 | Imm8S | Imm16 | Imm32; -#endif - return (fits_in_signed_byte (num) - ? (Imm8S | Imm8 | Imm16 | Imm32) - : fits_in_unsigned_byte (num) - ? (Imm8 | Imm16 | Imm32) - : (fits_in_signed_word (num) || fits_in_unsigned_word (num)) - ? (Imm16 | Imm32) - : (Imm32)); -} /* smallest_imm_type() */ - -static void -set_16bit_code_flag (new_16bit_code_flag) - int new_16bit_code_flag; -{ - flag_16bit_code = new_16bit_code_flag; -} - -const pseudo_typeS md_pseudo_table[] = -{ -#ifndef I386COFF - {"bss", s_bss, 0}, -#endif -#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO) - {"align", s_align_bytes, 0}, -#else - {"align", s_align_ptwo, 0}, -#endif - {"ffloat", float_cons, 'f'}, - {"dfloat", float_cons, 'd'}, - {"tfloat", float_cons, 'x'}, - {"value", cons, 2}, - {"noopt", s_ignore, 0}, - {"optim", s_ignore, 0}, - {"code16", set_16bit_code_flag, 1}, - {"code32", set_16bit_code_flag, 0}, - {0, 0, 0} -}; - -/* for interface with expression () */ -extern char *input_line_pointer; - -/* obstack for constructing various things in md_begin */ -struct obstack o; - -/* hash table for opcode lookup */ -static struct hash_control *op_hash; -/* hash table for register lookup */ -static struct hash_control *reg_hash; -/* hash table for prefix lookup */ -static struct hash_control *prefix_hash; - - -void -md_begin () -{ - const char *hash_err; - - obstack_begin (&o, 4096); - - /* initialize op_hash hash table */ - op_hash = hash_new (); - - { - register const template *optab; - register templates *core_optab; - char *prev_name; - - optab = i386_optab; /* setup for loop */ - prev_name = optab->name; - obstack_grow (&o, optab, sizeof (template)); - core_optab = (templates *) xmalloc (sizeof (templates)); - - for (optab++; optab < i386_optab_end; optab++) - { - if (!strcmp (optab->name, prev_name)) - { - /* same name as before --> append to current template list */ - obstack_grow (&o, optab, sizeof (template)); - } - else - { - /* different name --> ship out current template list; - add to hash table; & begin anew */ - /* Note: end must be set before start! since obstack_next_free - changes upon opstack_finish */ - core_optab->end = (template *) obstack_next_free (&o); - core_optab->start = (template *) obstack_finish (&o); - hash_err = hash_insert (op_hash, prev_name, (char *) core_optab); - if (hash_err) - { - hash_error: - as_fatal ("Internal Error: Can't hash %s: %s", prev_name, - hash_err); - } - prev_name = optab->name; - core_optab = (templates *) xmalloc (sizeof (templates)); - obstack_grow (&o, optab, sizeof (template)); - } - } - } - - /* initialize reg_hash hash table */ - reg_hash = hash_new (); - { - register const reg_entry *regtab; - - for (regtab = i386_regtab; regtab < i386_regtab_end; regtab++) - { - hash_err = hash_insert (reg_hash, regtab->reg_name, (PTR) regtab); - if (hash_err) - goto hash_error; - } - } - - esp = (reg_entry *) hash_find (reg_hash, "esp"); - ebp = (reg_entry *) hash_find (reg_hash, "ebp"); - - /* initialize reg_hash hash table */ - prefix_hash = hash_new (); - { - register const prefix_entry *prefixtab; - - for (prefixtab = i386_prefixtab; - prefixtab < i386_prefixtab_end; prefixtab++) - { - hash_err = hash_insert (prefix_hash, prefixtab->prefix_name, - (PTR) prefixtab); - if (hash_err) - goto hash_error; - } - } - - /* fill in lexical tables: opcode_chars, operand_chars, space_chars */ - { - register int c; - register char *p; - - for (c = 0; c < 256; c++) - { - if (islower (c) || isdigit (c)) - { - opcode_chars[c] = c; - register_chars[c] = c; - } - else if (isupper (c)) - { - opcode_chars[c] = tolower (c); - register_chars[c] = opcode_chars[c]; - } - else if (c == PREFIX_SEPERATOR) - { - opcode_chars[c] = c; - } - else if (c == ')' || c == '(') - { - register_chars[c] = c; - } - - if (isupper (c) || islower (c) || isdigit (c)) - operand_chars[c] = c; - - if (isdigit (c) || c == '-') - digit_chars[c] = c; - - if (isalpha (c) || c == '_' || c == '.' || isdigit (c)) - identifier_chars[c] = c; - -#ifdef LEX_AT - identifier_chars['@'] = '@'; -#endif - - if (c == ' ' || c == '\t') - space_chars[c] = c; - } - - for (p = operand_special_chars; *p != '\0'; p++) - operand_chars[(unsigned char) *p] = *p; - } - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (OUTPUT_FLAVOR == bfd_target_elf_flavour) - { - record_alignment (text_section, 2); - record_alignment (data_section, 2); - record_alignment (bss_section, 2); - } -#endif -} - -void -i386_print_statistics (file) - FILE *file; -{ - hash_print_statistics (file, "i386 opcode", op_hash); - hash_print_statistics (file, "i386 register", reg_hash); - hash_print_statistics (file, "i386 prefix", prefix_hash); -} - - -#ifdef DEBUG386 - -/* debugging routines for md_assemble */ -static void pi PARAMS ((char *, i386_insn *)); -static void pte PARAMS ((template *)); -static void pt PARAMS ((unsigned int)); -static void pe PARAMS ((expressionS *)); -static void ps PARAMS ((symbolS *)); - -static void -pi (line, x) - char *line; - i386_insn *x; -{ - register template *p; - int i; - - fprintf (stdout, "%s: template ", line); - pte (&x->tm); - fprintf (stdout, " modrm: mode %x reg %x reg/mem %x", - x->rm.mode, x->rm.reg, x->rm.regmem); - fprintf (stdout, " base %x index %x scale %x\n", - x->bi.base, x->bi.index, x->bi.scale); - for (i = 0; i < x->operands; i++) - { - fprintf (stdout, " #%d: ", i + 1); - pt (x->types[i]); - fprintf (stdout, "\n"); - if (x->types[i] - & (Reg | SReg2 | SReg3 | Control | Debug | Test | RegMMX)) - fprintf (stdout, "%s\n", x->regs[i]->reg_name); - if (x->types[i] & Imm) - pe (x->imms[i]); - if (x->types[i] & (Disp | Abs)) - pe (x->disps[i]); - } -} - -static void -pte (t) - template *t; -{ - int i; - fprintf (stdout, " %d operands ", t->operands); - fprintf (stdout, "opcode %x ", - t->base_opcode); - if (t->extension_opcode != None) - fprintf (stdout, "ext %x ", t->extension_opcode); - if (t->opcode_modifier & D) - fprintf (stdout, "D"); - if (t->opcode_modifier & W) - fprintf (stdout, "W"); - fprintf (stdout, "\n"); - for (i = 0; i < t->operands; i++) - { - fprintf (stdout, " #%d type ", i + 1); - pt (t->operand_types[i]); - fprintf (stdout, "\n"); - } -} - -static void -pe (e) - expressionS *e; -{ - fprintf (stdout, " operation %d\n", e->X_op); - fprintf (stdout, " add_number %d (%x)\n", - e->X_add_number, e->X_add_number); - if (e->X_add_symbol) - { - fprintf (stdout, " add_symbol "); - ps (e->X_add_symbol); - fprintf (stdout, "\n"); - } - if (e->X_op_symbol) - { - fprintf (stdout, " op_symbol "); - ps (e->X_op_symbol); - fprintf (stdout, "\n"); - } -} - -static void -ps (s) - symbolS *s; -{ - fprintf (stdout, "%s type %s%s", - S_GET_NAME (s), - S_IS_EXTERNAL (s) ? "EXTERNAL " : "", - segment_name (S_GET_SEGMENT (s))); -} - -struct type_name - { - unsigned int mask; - char *tname; - } - -type_names[] = -{ - { Reg8, "r8" }, - { Reg16, "r16" }, - { Reg32, "r32" }, - { Imm8, "i8" }, - { Imm8S, "i8s" }, - { Imm16, "i16" }, - { Imm32, "i32" }, - { Mem8, "Mem8" }, - { Mem16, "Mem16" }, - { Mem32, "Mem32" }, - { BaseIndex, "BaseIndex" }, - { Abs8, "Abs8" }, - { Abs16, "Abs16" }, - { Abs32, "Abs32" }, - { Disp8, "d8" }, - { Disp16, "d16" }, - { Disp32, "d32" }, - { SReg2, "SReg2" }, - { SReg3, "SReg3" }, - { Acc, "Acc" }, - { InOutPortReg, "InOutPortReg" }, - { ShiftCount, "ShiftCount" }, - { Imm1, "i1" }, - { Control, "control reg" }, - { Test, "test reg" }, - { FloatReg, "FReg" }, - { FloatAcc, "FAcc" }, - { JumpAbsolute, "Jump Absolute" }, - { RegMMX, "rMMX" }, - { 0, "" } -}; - -static void -pt (t) - unsigned int t; -{ - register struct type_name *ty; - - if (t == Unknown) - { - fprintf (stdout, "Unknown"); - } - else - { - for (ty = type_names; ty->mask; ty++) - if (t & ty->mask) - fprintf (stdout, "%s, ", ty->tname); - } - fflush (stdout); -} - -#endif /* DEBUG386 */ - -#ifdef BFD_ASSEMBLER -static bfd_reloc_code_real_type -reloc (size, pcrel, other) - int size; - int pcrel; - bfd_reloc_code_real_type other; -{ - if (other != NO_RELOC) return other; - - if (pcrel) - switch (size) - { - case 1: return BFD_RELOC_8_PCREL; - case 2: return BFD_RELOC_16_PCREL; - case 4: return BFD_RELOC_32_PCREL; - } - else - switch (size) - { - case 1: return BFD_RELOC_8; - case 2: return BFD_RELOC_16; - case 4: return BFD_RELOC_32; - } - - as_bad ("Can not do %d byte %srelocation", size, - pcrel ? "pc-relative " : ""); - return BFD_RELOC_NONE; -} - -/* - * Here we decide which fixups can be adjusted to make them relative to - * the beginning of the section instead of the symbol. Basically we need - * to make sure that the dynamic relocations are done correctly, so in - * some cases we force the original symbol to be used. - */ -int -tc_i386_fix_adjustable(fixP) - fixS * fixP; -{ -#ifdef OBJ_ELF - /* Prevent all adjustments to global symbols. */ - if (S_IS_EXTERN (fixP->fx_addsy)) - return 0; - if (S_IS_WEAK (fixP->fx_addsy)) - return 0; -#endif /* ! defined (OBJ_AOUT) */ - /* adjust_reloc_syms doesn't know about the GOT */ - if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF - || fixP->fx_r_type == BFD_RELOC_386_PLT32 - || fixP->fx_r_type == BFD_RELOC_386_GOT32) - return 0; - return 1; -} -#else -#define reloc(SIZE,PCREL,OTHER) 0 -#define BFD_RELOC_32 0 -#define BFD_RELOC_32_PCREL 0 -#define BFD_RELOC_386_PLT32 0 -#define BFD_RELOC_386_GOT32 0 -#define BFD_RELOC_386_GOTOFF 0 -#endif - -/* This is the guts of the machine-dependent assembler. LINE points to a - machine dependent instruction. This function is supposed to emit - the frags/bytes it assembles to. */ - -void -md_assemble (line) - char *line; -{ - /* Points to template once we've found it. */ - const template *t; - - /* Count the size of the instruction generated. */ - int insn_size = 0; - - /* Possible templates for current insn */ - templates *current_templates = (templates *) 0; - - int j; - - /* Wait prefix needs to come before any other prefixes, so handle it - specially. wait_prefix will hold the opcode modifier flag FWait - if a wait prefix is given. */ - int wait_prefix = 0; - - /* Initialize globals. */ - memset (&i, '\0', sizeof (i)); - for (j = 0; j < MAX_OPERANDS; j++) - i.disp_reloc[j] = NO_RELOC; - memset (disp_expressions, '\0', sizeof (disp_expressions)); - memset (im_expressions, '\0', sizeof (im_expressions)); - save_stack_p = save_stack; /* reset stack pointer */ - - /* First parse an opcode & call i386_operand for the operands. - We assume that the scrubber has arranged it so that line[0] is the valid - start of a (possibly prefixed) opcode. */ - { - char *l = line; - - /* 1 if operand is pending after ','. */ - unsigned int expecting_operand = 0; - /* 1 if we found a prefix only acceptable with string insns. */ - unsigned int expecting_string_instruction = 0; - /* Non-zero if operand parens not balanced. */ - unsigned int paren_not_balanced; - char *token_start = l; - - while (!is_space_char (*l) && *l != END_OF_INSN) - { - if (!is_opcode_char (*l)) - { - as_bad ("invalid character %s in opcode", output_invalid (*l)); - return; - } - else if (*l != PREFIX_SEPERATOR) - { - *l = opcode_chars[(unsigned char) *l]; /* fold case of opcodes */ - l++; - } - else - { - /* This opcode's got a prefix. */ - unsigned int q; - prefix_entry *prefix; - - if (l == token_start) - { - as_bad ("expecting prefix; got nothing"); - return; - } - END_STRING_AND_SAVE (l); - prefix = (prefix_entry *) hash_find (prefix_hash, token_start); - if (!prefix) - { - as_bad ("no such opcode prefix ('%s')", token_start); - return; - } - RESTORE_END_STRING (l); - /* check for repeated prefix */ - for (q = 0; q < i.prefixes; q++) - if (i.prefix[q] == prefix->prefix_code) - { - as_bad ("same prefix used twice; you don't really want this!"); - return; - } - if (prefix->prefix_code == FWAIT_OPCODE) - { - if (wait_prefix != 0) - { - as_bad ("same prefix used twice; you don't really want this!"); - return; - } - wait_prefix = FWait; - } - else - { - if (i.prefixes == MAX_PREFIXES) - { - as_bad ("too many opcode prefixes"); - return; - } - i.prefix[i.prefixes++] = prefix->prefix_code; - if (prefix->prefix_code == REPE - || prefix->prefix_code == REPNE) - expecting_string_instruction = 1; - } - /* skip past PREFIX_SEPERATOR and reset token_start */ - token_start = ++l; - } - } - END_STRING_AND_SAVE (l); - if (token_start == l) - { - as_bad ("expecting opcode; got nothing"); - return; - } - - /* Lookup insn in hash; try intel & att naming conventions if appropriate; - that is: we only use the opcode suffix 'b' 'w' or 'l' if we need to. */ - current_templates = (templates *) hash_find (op_hash, token_start); - if (!current_templates) - { - int last_index = strlen (token_start) - 1; - char last_char = token_start[last_index]; - switch (last_char) - { - case DWORD_OPCODE_SUFFIX: - case WORD_OPCODE_SUFFIX: - case BYTE_OPCODE_SUFFIX: - token_start[last_index] = '\0'; - current_templates = (templates *) hash_find (op_hash, token_start); - token_start[last_index] = last_char; - i.suffix = last_char; - } - if (!current_templates) - { - as_bad ("no such 386 instruction: `%s'", token_start); - return; - } - } - RESTORE_END_STRING (l); - - /* check for rep/repne without a string instruction */ - if (expecting_string_instruction && - !IS_STRING_INSTRUCTION (current_templates-> - start->base_opcode)) - { - as_bad ("expecting string instruction after rep/repne"); - return; - } - - /* There may be operands to parse. */ - if (*l != END_OF_INSN && - /* For string instructions, we ignore any operands if given. This - kludges, for example, 'rep/movsb %ds:(%esi), %es:(%edi)' where - the operands are always going to be the same, and are not really - encoded in machine code. */ - !IS_STRING_INSTRUCTION (current_templates-> - start->base_opcode)) - { - /* parse operands */ - do - { - /* skip optional white space before operand */ - while (!is_operand_char (*l) && *l != END_OF_INSN) - { - if (!is_space_char (*l)) - { - as_bad ("invalid character %s before %s operand", - output_invalid (*l), - ordinal_names[i.operands]); - return; - } - l++; - } - token_start = l; /* after white space */ - paren_not_balanced = 0; - while (paren_not_balanced || *l != ',') - { - if (*l == END_OF_INSN) - { - if (paren_not_balanced) - { - as_bad ("unbalanced parenthesis in %s operand.", - ordinal_names[i.operands]); - return; - } - else - break; /* we are done */ - } - else if (!is_operand_char (*l) && !is_space_char (*l)) - { - as_bad ("invalid character %s in %s operand", - output_invalid (*l), - ordinal_names[i.operands]); - return; - } - if (*l == '(') - ++paren_not_balanced; - if (*l == ')') - --paren_not_balanced; - l++; - } - if (l != token_start) - { /* yes, we've read in another operand */ - unsigned int operand_ok; - this_operand = i.operands++; - if (i.operands > MAX_OPERANDS) - { - as_bad ("spurious operands; (%d operands/instruction max)", - MAX_OPERANDS); - return; - } - /* now parse operand adding info to 'i' as we go along */ - END_STRING_AND_SAVE (l); - operand_ok = i386_operand (token_start); - RESTORE_END_STRING (l); /* restore old contents */ - if (!operand_ok) - return; - } - else - { - if (expecting_operand) - { - expecting_operand_after_comma: - as_bad ("expecting operand after ','; got nothing"); - return; - } - if (*l == ',') - { - as_bad ("expecting operand before ','; got nothing"); - return; - } - } - - /* now *l must be either ',' or END_OF_INSN */ - if (*l == ',') - { - if (*++l == END_OF_INSN) - { /* just skip it, if it's \n complain */ - goto expecting_operand_after_comma; - } - expecting_operand = 1; - } - } - while (*l != END_OF_INSN); /* until we get end of insn */ - } - } - - /* Now we've parsed the opcode into a set of templates, and have the - operands at hand. - - Next, we find a template that matches the given insn, - making sure the overlap of the given operands types is consistent - with the template operand types. */ - -#define MATCH(overlap,given_type) \ - (overlap && \ - (((overlap & (JumpAbsolute|BaseIndex|Mem8)) \ - == (given_type & (JumpAbsolute|BaseIndex|Mem8))) \ - || (overlap == InOutPortReg))) - - - /* If m0 and m1 are register matches they must be consistent - with the expected operand types t0 and t1. - That is, if both m0 & m1 are register matches - i.e. ( ((m0 & (Reg)) && (m1 & (Reg)) ) ? - then, either 1. or 2. must be true: - 1. the expected operand type register overlap is null: - (t0 & t1 & Reg) == 0 - AND - the given register overlap is null: - (m0 & m1 & Reg) == 0 - 2. the expected operand type register overlap == the given - operand type overlap: (t0 & t1 & m0 & m1 & Reg). - */ -#define CONSISTENT_REGISTER_MATCH(m0, m1, t0, t1) \ - ( ((m0 & (Reg)) && (m1 & (Reg))) ? \ - ( ((t0 & t1 & (Reg)) == 0 && (m0 & m1 & (Reg)) == 0) || \ - ((t0 & t1) & (m0 & m1) & (Reg)) \ - ) : 1) - { - register unsigned int overlap0, overlap1; - expressionS *exp; - unsigned int overlap2; - unsigned int found_reverse_match; - - overlap0 = overlap1 = overlap2 = found_reverse_match = 0; - for (t = current_templates->start; - t < current_templates->end; - t++) - { - /* must have right number of operands */ - if (i.operands != t->operands) - continue; - else if (!t->operands) - break; /* 0 operands always matches */ - - overlap0 = i.types[0] & t->operand_types[0]; - switch (t->operands) - { - case 1: - if (!MATCH (overlap0, i.types[0])) - continue; - break; - case 2: - case 3: - overlap1 = i.types[1] & t->operand_types[1]; - if (!MATCH (overlap0, i.types[0]) || - !MATCH (overlap1, i.types[1]) || - !CONSISTENT_REGISTER_MATCH (overlap0, overlap1, - t->operand_types[0], - t->operand_types[1])) - { - - /* check if other direction is valid ... */ - if (!(t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS)) - continue; - - /* try reversing direction of operands */ - overlap0 = i.types[0] & t->operand_types[1]; - overlap1 = i.types[1] & t->operand_types[0]; - if (!MATCH (overlap0, i.types[0]) || - !MATCH (overlap1, i.types[1]) || - !CONSISTENT_REGISTER_MATCH (overlap0, overlap1, - t->operand_types[1], - t->operand_types[0])) - { - /* does not match either direction */ - continue; - } - /* found a reverse match here -- slip through */ - /* found_reverse_match holds which of D or FloatD we've found */ - found_reverse_match = t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS; - } /* endif: not forward match */ - /* found either forward/reverse 2 operand match here */ - if (t->operands == 3) - { - overlap2 = i.types[2] & t->operand_types[2]; - if (!MATCH (overlap2, i.types[2]) || - !CONSISTENT_REGISTER_MATCH (overlap0, overlap2, - t->operand_types[0], - t->operand_types[2]) || - !CONSISTENT_REGISTER_MATCH (overlap1, overlap2, - t->operand_types[1], - t->operand_types[2])) - continue; - } - /* found either forward/reverse 2 or 3 operand match here: - slip through to break */ - } - break; /* we've found a match; break out of loop */ - } /* for (t = ... */ - if (t == current_templates->end) - { /* we found no match */ - as_bad ("operands given don't match any known 386 instruction"); - return; - } - - /* Copy the template we found. */ - i.tm = *t; - i.tm.opcode_modifier |= wait_prefix; - - if (found_reverse_match) - { - i.tm.operand_types[0] = t->operand_types[1]; - i.tm.operand_types[1] = t->operand_types[0]; - } - - /* If the matched instruction specifies an explicit opcode suffix, - use it - and make sure none has already been specified. */ - if (i.tm.opcode_modifier & (Data16|Data32)) - { - if (i.suffix) - { - as_bad ("extraneous opcode suffix given"); - return; - } - if (i.tm.opcode_modifier & Data16) - i.suffix = WORD_OPCODE_SUFFIX; - else - i.suffix = DWORD_OPCODE_SUFFIX; - } - - /* If there's no opcode suffix we try to invent one based on register - operands. */ - if (!i.suffix && i.reg_operands) - { - /* We take i.suffix from the LAST register operand specified. This - assumes that the last register operands is the destination register - operand. */ - int op; - for (op = 0; op < MAX_OPERANDS; op++) - if (i.types[op] & Reg) - { - i.suffix = ((i.types[op] & Reg8) ? BYTE_OPCODE_SUFFIX : - (i.types[op] & Reg16) ? WORD_OPCODE_SUFFIX : - DWORD_OPCODE_SUFFIX); - } - } - else if (i.suffix != 0 - && i.reg_operands != 0 - && (i.types[i.operands - 1] & Reg) != 0) - { - int bad; - - /* If the last operand is a register, make sure it is - compatible with the suffix. */ - - bad = 0; - switch (i.suffix) - { - default: - abort (); - case BYTE_OPCODE_SUFFIX: - /* If this is an eight bit register, it's OK. If it's the - 16 or 32 bit version of an eight bit register, we will - just use the low portion, and that's OK too. */ - if ((i.types[i.operands - 1] & Reg8) == 0 - && i.regs[i.operands - 1]->reg_num >= 4) - bad = 1; - break; - case WORD_OPCODE_SUFFIX: - case DWORD_OPCODE_SUFFIX: - /* We don't insist on the presence or absence of the e - prefix on the register, but we reject eight bit - registers. */ - if ((i.types[i.operands - 1] & Reg8) != 0) - bad = 1; - } - if (bad) - as_bad ("register does not match opcode suffix"); - } - - /* Make still unresolved immediate matches conform to size of immediate - given in i.suffix. Note: overlap2 cannot be an immediate! - We assume this. */ - if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32)) - && overlap0 != Imm8 && overlap0 != Imm8S - && overlap0 != Imm16 && overlap0 != Imm32) - { - if (!i.suffix) - { - as_bad ("no opcode suffix given; can't determine immediate size"); - return; - } - overlap0 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8 | Imm8S) : - (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32)); - } - if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32)) - && overlap1 != Imm8 && overlap1 != Imm8S - && overlap1 != Imm16 && overlap1 != Imm32) - { - if (!i.suffix) - { - as_bad ("no opcode suffix given; can't determine immediate size"); - return; - } - overlap1 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8 | Imm8S) : - (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32)); - } - - i.types[0] = overlap0; - i.types[1] = overlap1; - i.types[2] = overlap2; - - if (overlap0 & ImplicitRegister) - i.reg_operands--; - if (overlap1 & ImplicitRegister) - i.reg_operands--; - if (overlap2 & ImplicitRegister) - i.reg_operands--; - if (overlap0 & Imm1) - i.imm_operands = 0; /* kludge for shift insns */ - - /* Finalize opcode. First, we change the opcode based on the operand - size given by i.suffix: we never have to change things for byte insns, - or when no opcode suffix is need to size the operands. */ - - if (!i.suffix && (i.tm.opcode_modifier & W)) - { - as_bad ("no opcode suffix given and no register operands; can't size instruction"); - return; - } - - if (i.suffix && i.suffix != BYTE_OPCODE_SUFFIX) - { - /* Select between byte and word/dword operations. */ - if (i.tm.opcode_modifier & W) - i.tm.base_opcode |= W; - /* Now select between word & dword operations via the - operand size prefix. */ - if ((i.suffix == WORD_OPCODE_SUFFIX) ^ flag_16bit_code) - { - if (i.prefixes == MAX_PREFIXES) - { - as_bad ("%d prefixes given and data size prefix gives too many prefixes", - MAX_PREFIXES); - return; - } - i.prefix[i.prefixes++] = WORD_PREFIX_OPCODE; - } - } - - /* For insns with operands there are more diddles to do to the opcode. */ - if (i.operands) - { - /* Default segment register this instruction will use - for memory accesses. 0 means unknown. - This is only for optimizing out unnecessary segment overrides. */ - const seg_entry *default_seg = 0; - - /* True if this instruction uses a memory addressing mode, - and therefore may need an address-size prefix. */ - int uses_mem_addrmode = 0; - - - /* If we found a reverse match we must alter the opcode direction bit - found_reverse_match holds bit to set (different for int & - float insns). */ - - if (found_reverse_match) - { - i.tm.base_opcode |= found_reverse_match; - } - - /* The imul $imm, %reg instruction is converted into - imul $imm, %reg, %reg. */ - if (i.tm.opcode_modifier & imulKludge) - { - /* Pretend we saw the 3 operand case. */ - i.regs[2] = i.regs[1]; - i.reg_operands = 2; - } - - /* The clr %reg instruction is converted into xor %reg, %reg. */ - if (i.tm.opcode_modifier & iclrKludge) - { - i.regs[1] = i.regs[0]; - i.reg_operands = 2; - } - - /* Certain instructions expect the destination to be in the i.rm.reg - field. This is by far the exceptional case. For these - instructions, if the source operand is a register, we must reverse - the i.rm.reg and i.rm.regmem fields. We accomplish this by faking - that the two register operands were given in the reverse order. */ - if ((i.tm.opcode_modifier & ReverseRegRegmem) && i.reg_operands == 2) - { - unsigned int first_reg_operand = (i.types[0] & Reg) ? 0 : 1; - unsigned int second_reg_operand = first_reg_operand + 1; - reg_entry *tmp = i.regs[first_reg_operand]; - i.regs[first_reg_operand] = i.regs[second_reg_operand]; - i.regs[second_reg_operand] = tmp; - } - - if (i.tm.opcode_modifier & ShortForm) - { - /* The register or float register operand is in operand 0 or 1. */ - unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1; - /* Register goes in low 3 bits of opcode. */ - i.tm.base_opcode |= i.regs[op]->reg_num; - } - else if (i.tm.opcode_modifier & ShortFormW) - { - /* Short form with 0x8 width bit. Register is always dest. operand */ - i.tm.base_opcode |= i.regs[1]->reg_num; - if (i.suffix == WORD_OPCODE_SUFFIX || - i.suffix == DWORD_OPCODE_SUFFIX) - i.tm.base_opcode |= 0x8; - } - else if (i.tm.opcode_modifier & Seg2ShortForm) - { - if (i.tm.base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1) - { - as_bad ("you can't 'pop cs' on the 386."); - return; - } - i.tm.base_opcode |= (i.regs[0]->reg_num << 3); - } - else if (i.tm.opcode_modifier & Seg3ShortForm) - { - /* 'push %fs' is 0x0fa0; 'pop %fs' is 0x0fa1. - 'push %gs' is 0x0fa8; 'pop %fs' is 0x0fa9. - So, only if i.regs[0]->reg_num == 5 (%gs) do we need - to change the opcode. */ - if (i.regs[0]->reg_num == 5) - i.tm.base_opcode |= 0x08; - } - else if ((i.tm.base_opcode & ~DW) == MOV_AX_DISP32) - { - /* This is a special non-modrm instruction - that addresses memory with a 32-bit displacement mode anyway, - and thus requires an address-size prefix if in 16-bit mode. */ - uses_mem_addrmode = 1; - default_seg = &ds; - } - else if (i.tm.opcode_modifier & Modrm) - { - /* The opcode is completed (modulo i.tm.extension_opcode which - must be put into the modrm byte). - Now, we make the modrm & index base bytes based on all the - info we've collected. */ - - /* i.reg_operands MUST be the number of real register operands; - implicit registers do not count. */ - if (i.reg_operands == 2) - { - unsigned int source, dest; - source = ((i.types[0] - & (Reg - | SReg2 - | SReg3 - | Control - | Debug - | Test - | RegMMX)) - ? 0 : 1); - dest = source + 1; - i.rm.mode = 3; - /* We must be careful to make sure that all - segment/control/test/debug/MMX registers go into - the i.rm.reg field (despite the whether they are - source or destination operands). */ - if (i.regs[dest]->reg_type - & (SReg2 | SReg3 | Control | Debug | Test | RegMMX)) - { - i.rm.reg = i.regs[dest]->reg_num; - i.rm.regmem = i.regs[source]->reg_num; - } - else - { - i.rm.reg = i.regs[source]->reg_num; - i.rm.regmem = i.regs[dest]->reg_num; - } - } - else - { /* if it's not 2 reg operands... */ - if (i.mem_operands) - { - unsigned int fake_zero_displacement = 0; - unsigned int op = (i.types[0] & Mem) ? 0 : ((i.types[1] & Mem) ? 1 : 2); - - /* Encode memory operand into modrm byte and base index - byte. */ - - if (i.base_reg == esp && !i.index_reg) - { - /* <disp>(%esp) becomes two byte modrm with no index - register. */ - i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - i.rm.mode = mode_from_disp_size (i.types[op]); - i.bi.base = ESP_REG_NUM; - i.bi.index = NO_INDEX_REGISTER; - i.bi.scale = 0; /* Must be zero! */ - } - else if (i.base_reg == ebp && !i.index_reg) - { - if (!(i.types[op] & Disp)) - { - /* Must fake a zero byte displacement. There is - no direct way to code '(%ebp)' directly. */ - fake_zero_displacement = 1; - /* fake_zero_displacement code does not set this. */ - i.types[op] |= Disp8; - } - i.rm.mode = mode_from_disp_size (i.types[op]); - i.rm.regmem = EBP_REG_NUM; - } - else if (!i.base_reg && (i.types[op] & BaseIndex)) - { - /* There are three cases here. - Case 1: '<32bit disp>(,1)' -- indirect absolute. - (Same as cases 2 & 3 with NO index register) - Case 2: <32bit disp> (,<index>) -- no base register with disp - Case 3: (, <index>) --- no base register; - no disp (must add 32bit 0 disp). */ - i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - i.rm.mode = 0; /* 32bit mode */ - i.bi.base = NO_BASE_REGISTER; - i.types[op] &= ~Disp; - i.types[op] |= Disp32; /* Must be 32bit! */ - if (i.index_reg) - { /* case 2 or case 3 */ - i.bi.index = i.index_reg->reg_num; - i.bi.scale = i.log2_scale_factor; - if (i.disp_operands == 0) - fake_zero_displacement = 1; /* case 3 */ - } - else - { - i.bi.index = NO_INDEX_REGISTER; - i.bi.scale = 0; - } - } - else if (i.disp_operands && !i.base_reg && !i.index_reg) - { - /* Operand is just <32bit disp> */ - i.rm.regmem = EBP_REG_NUM; - i.rm.mode = 0; - i.types[op] &= ~Disp; - i.types[op] |= Disp32; - } - else - { - /* It's not a special case; rev'em up. */ - i.rm.regmem = i.base_reg->reg_num; - i.rm.mode = mode_from_disp_size (i.types[op]); - if (i.index_reg) - { - i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - i.bi.base = i.base_reg->reg_num; - i.bi.index = i.index_reg->reg_num; - i.bi.scale = i.log2_scale_factor; - if (i.base_reg == ebp && i.disp_operands == 0) - { /* pace */ - fake_zero_displacement = 1; - i.types[op] |= Disp8; - i.rm.mode = mode_from_disp_size (i.types[op]); - } - } - } - if (fake_zero_displacement) - { - /* Fakes a zero displacement assuming that i.types[op] - holds the correct displacement size. */ - exp = &disp_expressions[i.disp_operands++]; - i.disps[op] = exp; - exp->X_op = O_constant; - exp->X_add_number = 0; - exp->X_add_symbol = (symbolS *) 0; - exp->X_op_symbol = (symbolS *) 0; - } - - /* Find the default segment for the memory operand. - Used to optimize out explicit segment specifications. */ - if (i.seg) - { - unsigned int seg_index; - - if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING) - { - seg_index = (i.rm.mode << 3) | i.bi.base; - default_seg = two_byte_segment_defaults[seg_index]; - } - else - { - seg_index = (i.rm.mode << 3) | i.rm.regmem; - default_seg = one_byte_segment_defaults[seg_index]; - } - } - } - - /* Fill in i.rm.reg or i.rm.regmem field with register - operand (if any) based on i.tm.extension_opcode. - Again, we must be careful to make sure that - segment/control/debug/test/MMX registers are coded - into the i.rm.reg field. */ - if (i.reg_operands) - { - unsigned int op = - ((i.types[0] - & (Reg | SReg2 | SReg3 | Control | Debug - | Test | RegMMX)) - ? 0 - : ((i.types[1] - & (Reg | SReg2 | SReg3 | Control | Debug - | Test | RegMMX)) - ? 1 - : 2)); - /* If there is an extension opcode to put here, the - register number must be put into the regmem field. */ - if (i.tm.extension_opcode != None) - i.rm.regmem = i.regs[op]->reg_num; - else - i.rm.reg = i.regs[op]->reg_num; - - /* Now, if no memory operand has set i.rm.mode = 0, 1, 2 - we must set it to 3 to indicate this is a register - operand int the regmem field */ - if (!i.mem_operands) - i.rm.mode = 3; - } - - /* Fill in i.rm.reg field with extension opcode (if any). */ - if (i.tm.extension_opcode != None) - i.rm.reg = i.tm.extension_opcode; - } - - if (i.rm.mode != 3) - uses_mem_addrmode = 1; - } - - /* GAS currently doesn't support 16-bit memory addressing modes at all, - so if we're writing 16-bit code and using a memory addressing mode, - always spew out an address size prefix. */ - if (uses_mem_addrmode && flag_16bit_code) - { - if (i.prefixes == MAX_PREFIXES) - { - as_bad ("%d prefixes given and address size override gives too many prefixes", - MAX_PREFIXES); - return; - } - i.prefix[i.prefixes++] = ADDR_PREFIX_OPCODE; - } - - /* If a segment was explicitly specified, - and the specified segment is not the default, - use an opcode prefix to select it. - If we never figured out what the default segment is, - then default_seg will be zero at this point, - and the specified segment prefix will always be used. */ - if ((i.seg) && (i.seg != default_seg)) - { - if (i.prefixes == MAX_PREFIXES) - { - as_bad ("%d prefixes given and %s segment override gives too many prefixes", - MAX_PREFIXES, i.seg->seg_name); - return; - } - i.prefix[i.prefixes++] = i.seg->seg_prefix; - } - } - } - - /* Handle conversion of 'int $3' --> special int3 insn. */ - if (i.tm.base_opcode == INT_OPCODE && i.imms[0]->X_add_number == 3) - { - i.tm.base_opcode = INT3_OPCODE; - i.imm_operands = 0; - } - - /* We are ready to output the insn. */ - { - register char *p; - - /* Output jumps. */ - if (i.tm.opcode_modifier & Jump) - { - unsigned long n = i.disps[0]->X_add_number; - - if (i.disps[0]->X_op == O_constant) - { - if (fits_in_signed_byte (n)) - { - p = frag_more (2); - insn_size += 2; - p[0] = i.tm.base_opcode; - p[1] = n; - } - else - { /* It's an absolute word/dword displacement. */ - - /* Use only 16-bit jumps for 16-bit code, - because text segments are limited to 64K anyway; - use only 32-bit jumps for 32-bit code, - because they're faster. */ - int jmp_size = flag_16bit_code ? 2 : 4; - if (flag_16bit_code && !fits_in_signed_word (n)) - { - as_bad ("16-bit jump out of range"); - return; - } - - if (i.tm.base_opcode == JUMP_PC_RELATIVE) - { /* pace */ - /* unconditional jump */ - p = frag_more (1 + jmp_size); - insn_size += 1 + jmp_size; - p[0] = (char) 0xe9; - md_number_to_chars (&p[1], (valueT) n, jmp_size); - } - else - { - /* conditional jump */ - p = frag_more (2 + jmp_size); - insn_size += 2 + jmp_size; - p[0] = TWO_BYTE_OPCODE_ESCAPE; - p[1] = i.tm.base_opcode + 0x10; - md_number_to_chars (&p[2], (valueT) n, jmp_size); - } - } - } - else - { - if (flag_16bit_code) - { - FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE); - insn_size += 1; - } - - /* It's a symbol; end frag & setup for relax. - Make sure there are more than 6 chars left in the current frag; - if not we'll have to start a new one. */ - frag_grow (7); - p = frag_more (1); - insn_size += 1; - p[0] = i.tm.base_opcode; - frag_var (rs_machine_dependent, - 6, /* 2 opcode/prefix + 4 displacement */ - 1, - ((unsigned char) *p == JUMP_PC_RELATIVE - ? ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE) - : ENCODE_RELAX_STATE (COND_JUMP, BYTE)), - i.disps[0]->X_add_symbol, - (offsetT) n, p); - } - } - else if (i.tm.opcode_modifier & (JumpByte | JumpDword)) - { - int size = (i.tm.opcode_modifier & JumpByte) ? 1 : 4; - unsigned long n = i.disps[0]->X_add_number; - unsigned char *q; - - /* The jcx/jecx instruction might need a data size prefix. */ - for (q = i.prefix; q < i.prefix + i.prefixes; q++) - { - if (*q == WORD_PREFIX_OPCODE) - { - /* The jcxz/jecxz instructions are marked with Data16 - and Data32, which means that they may get - WORD_PREFIX_OPCODE added to the list of prefixes. - However, the are correctly distinguished using - ADDR_PREFIX_OPCODE. Here we look for - WORD_PREFIX_OPCODE, and actually emit - ADDR_PREFIX_OPCODE. This is a hack, but, then, so - is the instruction itself. - - If an explicit suffix is used for the loop - instruction, that actually controls whether we use - cx vs. ecx. This is also controlled by - ADDR_PREFIX_OPCODE. - - I don't know if there is any valid case in which we - want to emit WORD_PREFIX_OPCODE, but I am keeping - the old behaviour for safety. */ - - if (IS_JUMP_ON_CX_ZERO (i.tm.base_opcode) - || IS_LOOP_ECX_TIMES (i.tm.base_opcode)) - FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE); - else - FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE); - insn_size += 1; - break; - } - } - - if ((size == 4) && (flag_16bit_code)) - { - FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE); - insn_size += 1; - } - - if (fits_in_unsigned_byte (i.tm.base_opcode)) - { - FRAG_APPEND_1_CHAR (i.tm.base_opcode); - insn_size += 1; - } - else - { - p = frag_more (2); /* opcode can be at most two bytes */ - insn_size += 2; - /* put out high byte first: can't use md_number_to_chars! */ - *p++ = (i.tm.base_opcode >> 8) & 0xff; - *p = i.tm.base_opcode & 0xff; - } - - p = frag_more (size); - insn_size += size; - if (i.disps[0]->X_op == O_constant) - { - md_number_to_chars (p, (valueT) n, size); - if (size == 1 && !fits_in_signed_byte (n)) - { - as_bad ("loop/jecx only takes byte displacement; %lu shortened to %d", - n, *p); - } - } - else - { - fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.disps[0], 1, reloc (size, 1, i.disp_reloc[0])); - - } - } - else if (i.tm.opcode_modifier & JumpInterSegment) - { - if (flag_16bit_code) - { - FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE); - insn_size += 1; - } - - p = frag_more (1 + 2 + 4); /* 1 opcode; 2 segment; 4 offset */ - insn_size += 1 + 2 + 4; - p[0] = i.tm.base_opcode; - if (i.imms[1]->X_op == O_constant) - md_number_to_chars (p + 1, (valueT) i.imms[1]->X_add_number, 4); - else - fix_new_exp (frag_now, p + 1 - frag_now->fr_literal, 4, - i.imms[1], 0, BFD_RELOC_32); - if (i.imms[0]->X_op != O_constant) - as_bad ("can't handle non absolute segment in long call/jmp"); - md_number_to_chars (p + 5, (valueT) i.imms[0]->X_add_number, 2); - } - else - { - /* Output normal instructions here. */ - unsigned char *q; - - /* Hack for fwait. It must come before any prefixes, as it - really is an instruction rather than a prefix. */ - if ((i.tm.opcode_modifier & FWait) != 0) - { - p = frag_more (1); - insn_size += 1; - md_number_to_chars (p, (valueT) FWAIT_OPCODE, 1); - } - - /* The prefix bytes. */ - for (q = i.prefix; q < i.prefix + i.prefixes; q++) - { - p = frag_more (1); - insn_size += 1; - md_number_to_chars (p, (valueT) *q, 1); - } - - /* Now the opcode; be careful about word order here! */ - if (fits_in_unsigned_byte (i.tm.base_opcode)) - { - FRAG_APPEND_1_CHAR (i.tm.base_opcode); - insn_size += 1; - } - else if (fits_in_unsigned_word (i.tm.base_opcode)) - { - p = frag_more (2); - insn_size += 2; - /* put out high byte first: can't use md_number_to_chars! */ - *p++ = (i.tm.base_opcode >> 8) & 0xff; - *p = i.tm.base_opcode & 0xff; - } - else - { /* opcode is either 3 or 4 bytes */ - if (i.tm.base_opcode & 0xff000000) - { - p = frag_more (4); - insn_size += 4; - *p++ = (i.tm.base_opcode >> 24) & 0xff; - } - else - { - p = frag_more (3); - insn_size += 3; - } - *p++ = (i.tm.base_opcode >> 16) & 0xff; - *p++ = (i.tm.base_opcode >> 8) & 0xff; - *p = (i.tm.base_opcode) & 0xff; - } - - /* Now the modrm byte and base index byte (if present). */ - if (i.tm.opcode_modifier & Modrm) - { - p = frag_more (1); - insn_size += 1; - /* md_number_to_chars (p, i.rm, 1); */ - md_number_to_chars (p, - (valueT) (i.rm.regmem << 0 - | i.rm.reg << 3 - | i.rm.mode << 6), - 1); - /* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode) - ==> need second modrm byte. */ - if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3) - { - p = frag_more (1); - insn_size += 1; - /* md_number_to_chars (p, i.bi, 1); */ - md_number_to_chars (p, (valueT) (i.bi.base << 0 - | i.bi.index << 3 - | i.bi.scale << 6), - 1); - } - } - - if (i.disp_operands) - { - register unsigned int n; - - for (n = 0; n < i.operands; n++) - { - if (i.disps[n]) - { - if (i.disps[n]->X_op == O_constant) - { - if (i.types[n] & (Disp8 | Abs8)) - { - p = frag_more (1); - insn_size += 1; - md_number_to_chars (p, - (valueT) i.disps[n]->X_add_number, - 1); - } - else if (i.types[n] & (Disp16 | Abs16)) - { - p = frag_more (2); - insn_size += 2; - md_number_to_chars (p, - (valueT) i.disps[n]->X_add_number, - 2); - } - else - { /* Disp32|Abs32 */ - p = frag_more (4); - insn_size += 4; - md_number_to_chars (p, - (valueT) i.disps[n]->X_add_number, - 4); - } - } - else - { /* not absolute_section */ - /* need a 32-bit fixup (don't support 8bit non-absolute disps) */ - p = frag_more (4); - insn_size += 4; - fix_new_exp (frag_now, p - frag_now->fr_literal, 4, - i.disps[n], 0, - TC_RELOC(i.disp_reloc[n], BFD_RELOC_32)); - } - } - } - } /* end displacement output */ - - /* output immediate */ - if (i.imm_operands) - { - register unsigned int n; - - for (n = 0; n < i.operands; n++) - { - if (i.imms[n]) - { - if (i.imms[n]->X_op == O_constant) - { - if (i.types[n] & (Imm8 | Imm8S)) - { - p = frag_more (1); - insn_size += 1; - md_number_to_chars (p, - (valueT) i.imms[n]->X_add_number, - 1); - } - else if (i.types[n] & Imm16) - { - p = frag_more (2); - insn_size += 2; - md_number_to_chars (p, - (valueT) i.imms[n]->X_add_number, - 2); - } - else - { - p = frag_more (4); - insn_size += 4; - md_number_to_chars (p, - (valueT) i.imms[n]->X_add_number, - 4); - } - } - else - { /* not absolute_section */ - /* Need a 32-bit fixup (don't support 8bit - non-absolute ims). Try to support other - sizes ... */ - int r_type; - int size; - int pcrel = 0; - - if (i.types[n] & (Imm8 | Imm8S)) - size = 1; - else if (i.types[n] & Imm16) - size = 2; - else - size = 4; - r_type = reloc (size, 0, i.disp_reloc[0]); - p = frag_more (size); - insn_size += size; -#ifdef BFD_ASSEMBLER - if (r_type == BFD_RELOC_32 - && GOT_symbol - && GOT_symbol == i.imms[n]->X_add_symbol - && (i.imms[n]->X_op == O_symbol - || (i.imms[n]->X_op == O_add - && (i.imms[n]->X_op_symbol->sy_value.X_op - == O_subtract)))) - { - r_type = BFD_RELOC_386_GOTPC; - i.imms[n]->X_add_number += 3; - } -#endif - fix_new_exp (frag_now, p - frag_now->fr_literal, size, - i.imms[n], pcrel, r_type); - } - } - } - } /* end immediate output */ - } - -#ifdef DEBUG386 - if (flag_debug) - { - pi (line, &i); - } -#endif /* DEBUG386 */ - } -} - -/* Parse OPERAND_STRING into the i386_insn structure I. Returns non-zero - on error. */ - -static int -i386_operand (operand_string) - char *operand_string; -{ - register char *op_string = operand_string; - - /* Address of '\0' at end of operand_string. */ - char *end_of_operand_string = operand_string + strlen (operand_string); - - /* Start and end of displacement string expression (if found). */ - char *displacement_string_start = NULL; - char *displacement_string_end = NULL; - - /* We check for an absolute prefix (differentiating, - for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */ - if (*op_string == ABSOLUTE_PREFIX) - { - op_string++; - i.types[this_operand] |= JumpAbsolute; - } - - /* Check if operand is a register. */ - if (*op_string == REGISTER_PREFIX) - { - register reg_entry *r; - if (!(r = parse_register (op_string))) - { - as_bad ("bad register name ('%s')", op_string); - return 0; - } - /* Check for segment override, rather than segment register by - searching for ':' after %<x>s where <x> = s, c, d, e, f, g. */ - if ((r->reg_type & (SReg2 | SReg3)) && op_string[3] == ':') - { - switch (r->reg_num) - { - case 0: - i.seg = (seg_entry *) & es; - break; - case 1: - i.seg = (seg_entry *) & cs; - break; - case 2: - i.seg = (seg_entry *) & ss; - break; - case 3: - i.seg = (seg_entry *) & ds; - break; - case 4: - i.seg = (seg_entry *) & fs; - break; - case 5: - i.seg = (seg_entry *) & gs; - break; - } - op_string += 4; /* skip % <x> s : */ - operand_string = op_string; /* Pretend given string starts here. */ - if (!is_digit_char (*op_string) && !is_identifier_char (*op_string) - && *op_string != '(' && *op_string != ABSOLUTE_PREFIX) - { - as_bad ("bad memory operand after segment override"); - return 0; - } - /* Handle case of %es:*foo. */ - if (*op_string == ABSOLUTE_PREFIX) - { - op_string++; - i.types[this_operand] |= JumpAbsolute; - } - goto do_memory_reference; - } - i.types[this_operand] |= r->reg_type; - i.regs[this_operand] = r; - i.reg_operands++; - } - else if (*op_string == IMMEDIATE_PREFIX) - { /* ... or an immediate */ - char *save_input_line_pointer; - segT exp_seg = 0; - expressionS *exp; - - if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) - { - as_bad ("only 1 or 2 immediate operands are allowed"); - return 0; - } - - exp = &im_expressions[i.imm_operands++]; - i.imms[this_operand] = exp; - save_input_line_pointer = input_line_pointer; - input_line_pointer = ++op_string; /* must advance op_string! */ - SKIP_WHITESPACE (); - exp_seg = expression (exp); - if (*input_line_pointer != '\0') - { - /* This should be as_bad, but some versions of gcc, up to - about 2.8 and egcs 1.01, generate a bogus @GOTOFF(%ebx) - in certain cases. Oddly, the code in question turns out - to work correctly anyhow, so we make this just a warning - until those versions of gcc are obsolete. */ - as_warn ("warning: unrecognized characters `%s' in expression", - input_line_pointer); - } - input_line_pointer = save_input_line_pointer; - - if (exp->X_op == O_absent) - { - /* missing or bad expr becomes absolute 0 */ - as_bad ("missing or invalid immediate expression '%s' taken as 0", - operand_string); - exp->X_op = O_constant; - exp->X_add_number = 0; - exp->X_add_symbol = (symbolS *) 0; - exp->X_op_symbol = (symbolS *) 0; - i.types[this_operand] |= Imm; - } - else if (exp->X_op == O_constant) - { - i.types[this_operand] |= - smallest_imm_type ((unsigned long) exp->X_add_number); - } -#ifdef OBJ_AOUT - else if (exp_seg != text_section - && exp_seg != data_section - && exp_seg != bss_section - && exp_seg != undefined_section -#ifdef BFD_ASSEMBLER - && ! bfd_is_com_section (exp_seg) -#endif - ) - { - seg_unimplemented: - as_bad ("Unimplemented segment type %d in parse_operand", exp_seg); - return 0; - } -#endif - else - { - /* this is an address ==> 32bit */ - i.types[this_operand] |= Imm32; - } - /* shorten this type of this operand if the instruction wants - * fewer bits than are present in the immediate. The bit field - * code can put out 'andb $0xffffff, %al', for example. pace - * also 'movw $foo,(%eax)' - */ - switch (i.suffix) - { - case WORD_OPCODE_SUFFIX: - i.types[this_operand] |= Imm16; - break; - case BYTE_OPCODE_SUFFIX: - i.types[this_operand] |= Imm16 | Imm8 | Imm8S; - break; - } - } - else if (is_digit_char (*op_string) || is_identifier_char (*op_string) - || *op_string == '(') - { - /* This is a memory reference of some sort. */ - register char *base_string; - unsigned int found_base_index_form; - - do_memory_reference: - if (i.mem_operands == MAX_MEMORY_OPERANDS) - { - as_bad ("more than 1 memory reference in instruction"); - return 0; - } - i.mem_operands++; - - /* Determine type of memory operand from opcode_suffix; - no opcode suffix implies general memory references. */ - switch (i.suffix) - { - case BYTE_OPCODE_SUFFIX: - i.types[this_operand] |= Mem8; - break; - case WORD_OPCODE_SUFFIX: - i.types[this_operand] |= Mem16; - break; - case DWORD_OPCODE_SUFFIX: - default: - i.types[this_operand] |= Mem32; - } - - /* Check for base index form. We detect the base index form by - looking for an ')' at the end of the operand, searching - for the '(' matching it, and finding a REGISTER_PREFIX or ',' - after it. */ - base_string = end_of_operand_string - 1; - found_base_index_form = 0; - if (*base_string == ')') - { - unsigned int parens_balanced = 1; - /* We've already checked that the number of left & right ()'s are - equal, so this loop will not be infinite. */ - do - { - base_string--; - if (*base_string == ')') - parens_balanced++; - if (*base_string == '(') - parens_balanced--; - } - while (parens_balanced); - base_string++; /* Skip past '('. */ - if (*base_string == REGISTER_PREFIX || *base_string == ',') - found_base_index_form = 1; - } - - /* If we can't parse a base index register expression, we've found - a pure displacement expression. We set up displacement_string_start - and displacement_string_end for the code below. */ - if (!found_base_index_form) - { - displacement_string_start = op_string; - displacement_string_end = end_of_operand_string; - } - else - { - char *base_reg_name, *index_reg_name, *num_string; - int num; - - i.types[this_operand] |= BaseIndex; - - /* If there is a displacement set-up for it to be parsed later. */ - if (base_string != op_string + 1) - { - displacement_string_start = op_string; - displacement_string_end = base_string - 1; - } - - /* Find base register (if any). */ - if (*base_string != ',') - { - base_reg_name = base_string++; - /* skip past register name & parse it */ - while (isalpha (*base_string)) - base_string++; - if (base_string == base_reg_name + 1) - { - as_bad ("can't find base register name after '(%c'", - REGISTER_PREFIX); - return 0; - } - END_STRING_AND_SAVE (base_string); - if (!(i.base_reg = parse_register (base_reg_name))) - { - as_bad ("bad base register name ('%s')", base_reg_name); - return 0; - } - RESTORE_END_STRING (base_string); - } - - /* Now check seperator; must be ',' ==> index reg - OR num ==> no index reg. just scale factor - OR ')' ==> end. (scale factor = 1) */ - if (*base_string != ',' && *base_string != ')') - { - as_bad ("expecting ',' or ')' after base register in `%s'", - operand_string); - return 0; - } - - /* There may index reg here; and there may be a scale factor. */ - if (*base_string == ',' && *(base_string + 1) == REGISTER_PREFIX) - { - index_reg_name = ++base_string; - while (isalpha (*++base_string)); - END_STRING_AND_SAVE (base_string); - if (!(i.index_reg = parse_register (index_reg_name))) - { - as_bad ("bad index register name ('%s')", index_reg_name); - return 0; - } - RESTORE_END_STRING (base_string); - } - - /* Check for scale factor. */ - if (*base_string == ',' && isdigit (*(base_string + 1))) - { - num_string = ++base_string; - while (is_digit_char (*base_string)) - base_string++; - if (base_string == num_string) - { - as_bad ("can't find a scale factor after ','"); - return 0; - } - END_STRING_AND_SAVE (base_string); - /* We've got a scale factor. */ - if (!sscanf (num_string, "%d", &num)) - { - as_bad ("can't parse scale factor from '%s'", num_string); - return 0; - } - RESTORE_END_STRING (base_string); - switch (num) - { /* must be 1 digit scale */ - case 1: - i.log2_scale_factor = 0; - break; - case 2: - i.log2_scale_factor = 1; - break; - case 4: - i.log2_scale_factor = 2; - break; - case 8: - i.log2_scale_factor = 3; - break; - default: - as_bad ("expecting scale factor of 1, 2, 4, 8; got %d", num); - return 0; - } - } - else - { - if (!i.index_reg && *base_string == ',') - { - as_bad ("expecting index register or scale factor after ','; got '%c'", - *(base_string + 1)); - return 0; - } - } - } - - /* If there's an expression begining the operand, parse it, - assuming displacement_string_start and displacement_string_end - are meaningful. */ - if (displacement_string_start) - { - register expressionS *exp; - segT exp_seg = 0; - char *save_input_line_pointer; - exp = &disp_expressions[i.disp_operands]; - i.disps[this_operand] = exp; - i.disp_reloc[this_operand] = NO_RELOC; - i.disp_operands++; - save_input_line_pointer = input_line_pointer; - input_line_pointer = displacement_string_start; - END_STRING_AND_SAVE (displacement_string_end); - -#ifndef LEX_AT - { - /* - * We can have operands of the form - * <symbol>@GOTOFF+<nnn> - * Take the easy way out here and copy everything - * into a temporary buffer... - */ - register char *cp; - - cp = strchr (input_line_pointer, '@'); - if (cp != NULL) - { - char *tmpbuf; - - if (GOT_symbol == NULL) - GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); - - tmpbuf = (char *) alloca ((cp - input_line_pointer) + 20); - - if (strncmp (cp + 1, "PLT", 3) == 0) - { - i.disp_reloc[this_operand] = BFD_RELOC_386_PLT32; - *cp = '\0'; - strcpy (tmpbuf, input_line_pointer); - strcat (tmpbuf, cp + 1 + 3); - *cp = '@'; - } - else if (strncmp (cp + 1, "GOTOFF", 6) == 0) - { - i.disp_reloc[this_operand] = BFD_RELOC_386_GOTOFF; - *cp = '\0'; - strcpy (tmpbuf, input_line_pointer); - strcat (tmpbuf, cp + 1 + 6); - *cp = '@'; - } - else if (strncmp (cp + 1, "GOT", 3) == 0) - { - i.disp_reloc[this_operand] = BFD_RELOC_386_GOT32; - *cp = '\0'; - strcpy (tmpbuf, input_line_pointer); - strcat (tmpbuf, cp + 1 + 3); - *cp = '@'; - } - else - as_bad ("Bad reloc specifier '%s' in expression", cp + 1); - - input_line_pointer = tmpbuf; - } - } -#endif - - exp_seg = expression (exp); - -#ifdef BFD_ASSEMBLER - /* We do this to make sure that the section symbol is in - the symbol table. We will ultimately change the relocation - to be relative to the beginning of the section */ - if (i.disp_reloc[this_operand] == BFD_RELOC_386_GOTOFF) - { - if (S_IS_LOCAL(exp->X_add_symbol) - && S_GET_SEGMENT (exp->X_add_symbol) != undefined_section) - section_symbol(exp->X_add_symbol->bsym->section); - assert (exp->X_op == O_symbol); - exp->X_op = O_subtract; - exp->X_op_symbol = GOT_symbol; - i.disp_reloc[this_operand] = BFD_RELOC_32; - } -#endif - - if (*input_line_pointer) - as_bad ("Ignoring junk '%s' after expression", input_line_pointer); - RESTORE_END_STRING (displacement_string_end); - input_line_pointer = save_input_line_pointer; - if (exp->X_op == O_absent) - { - /* missing expr becomes absolute 0 */ - as_bad ("missing or invalid displacement '%s' taken as 0", - operand_string); - i.types[this_operand] |= (Disp | Abs); - exp->X_op = O_constant; - exp->X_add_number = 0; - exp->X_add_symbol = (symbolS *) 0; - exp->X_op_symbol = (symbolS *) 0; - } - else if (exp->X_op == O_constant) - { - i.types[this_operand] |= SMALLEST_DISP_TYPE (exp->X_add_number); - } - else if (exp_seg == text_section - || exp_seg == data_section - || exp_seg == bss_section - || exp_seg == undefined_section) - { - i.types[this_operand] |= Disp32; - } - else - { -#ifndef OBJ_AOUT - i.types[this_operand] |= Disp32; -#else - goto seg_unimplemented; -#endif - } - } - - /* Make sure the memory operand we've been dealt is valid. */ - if (i.base_reg && i.index_reg && - !(i.base_reg->reg_type & i.index_reg->reg_type & Reg)) - { - as_bad ("register size mismatch in (base,index,scale) expression"); - return 0; - } - /* - * special case for (%dx) while doing input/output op - */ - if ((i.base_reg && - (i.base_reg->reg_type == (Reg16 | InOutPortReg)) && - (i.index_reg == 0))) - { - i.types[this_operand] |= InOutPortReg; - return 1; - } - if ((i.base_reg && (i.base_reg->reg_type & Reg32) == 0) || - (i.index_reg && (i.index_reg->reg_type & Reg32) == 0)) - { - as_bad ("base/index register must be 32 bit register"); - return 0; - } - if (i.index_reg && i.index_reg == esp) - { - as_bad ("%s may not be used as an index register", esp->reg_name); - return 0; - } - } - else - { /* it's not a memory operand; argh! */ - as_bad ("invalid char %s begining %s operand '%s'", - output_invalid (*op_string), ordinal_names[this_operand], - op_string); - return 0; - } - return 1; /* normal return */ -} - -/* - * md_estimate_size_before_relax() - * - * Called just before relax(). - * Any symbol that is now undefined will not become defined. - * Return the correct fr_subtype in the frag. - * Return the initial "guess for fr_var" to caller. - * The guess for fr_var is ACTUALLY the growth beyond fr_fix. - * Whatever we do to grow fr_fix or fr_var contributes to our returned value. - * Although it may not be explicit in the frag, pretend fr_var starts with a - * 0 value. - */ -int -md_estimate_size_before_relax (fragP, segment) - register fragS *fragP; - register segT segment; -{ - register unsigned char *opcode; - register int old_fr_fix; - - old_fr_fix = fragP->fr_fix; - opcode = (unsigned char *) fragP->fr_opcode; - /* We've already got fragP->fr_subtype right; all we have to do is check - for un-relaxable symbols. */ - if (S_GET_SEGMENT (fragP->fr_symbol) != segment) - { - /* symbol is undefined in this segment */ - switch (opcode[0]) - { - case JUMP_PC_RELATIVE: /* make jmp (0xeb) a dword displacement jump */ - opcode[0] = 0xe9; /* dword disp jmp */ - fragP->fr_fix += 4; - fix_new (fragP, old_fr_fix, 4, - fragP->fr_symbol, - fragP->fr_offset, 1, - (GOT_symbol && /* Not quite right - we should switch on - presence of @PLT, but I cannot see how - to get to that from here. We should have - done this in md_assemble to really - get it right all of the time, but I - think it does not matter that much, as - this will be right most of the time. ERY*/ - S_GET_SEGMENT(fragP->fr_symbol) == undefined_section)? - BFD_RELOC_386_PLT32 : BFD_RELOC_32_PCREL); - break; - - default: - /* This changes the byte-displacement jump 0x7N --> - the dword-displacement jump 0x0f8N */ - opcode[1] = opcode[0] + 0x10; - opcode[0] = TWO_BYTE_OPCODE_ESCAPE; /* two-byte escape */ - fragP->fr_fix += 1 + 4; /* we've added an opcode byte */ - fix_new (fragP, old_fr_fix + 1, 4, - fragP->fr_symbol, - fragP->fr_offset, 1, - (GOT_symbol && /* Not quite right - we should switch on - presence of @PLT, but I cannot see how - to get to that from here. ERY */ - S_GET_SEGMENT(fragP->fr_symbol) == undefined_section)? - BFD_RELOC_386_PLT32 : BFD_RELOC_32_PCREL); - break; - } - frag_wane (fragP); - } - return (fragP->fr_var + fragP->fr_fix - old_fr_fix); -} /* md_estimate_size_before_relax() */ - -/* - * 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". - */ -#ifndef BFD_ASSEMBLER -void -md_convert_frag (headers, sec, fragP) - object_headers *headers; - segT sec; - register fragS *fragP; -#else -void -md_convert_frag (abfd, sec, fragP) - bfd *abfd; - segT sec; - register fragS *fragP; -#endif -{ - register unsigned char *opcode; - unsigned char *where_to_put_displacement = NULL; - unsigned int target_address; - unsigned int opcode_address; - unsigned int extension = 0; - int displacement_from_opcode_start; - - opcode = (unsigned char *) fragP->fr_opcode; - - /* Address we want to reach in file space. */ - target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset; -#ifdef BFD_ASSEMBLER /* not needed otherwise? */ - target_address += fragP->fr_symbol->sy_frag->fr_address; -#endif - - /* Address opcode resides at in file space. */ - opcode_address = fragP->fr_address + fragP->fr_fix; - - /* Displacement from opcode start to fill into instruction. */ - displacement_from_opcode_start = target_address - opcode_address; - - switch (fragP->fr_subtype) - { - case ENCODE_RELAX_STATE (COND_JUMP, BYTE): - case ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE): - /* don't have to change opcode */ - extension = 1; /* 1 opcode + 1 displacement */ - where_to_put_displacement = &opcode[1]; - break; - - case ENCODE_RELAX_STATE (COND_JUMP, WORD): - opcode[1] = TWO_BYTE_OPCODE_ESCAPE; - opcode[2] = opcode[0] + 0x10; - opcode[0] = WORD_PREFIX_OPCODE; - extension = 4; /* 3 opcode + 2 displacement */ - where_to_put_displacement = &opcode[3]; - break; - - case ENCODE_RELAX_STATE (UNCOND_JUMP, WORD): - opcode[1] = 0xe9; - opcode[0] = WORD_PREFIX_OPCODE; - extension = 3; /* 2 opcode + 2 displacement */ - where_to_put_displacement = &opcode[2]; - break; - - case ENCODE_RELAX_STATE (COND_JUMP, DWORD): - opcode[1] = opcode[0] + 0x10; - opcode[0] = TWO_BYTE_OPCODE_ESCAPE; - extension = 5; /* 2 opcode + 4 displacement */ - where_to_put_displacement = &opcode[2]; - break; - - case ENCODE_RELAX_STATE (UNCOND_JUMP, DWORD): - opcode[0] = 0xe9; - extension = 4; /* 1 opcode + 4 displacement */ - where_to_put_displacement = &opcode[1]; - break; - - default: - BAD_CASE (fragP->fr_subtype); - break; - } - /* now put displacement after opcode */ - md_number_to_chars ((char *) where_to_put_displacement, - (valueT) (displacement_from_opcode_start - extension), - SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); - fragP->fr_fix += extension; -} - - -int md_short_jump_size = 2; /* size of byte displacement jmp */ -int md_long_jump_size = 5; /* size of dword displacement jmp */ -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; - symbolS *to_symbol; -{ - long offset; - - offset = to_addr - (from_addr + 2); - md_number_to_chars (ptr, (valueT) 0xeb, 1); /* opcode for byte-disp jump */ - md_number_to_chars (ptr + 1, (valueT) offset, 1); -} - -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; -{ - long offset; - - if (flag_do_long_jump) - { - offset = to_addr - S_GET_VALUE (to_symbol); - md_number_to_chars (ptr, (valueT) 0xe9, 1);/* opcode for long jmp */ - md_number_to_chars (ptr + 1, (valueT) offset, 4); - fix_new (frag, (ptr + 1) - frag->fr_literal, 4, - to_symbol, (offsetT) 0, 0, BFD_RELOC_32); - } - else - { - offset = to_addr - (from_addr + 5); - md_number_to_chars (ptr, (valueT) 0xe9, 1); - md_number_to_chars (ptr + 1, (valueT) offset, 4); - } -} - -/* Apply a fixup (fixS) to segment data, once it has been determined - by our caller that we have all the info we need to fix it up. - - On the 386, immediates, displacements, and data pointers are all in - the same (little-endian) format, so we don't need to care about which - we are handling. */ - -int -md_apply_fix3 (fixP, valp, seg) - fixS *fixP; /* The fix we're to put in. */ - valueT *valp; /* Pointer to the value of the bits. */ - segT seg; /* Segment fix is from. */ -{ - register char *p = fixP->fx_where + fixP->fx_frag->fr_literal; - valueT value = *valp; - - if (fixP->fx_r_type == BFD_RELOC_32 && fixP->fx_pcrel) - fixP->fx_r_type = BFD_RELOC_32_PCREL; - -#if defined (BFD_ASSEMBLER) && !defined (TE_Mach) - /* - * This is a hack. There should be a better way to - * handle this. - */ - if (fixP->fx_r_type == BFD_RELOC_32_PCREL && fixP->fx_addsy) - { -#ifndef OBJ_AOUT - if (OUTPUT_FLAVOR == bfd_target_elf_flavour - || OUTPUT_FLAVOR == bfd_target_coff_flavour) - value += fixP->fx_where + fixP->fx_frag->fr_address; -#endif -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (OUTPUT_FLAVOR == bfd_target_elf_flavour - && (S_GET_SEGMENT (fixP->fx_addsy) == seg - || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)) - { - /* Yes, we add the values in twice. This is because - bfd_perform_relocation subtracts them out again. I think - bfd_perform_relocation is broken, but I don't dare change - it. FIXME. */ - value += fixP->fx_where + fixP->fx_frag->fr_address; - } -#endif -#if defined (OBJ_COFF) && defined (TE_PE) - /* For some reason, the PE format does not store a section - address offset for a PC relative symbol. */ - if (S_GET_SEGMENT (fixP->fx_addsy) != seg) - value += md_pcrel_from (fixP); -#endif - } - - /* Fix a few things - the dynamic linker expects certain values here, - and we must not dissappoint it. */ -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - if (OUTPUT_FLAVOR == bfd_target_elf_flavour - && fixP->fx_addsy) - switch(fixP->fx_r_type) { - case BFD_RELOC_386_PLT32: - /* Make the jump instruction point to the address of the operand. At - runtime we merely add the offset to the actual PLT entry. */ - value = 0xfffffffc; - break; - case BFD_RELOC_386_GOTPC: -/* - * This is tough to explain. We end up with this one if we have - * operands that look like "_GLOBAL_OFFSET_TABLE_+[.-.L284]". The goal - * here is to obtain the absolute address of the GOT, and it is strongly - * preferable from a performance point of view to avoid using a runtime - * relocation for this. The actual sequence of instructions often look - * something like: - * - * call .L66 - * .L66: - * popl %ebx - * addl $_GLOBAL_OFFSET_TABLE_+[.-.L66],%ebx - * - * The call and pop essentially return the absolute address of - * the label .L66 and store it in %ebx. The linker itself will - * ultimately change the first operand of the addl so that %ebx points to - * the GOT, but to keep things simple, the .o file must have this operand - * set so that it generates not the absolute address of .L66, but the - * absolute address of itself. This allows the linker itself simply - * treat a GOTPC relocation as asking for a pcrel offset to the GOT to be - * added in, and the addend of the relocation is stored in the operand - * field for the instruction itself. - * - * Our job here is to fix the operand so that it would add the correct - * offset so that %ebx would point to itself. The thing that is tricky is - * that .-.L66 will point to the beginning of the instruction, so we need - * to further modify the operand so that it will point to itself. - * There are other cases where you have something like: - * - * .long $_GLOBAL_OFFSET_TABLE_+[.-.L66] - * - * and here no correction would be required. Internally in the assembler - * we treat operands of this form as not being pcrel since the '.' is - * explicitly mentioned, and I wonder whether it would simplify matters - * to do it this way. Who knows. In earlier versions of the PIC patches, - * the pcrel_adjust field was used to store the correction, but since the - * expression is not pcrel, I felt it would be confusing to do it this way. - */ - value -= 1; - break; - case BFD_RELOC_386_GOT32: - value = 0; /* Fully resolved at runtime. No addend. */ - break; - case BFD_RELOC_386_GOTOFF: - break; - - default: - break; - } -#endif - -#endif - md_number_to_chars (p, value, fixP->fx_size); - - return 1; -} - -#if 0 -/* This is never used. */ -long /* Knows about the byte order in a word. */ -md_chars_to_number (con, nbytes) - unsigned char con[]; /* Low order byte 1st. */ - int nbytes; /* Number of bytes in the input. */ -{ - long retval; - for (retval = 0, con += nbytes - 1; nbytes--; con--) - { - retval <<= BITS_PER_CHAR; - retval |= *con; - } - return retval; -} -#endif /* 0 */ - - -#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': - case 'F': - prec = 2; - break; - - case 'd': - case 'D': - prec = 4; - break; - - case 'x': - case 'X': - prec = 5; - 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); - /* This loops outputs the LITTLENUMs in REVERSE order; in accord with - the bigendian 386. */ - for (wordP = words + prec - 1; prec--;) - { - md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - return 0; -} - -char output_invalid_buf[8]; - -static char * -output_invalid (c) - char c; -{ - if (isprint (c)) - sprintf (output_invalid_buf, "'%c'", c); - else - sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); - return output_invalid_buf; -} - -/* reg_string starts *before* REGISTER_PREFIX */ -static reg_entry * -parse_register (reg_string) - char *reg_string; -{ - register char *s = reg_string; - register char *p; - char reg_name_given[MAX_REG_NAME_SIZE]; - - s++; /* skip REGISTER_PREFIX */ - for (p = reg_name_given; is_register_char (*s); p++, s++) - { - *p = register_chars[(unsigned char) *s]; - if (p >= reg_name_given + MAX_REG_NAME_SIZE) - return (reg_entry *) 0; - } - *p = '\0'; - return (reg_entry *) hash_find (reg_hash, reg_name_given); -} - -#ifdef OBJ_ELF -CONST char *md_shortopts = "kmVQ:"; -#else -CONST char *md_shortopts = "m"; -#endif -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; -{ - switch (c) - { - case 'm': - flag_do_long_jump = 1; - break; - -#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) - /* -k: Ignore for FreeBSD compatibility. */ - case 'k': - break; - - /* -V: SVR4 argument to print version ID. */ - case 'V': - print_version_id (); - break; - - /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section - should be emitted or not. FIXME: Not implemented. */ - case 'Q': - break; -#endif - - default: - return 0; - } - return 1; -} - -void -md_show_usage (stream) - FILE *stream; -{ - fprintf (stream, "\ --m do long jump\n"); -} - -#ifdef BFD_ASSEMBLER -#ifdef OBJ_MAYBE_ELF -#ifdef OBJ_MAYBE_COFF - -/* Pick the target format to use. */ - -const char * -i386_target_format () -{ - switch (OUTPUT_FLAVOR) - { - case bfd_target_coff_flavour: - return "coff-i386"; - case bfd_target_elf_flavour: - return "elf32-i386"; - default: - abort (); - return NULL; - } -} - -#endif /* OBJ_MAYBE_COFF */ -#endif /* OBJ_MAYBE_ELF */ -#endif /* BFD_ASSEMBLER */ - -/* ARGSUSED */ -symbolS * -md_undefined_symbol (name) - char *name; -{ - if (*name == '_' && *(name+1) == 'G' - && strcmp(name, GLOBAL_OFFSET_TABLE_NAME) == 0) - { - if(!GOT_symbol) - { - if(symbol_find(name)) - as_bad("GOT already in symbol table"); - GOT_symbol = symbol_new (name, undefined_section, - (valueT) 0, &zero_address_frag); - }; - return GOT_symbol; - } - return 0; -} - -/* Round up a section size to the appropriate boundary. */ -valueT -md_section_align (segment, size) - segT segment; - valueT size; -{ -#ifdef OBJ_AOUT -#ifdef BFD_ASSEMBLER - /* For a.out, force the section size to be aligned. If we don't do - this, BFD will align it for us, but it will not write out the - final bytes of the section. This may be a bug in BFD, but it is - easier to fix it here since that is how the other a.out targets - work. */ - int align; - - align = bfd_get_section_alignment (stdoutput, segment); - size = ((size + (1 << align) - 1) & ((valueT) -1 << align)); -#endif -#endif - - return size; -} - -/* Exactly what point is a PC-relative offset relative TO? On the - i386, they're relative to the address of the offset, plus its - size. (??? Is this right? FIXME-SOON!) */ -long -md_pcrel_from (fixP) - fixS *fixP; -{ - return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; -} - -#ifndef I386COFF - -static void -s_bss (ignore) - int ignore; -{ - register int temp; - - temp = get_absolute_expression (); - subseg_set (bss_section, (subsegT) temp); - demand_empty_rest_of_line (); -} - -#endif - - -#ifdef BFD_ASSEMBLER - -void -i386_validate_fix (fixp) - fixS *fixp; -{ - if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) - { - fixp->fx_r_type = BFD_RELOC_386_GOTOFF; - fixp->fx_subsy = 0; - } -} - -#define F(SZ,PCREL) (((SZ) << 1) + (PCREL)) -#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break - -arelent * -tc_gen_reloc (section, fixp) - asection *section; - fixS *fixp; -{ - arelent *rel; - bfd_reloc_code_real_type code; - - switch(fixp->fx_r_type) - { - case BFD_RELOC_386_PLT32: - case BFD_RELOC_386_GOT32: - case BFD_RELOC_386_GOTOFF: - case BFD_RELOC_386_GOTPC: - case BFD_RELOC_RVA: - code = fixp->fx_r_type; - break; - default: - switch (F (fixp->fx_size, fixp->fx_pcrel)) - { - MAP (1, 0, BFD_RELOC_8); - MAP (2, 0, BFD_RELOC_16); - MAP (4, 0, BFD_RELOC_32); - MAP (1, 1, BFD_RELOC_8_PCREL); - MAP (2, 1, BFD_RELOC_16_PCREL); - MAP (4, 1, BFD_RELOC_32_PCREL); - default: - as_bad ("Can not do %d byte %srelocation", fixp->fx_size, - fixp->fx_pcrel ? "pc-relative " : ""); - } - } -#undef MAP -#undef F - - if (code == BFD_RELOC_32 - && GOT_symbol - && fixp->fx_addsy == GOT_symbol) - code = BFD_RELOC_386_GOTPC; - - rel = (arelent *) xmalloc (sizeof (arelent)); - rel->sym_ptr_ptr = &fixp->fx_addsy->bsym; - rel->address = fixp->fx_frag->fr_address + fixp->fx_where; - if (fixp->fx_pcrel) - rel->addend = fixp->fx_addnumber; - else - rel->addend = 0; - - rel->howto = bfd_reloc_type_lookup (stdoutput, code); - if (rel->howto == NULL) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - "Cannot represent relocation type %s", - bfd_get_reloc_code_name (code)); - /* Set howto to a garbage value so that we can keep going. */ - rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); - assert (rel->howto != NULL); - } - - return rel; -} - -#else /* ! BFD_ASSEMBLER */ - -#if (defined(OBJ_AOUT) | defined(OBJ_BOUT)) -void -tc_aout_fix_to_chars (where, fixP, segment_address_in_file) - char *where; - fixS *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. - */ - - static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2}; - long r_symbolnum; - - know (fixP->fx_addsy != NULL); - - md_number_to_chars (where, - (valueT) (fixP->fx_frag->fr_address - + fixP->fx_where - segment_address_in_file), - 4); - - r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) - ? S_GET_TYPE (fixP->fx_addsy) - : fixP->fx_addsy->sy_number); - - where[6] = (r_symbolnum >> 16) & 0x0ff; - where[5] = (r_symbolnum >> 8) & 0x0ff; - where[4] = r_symbolnum & 0x0ff; - where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08) - | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06) - | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f)); -} - -#endif /* OBJ_AOUT or OBJ_BOUT */ - -#if defined (I386COFF) - -short -tc_coff_fix2rtype (fixP) - fixS *fixP; -{ - if (fixP->fx_r_type == R_IMAGEBASE) - return R_IMAGEBASE; - - return (fixP->fx_pcrel ? - (fixP->fx_size == 1 ? R_PCRBYTE : - fixP->fx_size == 2 ? R_PCRWORD : - R_PCRLONG) : - (fixP->fx_size == 1 ? R_RELBYTE : - fixP->fx_size == 2 ? R_RELWORD : - R_DIR32)); -} - -int -tc_coff_sizemachdep (frag) - fragS *frag; -{ - if (frag->fr_next) - return (frag->fr_next->fr_address - frag->fr_address); - else - return 0; -} - -#endif /* I386COFF */ - -#endif /* BFD_ASSEMBLER? */ - -/* end of tc-i386.c */ diff --git a/contrib/binutils/gas/config/tc-i386.h b/contrib/binutils/gas/config/tc-i386.h deleted file mode 100644 index 51426423b90b..000000000000 --- a/contrib/binutils/gas/config/tc-i386.h +++ /dev/null @@ -1,445 +0,0 @@ -/* tc-i386.h -- Header file for tc-i386.c - Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation. - - 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 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. */ - -#ifndef TC_I386 -#define TC_I386 1 - -#ifdef ANSI_PROTOTYPES -struct fix; -#endif - -#define TARGET_BYTES_BIG_ENDIAN 0 - -#ifdef TE_LYNX -#define TARGET_FORMAT "coff-i386-lynx" -#endif - -#ifdef BFD_ASSEMBLER -/* This is used to determine relocation types in tc-i386.c. The first - parameter is the current relocation type, the second one is the desired - type. The idea is that if the original type is already some kind of PIC - relocation, we leave it alone, otherwise we give it the desired type */ - -#define TC_RELOC(X,Y) (((X) != BFD_RELOC_386_PLT32 && \ - (X) != BFD_RELOC_386_GOTOFF && \ - (X) != BFD_RELOC_386_GOT32 && \ - (X) != BFD_RELOC_386_GOTPC) ? Y : X) - -#define tc_fix_adjustable(X) tc_i386_fix_adjustable(X) -extern int tc_i386_fix_adjustable PARAMS ((struct fix *)); - -/* This is the relocation type for direct references to GLOBAL_OFFSET_TABLE. - * It comes up in complicated expressions such as - * _GLOBAL_OFFSET_TABLE_+[.-.L284], which cannot be expressed normally with - * the regular expressions. The fixup specified here when used at runtime - * implies that we should add the address of the GOT to the specified location, - * and as a result we have simplified the expression into something we can use. - */ -#define TC_RELOC_GLOBAL_OFFSET_TABLE BFD_RELOC_386_GOTPC - -/* This expression evaluates to false if the relocation is for a local object - for which we still want to do the relocation at runtime. True if we - are willing to perform this relocation while building the .o file. - This is only used for pcrel relocations, so GOTOFF does not need to be - checked here. I am not sure if some of the others are ever used with - pcrel, but it is easier to be safe than sorry. */ - -#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \ - ((FIX)->fx_r_type != BFD_RELOC_386_PLT32 \ - && (FIX)->fx_r_type != BFD_RELOC_386_GOT32 \ - && (FIX)->fx_r_type != BFD_RELOC_386_GOTPC) - -#define TARGET_ARCH bfd_arch_i386 - -#ifdef OBJ_AOUT -#ifdef TE_NetBSD -#define TARGET_FORMAT "a.out-i386-netbsd" -#endif -#ifdef TE_386BSD -#define TARGET_FORMAT "a.out-i386-bsd" -#endif -#ifdef TE_LINUX -#define TARGET_FORMAT "a.out-i386-linux" -#endif -#ifdef TE_Mach -#define TARGET_FORMAT "a.out-mach3" -#endif -#ifdef TE_DYNIX -#define TARGET_FORMAT "a.out-i386-dynix" -#endif -#ifndef TARGET_FORMAT -#define TARGET_FORMAT "a.out-i386" -#endif -#endif /* OBJ_AOUT */ - -#ifdef OBJ_ELF -#define TARGET_FORMAT "elf32-i386" -#endif - -#ifdef OBJ_MAYBE_ELF -#ifdef OBJ_MAYBE_COFF -extern const char *i386_target_format PARAMS ((void)); -#define TARGET_FORMAT i386_target_format () -#endif -#endif - -#else /* ! BFD_ASSEMBLER */ - -/* COFF STUFF */ - -#define COFF_MAGIC I386MAGIC -#define BFD_ARCH bfd_arch_i386 -#define COFF_FLAGS F_AR32WR -#define TC_COUNT_RELOC(x) ((x)->fx_addsy || (x)->fx_r_type==7) -#define TC_FORCE_RELOCATION(x) ((x)->fx_r_type==7) -#define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP) -extern short tc_coff_fix2rtype PARAMS ((struct fix *)); -#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag) -extern int tc_coff_sizemachdep PARAMS ((fragS *frag)); -#define SUB_SEGMENT_ALIGN(SEG) 2 -#define TC_RVA_RELOC 7 -/* Need this for PIC relocations */ -#define NEED_FX_R_TYPE - - -#ifdef TE_386BSD -/* The BSDI linker apparently rejects objects with a machine type of - M_386 (100). */ -#define AOUT_MACHTYPE 0 -#else -#define AOUT_MACHTYPE 100 -#endif - -#undef REVERSE_SORT_RELOCS - -#endif /* ! BFD_ASSEMBLER */ - -#ifdef BFD_ASSEMBLER -#define NO_RELOC BFD_RELOC_NONE -#else -#define NO_RELOC 0 -#endif -#define tc_coff_symbol_emit_hook(a) ; /* not used */ - -#ifndef BFD_ASSEMBLER -#ifndef OBJ_AOUT -#ifndef TE_PE -/* Local labels starts with .L */ -#define LOCAL_LABEL(name) (name[0] == '.' \ - && (name[1] == 'L' || name[1] == 'X' || name[1] == '.')) -#endif -#endif -#endif - -#define LOCAL_LABELS_FB 1 - -#define tc_aout_pre_write_hook(x) {;} /* not used */ -#define tc_crawl_symbol_chain(a) {;} /* not used */ -#define tc_headers_hook(a) {;} /* not used */ - -#define MAX_OPERANDS 3 /* max operands per insn */ -#define MAX_PREFIXES 5 /* max prefixes per opcode */ -#define MAX_IMMEDIATE_OPERANDS 2/* max immediates per insn */ -#define MAX_MEMORY_OPERANDS 2 /* max memory ref per insn (lcall uses 2) */ - -/* we define the syntax here (modulo base,index,scale syntax) */ -#define REGISTER_PREFIX '%' -#define IMMEDIATE_PREFIX '$' -#define ABSOLUTE_PREFIX '*' -#define PREFIX_SEPERATOR '/' - -#define TWO_BYTE_OPCODE_ESCAPE 0x0f -#define NOP_OPCODE (char) 0x90 - -/* register numbers */ -#define EBP_REG_NUM 5 -#define ESP_REG_NUM 4 - -/* modrm_byte.regmem for twobyte escape */ -#define ESCAPE_TO_TWO_BYTE_ADDRESSING ESP_REG_NUM -/* index_base_byte.index for no index register addressing */ -#define NO_INDEX_REGISTER ESP_REG_NUM -/* index_base_byte.base for no base register addressing */ -#define NO_BASE_REGISTER EBP_REG_NUM - -/* these are the att as opcode suffixes, making movl --> mov, for example */ -#define DWORD_OPCODE_SUFFIX 'l' -#define WORD_OPCODE_SUFFIX 'w' -#define BYTE_OPCODE_SUFFIX 'b' - -/* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */ -#define REGMEM_FIELD_HAS_REG 0x3/* always = 0x3 */ -#define REGMEM_FIELD_HAS_MEM (~REGMEM_FIELD_HAS_REG) - -#define END_OF_INSN '\0' - -/* - When an operand is read in it is classified by its type. This type includes - all the possible ways an operand can be used. Thus, '%eax' is both 'register - # 0' and 'The Accumulator'. In our language this is expressed by OR'ing - 'Reg32' (any 32 bit register) and 'Acc' (the accumulator). - Operands are classified so that we can match given operand types with - the opcode table in i386-opcode.h. - */ -#define Unknown 0x0 -/* register */ -#define Reg8 0x1 /* 8 bit reg */ -#define Reg16 0x2 /* 16 bit reg */ -#define Reg32 0x4 /* 32 bit reg */ -#define Reg (Reg8|Reg16|Reg32) /* gen'l register */ -#define WordReg (Reg16|Reg32) /* for push/pop operands */ -/* immediate */ -#define Imm8 0x8 /* 8 bit immediate */ -#define Imm8S 0x10 /* 8 bit immediate sign extended */ -#define Imm16 0x20 /* 16 bit immediate */ -#define Imm32 0x40 /* 32 bit immediate */ -#define Imm1 0x80 /* 1 bit immediate */ -#define ImmUnknown Imm32 /* for unknown expressions */ -#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */ -/* memory */ -#define Disp8 0x200 /* 8 bit displacement (for jumps) */ -#define Disp16 0x400 /* 16 bit displacement */ -#define Disp32 0x800 /* 32 bit displacement */ -#define Disp (Disp8|Disp16|Disp32) /* General displacement */ -#define DispUnknown Disp32 /* for unknown size displacements */ -#define Mem8 0x1000 -#define Mem16 0x2000 -#define Mem32 0x4000 -#define BaseIndex 0x8000 -#define Mem (Disp|Mem8|Mem16|Mem32|BaseIndex) /* General memory */ -#define WordMem (Mem16|Mem32|Disp|BaseIndex) -#define ByteMem (Mem8|Disp|BaseIndex) -/* specials */ -#define InOutPortReg 0x10000 /* register to hold in/out port addr = dx */ -#define ShiftCount 0x20000 /* register to hold shift cound = cl */ -#define Control 0x40000 /* Control register */ -#define Debug 0x80000 /* Debug register */ -#define Test 0x100000 /* Test register */ -#define FloatReg 0x200000 /* Float register */ -#define FloatAcc 0x400000 /* Float stack top %st(0) */ -#define SReg2 0x800000 /* 2 bit segment register */ -#define SReg3 0x1000000 /* 3 bit segment register */ -#define Acc 0x2000000 /* Accumulator %al or %ax or %eax */ -#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc) -#define JumpAbsolute 0x4000000 -#define Abs8 0x08000000 -#define Abs16 0x10000000 -#define Abs32 0x20000000 -#define Abs (Abs8|Abs16|Abs32) -#define RegMMX 0x40000000 /* MMX register */ - -#define Byte (Reg8|Imm8|Imm8S) -#define Word (Reg16|Imm16) -#define DWord (Reg32|Imm32) - -#define SMALLEST_DISP_TYPE(num) \ - fits_in_signed_byte(num) ? (Disp8|Disp32|Abs8|Abs32) : (Disp32|Abs32) - -typedef struct -{ - /* instruction name sans width suffix ("mov" for movl insns) */ - char *name; - - /* how many operands */ - unsigned int operands; - - /* base_opcode is the fundamental opcode byte with a optional prefix(es). */ - unsigned int base_opcode; - - /* extension_opcode is the 3 bit extension for group <n> insns. - If this template has no extension opcode (the usual case) use None */ - unsigned char extension_opcode; -#define None 0xff /* If no extension_opcode is possible. */ - - /* the bits in opcode_modifier are used to generate the final opcode from - the base_opcode. These bits also are used to detect alternate forms of - the same instruction */ - unsigned int opcode_modifier; - - /* opcode_modifier bits: */ -#define W 0x1 /* set if operands are words or dwords */ -#define D 0x2 /* D = 0 if Reg --> Regmem; D = 1 if Regmem --> Reg */ - /* direction flag for floating insns: MUST BE 0x400 */ -#define FloatD 0x400 - /* shorthand */ -#define DW (D|W) -#define ShortForm 0x10 /* register is in low 3 bits of opcode */ -#define ShortFormW 0x20 /* ShortForm and W bit is 0x8 */ -#define Seg2ShortForm 0x40 /* encoding of load segment reg insns */ -#define Seg3ShortForm 0x80 /* fs/gs segment register insns. */ -#define Jump 0x100 /* special case for jump insns. */ -#define JumpInterSegment 0x200 /* special case for intersegment leaps/calls */ - /* 0x400 CANNOT BE USED since it's already used by FloatD above */ -#define DONT_USE 0x400 -#define NoModrm 0x800 -#define Modrm 0x1000 -#define imulKludge 0x2000 -#define JumpByte 0x4000 -#define JumpDword 0x8000 -#define ReverseRegRegmem 0x10000 -#define Data16 0x20000 /* needs data prefix if in 32-bit mode */ -#define Data32 0x40000 /* needs data prefix if in 16-bit mode */ -#define iclrKludge 0x80000 /* used to convert clr to xor */ -#define FWait 0x100000 /* instruction needs FWAIT */ - - /* (opcode_modifier & COMES_IN_ALL_SIZES) is true if the - instuction comes in byte, word, and dword sizes and is encoded into - machine code in the canonical way. */ -#define COMES_IN_ALL_SIZES (W) - - /* (opcode_modifier & COMES_IN_BOTH_DIRECTIONS) indicates that the - source and destination operands can be reversed by setting either - the D (for integer insns) or the FloatD (for floating insns) bit - in base_opcode. */ -#define COMES_IN_BOTH_DIRECTIONS (D|FloatD) - - /* operand_types[i] describes the type of operand i. This is made - by OR'ing together all of the possible type masks. (e.g. - 'operand_types[i] = Reg|Imm' specifies that operand i can be - either a register or an immediate operand */ - unsigned int operand_types[3]; -} -template; - -/* - 'templates' is for grouping together 'template' structures for opcodes - of the same name. This is only used for storing the insns in the grand - ole hash table of insns. - The templates themselves start at START and range up to (but not including) - END. - */ -typedef struct - { - template *start; - template *end; - } templates; - -/* these are for register name --> number & type hash lookup */ -typedef struct - { - char *reg_name; - unsigned int reg_type; - unsigned int reg_num; - } - -reg_entry; - -typedef struct - { - char *seg_name; - unsigned int seg_prefix; - } - -seg_entry; - -/* these are for prefix name --> prefix code hash lookup */ -typedef struct - { - char *prefix_name; - unsigned char prefix_code; - } - -prefix_entry; - -/* 386 operand encoding bytes: see 386 book for details of this. */ -typedef struct - { - unsigned regmem:3; /* codes register or memory operand */ - unsigned reg:3; /* codes register operand (or extended opcode) */ - unsigned mode:2; /* how to interpret regmem & reg */ - } - -modrm_byte; - -/* 386 opcode byte to code indirect addressing. */ -typedef struct - { - unsigned base:3; - unsigned index:3; - unsigned scale:2; - } - -base_index_byte; - -/* The name of the global offset table generated by the compiler. Allow - this to be overridden if need be. */ -#ifndef GLOBAL_OFFSET_TABLE_NAME -#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" -#endif - -#ifdef BFD_ASSEMBLER -void i386_validate_fix PARAMS ((struct fix *)); -#define TC_VALIDATE_FIX(FIXP,SEGTYPE,SKIP) i386_validate_fix(FIXP) -#endif - -#endif /* TC_I386 */ - -#define md_operand(x) - -extern const struct relax_type md_relax_table[]; -#define TC_GENERIC_RELAX_TABLE md_relax_table - - -extern int flag_16bit_code; - -#ifdef BFD_ASSEMBLER -#define md_maybe_text() \ - ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) -#else -#define md_maybe_text() \ - (now_seg != data_section && now_seg != bss_section) -#endif - -#define md_do_align(n, fill, len, max, around) \ -if ((n) && !need_pass_2 \ - && (!(fill) || ((char)*(fill) == (char)0x90 && (len) == 1)) \ - && md_maybe_text ()) \ - { \ - char *p; \ - p = frag_var (rs_align_code, 15, 1, (relax_substateT) max, \ - (symbolS *) 0, (offsetT) (n), (char *) 0); \ - *p = 0x90; \ - goto around; \ - } - -extern void i386_align_code PARAMS ((fragS *, int)); - -#define HANDLE_ALIGN(fragP) \ -if (fragP->fr_type == rs_align_code) \ - i386_align_code (fragP, (fragP->fr_next->fr_address \ - - fragP->fr_address \ - - fragP->fr_fix)); - -/* call md_apply_fix3 with segment instead of md_apply_fix */ -#define MD_APPLY_FIX3 - -void i386_print_statistics PARAMS ((FILE *)); -#define tc_print_statistics i386_print_statistics - -#define md_number_to_chars number_to_chars_littleendian - -#ifdef SCO_ELF -#define tc_init_after_args() sco_id () -extern void sco_id PARAMS ((void)); -#endif - -#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ - -/* end of tc-i386.h */ diff --git a/contrib/binutils/gas/config/tc-m68851.h b/contrib/binutils/gas/config/tc-m68851.h deleted file mode 100644 index 0f6d74133752..000000000000 --- a/contrib/binutils/gas/config/tc-m68851.h +++ /dev/null @@ -1,304 +0,0 @@ -/* This file is tc-m68851.h - - Copyright (C) 1987-1992 Free Software Foundation, Inc. - - 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 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. */ - -/* - * pmmu.h - */ - -/* I suppose we have to copyright this file. Someone on the net sent it - to us as part of the changes for the m68851 Memory Management Unit */ - -/* Copyright (C) 1987 Free Software Foundation, Inc. - - This file is part of Gas, the GNU Assembler. - - The GNU assembler is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY. No author or distributor - accepts responsibility to anyone for the consequences of using it - or for whether it serves any particular purpose or works at all, - unless he says so in writing. Refer to the GNU Assembler General - Public License for full details. - - Everyone is granted permission to copy, modify and redistribute - the GNU Assembler, but only under the conditions described in the - GNU Assembler General Public License. A copy of this license is - supposed to have been given to you along with the GNU Assembler - so you can know your rights and responsibilities. It should be - in a file named COPYING. Among other things, the copyright - notice and this notice must be preserved on all copies. */ - -#ifdef m68851 - -/* - I didn't use much imagination in choosing the - following codes, so many of them aren't very - mnemonic. -rab - - P pmmu register - Possible values: - 000 TC Translation Control reg - 100 CAL Current Access Level - 101 VAL Validate Access Level - 110 SCC Stack Change Control - 111 AC Access Control - - W wide pmmu registers - Possible values: - 001 DRP Dma Root Pointer - 010 SRP Supervisor Root Pointer - 011 CRP Cpu Root Pointer - - f function code register - 0 SFC - 1 DFC - - V VAL register only - - X BADx, BACx - 100 BAD Breakpoint Acknowledge Data - 101 BAC Breakpoint Acknowledge Control - - Y PSR - Z PCSR - - | memory (modes 2-6, 7.*) - - */ - -/* - * these defines should be in m68k.c but - * i put them here to keep all the m68851 stuff - * together -rab - * JF--Make sure these #s don't clash with the ones in m68k.c - * That would be BAD. - */ -#define TC (FPS+1) /* 48 */ -#define DRP (TC+1) /* 49 */ -#define SRP (DRP+1) /* 50 */ -#define CRP (SRP+1) /* 51 */ -#define CAL (CRP+1) /* 52 */ -#define VAL (CAL+1) /* 53 */ -#define SCC (VAL+1) /* 54 */ -#define AC (SCC+1) /* 55 */ -#define BAD (AC+1) /* 56,57,58,59, 60,61,62,63 */ -#define BAC (BAD+8) /* 64,65,66,67, 68,69,70,71 */ -#define PSR (BAC+8) /* 72 */ -#define PCSR (PSR+1) /* 73 */ - -/* name */ /* opcode */ /* match */ /* args */ - -{"pbac", one(0xf0c7), one(0xffbf), "Bc"}, -{"pbacw", one(0xf087), one(0xffbf), "Bc"}, -{"pbas", one(0xf0c6), one(0xffbf), "Bc"}, -{"pbasw", one(0xf086), one(0xffbf), "Bc"}, -{"pbbc", one(0xf0c1), one(0xffbf), "Bc"}, -{"pbbcw", one(0xf081), one(0xffbf), "Bc"}, -{"pbbs", one(0xf0c0), one(0xffbf), "Bc"}, -{"pbbsw", one(0xf080), one(0xffbf), "Bc"}, -{"pbcc", one(0xf0cf), one(0xffbf), "Bc"}, -{"pbccw", one(0xf08f), one(0xffbf), "Bc"}, -{"pbcs", one(0xf0ce), one(0xffbf), "Bc"}, -{"pbcsw", one(0xf08e), one(0xffbf), "Bc"}, -{"pbgc", one(0xf0cd), one(0xffbf), "Bc"}, -{"pbgcw", one(0xf08d), one(0xffbf), "Bc"}, -{"pbgs", one(0xf0cc), one(0xffbf), "Bc"}, -{"pbgsw", one(0xf08c), one(0xffbf), "Bc"}, -{"pbic", one(0xf0cb), one(0xffbf), "Bc"}, -{"pbicw", one(0xf08b), one(0xffbf), "Bc"}, -{"pbis", one(0xf0ca), one(0xffbf), "Bc"}, -{"pbisw", one(0xf08a), one(0xffbf), "Bc"}, -{"pblc", one(0xf0c3), one(0xffbf), "Bc"}, -{"pblcw", one(0xf083), one(0xffbf), "Bc"}, -{"pbls", one(0xf0c2), one(0xffbf), "Bc"}, -{"pblsw", one(0xf082), one(0xffbf), "Bc"}, -{"pbsc", one(0xf0c5), one(0xffbf), "Bc"}, -{"pbscw", one(0xf085), one(0xffbf), "Bc"}, -{"pbss", one(0xf0c4), one(0xffbf), "Bc"}, -{"pbssw", one(0xf084), one(0xffbf), "Bc"}, -{"pbwc", one(0xf0c9), one(0xffbf), "Bc"}, -{"pbwcw", one(0xf089), one(0xffbf), "Bc"}, -{"pbws", one(0xf0c8), one(0xffbf), "Bc"}, -{"pbwsw", one(0xf088), one(0xffbf), "Bc"}, - - -{"pdbac", two(0xf048, 0x0007), two(0xfff8, 0xffff), "DsBw"}, -{"pdbas", two(0xf048, 0x0006), two(0xfff8, 0xffff), "DsBw"}, -{"pdbbc", two(0xf048, 0x0001), two(0xfff8, 0xffff), "DsBw"}, -{"pdbbs", two(0xf048, 0x0000), two(0xfff8, 0xffff), "DsBw"}, -{"pdbcc", two(0xf048, 0x000f), two(0xfff8, 0xffff), "DsBw"}, -{"pdbcs", two(0xf048, 0x000e), two(0xfff8, 0xffff), "DsBw"}, -{"pdbgc", two(0xf048, 0x000d), two(0xfff8, 0xffff), "DsBw"}, -{"pdbgs", two(0xf048, 0x000c), two(0xfff8, 0xffff), "DsBw"}, -{"pdbic", two(0xf048, 0x000b), two(0xfff8, 0xffff), "DsBw"}, -{"pdbis", two(0xf048, 0x000a), two(0xfff8, 0xffff), "DsBw"}, -{"pdblc", two(0xf048, 0x0003), two(0xfff8, 0xffff), "DsBw"}, -{"pdbls", two(0xf048, 0x0002), two(0xfff8, 0xffff), "DsBw"}, -{"pdbsc", two(0xf048, 0x0005), two(0xfff8, 0xffff), "DsBw"}, -{"pdbss", two(0xf048, 0x0004), two(0xfff8, 0xffff), "DsBw"}, -{"pdbwc", two(0xf048, 0x0009), two(0xfff8, 0xffff), "DsBw"}, -{"pdbws", two(0xf048, 0x0008), two(0xfff8, 0xffff), "DsBw"}, - -{"pflusha", two(0xf000, 0x2400), two(0xffff, 0xffff), "" }, - -{"pflush", two(0xf000, 0x3010), two(0xffc0, 0xfe10), "T3T9" }, -{"pflush", two(0xf000, 0x3810), two(0xffc0, 0xfe10), "T3T9&s" }, -{"pflush", two(0xf000, 0x3008), two(0xffc0, 0xfe18), "D3T9" }, -{"pflush", two(0xf000, 0x3808), two(0xffc0, 0xfe18), "D3T9&s" }, -{"pflush", two(0xf000, 0x3000), two(0xffc0, 0xfe1e), "f3T9" }, -{"pflush", two(0xf000, 0x3800), two(0xffc0, 0xfe1e), "f3T9&s" }, - -{"pflushs", two(0xf000, 0x3410), two(0xfff8, 0xfe10), "T3T9" }, -{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe00), "T3T9&s" }, -{"pflushs", two(0xf000, 0x3408), two(0xfff8, 0xfe18), "D3T9" }, -{"pflushs", two(0xf000, 0x3c08), two(0xfff8, 0xfe18), "D3T9&s" }, -{"pflushs", two(0xf000, 0x3400), two(0xfff8, 0xfe1e), "f3T9" }, -{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe1e), "f3T9&s"}, - -{"pflushr", two(0xf000, 0xa000), two(0xffc0, 0xffff), "|s" }, - -{"ploadr", two(0xf000, 0x2210), two(0xffc0, 0xfff0), "T3&s" }, -{"ploadr", two(0xf000, 0x2208), two(0xffc0, 0xfff8), "D3&s" }, -{"ploadr", two(0xf000, 0x2200), two(0xffc0, 0xfffe), "f3&s" }, -{"ploadw", two(0xf000, 0x2010), two(0xffc0, 0xfff0), "T3&s" }, -{"ploadw", two(0xf000, 0x2008), two(0xffc0, 0xfff8), "D3&s" }, -{"ploadw", two(0xf000, 0x2000), two(0xffc0, 0xfffe), "f3&s" }, - - /* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */ -{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "*sP8" }, -{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "P8%s" }, -{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "|sW8" }, -{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "W8~s" }, - - /* BADx, BACx */ -{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xe3e3), "*sX3" }, -{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xe3e3), "X3%s" }, - - /* PSR, PCSR */ - /* {"pmove", two(0xf000, 0x6100), two(oxffc0, oxffff), "*sZ8" }, */ -{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xffff), "*sY8" }, -{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xffff), "Y8%s" }, -{"pmove", two(0xf000, 0x6600), two(0xffc0, 0xffff), "Z8%s" }, - -{"prestore", one(0xf140), one(0xffc0), "&s"}, -{"prestore", one(0xf158), one(0xfff8), "+s"}, -{"psave", one(0xf100), one(0xffc0), "&s"}, -{"psave", one(0xf100), one(0xffc0), "+s"}, - -{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "@s"}, -{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "@s"}, -{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "@s"}, -{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "@s"}, -{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "@s"}, -{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "@s"}, -{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "@s"}, -{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "@s"}, -{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "@s"}, -{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "@s"}, -{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "@s"}, -{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "@s"}, -{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "@s"}, -{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "@s"}, -{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "@s"}, -{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "@s"}, - -{"ptestr", two(0xf000, 0x8210), two(0xffc0, 0xe3f0), "T3&sQ8" }, -{"ptestr", two(0xf000, 0x8310), two(0xffc0, 0xe310), "T3&sQ8A9" }, -{"ptestr", two(0xf000, 0x8208), two(0xffc0, 0xe3f8), "D3&sQ8" }, -{"ptestr", two(0xf000, 0x8308), two(0xffc0, 0xe318), "D3&sQ8A9" }, -{"ptestr", two(0xf000, 0x8200), two(0xffc0, 0xe3fe), "f3&sQ8" }, -{"ptestr", two(0xf000, 0x8300), two(0xffc0, 0xe31e), "f3&sQ8A9" }, - -{"ptestw", two(0xf000, 0x8010), two(0xffc0, 0xe3f0), "T3&sQ8" }, -{"ptestw", two(0xf000, 0x8110), two(0xffc0, 0xe310), "T3&sQ8A9" }, -{"ptestw", two(0xf000, 0x8008), two(0xffc0, 0xe3f8), "D3&sQ8" }, -{"ptestw", two(0xf000, 0x8108), two(0xffc0, 0xe318), "D3&sQ8A9" }, -{"ptestw", two(0xf000, 0x8000), two(0xffc0, 0xe3fe), "f3&sQ8" }, -{"ptestw", two(0xf000, 0x8100), two(0xffc0, 0xe31e), "f3&sQ8A9" }, - -{"ptrapacw", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w"}, -{"ptrapacl", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l"}, -{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), ""}, - -{"ptrapasw", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w"}, -{"ptrapasl", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l"}, -{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), ""}, - -{"ptrapbcw", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w"}, -{"ptrapbcl", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l"}, -{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), ""}, - -{"ptrapbsw", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w"}, -{"ptrapbsl", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l"}, -{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), ""}, - -{"ptrapccw", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w"}, -{"ptrapccl", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l"}, -{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), ""}, - -{"ptrapcsw", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w"}, -{"ptrapcsl", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l"}, -{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), ""}, - -{"ptrapgcw", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w"}, -{"ptrapgcl", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l"}, -{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), ""}, - -{"ptrapgsw", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w"}, -{"ptrapgsl", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l"}, -{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), ""}, - -{"ptrapicw", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w"}, -{"ptrapicl", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l"}, -{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), ""}, - -{"ptrapisw", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w"}, -{"ptrapisl", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l"}, -{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), ""}, - -{"ptraplcw", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w"}, -{"ptraplcl", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l"}, -{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), ""}, - -{"ptraplsw", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w"}, -{"ptraplsl", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l"}, -{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), ""}, - -{"ptrapscw", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w"}, -{"ptrapscl", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l"}, -{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), ""}, - -{"ptrapssw", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w"}, -{"ptrapssl", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l"}, -{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), ""}, - -{"ptrapwcw", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w"}, -{"ptrapwcl", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l"}, -{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), ""}, - -{"ptrapwsw", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w"}, -{"ptrapwsl", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l"}, -{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), ""}, - -{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s"}, -{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s" }, - -#endif /* m68851 */ - -/* end of tc-m68851.h */ diff --git a/contrib/binutils/gas/config/tc-sh.c b/contrib/binutils/gas/config/tc-sh.c deleted file mode 100644 index eaa6146eea75..000000000000 --- a/contrib/binutils/gas/config/tc-sh.c +++ /dev/null @@ -1,2335 +0,0 @@ -/* tc-sh.c -- Assemble code for the Hitachi Super-H - Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation. - - 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 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. */ - -/* - Written By Steve Chamberlain - sac@cygnus.com - */ - -#include <stdio.h> -#include "as.h" -#include "bfd.h" -#include "subsegs.h" -#define DEFINE_TABLE -#include "opcodes/sh-opc.h" -#include <ctype.h> -const char comment_chars[] = "!"; -const char line_separator_chars[] = ";"; -const char line_comment_chars[] = "!#"; - -static void s_uses PARAMS ((int)); - -static void sh_count_relocs PARAMS ((bfd *, segT, PTR)); -static void sh_frob_section PARAMS ((bfd *, segT, PTR)); - -/* 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 - */ - -void cons (); -void s_align_bytes (); -static void s_uacons PARAMS ((int)); - -int shl = 0; - -static void -little (ignore) - int ignore; -{ - shl = 1; - target_big_endian = 0; -} - -const pseudo_typeS md_pseudo_table[] = -{ - {"int", cons, 4}, - {"word", cons, 2}, - {"form", listing_psize, 0}, - {"little", little, 0}, - {"heading", listing_title, 0}, - {"import", s_ignore, 0}, - {"page", listing_eject, 0}, - {"program", s_ignore, 0}, - {"uses", s_uses, 0}, - {"uaword", s_uacons, 2}, - {"ualong", s_uacons, 4}, - {0, 0, 0} -}; - -/*int md_reloc_size; */ - -int sh_relax; /* set if -relax seen */ - -/* Whether -small was seen. */ - -int sh_small; - -const char EXP_CHARS[] = "eE"; - -/* 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 JREG 14 /* Register used as a temp when relaxing */ -#define ENCODE_RELAX(what,length) (((what) << 4) + (length)) -#define GET_WHAT(x) ((x>>4)) - -/* These are the two types of relaxable instrction */ -#define COND_JUMP 1 -#define UNCOND_JUMP 2 - -#define UNDEF_DISP 0 -#define COND8 1 -#define COND12 2 -#define COND32 3 -#define UNCOND12 1 -#define UNCOND32 2 -#define UNDEF_WORD_DISP 4 -#define END 5 - -#define UNCOND12 1 -#define UNCOND32 2 - -/* Branch displacements are from the address of the branch plus - four, thus all minimum and maximum values have 4 added to them. */ -#define COND8_F 258 -#define COND8_M -252 -#define COND8_LENGTH 2 - -/* There is one extra instruction before the branch, so we must add - two more bytes to account for it. */ -#define COND12_F 4100 -#define COND12_M -4090 -#define COND12_LENGTH 6 - -/* ??? The minimum and maximum values are wrong, but this does not matter - since this relocation type is not supported yet. */ -#define COND32_F (1<<30) -#define COND32_M -(1<<30) -#define COND32_LENGTH 14 - -#define UNCOND12_F 4098 -#define UNCOND12_M -4092 -#define UNCOND12_LENGTH 2 - -/* ??? The minimum and maximum values are wrong, but this does not matter - since this relocation type is not supported yet. */ -#define UNCOND32_F (1<<30) -#define UNCOND32_M -(1<<30) -#define UNCOND32_LENGTH 14 - -const relax_typeS md_relax_table[C (END, 0)] = { - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, - - { 0 }, - /* C (COND_JUMP, COND8) */ - { COND8_F, COND8_M, COND8_LENGTH, C (COND_JUMP, COND12) }, - /* C (COND_JUMP, COND12) */ - { COND12_F, COND12_M, COND12_LENGTH, C (COND_JUMP, COND32), }, - /* C (COND_JUMP, COND32) */ - { COND32_F, COND32_M, COND32_LENGTH, 0, }, - { 0 }, { 0 }, { 0 }, { 0 }, - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, - - { 0 }, - /* C (UNCOND_JUMP, UNCOND12) */ - { UNCOND12_F, UNCOND12_M, UNCOND12_LENGTH, C (UNCOND_JUMP, UNCOND32), }, - /* C (UNCOND_JUMP, UNCOND32) */ - { UNCOND32_F, UNCOND32_M, UNCOND32_LENGTH, 0, }, - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, - { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, -}; - -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 - */ - -void -md_begin () -{ - sh_opcode_info *opcode; - char *prev_name = ""; - - if (! shl) - target_big_endian = 1; - - opcode_hash_control = hash_new (); - - /* Insert unique names into hash table */ - for (opcode = sh_table; opcode->name; opcode++) - { - if (strcmp (prev_name, opcode->name)) - { - prev_name = opcode->name; - hash_insert (opcode_hash_control, opcode->name, (char *) opcode); - } - else - { - /* Make all the opcodes with the same name point to the same - string */ - opcode->name = prev_name; - } - } -} - -static int reg_m; -static int reg_n; -static int reg_b; - -static expressionS immediate; /* absolute expression */ - -typedef struct - { - sh_arg_type type; - int reg; - } - -sh_operand_info; - -/* try and parse a reg name, returns number of chars consumed */ -static int -parse_reg (src, mode, reg) - char *src; - int *mode; - int *reg; -{ - /* We use !isalnum for the next character after the register name, to - make sure that we won't accidentally recognize a symbol name such as - 'sram' as being a reference to the register 'sr'. */ - - if (src[0] == 'r') - { - if (src[1] >= '0' && src[1] <= '7' && strncmp(&src[2], "_bank", 5) == 0 - && ! isalnum (src[7])) - { - *mode = A_REG_B; - *reg = (src[1] - '0'); - return 7; - } - } - - if (src[0] == 'r') - { - if (src[1] == '1') - { - if (src[2] >= '0' && src[2] <= '5' && ! isalnum (src[3])) - { - *mode = A_REG_N; - *reg = 10 + src[2] - '0'; - return 3; - } - } - if (src[1] >= '0' && src[1] <= '9' && ! isalnum (src[2])) - { - *mode = A_REG_N; - *reg = (src[1] - '0'); - return 2; - } - } - - if (src[0] == 's' && src[1] == 's' && src[2] == 'r' && ! isalnum (src[3])) - { - *mode = A_SSR; - return 3; - } - - if (src[0] == 's' && src[1] == 'p' && src[2] == 'c' && ! isalnum (src[3])) - { - *mode = A_SPC; - return 3; - } - - if (src[0] == 's' && src[1] == 'g' && src[2] == 'r' && ! isalnum (src[3])) - { - *mode = A_SGR; - return 3; - } - - if (src[0] == 'd' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) - { - *mode = A_DBR; - return 3; - } - - if (src[0] == 's' && src[1] == 'r' && ! isalnum (src[2])) - { - *mode = A_SR; - return 2; - } - - if (src[0] == 's' && src[1] == 'p' && ! isalnum (src[2])) - { - *mode = A_REG_N; - *reg = 15; - return 2; - } - - if (src[0] == 'p' && src[1] == 'r' && ! isalnum (src[2])) - { - *mode = A_PR; - return 2; - } - if (src[0] == 'p' && src[1] == 'c' && ! isalnum (src[2])) - { - *mode = A_DISP_PC; - return 2; - } - if (src[0] == 'g' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) - { - *mode = A_GBR; - return 3; - } - if (src[0] == 'v' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) - { - *mode = A_VBR; - return 3; - } - - if (src[0] == 'm' && src[1] == 'a' && src[2] == 'c' && ! isalnum (src[4])) - { - if (src[3] == 'l') - { - *mode = A_MACL; - return 4; - } - if (src[3] == 'h') - { - *mode = A_MACH; - return 4; - } - } - if (src[0] == 'f' && src[1] == 'r') - { - if (src[2] == '1') - { - if (src[3] >= '0' && src[3] <= '5' && ! isalnum (src[4])) - { - *mode = F_REG_N; - *reg = 10 + src[3] - '0'; - return 4; - } - } - if (src[2] >= '0' && src[2] <= '9' && ! isalnum (src[3])) - { - *mode = F_REG_N; - *reg = (src[2] - '0'); - return 3; - } - } - if (src[0] == 'd' && src[1] == 'r') - { - if (src[2] == '1') - { - if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1) - && ! isalnum (src[4])) - { - *mode = D_REG_N; - *reg = 10 + src[3] - '0'; - return 4; - } - } - if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1) - && ! isalnum (src[3])) - { - *mode = D_REG_N; - *reg = (src[2] - '0'); - return 3; - } - } - if (src[0] == 'x' && src[1] == 'd') - { - if (src[2] == '1') - { - if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1) - && ! isalnum (src[4])) - { - *mode = X_REG_N; - *reg = 11 + src[3] - '0'; - return 4; - } - } - if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1) - && ! isalnum (src[3])) - { - *mode = X_REG_N; - *reg = (src[2] - '0') + 1; - return 3; - } - } - if (src[0] == 'f' && src[1] == 'v') - { - if (src[2] == '1'&& src[3] == '2' && ! isalnum (src[4])) - { - *mode = V_REG_N; - *reg = 12; - return 4; - } - if ((src[2] == '0' || src[2] == '4' || src[2] == '8') && ! isalnum (src[3])) - { - *mode = V_REG_N; - *reg = (src[2] - '0'); - return 3; - } - } - if (src[0] == 'f' && src[1] == 'p' && src[2] == 'u' && src[3] == 'l' - && ! isalnum (src[4])) - { - *mode = FPUL_N; - return 4; - } - - if (src[0] == 'f' && src[1] == 'p' && src[2] == 's' && src[3] == 'c' - && src[4] == 'r' && ! isalnum (src[5])) - { - *mode = FPSCR_N; - return 5; - } - - if (src[0] == 'x' && src[1] == 'm' && src[2] == 't' && src[3] == 'r' - && src[4] == 'x' && ! isalnum (src[5])) - { - *mode = XMTRX_M4; - return 5; - } - - return 0; -} - -static symbolS *dot() -{ - const char *fake; - - /* JF: '.' is pseudo symbol with value of current location - in current segment. */ - fake = FAKE_LABEL_NAME; - return symbol_new (fake, - now_seg, - (valueT) frag_now_fix (), - frag_now); - -} - - -static -char * -parse_exp (s) - char *s; -{ - char *save; - char *new; - - save = input_line_pointer; - input_line_pointer = s; - expression (&immediate); - if (immediate.X_op == O_absent) - as_bad ("missing operand"); - new = input_line_pointer; - input_line_pointer = save; - return new; -} - - -/* The many forms of operand: - - Rn Register direct - @Rn Register indirect - @Rn+ Autoincrement - @-Rn Autodecrement - @(disp:4,Rn) - @(disp:8,GBR) - @(disp:8,PC) - - @(R0,Rn) - @(R0,GBR) - - disp:8 - disp:12 - #imm8 - pr, gbr, vbr, macl, mach - - */ - -static -char * -parse_at (src, op) - char *src; - sh_operand_info *op; -{ - int len; - int mode; - src++; - if (src[0] == '-') - { - /* Must be predecrement */ - src++; - - len = parse_reg (src, &mode, &(op->reg)); - if (mode != A_REG_N) - as_bad ("illegal register after @-"); - - op->type = A_DEC_N; - src += len; - } - else if (src[0] == '(') - { - /* Could be @(disp, rn), @(disp, gbr), @(disp, pc), @(r0, gbr) or - @(r0, rn) */ - src++; - len = parse_reg (src, &mode, &(op->reg)); - if (len && mode == A_REG_N) - { - src += len; - if (op->reg != 0) - { - as_bad ("must be @(r0,...)"); - } - if (src[0] == ',') - src++; - /* Now can be rn or gbr */ - len = parse_reg (src, &mode, &(op->reg)); - if (mode == A_GBR) - { - op->type = A_R0_GBR; - } - else if (mode == A_REG_N) - { - op->type = A_IND_R0_REG_N; - } - else - { - as_bad ("syntax error in @(r0,...)"); - } - } - else - { - /* Must be an @(disp,.. thing) */ - src = parse_exp (src); - if (src[0] == ',') - src++; - /* Now can be rn, gbr or pc */ - len = parse_reg (src, &mode, &op->reg); - if (len) - { - if (mode == A_REG_N) - { - op->type = A_DISP_REG_N; - } - else if (mode == A_GBR) - { - op->type = A_DISP_GBR; - } - else if (mode == A_DISP_PC) - { - /* Turn a plain @(4,pc) into @(.+4,pc) */ - if (immediate.X_op == O_constant) { - immediate.X_add_symbol = dot(); - immediate.X_op = O_symbol; - } - op->type = A_DISP_PC; - } - else - { - as_bad ("syntax error in @(disp,[Rn, gbr, pc])"); - } - } - else - { - as_bad ("syntax error in @(disp,[Rn, gbr, pc])"); - } - } - src += len; - if (src[0] != ')') - as_bad ("expecting )"); - else - src++; - } - else - { - src += parse_reg (src, &mode, &(op->reg)); - if (mode != A_REG_N) - { - as_bad ("illegal register after @"); - } - if (src[0] == '+') - { - op->type = A_INC_N; - src++; - } - else - { - op->type = A_IND_N; - } - } - return src; -} - -static void -get_operand (ptr, op) - char **ptr; - sh_operand_info *op; -{ - char *src = *ptr; - int mode = -1; - unsigned int len; - - if (src[0] == '#') - { - src++; - *ptr = parse_exp (src); - op->type = A_IMM; - return; - } - - else if (src[0] == '@') - { - *ptr = parse_at (src, op); - return; - } - len = parse_reg (src, &mode, &(op->reg)); - if (len) - { - *ptr = src + len; - op->type = mode; - return; - } - else - { - /* Not a reg, the only thing left is a displacement */ - *ptr = parse_exp (src); - op->type = A_DISP_PC; - return; - } -} - -static -char * -get_operands (info, args, operand) - sh_opcode_info *info; - char *args; - sh_operand_info *operand; - -{ - char *ptr = args; - if (info->arg[0]) - { - ptr++; - - get_operand (&ptr, operand + 0); - if (info->arg[1]) - { - if (*ptr == ',') - { - ptr++; - } - get_operand (&ptr, operand + 1); - if (info->arg[2]) - { - if (*ptr == ',') - { - ptr++; - } - get_operand (&ptr, operand + 2); - } - else - { - operand[2].type = 0; - } - } - else - { - operand[1].type = 0; - operand[2].type = 0; - } - } - else - { - operand[0].type = 0; - operand[1].type = 0; - operand[2].type = 0; - } - return ptr; -} - -/* Passed a pointer to a list of opcodes which use different - addressing modes, return the opcode which matches the opcodes - provided - */ - -static -sh_opcode_info * -get_specific (opcode, operands) - sh_opcode_info *opcode; - sh_operand_info *operands; -{ - sh_opcode_info *this_try = opcode; - char *name = opcode->name; - int n = 0; - while (opcode->name) - { - this_try = opcode++; - if (this_try->name != name) - { - /* We've looked so far down the table that we've run out of - opcodes with the same name */ - return 0; - } - /* look at both operands needed by the opcodes and provided by - the user - since an arg test will often fail on the same arg - again and again, we'll try and test the last failing arg the - first on each opcode try */ - - for (n = 0; this_try->arg[n]; n++) - { - sh_operand_info *user = operands + n; - sh_arg_type arg = this_try->arg[n]; - switch (arg) - { - case A_IMM: - case A_BDISP12: - case A_BDISP8: - case A_DISP_GBR: - case A_DISP_PC: - case A_MACH: - case A_PR: - case A_MACL: - if (user->type != arg) - goto fail; - break; - case A_R0: - /* opcode needs r0 */ - if (user->type != A_REG_N || user->reg != 0) - goto fail; - break; - case A_R0_GBR: - if (user->type != A_R0_GBR || user->reg != 0) - goto fail; - break; - case F_FR0: - if (user->type != F_REG_N || user->reg != 0) - goto fail; - break; - - case A_REG_N: - case A_INC_N: - case A_DEC_N: - case A_IND_N: - case A_IND_R0_REG_N: - case A_DISP_REG_N: - case F_REG_N: - case D_REG_N: - case X_REG_N: - case V_REG_N: - case FPUL_N: - case FPSCR_N: - /* Opcode needs rn */ - if (user->type != arg) - goto fail; - reg_n = user->reg; - break; - case FD_REG_N: - if (user->type != F_REG_N && user->type != D_REG_N) - goto fail; - reg_n = user->reg; - break; - case DX_REG_N: - if (user->type != D_REG_N && user->type != X_REG_N) - goto fail; - reg_n = user->reg; - break; - case A_GBR: - case A_SR: - case A_VBR: - case A_SSR: - case A_SPC: - case A_SGR: - case A_DBR: - if (user->type != arg) - goto fail; - break; - - case A_REG_B: - if (user->type != arg) - goto fail; - reg_b = user->reg; - break; - - case A_REG_M: - case A_INC_M: - case A_DEC_M: - case A_IND_M: - case A_IND_R0_REG_M: - case A_DISP_REG_M: - /* Opcode needs rn */ - if (user->type != arg - A_REG_M + A_REG_N) - goto fail; - reg_m = user->reg; - break; - - case F_REG_M: - case D_REG_M: - case X_REG_M: - case V_REG_M: - case FPUL_M: - case FPSCR_M: - /* Opcode needs rn */ - if (user->type != arg - F_REG_M + F_REG_N) - goto fail; - reg_m = user->reg; - break; - case DX_REG_M: - if (user->type != D_REG_N && user->type != X_REG_N) - goto fail; - reg_m = user->reg; - break; - case XMTRX_M4: - if (user->type != XMTRX_M4) - goto fail; - reg_m = 4; - break; - - default: - printf ("unhandled %d\n", arg); - goto fail; - } - } - return this_try; - fail:; - } - - return 0; -} - -int -check (operand, low, high) - 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); - } - return operand->X_add_number; -} - - -static void -insert (where, how, pcrel) - char *where; - int how; - int pcrel; -{ - fix_new_exp (frag_now, - where - frag_now->fr_literal, - 2, - &immediate, - pcrel, - how); -} - -static void -build_relax (opcode) - sh_opcode_info *opcode; -{ - int high_byte = target_big_endian ? 0 : 1; - char *p; - - if (opcode->arg[0] == A_BDISP8) - { - p = frag_var (rs_machine_dependent, - md_relax_table[C (COND_JUMP, COND32)].rlx_length, - md_relax_table[C (COND_JUMP, COND8)].rlx_length, - C (COND_JUMP, 0), - immediate.X_add_symbol, - immediate.X_add_number, - 0); - p[high_byte] = (opcode->nibbles[0] << 4) | (opcode->nibbles[1]); - } - else if (opcode->arg[0] == A_BDISP12) - { - p = frag_var (rs_machine_dependent, - md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length, - md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length, - C (UNCOND_JUMP, 0), - immediate.X_add_symbol, - immediate.X_add_number, - 0); - p[high_byte] = (opcode->nibbles[0] << 4); - } - -} - -/* Now we know what sort of opcodes it is, lets build the bytes - - */ -static void -build_Mytes (opcode, operand) - sh_opcode_info *opcode; - sh_operand_info *operand; - -{ - int index; - char nbuf[4]; - char *output = frag_more (2); - int low_byte = target_big_endian ? 1 : 0; - nbuf[0] = 0; - nbuf[1] = 0; - nbuf[2] = 0; - nbuf[3] = 0; - - for (index = 0; index < 4; index++) - { - sh_nibble_type i = opcode->nibbles[index]; - if (i < 16) - { - nbuf[index] = i; - } - else - { - switch (i) - { - case REG_N: - nbuf[index] = reg_n; - break; - case REG_M: - nbuf[index] = reg_m; - break; - case REG_NM: - nbuf[index] = reg_n | (reg_m >> 2); - break; - case REG_B: - nbuf[index] = reg_b | 0x08; - break; - case DISP_4: - insert (output + low_byte, BFD_RELOC_SH_IMM4, 0); - break; - case IMM_4BY4: - insert (output + low_byte, BFD_RELOC_SH_IMM4BY4, 0); - break; - case IMM_4BY2: - insert (output + low_byte, BFD_RELOC_SH_IMM4BY2, 0); - break; - case IMM_4: - insert (output + low_byte, BFD_RELOC_SH_IMM4, 0); - break; - case IMM_8BY4: - insert (output + low_byte, BFD_RELOC_SH_IMM8BY4, 0); - break; - case IMM_8BY2: - insert (output + low_byte, BFD_RELOC_SH_IMM8BY2, 0); - break; - case IMM_8: - insert (output + low_byte, BFD_RELOC_SH_IMM8, 0); - break; - case PCRELIMM_8BY4: - insert (output, BFD_RELOC_SH_PCRELIMM8BY4, 1); - break; - case PCRELIMM_8BY2: - insert (output, BFD_RELOC_SH_PCRELIMM8BY2, 1); - break; - default: - printf ("failed for %d\n", i); - } - } - } - if (! target_big_endian) { - output[1] = (nbuf[0] << 4) | (nbuf[1]); - output[0] = (nbuf[2] << 4) | (nbuf[3]); - } - else { - output[0] = (nbuf[0] << 4) | (nbuf[1]); - output[1] = (nbuf[2] << 4) | (nbuf[3]); - } -} - -/* This is the guts of the machine-dependent assembler. STR points to a - machine dependent instruction. This function is supposed to emit - the frags/bytes it assembles to. - */ - -void -md_assemble (str) - char *str; -{ - unsigned char *op_start; - unsigned char *op_end; - sh_operand_info operand[3]; - sh_opcode_info *opcode; - char name[20]; - int nlen = 0; - /* Drop leading whitespace */ - while (*str == ' ') - str++; - - /* find the op code 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] = op_start[nlen]; - nlen++; - } - name[nlen] = 0; - - if (nlen == 0) - { - as_bad ("can't find opcode "); - } - - opcode = (sh_opcode_info *) hash_find (opcode_hash_control, name); - - if (opcode == NULL) - { - as_bad ("unknown opcode"); - return; - } - - if (sh_relax - && ! seg_info (now_seg)->tc_segment_info_data.in_code) - { - /* Output a CODE reloc to tell the linker that the following - bytes are instructions, not data. */ - fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, - BFD_RELOC_SH_CODE); - seg_info (now_seg)->tc_segment_info_data.in_code = 1; - } - - if (opcode->arg[0] == A_BDISP12 - || opcode->arg[0] == A_BDISP8) - { - parse_exp (op_end + 1); - build_relax (opcode); - } - else - { - if (opcode->arg[0] != A_END) - { - get_operands (opcode, op_end, operand); - } - opcode = get_specific (opcode, operand); - - if (opcode == 0) - { - /* Couldn't find an opcode which matched the operands */ - char *where = frag_more (2); - - where[0] = 0x0; - where[1] = 0x0; - as_bad ("invalid operands for opcode"); - return; - } - - build_Mytes (opcode, operand); - } - -} - -/* This routine is called each time a label definition is seen. It - emits a BFD_RELOC_SH_LABEL reloc if necessary. */ - -void -sh_frob_label () -{ - static fragS *last_label_frag; - static int last_label_offset; - - if (sh_relax - && seg_info (now_seg)->tc_segment_info_data.in_code) - { - int offset; - - offset = frag_now_fix (); - if (frag_now != last_label_frag - || offset != last_label_offset) - { - fix_new (frag_now, offset, 2, &abs_symbol, 0, 0, BFD_RELOC_SH_LABEL); - last_label_frag = frag_now; - last_label_offset = offset; - } - } -} - -/* This routine is called when the assembler is about to output some - data. It emits a BFD_RELOC_SH_DATA reloc if necessary. */ - -void -sh_flush_pending_output () -{ - if (sh_relax - && seg_info (now_seg)->tc_segment_info_data.in_code) - { - fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, - BFD_RELOC_SH_DATA); - seg_info (now_seg)->tc_segment_info_data.in_code = 0; - } -} - -symbolS * -DEFUN (md_undefined_symbol, (name), - char *name) -{ - return 0; -} - -#ifdef OBJ_COFF - -void -DEFUN (tc_crawl_symbol_chain, (headers), - object_headers * headers) -{ - printf ("call to tc_crawl_symbol_chain \n"); -} - -void -DEFUN (tc_headers_hook, (headers), - object_headers * headers) -{ - printf ("call to tc_headers_hook \n"); -} - -#endif - -/* Various routines to kill one day */ -/* 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. - */ -char * -md_atof (type, litP, sizeP) - int type; - char *litP; - int *sizeP; -{ - int prec; - LITTLENUM_TYPE words[4]; - char *t; - int i; - - 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 * 2; - - if (! target_big_endian) - { - for (i = prec - 1; i >= 0; i--) - { - md_number_to_chars (litP, (valueT) words[i], 2); - litP += 2; - } - } - else - { - for (i = 0; i < prec; i++) - { - md_number_to_chars (litP, (valueT) words[i], 2); - litP += 2; - } - } - - return NULL; -} - -/* Handle the .uses pseudo-op. This pseudo-op is used just before a - call instruction. It refers to a label of the instruction which - loads the register which the call uses. We use it to generate a - special reloc for the linker. */ - -static void -s_uses (ignore) - int ignore; -{ - expressionS ex; - - if (! sh_relax) - as_warn (".uses pseudo-op seen when not relaxing"); - - expression (&ex); - - if (ex.X_op != O_symbol || ex.X_add_number != 0) - { - as_bad ("bad .uses format"); - ignore_rest_of_line (); - return; - } - - fix_new_exp (frag_now, frag_now_fix (), 2, &ex, 1, BFD_RELOC_SH_USES); - - demand_empty_rest_of_line (); -} - -CONST char *md_shortopts = ""; -struct option md_longopts[] = { - -#define OPTION_RELAX (OPTION_MD_BASE) -#define OPTION_LITTLE (OPTION_MD_BASE + 1) -#define OPTION_SMALL (OPTION_LITTLE + 1) - - {"relax", no_argument, NULL, OPTION_RELAX}, - {"little", no_argument, NULL, OPTION_LITTLE}, - {"small", no_argument, NULL, OPTION_SMALL}, - {NULL, no_argument, NULL, 0} -}; -size_t md_longopts_size = sizeof(md_longopts); - -int -md_parse_option (c, arg) - int c; - char *arg; -{ - switch (c) - { - case OPTION_RELAX: - sh_relax = 1; - break; - - case OPTION_LITTLE: - shl = 1; - target_big_endian = 0; - break; - - case OPTION_SMALL: - sh_small = 1; - break; - - default: - return 0; - } - - return 1; -} - -void -md_show_usage (stream) - FILE *stream; -{ - fprintf(stream, "\ -SH options:\n\ --little generate little endian code\n\ --relax alter jump instructions for long displacements\n\ --small align sections to 4 byte boundaries, not 16\n"); -} - -int md_short_jump_size; - -void -tc_Nout_fix_to_chars () -{ - printf ("call to tc_Nout_fix_to_chars \n"); - abort (); -} - -void -md_create_short_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) - char *ptr; - addressT from_Nddr; - addressT to_Nddr; - fragS *frag; - symbolS *to_symbol; -{ - as_fatal ("failed sanity check."); -} - -void -md_create_long_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) - char *ptr; - addressT from_Nddr, to_Nddr; - fragS *frag; - symbolS *to_symbol; -{ - as_fatal ("failed sanity check."); -} - -/* This struct is used to pass arguments to sh_count_relocs through - bfd_map_over_sections. */ - -struct sh_count_relocs -{ - /* Symbol we are looking for. */ - symbolS *sym; - /* Count of relocs found. */ - int count; -}; - -/* Count the number of fixups in a section which refer to a particular - symbol. When using BFD_ASSEMBLER, this is called via - bfd_map_over_sections. */ - -/*ARGSUSED*/ -static void -sh_count_relocs (abfd, sec, data) - bfd *abfd; - segT sec; - PTR data; -{ - struct sh_count_relocs *info = (struct sh_count_relocs *) data; - segment_info_type *seginfo; - symbolS *sym; - fixS *fix; - - seginfo = seg_info (sec); - if (seginfo == NULL) - return; - - sym = info->sym; - for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next) - { - if (fix->fx_addsy == sym) - { - ++info->count; - fix->fx_tcbit = 1; - } - } -} - -/* Handle the count relocs for a particular section. When using - BFD_ASSEMBLER, this is called via bfd_map_over_sections. */ - -/*ARGSUSED*/ -static void -sh_frob_section (abfd, sec, ignore) - bfd *abfd; - segT sec; - PTR ignore; -{ - segment_info_type *seginfo; - fixS *fix; - - seginfo = seg_info (sec); - if (seginfo == NULL) - return; - - for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next) - { - symbolS *sym; - bfd_vma val; - fixS *fscan; - struct sh_count_relocs info; - - if (fix->fx_r_type != BFD_RELOC_SH_USES) - continue; - - /* The BFD_RELOC_SH_USES reloc should refer to a defined local - symbol in the same section. */ - sym = fix->fx_addsy; - if (sym == NULL - || fix->fx_subsy != NULL - || fix->fx_addnumber != 0 - || S_GET_SEGMENT (sym) != sec -#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF) - || S_GET_STORAGE_CLASS (sym) == C_EXT -#endif - || S_IS_EXTERNAL (sym)) - { - as_warn_where (fix->fx_file, fix->fx_line, - ".uses does not refer to a local symbol in the same section"); - continue; - } - - /* Look through the fixups again, this time looking for one - at the same location as sym. */ - val = S_GET_VALUE (sym); - for (fscan = seginfo->fix_root; - fscan != NULL; - fscan = fscan->fx_next) - if (val == fscan->fx_frag->fr_address + fscan->fx_where - && fscan->fx_r_type != BFD_RELOC_SH_ALIGN - && fscan->fx_r_type != BFD_RELOC_SH_CODE - && fscan->fx_r_type != BFD_RELOC_SH_DATA - && fscan->fx_r_type != BFD_RELOC_SH_LABEL) - break; - if (fscan == NULL) - { - as_warn_where (fix->fx_file, fix->fx_line, - "can't find fixup pointed to by .uses"); - continue; - } - - if (fscan->fx_tcbit) - { - /* We've already done this one. */ - continue; - } - - /* fscan should also be a fixup to a local symbol in the same - section. */ - sym = fscan->fx_addsy; - if (sym == NULL - || fscan->fx_subsy != NULL - || fscan->fx_addnumber != 0 - || S_GET_SEGMENT (sym) != sec -#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF) - || S_GET_STORAGE_CLASS (sym) == C_EXT -#endif - || S_IS_EXTERNAL (sym)) - { - as_warn_where (fix->fx_file, fix->fx_line, - ".uses target does not refer to a local symbol in the same section"); - continue; - } - - /* Now we look through all the fixups of all the sections, - counting the number of times we find a reference to sym. */ - info.sym = sym; - info.count = 0; -#ifdef BFD_ASSEMBLER - bfd_map_over_sections (stdoutput, sh_count_relocs, (PTR) &info); -#else - { - int iscan; - - for (iscan = SEG_E0; iscan < SEG_UNKNOWN; iscan++) - sh_count_relocs ((bfd *) NULL, iscan, (PTR) &info); - } -#endif - - if (info.count < 1) - abort (); - - /* Generate a BFD_RELOC_SH_COUNT fixup at the location of sym. - We have already adjusted the value of sym to include the - fragment address, so we undo that adjustment here. */ - subseg_change (sec, 0); - fix_new (sym->sy_frag, S_GET_VALUE (sym) - sym->sy_frag->fr_address, - 4, &abs_symbol, info.count, 0, BFD_RELOC_SH_COUNT); - } -} - -/* This function is called after the symbol table has been completed, - but before the relocs or section contents have been written out. - If we have seen any .uses pseudo-ops, they point to an instruction - which loads a register with the address of a function. We look - through the fixups to find where the function address is being - loaded from. We then generate a COUNT reloc giving the number of - times that function address is referred to. The linker uses this - information when doing relaxing, to decide when it can eliminate - the stored function address entirely. */ - -void -sh_frob_file () -{ - if (! sh_relax) - return; - -#ifdef BFD_ASSEMBLER - bfd_map_over_sections (stdoutput, sh_frob_section, (PTR) NULL); -#else - { - int iseg; - - for (iseg = SEG_E0; iseg < SEG_UNKNOWN; iseg++) - sh_frob_section ((bfd *) NULL, iseg, (PTR) NULL); - } -#endif -} - -/* Called after relaxing. Set the correct sizes of the fragments, and - create relocs so that md_apply_fix will fill in the correct values. */ - -void -md_convert_frag (headers, seg, fragP) -#ifdef BFD_ASSEMBLER - bfd *headers; -#else - object_headers *headers; -#endif - segT seg; - fragS *fragP; -{ - int donerelax = 0; - - switch (fragP->fr_subtype) - { - case C (COND_JUMP, COND8): - subseg_change (seg, 0); - fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, - 1, BFD_RELOC_SH_PCDISP8BY2); - fragP->fr_fix += 2; - fragP->fr_var = 0; - break; - - case C (UNCOND_JUMP, UNCOND12): - subseg_change (seg, 0); - fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, - 1, BFD_RELOC_SH_PCDISP12BY2); - fragP->fr_fix += 2; - fragP->fr_var = 0; - break; - - case C (UNCOND_JUMP, UNCOND32): - case C (UNCOND_JUMP, UNDEF_WORD_DISP): - if (fragP->fr_symbol == NULL) - as_bad ("at 0x%lx, displacement overflows 12-bit field", - (unsigned long) fragP->fr_address); - else - as_bad ("at 0x%lx, displacement to %sdefined symbol %s overflows 12-bit field", - (unsigned long) fragP->fr_address, - S_IS_DEFINED (fragP->fr_symbol) ? "" : "un", - S_GET_NAME (fragP->fr_symbol)); - -#if 0 /* This code works, but generates poor code and the compiler - should never produce a sequence that requires it to be used. */ - - /* A jump wont fit in 12 bits, make code which looks like - bra foo - mov.w @(0, PC), r14 - .long disp - foo: bra @r14 - */ - int t = buffer[0] & 0x10; - - buffer[highbyte] = 0xa0; /* branch over move and disp */ - buffer[lowbyte] = 3; - buffer[highbyte+2] = 0xd0 | JREG; /* Build mov insn */ - buffer[lowbyte+2] = 0x00; - - buffer[highbyte+4] = 0; /* space for 32 bit jump disp */ - buffer[lowbyte+4] = 0; - buffer[highbyte+6] = 0; - buffer[lowbyte+6] = 0; - - buffer[highbyte+8] = 0x40 | JREG; /* Build jmp @JREG */ - buffer[lowbyte+8] = t ? 0xb : 0x2b; - - buffer[highbyte+10] = 0x20; /* build nop */ - buffer[lowbyte+10] = 0x0b; - - /* Make reloc for the long disp */ - fix_new (fragP, - fragP->fr_fix + 4, - 4, - fragP->fr_symbol, - fragP->fr_offset, - 0, - BFD_RELOC_32); - fragP->fr_fix += UNCOND32_LENGTH; - fragP->fr_var = 0; - donerelax = 1; -#endif - - break; - - case C (COND_JUMP, COND12): - /* A bcond won't fit, so turn it into a b!cond; bra disp; nop */ - { - unsigned char *buffer = - (unsigned char *) (fragP->fr_fix + fragP->fr_literal); - int highbyte = target_big_endian ? 0 : 1; - int lowbyte = target_big_endian ? 1 : 0; - - /* Toggle the true/false bit of the bcond. */ - buffer[highbyte] ^= 0x2; - - /* Build a relocation to six bytes farther on. */ - subseg_change (seg, 0); - fix_new (fragP, fragP->fr_fix, 2, -#ifdef BFD_ASSEMBLER - section_symbol (seg), -#else - seg_info (seg)->dot, -#endif - fragP->fr_address + fragP->fr_fix + 6, - 1, BFD_RELOC_SH_PCDISP8BY2); - - /* Set up a jump instruction. */ - buffer[highbyte + 2] = 0xa0; - buffer[lowbyte + 2] = 0; - fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol, - fragP->fr_offset, 1, BFD_RELOC_SH_PCDISP12BY2); - - /* Fill in a NOP instruction. */ - buffer[highbyte + 4] = 0x0; - buffer[lowbyte + 4] = 0x9; - - fragP->fr_fix += 6; - fragP->fr_var = 0; - donerelax = 1; - } - break; - - case C (COND_JUMP, COND32): - case C (COND_JUMP, UNDEF_WORD_DISP): - if (fragP->fr_symbol == NULL) - as_bad ("at 0x%lx, displacement overflows 8-bit field", - (unsigned long) fragP->fr_address); - else - as_bad ("at 0x%lx, displacement to %sdefined symbol %s overflows 8-bit field ", - (unsigned long) fragP->fr_address, - S_IS_DEFINED (fragP->fr_symbol) ? "" : "un", - S_GET_NAME (fragP->fr_symbol)); - -#if 0 /* This code works, but generates poor code, and the compiler - should never produce a sequence that requires it to be used. */ - - /* A bcond won't fit and it won't go into a 12 bit - displacement either, the code sequence looks like: - b!cond foop - mov.w @(n, PC), r14 - jmp @r14 - nop - .long where - foop: - */ - - buffer[0] ^= 0x2; /* Toggle T/F bit */ -#define JREG 14 - buffer[1] = 5; /* branch over mov, jump, nop and ptr */ - buffer[2] = 0xd0 | JREG; /* Build mov insn */ - buffer[3] = 0x2; - buffer[4] = 0x40 | JREG; /* Build jmp @JREG */ - buffer[5] = 0x0b; - buffer[6] = 0x20; /* build nop */ - buffer[7] = 0x0b; - buffer[8] = 0; /* space for 32 bit jump disp */ - buffer[9] = 0; - buffer[10] = 0; - buffer[11] = 0; - buffer[12] = 0; - buffer[13] = 0; - /* Make reloc for the long disp */ - fix_new (fragP, - fragP->fr_fix + 8, - 4, - fragP->fr_symbol, - fragP->fr_offset, - 0, - BFD_RELOC_32); - fragP->fr_fix += COND32_LENGTH; - fragP->fr_var = 0; - donerelax = 1; -#endif - - break; - - default: - abort (); - } - - if (donerelax && !sh_relax) - as_warn_where (fragP->fr_file, fragP->fr_line, - "overflow in branch to %s; converted into longer instruction sequence", - (fragP->fr_symbol != NULL - ? S_GET_NAME (fragP->fr_symbol) - : "")); -} - -valueT -DEFUN (md_section_align, (seg, size), - segT seg AND - valueT size) -{ -#ifdef BFD_ASSEMBLER -#ifdef OBJ_ELF - return size; -#else /* ! OBJ_ELF */ - return ((size + (1 << bfd_get_section_alignment (stdoutput, seg)) - 1) - & (-1 << bfd_get_section_alignment (stdoutput, seg))); -#endif /* ! OBJ_ELF */ -#else /* ! BFD_ASSEMBLER */ - return ((size + (1 << section_alignment[(int) seg]) - 1) - & (-1 << section_alignment[(int) seg])); -#endif /* ! BFD_ASSEMBLER */ -} - -/* This static variable is set by s_uacons to tell sh_cons_align that - the expession does not need to be aligned. */ - -static int sh_no_align_cons = 0; - -/* This handles the unaligned space allocation pseudo-ops, such as - .uaword. .uaword is just like .word, but the value does not need - to be aligned. */ - -static void -s_uacons (bytes) - int bytes; -{ - /* Tell sh_cons_align not to align this value. */ - sh_no_align_cons = 1; - cons (bytes); -} - -/* If a .word, et. al., pseud-op is seen, warn if the value is not - aligned correctly. Note that this can cause warnings to be issued - when assembling initialized structured which were declared with the - packed attribute. FIXME: Perhaps we should require an option to - enable this warning? */ - -void -sh_cons_align (nbytes) - int nbytes; -{ - int nalign; - char *p; - - if (sh_no_align_cons) - { - /* This is an unaligned pseudo-op. */ - sh_no_align_cons = 0; - return; - } - - nalign = 0; - while ((nbytes & 1) == 0) - { - ++nalign; - nbytes >>= 1; - } - - if (nalign == 0) - return; - - if (now_seg == absolute_section) - { - if ((abs_section_offset & ((1 << nalign) - 1)) != 0) - as_warn ("misaligned data"); - return; - } - - p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0, - (symbolS *) NULL, (offsetT) nalign, (char *) NULL); - - record_alignment (now_seg, nalign); -} - -/* When relaxing, we need to output a reloc for any .align directive - that requests alignment to a four byte boundary or larger. This is - also where we check for misaligned data. */ - -void -sh_handle_align (frag) - fragS *frag; -{ - if (sh_relax - && frag->fr_type == rs_align - && frag->fr_address + frag->fr_fix > 0 - && frag->fr_offset > 1 - && now_seg != bss_section) - fix_new (frag, frag->fr_fix, 2, &abs_symbol, frag->fr_offset, 0, - BFD_RELOC_SH_ALIGN); - - if (frag->fr_type == rs_align_code - && frag->fr_next->fr_address - frag->fr_address - frag->fr_fix != 0) - as_warn_where (frag->fr_file, frag->fr_line, "misaligned data"); -} - -/* This macro decides whether a particular reloc is an entry in a - switch table. It is used when relaxing, because the linker needs - to know about all such entries so that it can adjust them if - necessary. */ - -#ifdef BFD_ASSEMBLER -#define SWITCH_TABLE_CONS(fix) (0) -#else -#define SWITCH_TABLE_CONS(fix) \ - ((fix)->fx_r_type == 0 \ - && ((fix)->fx_size == 2 \ - || (fix)->fx_size == 1 \ - || (fix)->fx_size == 4)) -#endif - -#define SWITCH_TABLE(fix) \ - ((fix)->fx_addsy != NULL \ - && (fix)->fx_subsy != NULL \ - && S_GET_SEGMENT ((fix)->fx_addsy) == text_section \ - && S_GET_SEGMENT ((fix)->fx_subsy) == text_section \ - && ((fix)->fx_r_type == BFD_RELOC_32 \ - || (fix)->fx_r_type == BFD_RELOC_16 \ - || (fix)->fx_r_type == BFD_RELOC_8 \ - || SWITCH_TABLE_CONS (fix))) - -/* See whether we need to force a relocation into the output file. - This is used to force out switch and PC relative relocations when - relaxing. */ - -int -sh_force_relocation (fix) - fixS *fix; -{ - if (! sh_relax) - return 0; - - return (fix->fx_pcrel - || SWITCH_TABLE (fix) - || fix->fx_r_type == BFD_RELOC_SH_COUNT - || fix->fx_r_type == BFD_RELOC_SH_ALIGN - || fix->fx_r_type == BFD_RELOC_SH_CODE - || fix->fx_r_type == BFD_RELOC_SH_DATA - || fix->fx_r_type == BFD_RELOC_SH_LABEL); -} - -/* Apply a fixup to the object file. */ - -#ifdef BFD_ASSEMBLER -int -md_apply_fix (fixP, valp) - fixS *fixP; - valueT *valp; -#else -void -md_apply_fix (fixP, val) - fixS *fixP; - long val; -#endif -{ - char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; - int lowbyte = target_big_endian ? 1 : 0; - int highbyte = target_big_endian ? 0 : 1; -#ifdef BFD_ASSEMBLER - long val = *valp; -#endif - long max, min; - int shift; - -#ifndef BFD_ASSEMBLER - if (fixP->fx_r_type == 0) - { - if (fixP->fx_size == 2) - fixP->fx_r_type = BFD_RELOC_16; - else if (fixP->fx_size == 4) - fixP->fx_r_type = BFD_RELOC_32; - else if (fixP->fx_size == 1) - fixP->fx_r_type = BFD_RELOC_8; - else - abort (); - } -#endif - - max = min = 0; - shift = 0; - switch (fixP->fx_r_type) - { - case BFD_RELOC_SH_IMM4: - max = 0xf; - *buf = (*buf & 0xf0) | (val & 0xf); - break; - - case BFD_RELOC_SH_IMM4BY2: - max = 0xf; - shift = 1; - *buf = (*buf & 0xf0) | ((val >> 1) & 0xf); - break; - - case BFD_RELOC_SH_IMM4BY4: - max = 0xf; - shift = 2; - *buf = (*buf & 0xf0) | ((val >> 2) & 0xf); - break; - - case BFD_RELOC_SH_IMM8BY2: - max = 0xff; - shift = 1; - *buf = val >> 1; - break; - - case BFD_RELOC_SH_IMM8BY4: - max = 0xff; - shift = 2; - *buf = val >> 2; - break; - - case BFD_RELOC_8: - case BFD_RELOC_SH_IMM8: - /* Sometimes the 8 bit value is sign extended (e.g., add) and - sometimes it is not (e.g., and). We permit any 8 bit value. - Note that adding further restrictions may invalidate - reasonable looking assembly code, such as ``and -0x1,r0''. */ - max = 0xff; - min = - 0xff; - *buf++ = val; - break; - - case BFD_RELOC_SH_PCRELIMM8BY4: - /* The lower two bits of the PC are cleared before the - displacement is added in. We can assume that the destination - is on a 4 byte bounday. If this instruction is also on a 4 - byte boundary, then we want - (target - here) / 4 - and target - here is a multiple of 4. - Otherwise, we are on a 2 byte boundary, and we want - (target - (here - 2)) / 4 - and target - here is not a multiple of 4. Computing - (target - (here - 2)) / 4 == (target - here + 2) / 4 - works for both cases, since in the first case the addition of - 2 will be removed by the division. target - here is in the - variable val. */ - val = (val + 2) / 4; - if (val & ~0xff) - as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); - buf[lowbyte] = val; - break; - - case BFD_RELOC_SH_PCRELIMM8BY2: - val /= 2; - if (val & ~0xff) - as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); - buf[lowbyte] = val; - break; - - case BFD_RELOC_SH_PCDISP8BY2: - val /= 2; - if (val < -0x80 || val > 0x7f) - as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); - buf[lowbyte] = val; - break; - - case BFD_RELOC_SH_PCDISP12BY2: - val /= 2; - if (val < -0x800 || val >= 0x7ff) - as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); - buf[lowbyte] = val & 0xff; - buf[highbyte] |= (val >> 8) & 0xf; - break; - - case BFD_RELOC_32: - if (! target_big_endian) - { - *buf++ = val >> 0; - *buf++ = val >> 8; - *buf++ = val >> 16; - *buf++ = val >> 24; - } - else - { - *buf++ = val >> 24; - *buf++ = val >> 16; - *buf++ = val >> 8; - *buf++ = val >> 0; - } - break; - - case BFD_RELOC_16: - if (! target_big_endian) - { - *buf++ = val >> 0; - *buf++ = val >> 8; - } - else - { - *buf++ = val >> 8; - *buf++ = val >> 0; - } - break; - - case BFD_RELOC_SH_USES: - /* Pass the value into sh_coff_reloc_mangle. */ - fixP->fx_addnumber = val; - break; - - case BFD_RELOC_SH_COUNT: - case BFD_RELOC_SH_ALIGN: - case BFD_RELOC_SH_CODE: - case BFD_RELOC_SH_DATA: - case BFD_RELOC_SH_LABEL: - /* Nothing to do here. */ - break; - - default: - abort (); - } - - if (shift != 0) - { - if ((val & ((1 << shift) - 1)) != 0) - as_bad_where (fixP->fx_file, fixP->fx_line, "misaligned offset"); - if (val >= 0) - val >>= shift; - else - val = ((val >> shift) - | ((long) -1 & ~ ((long) -1 >> shift))); - } - if (max != 0 && (val < min || val > max)) - as_bad_where (fixP->fx_file, fixP->fx_line, "offset out of range"); - -#ifdef BFD_ASSEMBLER - return 0; -#endif -} - -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; -{ - switch (fragP->fr_subtype) - { - case C (UNCOND_JUMP, UNDEF_DISP): - /* used to be a branch to somewhere which was unknown */ - if (!fragP->fr_symbol) - { - fragP->fr_subtype = C (UNCOND_JUMP, UNCOND12); - fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length; - } - else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) - { - fragP->fr_subtype = C (UNCOND_JUMP, UNCOND12); - fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length; - } - else - { - fragP->fr_subtype = C (UNCOND_JUMP, UNDEF_WORD_DISP); - fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length; - return md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length; - } - break; - - default: - abort (); - 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, COND8); - fragP->fr_var = md_relax_table[C (COND_JUMP, COND8)].rlx_length; - } - 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); - fragP->fr_var = md_relax_table[C (COND_JUMP, COND32)].rlx_length; - return md_relax_table[C (COND_JUMP, COND32)].rlx_length; - } - else - { - /* We know the abs value */ - fragP->fr_subtype = C (COND_JUMP, COND8); - fragP->fr_var = md_relax_table[C (COND_JUMP, COND8)].rlx_length; - } - - break; - } - return fragP->fr_var; -} - -/* Put number into target byte order */ - -void -md_number_to_chars (ptr, use, nbytes) - char *ptr; - valueT use; - int nbytes; -{ - if (! target_big_endian) - number_to_chars_littleendian (ptr, use, nbytes); - else - number_to_chars_bigendian (ptr, use, nbytes); -} - -long -md_pcrel_from (fixP) - fixS *fixP; -{ - return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address + 2; -} - -#ifdef OBJ_COFF - -int -tc_coff_sizemachdep (frag) - fragS *frag; -{ - return md_relax_table[frag->fr_subtype].rlx_length; -} - -#endif /* OBJ_COFF */ - -/* When we align the .text section, insert the correct NOP pattern. */ - -int -sh_do_align (n, fill, len, max) - int n; - const char *fill; - int len; - int max; -{ - if (fill == NULL -#ifdef BFD_ASSEMBLER - && (now_seg->flags & SEC_CODE) != 0 -#else - && now_seg != data_section - && now_seg != bss_section -#endif - && n > 1) - { - static const unsigned char big_nop_pattern[] = { 0x00, 0x09 }; - static const unsigned char little_nop_pattern[] = { 0x09, 0x00 }; - - /* First align to a 2 byte boundary, in case there is an odd - .byte. */ - frag_align (1, 0, 0); - if (target_big_endian) - frag_align_pattern (n, big_nop_pattern, sizeof big_nop_pattern, max); - else - frag_align_pattern (n, little_nop_pattern, sizeof little_nop_pattern, - max); - return 1; - } - - return 0; -} - -#ifndef BFD_ASSEMBLER -#ifdef OBJ_COFF - -/* Map BFD relocs to SH COFF relocs. */ - -struct reloc_map -{ - bfd_reloc_code_real_type bfd_reloc; - int sh_reloc; -}; - -static const struct reloc_map coff_reloc_map[] = -{ - { BFD_RELOC_32, R_SH_IMM32 }, - { BFD_RELOC_16, R_SH_IMM16 }, - { BFD_RELOC_8, R_SH_IMM8 }, - { BFD_RELOC_SH_PCDISP8BY2, R_SH_PCDISP8BY2 }, - { BFD_RELOC_SH_PCDISP12BY2, R_SH_PCDISP }, - { BFD_RELOC_SH_IMM4, R_SH_IMM4 }, - { BFD_RELOC_SH_IMM4BY2, R_SH_IMM4BY2 }, - { BFD_RELOC_SH_IMM4BY4, R_SH_IMM4BY4 }, - { BFD_RELOC_SH_IMM8, R_SH_IMM8 }, - { BFD_RELOC_SH_IMM8BY2, R_SH_IMM8BY2 }, - { BFD_RELOC_SH_IMM8BY4, R_SH_IMM8BY4 }, - { BFD_RELOC_SH_PCRELIMM8BY2, R_SH_PCRELIMM8BY2 }, - { BFD_RELOC_SH_PCRELIMM8BY4, R_SH_PCRELIMM8BY4 }, - { BFD_RELOC_8_PCREL, R_SH_SWITCH8 }, - { BFD_RELOC_SH_SWITCH16, R_SH_SWITCH16 }, - { BFD_RELOC_SH_SWITCH32, R_SH_SWITCH32 }, - { BFD_RELOC_SH_USES, R_SH_USES }, - { BFD_RELOC_SH_COUNT, R_SH_COUNT }, - { BFD_RELOC_SH_ALIGN, R_SH_ALIGN }, - { BFD_RELOC_SH_CODE, R_SH_CODE }, - { BFD_RELOC_SH_DATA, R_SH_DATA }, - { BFD_RELOC_SH_LABEL, R_SH_LABEL }, - { BFD_RELOC_UNUSED, 0 } -}; - -/* Adjust a reloc for the SH. This is similar to the generic code, - but does some minor tweaking. */ - -void -sh_coff_reloc_mangle (seg, fix, intr, paddr) - segment_info_type *seg; - fixS *fix; - struct internal_reloc *intr; - unsigned int paddr; -{ - symbolS *symbol_ptr = fix->fx_addsy; - symbolS *dot; - - intr->r_vaddr = paddr + fix->fx_frag->fr_address + fix->fx_where; - - if (! SWITCH_TABLE (fix)) - { - const struct reloc_map *rm; - - for (rm = coff_reloc_map; rm->bfd_reloc != BFD_RELOC_UNUSED; rm++) - if (rm->bfd_reloc == (bfd_reloc_code_real_type) fix->fx_r_type) - break; - if (rm->bfd_reloc == BFD_RELOC_UNUSED) - as_bad_where (fix->fx_file, fix->fx_line, - "Can not represent %s relocation in this object file format", - bfd_get_reloc_code_name (fix->fx_r_type)); - intr->r_type = rm->sh_reloc; - intr->r_offset = 0; - } - else - { - know (sh_relax); - - if (fix->fx_r_type == BFD_RELOC_16) - intr->r_type = R_SH_SWITCH16; - else if (fix->fx_r_type == BFD_RELOC_8) - intr->r_type = R_SH_SWITCH8; - else if (fix->fx_r_type == BFD_RELOC_32) - intr->r_type = R_SH_SWITCH32; - else - abort (); - - /* For a switch reloc, we set r_offset to the difference between - the reloc address and the subtrahend. When the linker is - doing relaxing, it can use the determine the starting and - ending points of the switch difference expression. */ - intr->r_offset = intr->r_vaddr - S_GET_VALUE (fix->fx_subsy); - } - - /* PC relative relocs are always against the current section. */ - if (symbol_ptr == NULL) - { - switch (fix->fx_r_type) - { - case BFD_RELOC_SH_PCRELIMM8BY2: - case BFD_RELOC_SH_PCRELIMM8BY4: - case BFD_RELOC_SH_PCDISP8BY2: - case BFD_RELOC_SH_PCDISP12BY2: - case BFD_RELOC_SH_USES: - symbol_ptr = seg->dot; - break; - default: - break; - } - } - - if (fix->fx_r_type == BFD_RELOC_SH_USES) - { - /* We can't store the offset in the object file, since this - reloc does not take up any space, so we store it in r_offset. - The fx_addnumber field was set in md_apply_fix. */ - intr->r_offset = fix->fx_addnumber; - } - else if (fix->fx_r_type == BFD_RELOC_SH_COUNT) - { - /* We can't store the count in the object file, since this reloc - does not take up any space, so we store it in r_offset. The - fx_offset field was set when the fixup was created in - sh_coff_frob_file. */ - intr->r_offset = fix->fx_offset; - /* This reloc is always absolute. */ - symbol_ptr = NULL; - } - else if (fix->fx_r_type == BFD_RELOC_SH_ALIGN) - { - /* Store the alignment in the r_offset field. */ - intr->r_offset = fix->fx_offset; - /* This reloc is always absolute. */ - symbol_ptr = NULL; - } - else if (fix->fx_r_type == BFD_RELOC_SH_CODE - || fix->fx_r_type == BFD_RELOC_SH_DATA - || fix->fx_r_type == BFD_RELOC_SH_LABEL) - { - /* These relocs are always absolute. */ - symbol_ptr = NULL; - } - - /* Turn the segment of the symbol into an offset. */ - if (symbol_ptr != NULL) - { - dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; - if (dot != NULL) - intr->r_symndx = dot->sy_number; - else - intr->r_symndx = symbol_ptr->sy_number; - } - else - intr->r_symndx = -1; -} - -#endif /* OBJ_COFF */ -#endif /* ! BFD_ASSEMBLER */ - -#ifdef BFD_ASSEMBLER - -/* Create a reloc. */ - -arelent * -tc_gen_reloc (section, fixp) - asection *section; - fixS *fixp; -{ - arelent *rel; - bfd_reloc_code_real_type r_type; - - rel = (arelent *) xmalloc (sizeof (arelent)); - rel->sym_ptr_ptr = &fixp->fx_addsy->bsym; - rel->address = fixp->fx_frag->fr_address + fixp->fx_where; - - r_type = fixp->fx_r_type; - - if (SWITCH_TABLE (fixp)) - { - rel->addend = rel->address - S_GET_VALUE (fixp->fx_subsy); - if (r_type == BFD_RELOC_16) - r_type = BFD_RELOC_SH_SWITCH16; - else if (r_type == BFD_RELOC_8) - r_type = BFD_RELOC_8_PCREL; - else if (r_type == BFD_RELOC_32) - r_type = BFD_RELOC_SH_SWITCH32; - else - abort (); - } - else if (r_type == BFD_RELOC_SH_USES) - rel->addend = fixp->fx_addnumber; - else if (r_type == BFD_RELOC_SH_COUNT) - rel->addend = fixp->fx_offset; - else if (r_type == BFD_RELOC_SH_ALIGN) - rel->addend = fixp->fx_offset; - else if (fixp->fx_pcrel) - rel->addend = fixp->fx_addnumber; - else - rel->addend = 0; - - rel->howto = bfd_reloc_type_lookup (stdoutput, r_type); - if (rel->howto == NULL) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - "Cannot represent relocation type %s", - bfd_get_reloc_code_name (r_type)); - /* Set howto to a garbage value so that we can keep going. */ - rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); - assert (rel->howto != NULL); - } - - return rel; -} - -#endif /* BFD_ASSEMBLER */ diff --git a/contrib/binutils/gas/config/tc-sh.h b/contrib/binutils/gas/config/tc-sh.h deleted file mode 100644 index a18029b020d6..000000000000 --- a/contrib/binutils/gas/config/tc-sh.h +++ /dev/null @@ -1,141 +0,0 @@ -/* This file is tc-sh.h - Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc. - - 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 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. */ - -#define TC_SH - -#define TARGET_BYTES_BIG_ENDIAN 0 - -#define TARGET_ARCH bfd_arch_sh - -/* Whether in little endian mode. */ -extern int shl; - -/* Whether -relax was used. */ -extern int sh_relax; - -/* Whether -small was used. */ -extern int sh_small; - -/* Don't try to break words. */ -#define WORKING_DOT_WORD - -/* We require .long, et. al., to be aligned correctly. */ -#define md_cons_align(nbytes) sh_cons_align (nbytes) -extern void sh_cons_align PARAMS ((int)); - -/* When relaxing, we need to generate relocations for alignment - directives. */ -#define HANDLE_ALIGN(frag) sh_handle_align (frag) -extern void sh_handle_align PARAMS ((fragS *)); - -/* We need to force out some relocations when relaxing. */ -#define TC_FORCE_RELOCATION(fix) sh_force_relocation (fix) -extern int sh_force_relocation (); - -#define IGNORE_NONSTANDARD_ESCAPES - -#define LISTING_HEADER (shl ? "Hitachi Super-H GAS Little Endian" : "Hitachi Super-H GAS Big Endian") - -#define md_operand(x) - -extern const struct relax_type md_relax_table[]; -#define TC_GENERIC_RELAX_TABLE md_relax_table - -/* We use a special alignment function to insert the correct nop - pattern. */ -extern int sh_do_align PARAMS ((int, const char *, int, int)); -#define md_do_align(n,fill,len,max,l) if (sh_do_align (n,fill,len,max)) goto l - -/* We record, for each section, whether we have most recently output a - CODE reloc or a DATA reloc. */ -struct sh_segment_info_type -{ - int in_code : 1; -}; -#define TC_SEGMENT_INFO_TYPE struct sh_segment_info_type - -/* We call a routine to emit a reloc for a label, so that the linker - can align loads and stores without crossing a label. */ -extern void sh_frob_label PARAMS ((void)); -#define tc_frob_label(sym) sh_frob_label () - -/* We call a routine to flush pending output in order to output a DATA - reloc when required. */ -extern void sh_flush_pending_output PARAMS ((void)); -#define md_flush_pending_output() sh_flush_pending_output () - -#ifdef BFD_ASSEMBLER -#define tc_frob_file_before_adjust sh_frob_file -#else -#define tc_frob_file sh_frob_file -#endif -extern void sh_frob_file PARAMS ((void)); - -#ifdef OBJ_COFF -/* COFF specific definitions. */ - -#define DO_NOT_STRIP 0 - -/* This macro translates between an internal fix and an coff reloc type */ -#define TC_COFF_FIX2RTYPE(fix) ((fix)->fx_r_type) - -#define BFD_ARCH TARGET_ARCH - -#define COFF_MAGIC (shl ? SH_ARCH_MAGIC_LITTLE : SH_ARCH_MAGIC_BIG) - -/* We need to write out relocs which have not been completed. */ -#define TC_COUNT_RELOC(fix) ((fix)->fx_addsy != NULL) - -#define TC_RELOC_MANGLE(seg, fix, int, paddr) \ - sh_coff_reloc_mangle ((seg), (fix), (int), (paddr)) -extern void sh_coff_reloc_mangle (); - -#define tc_coff_symbol_emit_hook(a) ; /* not used */ - -#define NEED_FX_R_TYPE 1 - -#define TC_KEEP_FX_OFFSET 1 - -#define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag) -extern int tc_coff_sizemachdep PARAMS ((fragS *)); - -/* We align most sections to a 16 byte boundary. */ -#define SUB_SEGMENT_ALIGN(SEG) \ - (strncmp (obj_segment_name (SEG), ".stabstr", 8) == 0 \ - ? 0 \ - : ((strncmp (obj_segment_name (SEG), ".stab", 5) == 0 \ - || strcmp (obj_segment_name (SEG), ".ctors") == 0 \ - || strcmp (obj_segment_name (SEG), ".dtors") == 0) \ - ? 2 \ - : (sh_small ? 2 : 4))) - -#endif /* OBJ_COFF */ - -#ifdef OBJ_ELF -/* ELF specific definitions. */ - -/* Whether or not the target is big endian */ -extern int target_big_endian; - -#define TARGET_FORMAT (shl ? "elf32-shl" : "elf32-sh") - -#endif /* OBJ_ELF */ - -/* end of tc-sh.h */ diff --git a/contrib/binutils/gas/config/tc-sparc.c b/contrib/binutils/gas/config/tc-sparc.c deleted file mode 100644 index 18d657229895..000000000000 --- a/contrib/binutils/gas/config/tc-sparc.c +++ /dev/null @@ -1,3364 +0,0 @@ -/* tc-sparc.c -- Assemble for the SPARC - Copyright (C) 1989, 90-96, 97, 1998 Free Software Foundation, Inc. - 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 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. */ - -#include <stdio.h> -#include <ctype.h> - -#include "as.h" -#include "subsegs.h" - -#include "opcode/sparc.h" - -#ifdef OBJ_ELF -#include "elf/sparc.h" -#endif - -static struct sparc_arch *lookup_arch PARAMS ((char *)); -static void init_default_arch PARAMS ((void)); -static void sparc_ip PARAMS ((char *, const struct sparc_opcode **)); -static int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma)); -static int in_unsigned_range PARAMS ((bfd_vma, bfd_vma)); -static int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma)); -static int sparc_ffs PARAMS ((unsigned int)); -static bfd_vma BSR PARAMS ((bfd_vma, int)); -static int cmp_reg_entry PARAMS ((const PTR, const PTR)); -static int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *)); -static int parse_const_expr_arg PARAMS ((char **, int *)); -static int get_expression PARAMS ((char *str)); - -/* Default architecture. */ -/* ??? The default value should be V8, but sparclite support was added - by making it the default. GCC now passes -Asparclite, so maybe sometime in - the future we can set this to V8. */ -#ifndef DEFAULT_ARCH -#define DEFAULT_ARCH "sparclite" -#endif -static char *default_arch = DEFAULT_ARCH; - -/* Non-zero if the initial values of `max_architecture' and `sparc_arch_size' - have been set. */ -static int default_init_p; - -/* Current architecture. We don't bump up unless necessary. */ -static enum sparc_opcode_arch_val current_architecture = SPARC_OPCODE_ARCH_V6; - -/* The maximum architecture level we can bump up to. - In a 32 bit environment, don't allow bumping up to v9 by default. - The native assembler works this way. The user is required to pass - an explicit argument before we'll create v9 object files. However, if - we don't see any v9 insns, a v8plus object file is not created. */ -static enum sparc_opcode_arch_val max_architecture; - -/* Either 32 or 64, selects file format. */ -static int sparc_arch_size; -/* Initial (default) value, recorded separately in case a user option - changes the value before md_show_usage is called. */ -static int default_arch_size; - -#ifdef OBJ_ELF -/* The currently selected v9 memory model. Currently only used for - ELF. */ -static enum { MM_TSO, MM_PSO, MM_RMO } sparc_memory_model = MM_RMO; -#endif - -static int architecture_requested; -static int warn_on_bump; - -/* If warn_on_bump and the needed architecture is higher than this - architecture, issue a warning. */ -static enum sparc_opcode_arch_val warn_after_architecture; - -/* Non-zero if we are generating PIC code. */ -int sparc_pic_code; - -/* Non-zero if we should give an error when misaligned data is seen. */ -static int enforce_aligned_data; - -extern int target_big_endian; - -/* V9 has big and little endian data, but instructions are always big endian. - The sparclet has bi-endian support but both data and insns have the same - endianness. Global `target_big_endian' is used for data. The following - macro is used for instructions. */ -#define INSN_BIG_ENDIAN (target_big_endian \ - || SPARC_OPCODE_ARCH_V9_P (max_architecture)) - -/* handle of the OPCODE hash table */ -static struct hash_control *op_hash; - -static void s_data1 PARAMS ((void)); -static void s_seg PARAMS ((int)); -static void s_proc PARAMS ((int)); -static void s_reserve PARAMS ((int)); -static void s_common PARAMS ((int)); -static void s_empty PARAMS ((int)); -static void s_uacons PARAMS ((int)); - -const pseudo_typeS md_pseudo_table[] = -{ - {"align", s_align_bytes, 0}, /* Defaulting is invalid (0) */ - {"common", s_common, 0}, - {"empty", s_empty, 0}, - {"global", s_globl, 0}, - {"half", cons, 2}, - {"optim", s_ignore, 0}, - {"proc", s_proc, 0}, - {"reserve", s_reserve, 0}, - {"seg", s_seg, 0}, - {"skip", s_space, 0}, - {"word", cons, 4}, - {"xword", cons, 8}, - {"uahalf", s_uacons, 2}, - {"uaword", s_uacons, 4}, - {"uaxword", s_uacons, 8}, -#ifdef OBJ_ELF - /* these are specific to sparc/svr4 */ - {"pushsection", obj_elf_section, 0}, - {"popsection", obj_elf_previous, 0}, - {"2byte", s_uacons, 2}, - {"4byte", s_uacons, 4}, - {"8byte", s_uacons, 8}, -#endif - {NULL, 0, 0}, -}; - -const int md_reloc_size = 12; /* Size of relocation record */ - -/* 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[] = "!"; /* JF removed '|' from 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 */ -/* 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 started like this one will always - work if '/' isn't otherwise defined. */ -const char line_comment_chars[] = "#"; - -const char line_separator_chars[] = ""; - -/* 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 */ -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. */ - -static unsigned char octal[256]; -#define isoctal(c) octal[(unsigned char) (c)] -static unsigned char toHex[256]; - -struct sparc_it - { - char *error; - unsigned long opcode; - struct nlist *nlistp; - expressionS exp; - int pcrel; - bfd_reloc_code_real_type reloc; - }; - -struct sparc_it the_insn, set_insn; - -static void output_insn - PARAMS ((const struct sparc_opcode *, struct sparc_it *)); - -/* Table of arguments to -A. - The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect - for this use. That table is for opcodes only. This table is for opcodes - and file formats. */ - -static struct sparc_arch { - char *name; - char *opcode_arch; - /* Default word size, as specified during configuration. - A value of zero means can't be used to specify default architecture. */ - int default_arch_size; - /* Allowable arg to -A? */ - int user_option_p; -} sparc_arch_table[] = { - { "v6", "v6", 0, 1 }, - { "v7", "v7", 0, 1 }, - { "v8", "v8", 32, 1 }, - { "sparclet", "sparclet", 32, 1 }, - { "sparclite", "sparclite", 32, 1 }, - { "v8plus", "v9", 0, 1 }, - { "v8plusa", "v9a", 0, 1 }, - { "v9", "v9", 0, 1 }, - { "v9a", "v9a", 0, 1 }, - /* This exists to allow configure.in/Makefile.in to pass one - value to specify both the default machine and default word size. */ - { "v9-64", "v9", 64, 0 }, - { NULL, NULL, 0 } -}; - -static struct sparc_arch * -lookup_arch (name) - char *name; -{ - struct sparc_arch *sa; - - for (sa = &sparc_arch_table[0]; sa->name != NULL; sa++) - if (strcmp (sa->name, name) == 0) - break; - if (sa->name == NULL) - return NULL; - return sa; -} - -/* Initialize the default opcode arch and word size from the default - architecture name. */ - -static void -init_default_arch () -{ - struct sparc_arch *sa = lookup_arch (default_arch); - - if (sa == NULL - || sa->default_arch_size == 0) - as_fatal ("Invalid default architecture, broken assembler."); - - max_architecture = sparc_opcode_lookup_arch (sa->opcode_arch); - if (max_architecture == SPARC_OPCODE_ARCH_BAD) - as_fatal ("Bad opcode table, broken assembler."); - default_arch_size = sparc_arch_size = sa->default_arch_size; - default_init_p = 1; -} - -/* Called by TARGET_FORMAT. */ - -const char * -sparc_target_format () -{ - /* We don't get a chance to initialize anything before we're called, - so handle that now. */ - if (! default_init_p) - init_default_arch (); - -#ifdef OBJ_AOUT -#ifdef TE_NetBSD - return "a.out-sparc-netbsd"; -#else -#ifdef TE_SPARCAOUT - return target_big_endian ? "a.out-sunos-big" : "a.out-sparc-little"; -#else - return "a.out-sunos-big"; -#endif -#endif -#endif - -#ifdef OBJ_BOUT - return "b.out.big"; -#endif - -#ifdef OBJ_COFF -#ifdef TE_LYNX - return "coff-sparc-lynx"; -#else - return "coff-sparc"; -#endif -#endif - -#ifdef OBJ_ELF - return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc"; -#endif - - abort (); -} - -/* - * md_parse_option - * Invocation line includes a switch not recognized by the base assembler. - * See if it's a processor-specific option. These are: - * - * -bump - * Warn on architecture bumps. See also -A. - * - * -Av6, -Av7, -Av8, -Asparclite, -Asparclet - * Standard 32 bit architectures. - * -Av8plus, -Av8plusa - * Sparc64 in a 32 bit world. - * -Av9, -Av9a - * Sparc64 in either a 32 or 64 bit world (-32/-64 says which). - * This used to only mean 64 bits, but properly specifying it - * complicated gcc's ASM_SPECs, so now opcode selection is - * specified orthogonally to word size (except when specifying - * the default, but that is an internal implementation detail). - * -xarch=v8plus, -xarch=v8plusa - * Same as -Av8plus{,a}, for compatibility with Sun's assembler. - * - * Select the architecture and possibly the file format. - * Instructions or features not supported by the selected - * architecture cause fatal errors. - * - * The default is to start at v6, and bump the architecture up - * whenever an instruction is seen at a higher level. In 32 bit - * environments, v9 is not bumped up to, the user must pass - * -Av8plus{,a}. - * - * If -bump is specified, a warning is printing when bumping to - * higher levels. - * - * If an architecture is specified, all instructions must match - * that architecture. Any higher level instructions are flagged - * as errors. Note that in the 32 bit environment specifying - * -Av8plus does not automatically create a v8plus object file, a - * v9 insn must be seen. - * - * If both an architecture and -bump are specified, the - * architecture starts at the specified level, but bumps are - * warnings. Note that we can't set `current_architecture' to - * the requested level in this case: in the 32 bit environment, - * we still must avoid creating v8plus object files unless v9 - * insns are seen. - * - * Note: - * Bumping between incompatible architectures is always an - * error. For example, from sparclite to v9. - */ - -#ifdef OBJ_ELF -CONST char *md_shortopts = "A:K:VQ:sq"; -#else -#ifdef OBJ_AOUT -CONST char *md_shortopts = "A:k"; -#else -CONST char *md_shortopts = "A:"; -#endif -#endif -struct option md_longopts[] = { -#define OPTION_BUMP (OPTION_MD_BASE) - {"bump", no_argument, NULL, OPTION_BUMP}, -#define OPTION_SPARC (OPTION_MD_BASE + 1) - {"sparc", no_argument, NULL, OPTION_SPARC}, -#define OPTION_XARCH (OPTION_MD_BASE + 2) - {"xarch", required_argument, NULL, OPTION_XARCH}, -#ifdef OBJ_ELF -#define OPTION_32 (OPTION_MD_BASE + 3) - {"32", no_argument, NULL, OPTION_32}, -#define OPTION_64 (OPTION_MD_BASE + 4) - {"64", no_argument, NULL, OPTION_64}, -#define OPTION_TSO (OPTION_MD_BASE + 5) - {"TSO", no_argument, NULL, OPTION_TSO}, -#define OPTION_PSO (OPTION_MD_BASE + 6) - {"PSO", no_argument, NULL, OPTION_PSO}, -#define OPTION_RMO (OPTION_MD_BASE + 7) - {"RMO", no_argument, NULL, OPTION_RMO}, -#endif -#ifdef SPARC_BIENDIAN -#define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8) - {"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN}, -#define OPTION_BIG_ENDIAN (OPTION_MD_BASE + 9) - {"EB", no_argument, NULL, OPTION_BIG_ENDIAN}, -#endif -#define OPTION_ENFORCE_ALIGNED_DATA (OPTION_MD_BASE + 10) - {"enforce-aligned-data", no_argument, NULL, OPTION_ENFORCE_ALIGNED_DATA}, - {NULL, no_argument, NULL, 0} -}; -size_t md_longopts_size = sizeof(md_longopts); - -int -md_parse_option (c, arg) - int c; - char *arg; -{ - /* We don't get a chance to initialize anything before we're called, - so handle that now. */ - if (! default_init_p) - init_default_arch (); - - switch (c) - { - case OPTION_BUMP: - warn_on_bump = 1; - warn_after_architecture = SPARC_OPCODE_ARCH_V6; - break; - - case OPTION_XARCH: - /* This is for compatibility with Sun's assembler. */ - if (strcmp (arg, "v8plus") != 0 - && strcmp (arg, "v8plusa") != 0) - { - as_bad ("invalid architecture -xarch=%s", arg); - return 0; - } - - /* fall through */ - - case 'A': - { - struct sparc_arch *sa; - enum sparc_opcode_arch_val opcode_arch; - - sa = lookup_arch (arg); - if (sa == NULL - || ! sa->user_option_p) - { - as_bad ("invalid architecture -A%s", arg); - return 0; - } - - opcode_arch = sparc_opcode_lookup_arch (sa->opcode_arch); - if (opcode_arch == SPARC_OPCODE_ARCH_BAD) - as_fatal ("Bad opcode table, broken assembler."); - - max_architecture = opcode_arch; - architecture_requested = 1; - } - break; - - case OPTION_SPARC: - /* Ignore -sparc, used by SunOS make default .s.o rule. */ - break; - - case OPTION_ENFORCE_ALIGNED_DATA: - enforce_aligned_data = 1; - break; - -#ifdef SPARC_BIENDIAN - case OPTION_LITTLE_ENDIAN: - target_big_endian = 0; - break; - case OPTION_BIG_ENDIAN: - target_big_endian = 1; - break; -#endif - -#ifdef OBJ_AOUT - case 'k': - sparc_pic_code = 1; - break; -#endif - -#ifdef OBJ_ELF - case OPTION_32: - case OPTION_64: - { - const char **list, **l; - - sparc_arch_size = c == OPTION_32 ? 32 : 64; - list = bfd_target_list (); - for (l = list; *l != NULL; l++) - { - if (sparc_arch_size == 32) - { - if (strcmp (*l, "elf32-sparc") == 0) - break; - } - else - { - if (strcmp (*l, "elf64-sparc") == 0) - break; - } - } - if (*l == NULL) - as_fatal ("No compiled in support for %d bit object file format", - sparc_arch_size); - free (list); - } - break; - - case OPTION_TSO: - sparc_memory_model = MM_TSO; - break; - - case OPTION_PSO: - sparc_memory_model = MM_PSO; - break; - - case OPTION_RMO: - sparc_memory_model = MM_RMO; - break; - - case 'V': - print_version_id (); - break; - - case 'Q': - /* Qy - do emit .comment - Qn - do not emit .comment */ - break; - - case 's': - /* use .stab instead of .stab.excl */ - break; - - case 'q': - /* quick -- native assembler does fewer checks */ - break; - - case 'K': - if (strcmp (arg, "PIC") != 0) - as_warn ("Unrecognized option following -K"); - else - sparc_pic_code = 1; - break; -#endif - - default: - return 0; - } - - return 1; -} - -void -md_show_usage (stream) - FILE *stream; -{ - const struct sparc_arch *arch; - - /* We don't get a chance to initialize anything before we're called, - so handle that now. */ - if (! default_init_p) - init_default_arch (); - - fprintf(stream, "SPARC options:\n"); - for (arch = &sparc_arch_table[0]; arch->name; arch++) - { - if (arch != &sparc_arch_table[0]) - fprintf (stream, " | "); - if (arch->user_option_p) - fprintf (stream, "-A%s", arch->name); - } - fprintf (stream, "\n-xarch=v8plus | -xarch=v8plusa\n"); - fprintf (stream, "\ - specify variant of SPARC architecture\n\ --bump warn when assembler switches architectures\n\ --sparc ignored\n\ ---enforce-aligned-data force .long, etc., to be aligned correctly\n"); -#ifdef OBJ_AOUT - fprintf (stream, "\ --k generate PIC\n"); -#endif -#ifdef OBJ_ELF - fprintf (stream, "\ --32 create 32 bit object file\n\ --64 create 64 bit object file\n"); - fprintf (stream, "\ - [default is %d]\n", default_arch_size); - fprintf (stream, "\ --TSO use Total Store Ordering\n\ --PSO use Partial Store Ordering\n\ --RMO use Relaxed Memory Ordering\n"); - fprintf (stream, "\ - [default is %s]\n", (default_arch_size == 64) ? "RMO" : "TSO"); - fprintf (stream, "\ --KPIC generate PIC\n\ --V print assembler version number\n\ --q ignored\n\ --Qy, -Qn ignored\n\ --s ignored\n"); -#endif -#ifdef SPARC_BIENDIAN - fprintf (stream, "\ --EL generate code for a little endian machine\n\ --EB generate code for a big endian machine\n"); -#endif -} - -/* sparc64 priviledged registers */ - -struct priv_reg_entry - { - char *name; - int regnum; - }; - -struct priv_reg_entry priv_reg_table[] = -{ - {"tpc", 0}, - {"tnpc", 1}, - {"tstate", 2}, - {"tt", 3}, - {"tick", 4}, - {"tba", 5}, - {"pstate", 6}, - {"tl", 7}, - {"pil", 8}, - {"cwp", 9}, - {"cansave", 10}, - {"canrestore", 11}, - {"cleanwin", 12}, - {"otherwin", 13}, - {"wstate", 14}, - {"fq", 15}, - {"ver", 31}, - {"", -1}, /* end marker */ -}; - -/* v9a specific asrs */ - -struct priv_reg_entry v9a_asr_table[] = -{ - {"tick_cmpr", 23}, - {"softint", 22}, - {"set_softint", 20}, - {"pic", 17}, - {"pcr", 16}, - {"gsr", 19}, - {"dcr", 18}, - {"clear_softint", 21}, - {"", -1}, /* end marker */ -}; - -static int -cmp_reg_entry (parg, qarg) - const PTR parg; - const PTR qarg; -{ - const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg; - const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg; - - return strcmp (q->name, p->name); -} - -/* 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 () -{ - register const char *retval = NULL; - int lose = 0; - register unsigned int i = 0; - - /* We don't get a chance to initialize anything before md_parse_option - is called, and it may not be called, so handle default initialization - now if not already done. */ - if (! default_init_p) - init_default_arch (); - - op_hash = hash_new (); - - while (i < (unsigned int) sparc_num_opcodes) - { - const char *name = sparc_opcodes[i].name; - retval = hash_insert (op_hash, name, (PTR) &sparc_opcodes[i]); - if (retval != NULL) - { - fprintf (stderr, "internal error: can't hash `%s': %s\n", - sparc_opcodes[i].name, retval); - lose = 1; - } - do - { - if (sparc_opcodes[i].match & sparc_opcodes[i].lose) - { - fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n", - sparc_opcodes[i].name, sparc_opcodes[i].args); - lose = 1; - } - ++i; - } - while (i < (unsigned int) sparc_num_opcodes - && !strcmp (sparc_opcodes[i].name, name)); - } - - if (lose) - as_fatal ("Broken assembler. No assembly attempted."); - - for (i = '0'; i < '8'; ++i) - octal[i] = 1; - for (i = '0'; i <= '9'; ++i) - toHex[i] = i - '0'; - for (i = 'a'; i <= 'f'; ++i) - toHex[i] = i + 10 - 'a'; - for (i = 'A'; i <= 'F'; ++i) - toHex[i] = i + 10 - 'A'; - - qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]), - sizeof (priv_reg_table[0]), cmp_reg_entry); - - /* If -bump, record the architecture level at which we start issuing - warnings. The behaviour is different depending upon whether an - architecture was explicitly specified. If it wasn't, we issue warnings - for all upwards bumps. If it was, we don't start issuing warnings until - we need to bump beyond the requested architecture or when we bump between - conflicting architectures. */ - - if (warn_on_bump - && architecture_requested) - { - /* `max_architecture' records the requested architecture. - Issue warnings if we go above it. */ - warn_after_architecture = max_architecture; - - /* Find the highest architecture level that doesn't conflict with - the requested one. */ - for (max_architecture = SPARC_OPCODE_ARCH_MAX; - max_architecture > warn_after_architecture; - --max_architecture) - if (! SPARC_OPCODE_CONFLICT_P (max_architecture, - warn_after_architecture)) - break; - } -} - -/* Called after all assembly has been done. */ - -void -sparc_md_end () -{ - if (sparc_arch_size == 64) - { - if (current_architecture == SPARC_OPCODE_ARCH_V9A) - bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9a); - else - bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v9); - } - else - { - if (current_architecture == SPARC_OPCODE_ARCH_V9) - bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plus); - else if (current_architecture == SPARC_OPCODE_ARCH_V9A) - bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_v8plusa); - else if (current_architecture == SPARC_OPCODE_ARCH_SPARCLET) - bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc_sparclet); - else - { - /* The sparclite is treated like a normal sparc. Perhaps it shouldn't - be but for now it is (since that's the way it's always been - treated). */ - bfd_set_arch_mach (stdoutput, bfd_arch_sparc, bfd_mach_sparc); - } - } -} - -/* Return non-zero if VAL is in the range -(MAX+1) to MAX. */ - -static INLINE int -in_signed_range (val, max) - bfd_signed_vma val, max; -{ - if (max <= 0) - abort (); - if (val > max) - return 0; - if (val < ~max) - return 0; - return 1; -} - -/* Return non-zero if VAL is in the range 0 to MAX. */ - -static INLINE int -in_unsigned_range (val, max) - bfd_vma val, max; -{ - if (val > max) - return 0; - return 1; -} - -/* Return non-zero if VAL is in the range -(MAX/2+1) to MAX. - (e.g. -15 to +31). */ - -static INLINE int -in_bitfield_range (val, max) - bfd_signed_vma val, max; -{ - if (max <= 0) - abort (); - if (val > max) - return 0; - if (val < ~(max >> 1)) - return 0; - return 1; -} - -static int -sparc_ffs (mask) - unsigned int mask; -{ - int i; - - if (mask == 0) - return -1; - - for (i = 0; (mask & 1) == 0; ++i) - mask >>= 1; - return i; -} - -/* Implement big shift right. */ -static bfd_vma -BSR (val, amount) - bfd_vma val; - int amount; -{ - if (sizeof (bfd_vma) <= 4 && amount >= 32) - as_fatal ("Support for 64-bit arithmetic not compiled in."); - return val >> amount; -} - -/* For communication between sparc_ip and get_expression. */ -static char *expr_end; - -/* For communication between md_assemble and sparc_ip. */ -static int special_case; - -/* Values for `special_case'. - Instructions that require wierd handling because they're longer than - 4 bytes. */ -#define SPECIAL_CASE_NONE 0 -#define SPECIAL_CASE_SET 1 -#define SPECIAL_CASE_SETSW 2 -#define SPECIAL_CASE_SETX 3 -/* FIXME: sparc-opc.c doesn't have necessary "S" trigger to enable this. */ -#define SPECIAL_CASE_FDIV 4 - -/* Bit masks of various insns. */ -#define NOP_INSN 0x01000000 -#define OR_INSN 0x80100000 -#define FMOVS_INSN 0x81A00020 -#define SETHI_INSN 0x01000000 -#define SLLX_INSN 0x81281000 -#define SRA_INSN 0x81380000 - -/* The last instruction to be assembled. */ -static const struct sparc_opcode *last_insn; -/* The assembled opcode of `last_insn'. */ -static unsigned long last_opcode; - -/* Main entry point to assemble one instruction. */ - -void -md_assemble (str) - char *str; -{ - const struct sparc_opcode *insn; - - know (str); - special_case = SPECIAL_CASE_NONE; - sparc_ip (str, &insn); - - /* We warn about attempts to put a floating point branch in a delay slot, - unless the delay slot has been annulled. */ - if (insn != NULL - && last_insn != NULL - && (insn->flags & F_FBR) != 0 - && (last_insn->flags & F_DELAYED) != 0 - /* ??? This test isn't completely accurate. We assume anything with - F_{UNBR,CONDBR,FBR} set is annullable. */ - && ((last_insn->flags & (F_UNBR | F_CONDBR | F_FBR)) == 0 - || (last_opcode & ANNUL) == 0)) - as_warn ("FP branch in delay slot"); - - /* SPARC before v9 requires a nop instruction between a floating - point instruction and a floating point branch. We insert one - automatically, with a warning. */ - if (max_architecture < SPARC_OPCODE_ARCH_V9 - && insn != NULL - && last_insn != NULL - && (insn->flags & F_FBR) != 0 - && (last_insn->flags & F_FLOAT) != 0) - { - struct sparc_it nop_insn; - - nop_insn.opcode = NOP_INSN; - nop_insn.reloc = BFD_RELOC_NONE; - output_insn (insn, &nop_insn); - as_warn ("FP branch preceded by FP instruction; NOP inserted"); - } - - switch (special_case) - { - case SPECIAL_CASE_NONE: - /* normal insn */ - output_insn (insn, &the_insn); - break; - - case SPECIAL_CASE_SET: - { - int need_hi22_p = 0; - - /* "set" is not defined for negative numbers in v9: it doesn't yield - what you expect it to. */ - if (SPARC_OPCODE_ARCH_V9_P (max_architecture) - && the_insn.exp.X_op == O_constant) - { - if (the_insn.exp.X_add_number < 0) - as_warn ("set: used with negative number"); - else if (the_insn.exp.X_add_number > (offsetT) 0xffffffff) - as_warn ("set: number larger than 4294967295"); - } - - /* See if operand is absolute and small; skip sethi if so. */ - if (the_insn.exp.X_op != O_constant - || the_insn.exp.X_add_number >= (1 << 12) - || the_insn.exp.X_add_number < -(1 << 12)) - { - output_insn (insn, &the_insn); - need_hi22_p = 1; - } - /* See if operand has no low-order bits; skip OR if so. */ - if (the_insn.exp.X_op != O_constant - || (need_hi22_p && (the_insn.exp.X_add_number & 0x3FF) != 0) - || ! need_hi22_p) - { - int rd = (the_insn.opcode & RD (~0)) >> 25; - the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (rd) : 0) - | RD (rd) - | IMMED - | (the_insn.exp.X_add_number - & (need_hi22_p ? 0x3ff : 0x1fff))); - the_insn.reloc = (the_insn.exp.X_op != O_constant - ? BFD_RELOC_LO10 - : BFD_RELOC_NONE); - output_insn (insn, &the_insn); - } - break; - } - - case SPECIAL_CASE_SETSW: - { - /* FIXME: Not finished. */ - break; - } - - case SPECIAL_CASE_SETX: - { -#define SIGNEXT32(x) ((((x) & 0xffffffff) ^ 0x80000000) - 0x80000000) - int upper32 = SIGNEXT32 (BSR (the_insn.exp.X_add_number, 32)); - int lower32 = SIGNEXT32 (the_insn.exp.X_add_number); -#undef SIGNEXT32 - int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14; - int dstreg = (the_insn.opcode & RD (~0)) >> 25; - /* Output directly to dst reg if lower 32 bits are all zero. */ - int upper_dstreg = (the_insn.exp.X_op == O_constant - && lower32 == 0) ? dstreg : tmpreg; - int need_hh22_p = 0, need_hm10_p = 0, need_hi22_p = 0, need_lo10_p = 0; - - /* The tmp reg should not be the dst reg. */ - if (tmpreg == dstreg) - as_warn ("setx: temporary register same as destination register"); - - /* Reset X_add_number, we've extracted it as upper32/lower32. - Otherwise fixup_segment will complain about not being able to - write an 8 byte number in a 4 byte field. */ - the_insn.exp.X_add_number = 0; - - /* ??? Obviously there are other optimizations we can do - (e.g. sethi+shift for 0x1f0000000) and perhaps we shouldn't be - doing some of these. Later. If you do change things, try to - change all of this to be table driven as well. */ - - /* What to output depends on the number if it's constant. - Compute that first, then output what we've decided upon. */ - if (the_insn.exp.X_op != O_constant) - need_hh22_p = need_hm10_p = need_hi22_p = need_lo10_p = 1; - else - { - /* Only need hh22 if `or' insn can't handle constant. */ - if (upper32 < -(1 << 12) || upper32 >= (1 << 12)) - need_hh22_p = 1; - - /* Does bottom part (after sethi) have bits? */ - if ((need_hh22_p && (upper32 & 0x3ff) != 0) - /* No hh22, but does upper32 still have bits we can't set - from lower32? */ - || (! need_hh22_p - && upper32 != 0 - && (upper32 != -1 || lower32 >= 0))) - need_hm10_p = 1; - - /* If the lower half is all zero, we build the upper half directly - into the dst reg. */ - if (lower32 != 0 - /* Need lower half if number is zero. */ - || (! need_hh22_p && ! need_hm10_p)) - { - /* No need for sethi if `or' insn can handle constant. */ - if (lower32 < -(1 << 12) || lower32 >= (1 << 12) - /* Note that we can't use a negative constant in the `or' - insn unless the upper 32 bits are all ones. */ - || (lower32 < 0 && upper32 != -1)) - need_hi22_p = 1; - - /* Does bottom part (after sethi) have bits? */ - if ((need_hi22_p && (lower32 & 0x3ff) != 0) - /* No sethi. */ - || (! need_hi22_p && (lower32 & 0x1fff) != 0) - /* Need `or' if we didn't set anything else. */ - || (! need_hi22_p && ! need_hh22_p && ! need_hm10_p)) - need_lo10_p = 1; - } - } - - if (need_hh22_p) - { - the_insn.opcode = (SETHI_INSN | RD (upper_dstreg) - | ((upper32 >> 10) & 0x3fffff)); - the_insn.reloc = (the_insn.exp.X_op != O_constant - ? BFD_RELOC_SPARC_HH22 : BFD_RELOC_NONE); - output_insn (insn, &the_insn); - } - - if (need_hm10_p) - { - the_insn.opcode = (OR_INSN - | (need_hh22_p ? RS1 (upper_dstreg) : 0) - | RD (upper_dstreg) - | IMMED - | (upper32 - & (need_hh22_p ? 0x3ff : 0x1fff))); - the_insn.reloc = (the_insn.exp.X_op != O_constant - ? BFD_RELOC_SPARC_HM10 : BFD_RELOC_NONE); - output_insn (insn, &the_insn); - } - - if (need_hi22_p) - { - the_insn.opcode = (SETHI_INSN | RD (dstreg) - | ((lower32 >> 10) & 0x3fffff)); - the_insn.reloc = BFD_RELOC_HI22; - output_insn (insn, &the_insn); - } - - if (need_lo10_p) - { - /* FIXME: One nice optimization to do here is to OR the low part - with the highpart if hi22 isn't needed and the low part is - positive. */ - the_insn.opcode = (OR_INSN | (need_hi22_p ? RS1 (dstreg) : 0) - | RD (dstreg) - | IMMED - | (lower32 - & (need_hi22_p ? 0x3ff : 0x1fff))); - the_insn.reloc = BFD_RELOC_LO10; - output_insn (insn, &the_insn); - } - - /* If we needed to build the upper part, shift it into place. */ - if (need_hh22_p || need_hm10_p) - { - the_insn.opcode = (SLLX_INSN | RS1 (upper_dstreg) | RD (upper_dstreg) - | IMMED | 32); - the_insn.reloc = BFD_RELOC_NONE; - output_insn (insn, &the_insn); - } - - /* If we needed to build both upper and lower parts, OR them together. */ - if ((need_hh22_p || need_hm10_p) - && (need_hi22_p || need_lo10_p)) - { - the_insn.opcode = (OR_INSN | RS1 (dstreg) | RS2 (upper_dstreg) - | RD (dstreg)); - the_insn.reloc = BFD_RELOC_NONE; - output_insn (insn, &the_insn); - } - /* We didn't need both regs, but we may have to sign extend lower32. */ - else if (need_hi22_p && upper32 == -1) - { - the_insn.opcode = (SRA_INSN | RS1 (dstreg) | RD (dstreg) - | IMMED | 0); - the_insn.reloc = BFD_RELOC_NONE; - output_insn (insn, &the_insn); - } - break; - } - - case SPECIAL_CASE_FDIV: - { - int rd = (the_insn.opcode >> 25) & 0x1f; - - output_insn (insn, &the_insn); - - /* According to information leaked from Sun, the "fdiv" instructions - on early SPARC machines would produce incorrect results sometimes. - The workaround is to add an fmovs of the destination register to - itself just after the instruction. This was true on machines - with Weitek 1165 float chips, such as the Sun-4/260 and /280. */ - assert (the_insn.reloc == BFD_RELOC_NONE); - the_insn.opcode = FMOVS_INSN | rd | RD (rd); - output_insn (insn, &the_insn); - break; - } - - default: - as_fatal ("failed special case insn sanity check"); - } -} - -/* Subroutine of md_assemble to do the actual parsing. */ - -static void -sparc_ip (str, pinsn) - char *str; - const struct sparc_opcode **pinsn; -{ - char *error_message = ""; - char *s; - const char *args; - char c; - const struct sparc_opcode *insn; - char *argsStart; - unsigned long opcode; - unsigned int mask = 0; - int match = 0; - int comma = 0; - int v9_arg_p; - - for (s = str; islower ((unsigned char) *s) || (*s >= '0' && *s <= '3'); ++s) - ; - - switch (*s) - { - case '\0': - break; - - case ',': - comma = 1; - - /*FALLTHROUGH */ - - case ' ': - *s++ = '\0'; - break; - - default: - as_fatal ("Unknown opcode: `%s'", str); - } - insn = (struct sparc_opcode *) hash_find (op_hash, str); - *pinsn = insn; - if (insn == NULL) - { - as_bad ("Unknown opcode: `%s'", str); - return; - } - if (comma) - { - *--s = ','; - } - - argsStart = s; - for (;;) - { - opcode = insn->match; - memset (&the_insn, '\0', sizeof (the_insn)); - the_insn.reloc = BFD_RELOC_NONE; - v9_arg_p = 0; - - /* - * Build the opcode, checking as we go to make - * sure that the operands match - */ - for (args = insn->args;; ++args) - { - switch (*args) - { - case 'K': - { - int kmask = 0; - - /* Parse a series of masks. */ - if (*s == '#') - { - while (*s == '#') - { - int mask; - - if (! parse_keyword_arg (sparc_encode_membar, &s, - &mask)) - { - error_message = ": invalid membar mask name"; - goto error; - } - kmask |= mask; - while (*s == ' ') { ++s; continue; } - if (*s == '|' || *s == '+') - ++s; - while (*s == ' ') { ++s; continue; } - } - } - else - { - if (! parse_const_expr_arg (&s, &kmask)) - { - error_message = ": invalid membar mask expression"; - goto error; - } - if (kmask < 0 || kmask > 127) - { - error_message = ": invalid membar mask number"; - goto error; - } - } - - opcode |= MEMBAR (kmask); - continue; - } - - case '*': - { - int fcn = 0; - - /* Parse a prefetch function. */ - if (*s == '#') - { - if (! parse_keyword_arg (sparc_encode_prefetch, &s, &fcn)) - { - error_message = ": invalid prefetch function name"; - goto error; - } - } - else - { - if (! parse_const_expr_arg (&s, &fcn)) - { - error_message = ": invalid prefetch function expression"; - goto error; - } - if (fcn < 0 || fcn > 31) - { - error_message = ": invalid prefetch function number"; - goto error; - } - } - opcode |= RD (fcn); - continue; - } - - case '!': - case '?': - /* Parse a sparc64 privileged register. */ - if (*s == '%') - { - struct priv_reg_entry *p = priv_reg_table; - unsigned int len = 9999999; /* init to make gcc happy */ - - s += 1; - while (p->name[0] > s[0]) - p++; - while (p->name[0] == s[0]) - { - len = strlen (p->name); - if (strncmp (p->name, s, len) == 0) - break; - p++; - } - if (p->name[0] != s[0]) - { - error_message = ": unrecognizable privileged register"; - goto error; - } - if (*args == '?') - opcode |= (p->regnum << 14); - else - opcode |= (p->regnum << 25); - s += len; - continue; - } - else - { - error_message = ": unrecognizable privileged register"; - goto error; - } - - case '_': - case '/': - /* Parse a v9a ancillary state register. */ - if (*s == '%') - { - struct priv_reg_entry *p = v9a_asr_table; - unsigned int len = 9999999; /* init to make gcc happy */ - - s += 1; - while (p->name[0] > s[0]) - p++; - while (p->name[0] == s[0]) - { - len = strlen (p->name); - if (strncmp (p->name, s, len) == 0) - break; - p++; - } - if (p->name[0] != s[0]) - { - error_message = ": unrecognizable v9a ancillary state register"; - goto error; - } - if (*args == '/' && (p->regnum == 20 || p->regnum == 21)) - { - error_message = ": rd on write only ancillary state register"; - goto error; - } - if (*args == '/') - opcode |= (p->regnum << 14); - else - opcode |= (p->regnum << 25); - s += len; - continue; - } - else - { - error_message = ": unrecognizable v9a ancillary state register"; - goto error; - } - - case 'M': - case 'm': - if (strncmp (s, "%asr", 4) == 0) - { - s += 4; - - if (isdigit ((unsigned char) *s)) - { - long num = 0; - - while (isdigit ((unsigned char) *s)) - { - num = num * 10 + *s - '0'; - ++s; - } - - if (current_architecture >= SPARC_OPCODE_ARCH_V9) - { - if (num < 16 || 31 < num) - { - error_message = ": asr number must be between 16 and 31"; - goto error; - } - } - else - { - if (num < 0 || 31 < num) - { - error_message = ": asr number must be between 0 and 31"; - goto error; - } - } - - opcode |= (*args == 'M' ? RS1 (num) : RD (num)); - continue; - } - else - { - error_message = ": expecting %asrN"; - goto error; - } - } /* if %asr */ - break; - - case 'I': - the_insn.reloc = BFD_RELOC_SPARC_11; - goto immediate; - - case 'j': - the_insn.reloc = BFD_RELOC_SPARC_10; - goto immediate; - - case 'X': - /* V8 systems don't understand BFD_RELOC_SPARC_5. */ - if (SPARC_OPCODE_ARCH_V9_P (max_architecture)) - the_insn.reloc = BFD_RELOC_SPARC_5; - else - the_insn.reloc = BFD_RELOC_SPARC13; - /* These fields are unsigned, but for upward compatibility, - allow negative values as well. */ - goto immediate; - - case 'Y': - /* V8 systems don't understand BFD_RELOC_SPARC_6. */ - if (SPARC_OPCODE_ARCH_V9_P (max_architecture)) - the_insn.reloc = BFD_RELOC_SPARC_6; - else - the_insn.reloc = BFD_RELOC_SPARC13; - /* These fields are unsigned, but for upward compatibility, - allow negative values as well. */ - goto immediate; - - case 'k': - the_insn.reloc = /* RELOC_WDISP2_14 */ BFD_RELOC_SPARC_WDISP16; - the_insn.pcrel = 1; - goto immediate; - - case 'G': - the_insn.reloc = BFD_RELOC_SPARC_WDISP19; - the_insn.pcrel = 1; - goto immediate; - - case 'N': - if (*s == 'p' && s[1] == 'n') - { - s += 2; - continue; - } - break; - - case 'T': - if (*s == 'p' && s[1] == 't') - { - s += 2; - continue; - } - break; - - case 'z': - if (*s == ' ') - { - ++s; - } - if (strncmp (s, "%icc", 4) == 0) - { - s += 4; - continue; - } - break; - - case 'Z': - if (*s == ' ') - { - ++s; - } - if (strncmp (s, "%xcc", 4) == 0) - { - s += 4; - continue; - } - break; - - case '6': - if (*s == ' ') - { - ++s; - } - if (strncmp (s, "%fcc0", 5) == 0) - { - s += 5; - continue; - } - break; - - case '7': - if (*s == ' ') - { - ++s; - } - if (strncmp (s, "%fcc1", 5) == 0) - { - s += 5; - continue; - } - break; - - case '8': - if (*s == ' ') - { - ++s; - } - if (strncmp (s, "%fcc2", 5) == 0) - { - s += 5; - continue; - } - break; - - case '9': - if (*s == ' ') - { - ++s; - } - if (strncmp (s, "%fcc3", 5) == 0) - { - s += 5; - continue; - } - break; - - case 'P': - if (strncmp (s, "%pc", 3) == 0) - { - s += 3; - continue; - } - break; - - case 'W': - if (strncmp (s, "%tick", 5) == 0) - { - s += 5; - continue; - } - break; - - case '\0': /* end of args */ - if (*s == '\0') - { - match = 1; - } - break; - - case '+': - if (*s == '+') - { - ++s; - continue; - } - if (*s == '-') - { - continue; - } - break; - - case '[': /* these must match exactly */ - case ']': - case ',': - case ' ': - if (*s++ == *args) - continue; - break; - - case '#': /* must be at least one digit */ - if (isdigit ((unsigned char) *s++)) - { - while (isdigit ((unsigned char) *s)) - { - ++s; - } - continue; - } - break; - - case 'C': /* coprocessor state register */ - if (strncmp (s, "%csr", 4) == 0) - { - s += 4; - continue; - } - break; - - case 'b': /* next operand is a coprocessor register */ - case 'c': - case 'D': - if (*s++ == '%' && *s++ == 'c' && isdigit ((unsigned char) *s)) - { - mask = *s++; - if (isdigit ((unsigned char) *s)) - { - mask = 10 * (mask - '0') + (*s++ - '0'); - if (mask >= 32) - { - break; - } - } - else - { - mask -= '0'; - } - switch (*args) - { - - case 'b': - opcode |= mask << 14; - continue; - - case 'c': - opcode |= mask; - continue; - - case 'D': - opcode |= mask << 25; - continue; - } - } - break; - - case 'r': /* next operand must be a register */ - case 'O': - case '1': - case '2': - case 'd': - if (*s++ == '%') - { - switch (c = *s++) - { - - case 'f': /* frame pointer */ - if (*s++ == 'p') - { - mask = 0x1e; - break; - } - goto error; - - case 'g': /* global register */ - if (isoctal (c = *s++)) - { - mask = c - '0'; - break; - } - goto error; - - case 'i': /* in register */ - if (isoctal (c = *s++)) - { - mask = c - '0' + 24; - break; - } - goto error; - - case 'l': /* local register */ - if (isoctal (c = *s++)) - { - mask = (c - '0' + 16); - break; - } - goto error; - - case 'o': /* out register */ - if (isoctal (c = *s++)) - { - mask = (c - '0' + 8); - break; - } - goto error; - - case 's': /* stack pointer */ - if (*s++ == 'p') - { - mask = 0xe; - break; - } - goto error; - - case 'r': /* any register */ - if (!isdigit ((unsigned char) (c = *s++))) - { - goto error; - } - /* FALLTHROUGH */ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (isdigit ((unsigned char) *s)) - { - if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) - { - goto error; - } - } - else - { - c -= '0'; - } - mask = c; - break; - - default: - goto error; - } - - /* Got the register, now figure out where - it goes in the opcode. */ - switch (*args) - { - case '1': - opcode |= mask << 14; - continue; - - case '2': - opcode |= mask; - continue; - - case 'd': - opcode |= mask << 25; - continue; - - case 'r': - opcode |= (mask << 25) | (mask << 14); - continue; - - case 'O': - opcode |= (mask << 25) | (mask << 0); - continue; - } - } - break; - - case 'e': /* next operand is a floating point register */ - case 'v': - case 'V': - - case 'f': - case 'B': - case 'R': - - case 'g': - case 'H': - case 'J': - { - char format; - - if (*s++ == '%' - && ((format = *s) == 'f') - && isdigit ((unsigned char) *++s)) - { - for (mask = 0; isdigit ((unsigned char) *s); ++s) - { - mask = 10 * mask + (*s - '0'); - } /* read the number */ - - if ((*args == 'v' - || *args == 'B' - || *args == 'H') - && (mask & 1)) - { - break; - } /* register must be even numbered */ - - if ((*args == 'V' - || *args == 'R' - || *args == 'J') - && (mask & 3)) - { - break; - } /* register must be multiple of 4 */ - - if (mask >= 64) - { - if (SPARC_OPCODE_ARCH_V9_P (max_architecture)) - error_message = ": There are only 64 f registers; [0-63]"; - else - error_message = ": There are only 32 f registers; [0-31]"; - goto error; - } /* on error */ - else if (mask >= 32) - { - if (SPARC_OPCODE_ARCH_V9_P (max_architecture)) - { - v9_arg_p = 1; - mask -= 31; /* wrap high bit */ - } - else - { - error_message = ": There are only 32 f registers; [0-31]"; - goto error; - } - } - } - else - { - break; - } /* if not an 'f' register. */ - - switch (*args) - { - case 'v': - case 'V': - case 'e': - opcode |= RS1 (mask); - continue; - - - case 'f': - case 'B': - case 'R': - opcode |= RS2 (mask); - continue; - - case 'g': - case 'H': - case 'J': - opcode |= RD (mask); - continue; - } /* pack it in. */ - - know (0); - break; - } /* float arg */ - - case 'F': - if (strncmp (s, "%fsr", 4) == 0) - { - s += 4; - continue; - } - break; - - case '0': /* 64 bit immediate (setx insn) */ - the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere */ - goto immediate; - - case 'h': /* high 22 bits */ - the_insn.reloc = BFD_RELOC_HI22; - goto immediate; - - case 'l': /* 22 bit PC relative immediate */ - the_insn.reloc = BFD_RELOC_SPARC_WDISP22; - the_insn.pcrel = 1; - goto immediate; - - case 'L': /* 30 bit immediate */ - the_insn.reloc = BFD_RELOC_32_PCREL_S2; - the_insn.pcrel = 1; - goto immediate; - - case 'n': /* 22 bit immediate */ - the_insn.reloc = BFD_RELOC_SPARC22; - goto immediate; - - case 'i': /* 13 bit immediate */ - the_insn.reloc = BFD_RELOC_SPARC13; - - /* fallthrough */ - - immediate: - if (*s == ' ') - s++; - - /* Check for %hi, etc. */ - if (*s == '%') - { - static struct ops { - /* The name as it appears in assembler. */ - char *name; - /* strlen (name), precomputed for speed */ - int len; - /* The reloc this pseudo-op translates to. */ - int reloc; - /* Non-zero if for v9 only. */ - int v9_p; - /* Non-zero if can be used in pc-relative contexts. */ - int pcrel_p;/*FIXME:wip*/ - } ops[] = { - /* hix/lox must appear before hi/lo so %hix won't be - mistaken for %hi. */ - { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 }, - { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 }, - { "hi", 2, BFD_RELOC_HI22, 0, 1 }, - { "lo", 2, BFD_RELOC_LO10, 0, 1 }, - { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 }, - { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 }, - { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 }, - { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 }, - { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 }, - { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 }, - { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 }, - { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 }, - { NULL } - }; - struct ops *o; - - for (o = ops; o->name; o++) - if (strncmp (s + 1, o->name, o->len) == 0) - break; - if (o->name == NULL) - break; - - the_insn.reloc = o->reloc; - s += o->len + 1; - v9_arg_p = o->v9_p; - } - - /* Note that if the get_expression() fails, we will still - have created U entries in the symbol table for the - 'symbols' in the input string. Try not to create U - symbols for registers, etc. */ - { - /* This stuff checks to see if the expression ends in - +%reg. If it does, it removes the register from - the expression, and re-sets 's' to point to the - right place. */ - - char *s1; - - for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ; - - if (s1 != s && isdigit ((unsigned char) s1[-1])) - { - if (s1[-2] == '%' && s1[-3] == '+') - { - s1 -= 3; - *s1 = '\0'; - (void) get_expression (s); - *s1 = '+'; - s = s1; - continue; - } - else if (strchr ("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+') - { - s1 -= 4; - *s1 = '\0'; - (void) get_expression (s); - *s1 = '+'; - s = s1; - continue; - } - } - } - (void) get_expression (s); - s = expr_end; - - /* Check for constants that don't require emitting a reloc. */ - if (the_insn.exp.X_op == O_constant - && the_insn.exp.X_add_symbol == 0 - && the_insn.exp.X_op_symbol == 0) - { - /* For pc-relative call instructions, we reject - constants to get better code. */ - if (the_insn.pcrel - && the_insn.reloc == BFD_RELOC_32_PCREL_S2 - && in_signed_range (the_insn.exp.X_add_number, 0x3fff)) - { - error_message = ": PC-relative operand can't be a constant"; - goto error; - } - - /* Constants that won't fit are checked in md_apply_fix3 - and bfd_install_relocation. - ??? It would be preferable to install the constants - into the insn here and save having to create a fixS - for each one. There already exists code to handle - all the various cases (e.g. in md_apply_fix3 and - bfd_install_relocation) so duplicating all that code - here isn't right. */ - } - - continue; - - case 'a': - if (*s++ == 'a') - { - opcode |= ANNUL; - continue; - } - break; - - case 'A': - { - int asi = 0; - - /* Parse an asi. */ - if (*s == '#') - { - if (! parse_keyword_arg (sparc_encode_asi, &s, &asi)) - { - error_message = ": invalid ASI name"; - goto error; - } - } - else - { - if (! parse_const_expr_arg (&s, &asi)) - { - error_message = ": invalid ASI expression"; - goto error; - } - if (asi < 0 || asi > 255) - { - error_message = ": invalid ASI number"; - goto error; - } - } - opcode |= ASI (asi); - continue; - } /* alternate space */ - - case 'p': - if (strncmp (s, "%psr", 4) == 0) - { - s += 4; - continue; - } - break; - - case 'q': /* floating point queue */ - if (strncmp (s, "%fq", 3) == 0) - { - s += 3; - continue; - } - break; - - case 'Q': /* coprocessor queue */ - if (strncmp (s, "%cq", 3) == 0) - { - s += 3; - continue; - } - break; - - case 'S': - if (strcmp (str, "set") == 0 - || strcmp (str, "setuw") == 0) - { - special_case = SPECIAL_CASE_SET; - continue; - } - else if (strcmp (str, "setsw") == 0) - { - special_case = SPECIAL_CASE_SETSW; - continue; - } - else if (strcmp (str, "setx") == 0) - { - special_case = SPECIAL_CASE_SETX; - continue; - } - else if (strncmp (str, "fdiv", 4) == 0) - { - special_case = SPECIAL_CASE_FDIV; - continue; - } - break; - - case 'o': - if (strncmp (s, "%asi", 4) != 0) - break; - s += 4; - continue; - - case 's': - if (strncmp (s, "%fprs", 5) != 0) - break; - s += 5; - continue; - - case 'E': - if (strncmp (s, "%ccr", 4) != 0) - break; - s += 4; - continue; - - case 't': - if (strncmp (s, "%tbr", 4) != 0) - break; - s += 4; - continue; - - case 'w': - if (strncmp (s, "%wim", 4) != 0) - break; - s += 4; - continue; - - case 'x': - { - char *push = input_line_pointer; - expressionS e; - - input_line_pointer = s; - expression (&e); - if (e.X_op == O_constant) - { - int n = e.X_add_number; - if (n != e.X_add_number || (n & ~0x1ff) != 0) - as_bad ("OPF immediate operand out of range (0-0x1ff)"); - else - opcode |= e.X_add_number << 5; - } - else - as_bad ("non-immediate OPF operand, ignored"); - s = input_line_pointer; - input_line_pointer = push; - continue; - } - - case 'y': - if (strncmp (s, "%y", 2) != 0) - break; - s += 2; - continue; - - case 'u': - case 'U': - { - /* Parse a sparclet cpreg. */ - int cpreg; - if (! parse_keyword_arg (sparc_encode_sparclet_cpreg, &s, &cpreg)) - { - error_message = ": invalid cpreg name"; - goto error; - } - opcode |= (*args == 'U' ? RS1 (cpreg) : RD (cpreg)); - continue; - } - - default: - as_fatal ("failed sanity check."); - } /* switch on arg code */ - - /* Break out of for() loop. */ - break; - } /* for each arg that we expect */ - - error: - if (match == 0) - { - /* Args don't match. */ - if (&insn[1] - sparc_opcodes < sparc_num_opcodes - && (insn->name == insn[1].name - || !strcmp (insn->name, insn[1].name))) - { - ++insn; - s = argsStart; - continue; - } - else - { - as_bad ("Illegal operands%s", error_message); - return; - } - } - else - { - /* We have a match. Now see if the architecture is ok. */ - int needed_arch_mask = insn->architecture; - - if (v9_arg_p) - { - needed_arch_mask &= ~ ((1 << SPARC_OPCODE_ARCH_V9) - | (1 << SPARC_OPCODE_ARCH_V9A)); - needed_arch_mask |= (1 << SPARC_OPCODE_ARCH_V9); - } - - if (needed_arch_mask & SPARC_OPCODE_SUPPORTED (current_architecture)) - ; /* ok */ - /* Can we bump up the architecture? */ - else if (needed_arch_mask & SPARC_OPCODE_SUPPORTED (max_architecture)) - { - enum sparc_opcode_arch_val needed_architecture = - sparc_ffs (SPARC_OPCODE_SUPPORTED (max_architecture) - & needed_arch_mask); - - assert (needed_architecture <= SPARC_OPCODE_ARCH_MAX); - if (warn_on_bump - && needed_architecture > warn_after_architecture) - { - as_warn ("architecture bumped from \"%s\" to \"%s\" on \"%s\"", - sparc_opcode_archs[current_architecture].name, - sparc_opcode_archs[needed_architecture].name, - str); - warn_after_architecture = needed_architecture; - } - current_architecture = needed_architecture; - } - /* Conflict. */ - /* ??? This seems to be a bit fragile. What if the next entry in - the opcode table is the one we want and it is supported? - It is possible to arrange the table today so that this can't - happen but what about tomorrow? */ - else - { - int arch,printed_one_p = 0; - char *p; - char required_archs[SPARC_OPCODE_ARCH_MAX * 16]; - - /* Create a list of the architectures that support the insn. */ - needed_arch_mask &= ~ SPARC_OPCODE_SUPPORTED (max_architecture); - p = required_archs; - arch = sparc_ffs (needed_arch_mask); - while ((1 << arch) <= needed_arch_mask) - { - if ((1 << arch) & needed_arch_mask) - { - if (printed_one_p) - *p++ = '|'; - strcpy (p, sparc_opcode_archs[arch].name); - p += strlen (p); - printed_one_p = 1; - } - ++arch; - } - - as_bad ("Architecture mismatch on \"%s\".", str); - as_tsktsk (" (Requires %s; requested architecture is %s.)", - required_archs, - sparc_opcode_archs[max_architecture].name); - return; - } - } /* if no match */ - - break; - } /* forever looking for a match */ - - the_insn.opcode = opcode; -} - -/* Parse an argument that can be expressed as a keyword. - (eg: #StoreStore or %ccfr). - The result is a boolean indicating success. - If successful, INPUT_POINTER is updated. */ - -static int -parse_keyword_arg (lookup_fn, input_pointerP, valueP) - int (*lookup_fn) PARAMS ((const char *)); - char **input_pointerP; - int *valueP; -{ - int value; - char c, *p, *q; - - p = *input_pointerP; - for (q = p + (*p == '#' || *p == '%'); - isalnum ((unsigned char) *q) || *q == '_'; - ++q) - continue; - c = *q; - *q = 0; - value = (*lookup_fn) (p); - *q = c; - if (value == -1) - return 0; - *valueP = value; - *input_pointerP = q; - return 1; -} - -/* Parse an argument that is a constant expression. - The result is a boolean indicating success. */ - -static int -parse_const_expr_arg (input_pointerP, valueP) - char **input_pointerP; - int *valueP; -{ - char *save = input_line_pointer; - expressionS exp; - - input_line_pointer = *input_pointerP; - /* The next expression may be something other than a constant - (say if we're not processing the right variant of the insn). - Don't call expression unless we're sure it will succeed as it will - signal an error (which we want to defer until later). */ - /* FIXME: It might be better to define md_operand and have it recognize - things like %asi, etc. but continuing that route through to the end - is a lot of work. */ - if (*input_line_pointer == '%') - { - input_line_pointer = save; - return 0; - } - expression (&exp); - *input_pointerP = input_line_pointer; - input_line_pointer = save; - if (exp.X_op != O_constant) - return 0; - *valueP = exp.X_add_number; - return 1; -} - -/* Subroutine of sparc_ip to parse an expression. */ - -static int -get_expression (str) - char *str; -{ - char *save_in; - segT seg; - - save_in = input_line_pointer; - input_line_pointer = str; - seg = expression (&the_insn.exp); - if (seg != absolute_section - && seg != text_section - && seg != data_section - && seg != bss_section - && seg != undefined_section) - { - the_insn.error = "bad segment"; - expr_end = input_line_pointer; - input_line_pointer = save_in; - return 1; - } - expr_end = input_line_pointer; - input_line_pointer = save_in; - return 0; -} - -/* Subroutine of md_assemble to output one insn. */ - -static void -output_insn (insn, the_insn) - const struct sparc_opcode *insn; - struct sparc_it *the_insn; -{ - char *toP = frag_more (4); - - /* put out the opcode */ - if (INSN_BIG_ENDIAN) - number_to_chars_bigendian (toP, (valueT) the_insn->opcode, 4); - else - number_to_chars_littleendian (toP, (valueT) the_insn->opcode, 4); - - /* put out the symbol-dependent stuff */ - if (the_insn->reloc != BFD_RELOC_NONE) - { - fixS *fixP = fix_new_exp (frag_now, /* which frag */ - (toP - frag_now->fr_literal), /* where */ - 4, /* size */ - &the_insn->exp, - the_insn->pcrel, - the_insn->reloc); - /* Turn off overflow checking in fixup_segment. We'll do our - own overflow checking in md_apply_fix3. This is necessary because - the insn size is 4 and fixup_segment will signal an overflow for - large 8 byte quantities. */ - fixP->fx_no_overflow = 1; - } - - last_insn = insn; - last_opcode = the_insn->opcode; -} - -/* - This is identical to the md_atof in m68k.c. I think this is right, - but I'm not sure. - - 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 - -char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; -{ - int i,prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - char *t; - - switch (type) - { - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - 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); - - if (target_big_endian) - { - for (i = 0; i < prec; i++) - { - md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - } - else - { - for (i = prec - 1; i >= 0; i--) - { - md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - } - - return 0; -} - -/* 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; -{ - if (target_big_endian) - number_to_chars_bigendian (buf, val, n); - else - number_to_chars_littleendian (buf, val, n); -} - -/* Apply a fixS to the frags, now that we know the value it ought to - hold. */ - -int -md_apply_fix3 (fixP, value, segment) - fixS *fixP; - valueT *value; - segT segment; -{ - char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; - offsetT val; - long insn; - - val = *value; - - assert (fixP->fx_r_type < BFD_RELOC_UNUSED); - - fixP->fx_addnumber = val; /* Remember value for emit_reloc */ - -#ifdef OBJ_ELF - /* FIXME: SPARC ELF relocations don't use an addend in the data - field itself. This whole approach should be somehow combined - with the calls to bfd_install_relocation. Also, the value passed - in by fixup_segment includes the value of a defined symbol. We - don't want to include the value of an externally visible symbol. */ - if (fixP->fx_addsy != NULL) - { - if (fixP->fx_addsy->sy_used_in_reloc - && (S_IS_EXTERNAL (fixP->fx_addsy) - || S_IS_WEAK (fixP->fx_addsy) - || (sparc_pic_code && ! fixP->fx_pcrel) - || (S_GET_SEGMENT (fixP->fx_addsy) != segment - && ((bfd_get_section_flags (stdoutput, - S_GET_SEGMENT (fixP->fx_addsy)) - & SEC_LINK_ONCE) != 0 - || strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)), - ".gnu.linkonce", - sizeof ".gnu.linkonce" - 1) == 0))) - && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section - && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section - && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy))) - fixP->fx_addnumber -= S_GET_VALUE (fixP->fx_addsy); - return 1; - } -#endif - - /* This is a hack. There should be a better way to - handle this. Probably in terms of howto fields, once - we can look at these fixups in terms of howtos. */ - if (fixP->fx_r_type == BFD_RELOC_32_PCREL_S2 && fixP->fx_addsy) - val += fixP->fx_where + fixP->fx_frag->fr_address; - -#ifdef OBJ_AOUT - /* FIXME: More ridiculous gas reloc hacking. If we are going to - generate a reloc, then we just want to let the reloc addend set - the value. We do not want to also stuff the addend into the - object file. Including the addend in the object file works when - doing a static link, because the linker will ignore the object - file contents. However, the dynamic linker does not ignore the - object file contents. */ - if (fixP->fx_addsy != NULL - && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2) - val = 0; - - /* When generating PIC code, we do not want an addend for a reloc - against a local symbol. We adjust fx_addnumber to cancel out the - value already included in val, and to also cancel out the - adjustment which bfd_install_relocation will create. */ - if (sparc_pic_code - && fixP->fx_r_type != BFD_RELOC_32_PCREL_S2 - && fixP->fx_addsy != NULL - && ! S_IS_COMMON (fixP->fx_addsy) - && (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) == 0) - fixP->fx_addnumber -= 2 * S_GET_VALUE (fixP->fx_addsy); -#endif - - /* If this is a data relocation, just output VAL. */ - - if (fixP->fx_r_type == BFD_RELOC_16) - { - md_number_to_chars (buf, val, 2); - } - else if (fixP->fx_r_type == BFD_RELOC_32) - { - md_number_to_chars (buf, val, 4); - } - else if (fixP->fx_r_type == BFD_RELOC_64) - { - md_number_to_chars (buf, val, 8); - } - else - { - /* It's a relocation against an instruction. */ - - if (INSN_BIG_ENDIAN) - insn = bfd_getb32 ((unsigned char *) buf); - else - insn = bfd_getl32 ((unsigned char *) buf); - - switch (fixP->fx_r_type) - { - case BFD_RELOC_32_PCREL_S2: - val = val >> 2; - /* FIXME: This increment-by-one deserves a comment of why it's - being done! */ - if (! sparc_pic_code - || fixP->fx_addsy == NULL - || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0) - ++val; - insn |= val & 0x3fffffff; - break; - - case BFD_RELOC_SPARC_11: - if (! in_signed_range (val, 0x7ff)) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - insn |= val & 0x7ff; - break; - - case BFD_RELOC_SPARC_10: - if (! in_signed_range (val, 0x3ff)) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - insn |= val & 0x3ff; - break; - - case BFD_RELOC_SPARC_7: - if (! in_bitfield_range (val, 0x7f)) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - insn |= val & 0x7f; - break; - - case BFD_RELOC_SPARC_6: - if (! in_bitfield_range (val, 0x3f)) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - insn |= val & 0x3f; - break; - - case BFD_RELOC_SPARC_5: - if (! in_bitfield_range (val, 0x1f)) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - insn |= val & 0x1f; - break; - - case BFD_RELOC_SPARC_WDISP16: - /* FIXME: simplify */ - if (((val > 0) && (val & ~0x3fffc)) - || ((val < 0) && (~(val - 1) & ~0x3fffc))) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - /* FIXME: The +1 deserves a comment. */ - val = (val >> 2) + 1; - insn |= ((val & 0xc000) << 6) | (val & 0x3fff); - break; - - case BFD_RELOC_SPARC_WDISP19: - /* FIXME: simplify */ - if (((val > 0) && (val & ~0x1ffffc)) - || ((val < 0) && (~(val - 1) & ~0x1ffffc))) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - /* FIXME: The +1 deserves a comment. */ - val = (val >> 2) + 1; - insn |= val & 0x7ffff; - break; - - case BFD_RELOC_SPARC_HH22: - val = BSR (val, 32); - /* intentional fallthrough */ - - case BFD_RELOC_SPARC_LM22: - case BFD_RELOC_HI22: - if (!fixP->fx_addsy) - { - insn |= (val >> 10) & 0x3fffff; - } - else - { - /* FIXME: Need comment explaining why we do this. */ - insn &= ~0xffff; - } - break; - - case BFD_RELOC_SPARC22: - if (val & ~0x003fffff) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - insn |= (val & 0x3fffff); - break; - - case BFD_RELOC_SPARC_HM10: - val = BSR (val, 32); - /* intentional fallthrough */ - - case BFD_RELOC_LO10: - if (!fixP->fx_addsy) - { - insn |= val & 0x3ff; - } - else - { - /* FIXME: Need comment explaining why we do this. */ - insn &= ~0xff; - } - break; - - case BFD_RELOC_SPARC13: - if (! in_signed_range (val, 0x1fff)) - as_bad_where (fixP->fx_file, fixP->fx_line, "relocation overflow"); - insn |= val & 0x1fff; - break; - - case BFD_RELOC_SPARC_WDISP22: - val = (val >> 2) + 1; - /* FALLTHROUGH */ - case BFD_RELOC_SPARC_BASE22: - insn |= val & 0x3fffff; - break; - - case BFD_RELOC_SPARC_H44: - if (!fixP->fx_addsy) - { - bfd_vma tval = val; - tval >>= 22; - insn |= tval & 0x3fffff; - } - break; - - case BFD_RELOC_SPARC_M44: - if (!fixP->fx_addsy) - insn |= (val >> 12) & 0x3ff; - break; - - case BFD_RELOC_SPARC_L44: - if (!fixP->fx_addsy) - insn |= val & 0xfff; - break; - - case BFD_RELOC_SPARC_HIX22: - if (!fixP->fx_addsy) - { - val ^= ~ (offsetT) 0; - insn |= (val >> 10) & 0x3fffff; - } - break; - - case BFD_RELOC_SPARC_LOX10: - if (!fixP->fx_addsy) - insn |= 0x1c00 | (val & 0x3ff); - break; - - case BFD_RELOC_NONE: - default: - as_bad_where (fixP->fx_file, fixP->fx_line, - "bad or unhandled relocation type: 0x%02x", - fixP->fx_r_type); - break; - } - - if (INSN_BIG_ENDIAN) - bfd_putb32 (insn, (unsigned char *) buf); - else - bfd_putl32 (insn, (unsigned char *) buf); - } - - /* Are we finished with this relocation now? */ - if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) - fixP->fx_done = 1; - - return 1; -} - -/* Translate internal representation of relocation info to BFD target - format. */ -arelent * -tc_gen_reloc (section, fixp) - asection *section; - fixS *fixp; -{ - arelent *reloc; - bfd_reloc_code_real_type code; - - reloc = (arelent *) xmalloc (sizeof (arelent)); - - reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; - reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - - switch (fixp->fx_r_type) - { - case BFD_RELOC_16: - case BFD_RELOC_32: - case BFD_RELOC_HI22: - case BFD_RELOC_LO10: - case BFD_RELOC_32_PCREL_S2: - case BFD_RELOC_SPARC13: - case BFD_RELOC_SPARC_BASE13: - case BFD_RELOC_SPARC_WDISP16: - case BFD_RELOC_SPARC_WDISP19: - case BFD_RELOC_SPARC_WDISP22: - case BFD_RELOC_64: - case BFD_RELOC_SPARC_5: - case BFD_RELOC_SPARC_6: - case BFD_RELOC_SPARC_7: - case BFD_RELOC_SPARC_10: - case BFD_RELOC_SPARC_11: - case BFD_RELOC_SPARC_HH22: - case BFD_RELOC_SPARC_HM10: - case BFD_RELOC_SPARC_LM22: - case BFD_RELOC_SPARC_PC_HH22: - case BFD_RELOC_SPARC_PC_HM10: - case BFD_RELOC_SPARC_PC_LM22: - case BFD_RELOC_SPARC_H44: - case BFD_RELOC_SPARC_M44: - case BFD_RELOC_SPARC_L44: - case BFD_RELOC_SPARC_HIX22: - case BFD_RELOC_SPARC_LOX10: - code = fixp->fx_r_type; - break; - default: - abort (); - return NULL; - } - -#if defined (OBJ_ELF) || defined (OBJ_AOUT) - /* If we are generating PIC code, we need to generate a different - set of relocs. */ - -#ifdef OBJ_ELF -#define GOT_NAME "_GLOBAL_OFFSET_TABLE_" -#else -#define GOT_NAME "__GLOBAL_OFFSET_TABLE_" -#endif - - if (sparc_pic_code) - { - switch (code) - { - case BFD_RELOC_32_PCREL_S2: - if (! S_IS_DEFINED (fixp->fx_addsy) - || S_IS_COMMON (fixp->fx_addsy) - || S_IS_EXTERNAL (fixp->fx_addsy) - || S_IS_WEAK (fixp->fx_addsy)) - code = BFD_RELOC_SPARC_WPLT30; - break; - case BFD_RELOC_HI22: - if (fixp->fx_addsy != NULL - && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0) - code = BFD_RELOC_SPARC_PC22; - else - code = BFD_RELOC_SPARC_GOT22; - break; - case BFD_RELOC_LO10: - if (fixp->fx_addsy != NULL - && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0) - code = BFD_RELOC_SPARC_PC10; - else - code = BFD_RELOC_SPARC_GOT10; - break; - case BFD_RELOC_SPARC13: - code = BFD_RELOC_SPARC_GOT13; - break; - default: - break; - } - } -#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT) */ - - reloc->howto = bfd_reloc_type_lookup (stdoutput, code); - if (reloc->howto == 0) - { - as_bad_where (fixp->fx_file, fixp->fx_line, - "internal error: can't export reloc type %d (`%s')", - fixp->fx_r_type, bfd_get_reloc_code_name (code)); - return 0; - } - - /* @@ Why fx_addnumber sometimes and fx_offset other times? */ -#ifdef OBJ_AOUT - - if (reloc->howto->pc_relative == 0 - || code == BFD_RELOC_SPARC_PC10 - || code == BFD_RELOC_SPARC_PC22) - reloc->addend = fixp->fx_addnumber; - else - reloc->addend = fixp->fx_offset - reloc->address; - -#else /* elf or coff */ - - if (reloc->howto->pc_relative == 0 - || code == BFD_RELOC_SPARC_PC10 - || code == BFD_RELOC_SPARC_PC22) - reloc->addend = fixp->fx_addnumber; - else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0) - reloc->addend = (section->vma - + fixp->fx_addnumber - + md_pcrel_from (fixp)); - else - reloc->addend = fixp->fx_offset; -#endif - - return reloc; -} - -/* We have no need to default values of symbols. */ - -/* ARGSUSED */ -symbolS * -md_undefined_symbol (name) - 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; -{ -#ifndef OBJ_ELF - /* This is not right for ELF; a.out wants it, and COFF will force - the alignment anyways. */ - valueT align = ((valueT) 1 - << (valueT) bfd_get_section_alignment (stdoutput, segment)); - valueT newsize; - /* turn alignment value into a mask */ - align--; - newsize = (size + align) & ~align; - return newsize; -#else - return size; -#endif -} - -/* 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; -{ - long ret; - - ret = fixP->fx_where + fixP->fx_frag->fr_address; - if (! sparc_pic_code - || fixP->fx_addsy == NULL - || (fixP->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0) - ret += fixP->fx_size; - return ret; -} - -/* - * sort of like s_lcomm - */ - -#ifndef OBJ_ELF -static int max_alignment = 15; -#endif - -static void -s_reserve (ignore) - int ignore; -{ - char *name; - char *p; - char c; - int align; - int size; - int temp; - symbolS *symbolP; - - name = input_line_pointer; - c = get_symbol_end (); - p = input_line_pointer; - *p = c; - SKIP_WHITESPACE (); - - if (*input_line_pointer != ',') - { - as_bad ("Expected comma after name"); - ignore_rest_of_line (); - return; - } - - ++input_line_pointer; - - if ((size = get_absolute_expression ()) < 0) - { - as_bad ("BSS length (%d.) <0! Ignored.", size); - ignore_rest_of_line (); - return; - } /* bad length */ - - *p = 0; - symbolP = symbol_find_or_make (name); - *p = c; - - if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0 - && strncmp (input_line_pointer, ",\".bss\"", 7) != 0) - { - as_bad ("bad .reserve segment -- expected BSS segment"); - return; - } - - if (input_line_pointer[2] == '.') - input_line_pointer += 7; - else - input_line_pointer += 6; - SKIP_WHITESPACE (); - - if (*input_line_pointer == ',') - { - ++input_line_pointer; - - SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') - { - as_bad ("Missing alignment"); - return; - } - - align = get_absolute_expression (); -#ifndef OBJ_ELF - if (align > max_alignment) - { - align = max_alignment; - as_warn ("Alignment too large: %d. assumed.", align); - } -#endif - if (align < 0) - { - align = 0; - as_warn ("Alignment negative. 0 assumed."); - } - - record_alignment (bss_section, align); - - /* convert to a power of 2 alignment */ - for (temp = 0; (align & 1) == 0; align >>= 1, ++temp);; - - if (align != 1) - { - as_bad ("Alignment not a power of 2"); - ignore_rest_of_line (); - return; - } /* not a power of two */ - - align = temp; - } /* if has optional alignment */ - else - align = 0; - - if (!S_IS_DEFINED (symbolP) -#ifdef OBJ_AOUT - && S_GET_OTHER (symbolP) == 0 - && S_GET_DESC (symbolP) == 0 -#endif - ) - { - if (! need_pass_2) - { - char *pfrag; - segT current_seg = now_seg; - subsegT current_subseg = now_subseg; - - subseg_set (bss_section, 1); /* switch to bss */ - - if (align) - frag_align (align, 0, 0); /* do alignment */ - - /* detach from old frag */ - if (S_GET_SEGMENT(symbolP) == bss_section) - symbolP->sy_frag->fr_symbol = NULL; - - symbolP->sy_frag = frag_now; - pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, - (offsetT) size, (char *)0); - *pfrag = 0; - - S_SET_SEGMENT (symbolP, bss_section); - - subseg_set (current_seg, current_subseg); - } - } - else - { - as_warn("Ignoring attempt to re-define symbol %s", - S_GET_NAME (symbolP)); - } /* if not redefining */ - - demand_empty_rest_of_line (); -} - -static void -s_common (ignore) - int ignore; -{ - char *name; - char c; - char *p; - int temp, size; - symbolS *symbolP; - - name = input_line_pointer; - c = get_symbol_end (); - /* just after name is now '\0' */ - p = input_line_pointer; - *p = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - as_bad ("Expected comma after symbol-name"); - ignore_rest_of_line (); - return; - } - input_line_pointer++; /* skip ',' */ - if ((temp = get_absolute_expression ()) < 0) - { - as_bad (".COMMon length (%d.) <0! Ignored.", temp); - ignore_rest_of_line (); - return; - } - size = temp; - *p = 0; - symbolP = symbol_find_or_make (name); - *p = c; - if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) - { - as_bad ("Ignoring attempt to re-define symbol"); - ignore_rest_of_line (); - return; - } - if (S_GET_VALUE (symbolP) != 0) - { - if (S_GET_VALUE (symbolP) != (valueT) size) - { - as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.", - S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); - } - } - else - { -#ifndef OBJ_ELF - S_SET_VALUE (symbolP, (valueT) size); - S_SET_EXTERNAL (symbolP); -#endif - } - know (symbolP->sy_frag == &zero_address_frag); - if (*input_line_pointer != ',') - { - as_bad ("Expected comma after common length"); - ignore_rest_of_line (); - return; - } - input_line_pointer++; - SKIP_WHITESPACE (); - if (*input_line_pointer != '"') - { - temp = get_absolute_expression (); -#ifndef OBJ_ELF - if (temp > max_alignment) - { - temp = max_alignment; - as_warn ("Common alignment too large: %d. assumed", temp); - } -#endif - if (temp < 0) - { - temp = 0; - as_warn ("Common alignment negative; 0 assumed"); - } -#ifdef OBJ_ELF - if (symbolP->local) - { - segT old_sec; - int old_subsec; - char *p; - int align; - - old_sec = now_seg; - old_subsec = now_subseg; - align = temp; - record_alignment (bss_section, align); - subseg_set (bss_section, 0); - if (align) - frag_align (align, 0, 0); - if (S_GET_SEGMENT (symbolP) == bss_section) - symbolP->sy_frag->fr_symbol = 0; - symbolP->sy_frag = frag_now; - p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, - (offsetT) size, (char *) 0); - *p = 0; - S_SET_SEGMENT (symbolP, bss_section); - S_CLEAR_EXTERNAL (symbolP); - subseg_set (old_sec, old_subsec); - } - else -#endif - { - allocate_common: - S_SET_VALUE (symbolP, (valueT) size); -#ifdef OBJ_ELF - S_SET_ALIGN (symbolP, temp); -#endif - S_SET_EXTERNAL (symbolP); - S_SET_SEGMENT (symbolP, bfd_com_section_ptr); - } - } - else - { - input_line_pointer++; - /* @@ Some use the dot, some don't. Can we get some consistency?? */ - if (*input_line_pointer == '.') - input_line_pointer++; - /* @@ Some say data, some say bss. */ - if (strncmp (input_line_pointer, "bss\"", 4) - && strncmp (input_line_pointer, "data\"", 5)) - { - while (*--input_line_pointer != '"') - ; - input_line_pointer--; - goto bad_common_segment; - } - while (*input_line_pointer++ != '"') - ; - goto allocate_common; - } - -#ifdef BFD_ASSEMBLER - symbolP->bsym->flags |= BSF_OBJECT; -#endif - - demand_empty_rest_of_line (); - return; - - { - bad_common_segment: - p = input_line_pointer; - while (*p && *p != '\n') - p++; - c = *p; - *p = '\0'; - as_bad ("bad .common segment %s", input_line_pointer + 1); - *p = c; - input_line_pointer = p; - ignore_rest_of_line (); - return; - } -} - -/* Handle the .empty pseudo-op. This supresses the warnings about - invalid delay slot usage. */ - -static void -s_empty (ignore) - int ignore; -{ - /* The easy way to implement is to just forget about the last - instruction. */ - last_insn = NULL; -} - -static void -s_seg (ignore) - int ignore; -{ - - if (strncmp (input_line_pointer, "\"text\"", 6) == 0) - { - input_line_pointer += 6; - s_text (0); - return; - } - if (strncmp (input_line_pointer, "\"data\"", 6) == 0) - { - input_line_pointer += 6; - s_data (0); - return; - } - if (strncmp (input_line_pointer, "\"data1\"", 7) == 0) - { - input_line_pointer += 7; - s_data1 (); - return; - } - if (strncmp (input_line_pointer, "\"bss\"", 5) == 0) - { - input_line_pointer += 5; - /* We only support 2 segments -- text and data -- for now, so - things in the "bss segment" will have to go into data for now. - You can still allocate SEG_BSS stuff with .lcomm or .reserve. */ - subseg_set (data_section, 255); /* FIXME-SOMEDAY */ - return; - } - as_bad ("Unknown segment type"); - demand_empty_rest_of_line (); -} - -static void -s_data1 () -{ - subseg_set (data_section, 1); - demand_empty_rest_of_line (); -} - -static void -s_proc (ignore) - int ignore; -{ - while (!is_end_of_line[(unsigned char) *input_line_pointer]) - { - ++input_line_pointer; - } - ++input_line_pointer; -} - -/* This static variable is set by s_uacons to tell sparc_cons_align - that the expession does not need to be aligned. */ - -static int sparc_no_align_cons = 0; - -/* This handles the unaligned space allocation pseudo-ops, such as - .uaword. .uaword is just like .word, but the value does not need - to be aligned. */ - -static void -s_uacons (bytes) - int bytes; -{ - /* Tell sparc_cons_align not to align this value. */ - sparc_no_align_cons = 1; - cons (bytes); -} - -/* If the --enforce-aligned-data option is used, we require .word, - et. al., to be aligned correctly. We do it by setting up an - rs_align_code frag, and checking in HANDLE_ALIGN to make sure that - no unexpected alignment was introduced. - - The SunOS and Solaris native assemblers enforce aligned data by - default. We don't want to do that, because gcc can deliberately - generate misaligned data if the packed attribute is used. Instead, - we permit misaligned data by default, and permit the user to set an - option to check for it. */ - -void -sparc_cons_align (nbytes) - int nbytes; -{ - int nalign; - char *p; - - /* Only do this if we are enforcing aligned data. */ - if (! enforce_aligned_data) - return; - - if (sparc_no_align_cons) - { - /* This is an unaligned pseudo-op. */ - sparc_no_align_cons = 0; - return; - } - - nalign = 0; - while ((nbytes & 1) == 0) - { - ++nalign; - nbytes >>= 1; - } - - if (nalign == 0) - return; - - if (now_seg == absolute_section) - { - if ((abs_section_offset & ((1 << nalign) - 1)) != 0) - as_bad ("misaligned data"); - return; - } - - p = frag_var (rs_align_code, 1, 1, (relax_substateT) 0, - (symbolS *) NULL, (offsetT) nalign, (char *) NULL); - - record_alignment (now_seg, nalign); -} - -/* This is where we do the unexpected alignment check. - This is called from HANDLE_ALIGN in tc-sparc.h. */ - -void -sparc_handle_align (fragp) - fragS *fragp; -{ - if (fragp->fr_type == rs_align_code && !fragp->fr_subtype - && fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix != 0) - as_bad_where (fragp->fr_file, fragp->fr_line, "misaligned data"); - if (fragp->fr_type == rs_align_code && fragp->fr_subtype == 1024) - { - int count = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; - - if (count >= 4 && !(count & 3) && count <= 1024 && !((long)(fragp->fr_literal + fragp->fr_fix) & 3)) - { - unsigned *p = (unsigned *)(fragp->fr_literal + fragp->fr_fix); - int i; - - for (i = 0; i < count; i += 4) - *p++ = 0x01000000; /* nop */ - if (SPARC_OPCODE_ARCH_V9_P (max_architecture) && count > 8) - *(unsigned *)(fragp->fr_literal + fragp->fr_fix) = - 0x30680000 | (count >> 2); /* ba,a,pt %xcc, 1f */ - fragp->fr_var = count; - } - } -} - -#ifdef OBJ_ELF -/* Some special processing for a Sparc ELF file. */ - -void -sparc_elf_final_processing () -{ - /* Set the Sparc ELF flag bits. FIXME: There should probably be some - sort of BFD interface for this. */ - if (sparc_arch_size == 64) - switch (sparc_memory_model) - { - case MM_RMO: - elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_RMO; - break; - case MM_PSO: - elf_elfheader (stdoutput)->e_flags |= EF_SPARCV9_PSO; - break; - } - else if (current_architecture >= SPARC_OPCODE_ARCH_V9) - elf_elfheader (stdoutput)->e_flags |= EF_SPARC_32PLUS; - if (current_architecture == SPARC_OPCODE_ARCH_V9A) - elf_elfheader (stdoutput)->e_flags |= EF_SPARC_SUN_US1; -} -#endif diff --git a/contrib/binutils/gas/config/tc-sparc.h b/contrib/binutils/gas/config/tc-sparc.h deleted file mode 100644 index bb09bd4a433c..000000000000 --- a/contrib/binutils/gas/config/tc-sparc.h +++ /dev/null @@ -1,149 +0,0 @@ -/* tc-sparc.h - Macros and type defines for the sparc. - Copyright (C) 1989, 90-96, 97, 1998 Free Software Foundation, Inc. - - 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 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. */ - -#ifndef TC_SPARC -#define TC_SPARC 1 - -#ifdef ANSI_PROTOTYPES -struct frag; -#endif - -/* This is used to set the default value for `target_big_endian'. */ -#define TARGET_BYTES_BIG_ENDIAN 1 - -#define LOCAL_LABELS_FB 1 - -#define TARGET_ARCH bfd_arch_sparc - -extern const char *sparc_target_format PARAMS ((void)); -#define TARGET_FORMAT sparc_target_format () - -#ifdef TE_SPARCAOUT -/* Bi-endian support may eventually be unconditional, but until things are - working well it's only provided for targets that need it. */ -#define SPARC_BIENDIAN -#endif - -#define WORKING_DOT_WORD - -#define md_convert_frag(b,s,f) {as_fatal ("sparc convert_frag\n");} -#define md_create_long_jump(p,f,t,fr,s) as_fatal("sparc_create_long_jump") -#define md_create_short_jump(p,f,t,fr,s) as_fatal("sparc_create_short_jump") -#define md_estimate_size_before_relax(f,s) \ - (as_fatal("estimate_size_before_relax called"),1) - -#define LISTING_HEADER "SPARC GAS " - -extern int sparc_pic_code; - -#define md_do_align(n, fill, len, max, around) \ -if ((n) && (n) <= 10 && !need_pass_2 && !(fill) \ - && now_seg != data_section && now_seg != bss_section) \ - { \ - char *p; \ - p = frag_var (rs_align_code, 1024, 1, (relax_substateT) 1024, \ - (symbolS *) 0, (offsetT) (n), (char *) 0); \ - *p = 0x00; \ - goto around; \ - } - -/* We require .word, et. al., to be aligned correctly. */ -#define md_cons_align(nbytes) sparc_cons_align (nbytes) -extern void sparc_cons_align PARAMS ((int)); -#define HANDLE_ALIGN(fragp) sparc_handle_align (fragp) -extern void sparc_handle_align PARAMS ((struct frag *)); - -#if defined (OBJ_ELF) || defined (OBJ_AOUT) - -/* This expression evaluates to false if the relocation is for a local - object for which we still want to do the relocation at runtime. - True if we are willing to perform this relocation while building - the .o file. - - If the reloc is against an externally visible symbol, then the - a.out assembler should not do the relocation if generating PIC, and - the ELF assembler should never do the relocation. */ - -#ifdef OBJ_ELF -#define obj_relocate_extern 0 -#else -#define obj_relocate_extern (! sparc_pic_code) -#endif - -#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \ - (obj_relocate_extern \ - || (FIX)->fx_addsy == NULL \ - || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \ - && ! S_IS_WEAK ((FIX)->fx_addsy) \ - && S_IS_DEFINED ((FIX)->fx_addsy) \ - && ! S_IS_COMMON ((FIX)->fx_addsy))) -#endif - -/* I know that "call 0" fails in sparc-coff if this doesn't return 1. I - don't know about other relocation types, or other formats, yet. */ -#ifdef OBJ_COFF -#define TC_FORCE_RELOCATION(FIXP) \ - ((FIXP)->fx_r_type == BFD_RELOC_32_PCREL_S2 \ - && ((FIXP)->fx_addsy == 0 \ - || S_GET_SEGMENT ((FIXP)->fx_addsy) == absolute_section)) -#define RELOC_REQUIRES_SYMBOL -#endif - -#define MD_APPLY_FIX3 -#define TC_HANDLES_FX_DONE - -#ifdef OBJ_ELF -/* Keep relocations against global symbols. Don't turn them into - relocations against sections. This is required for the dynamic - linker to operate properly. When generating PIC, we need to keep - any non PC relative reloc. */ -#define tc_fix_adjustable(FIX) \ - (! S_IS_EXTERNAL ((FIX)->fx_addsy) \ - && ! S_IS_WEAK ((FIX)->fx_addsy) \ - && (! sparc_pic_code \ - || (FIX)->fx_pcrel \ - || ((FIX)->fx_subsy != NULL \ - && (S_GET_SEGMENT ((FIX)->fx_subsy) \ - == S_GET_SEGMENT ((FIX)->fx_addsy))) \ - || strchr (S_GET_NAME ((FIX)->fx_addsy), '\001') != NULL \ - || strchr (S_GET_NAME ((FIX)->fx_addsy), '\002') != NULL)) -#endif - -#ifdef OBJ_AOUT -/* When generating PIC code, we must not adjust any reloc which will - turn into a reloc against the global offset table. */ -#define tc_fix_adjustable(FIX) \ - (! sparc_pic_code \ - || (FIX)->fx_pcrel \ - || (FIX)->fx_r_type == BFD_RELOC_16 \ - || (FIX)->fx_r_type == BFD_RELOC_32) -#endif - -#define elf_tc_final_processing sparc_elf_final_processing -extern void sparc_elf_final_processing PARAMS ((void)); - -#define md_operand(x) - -extern void sparc_md_end PARAMS ((void)); -#define md_end() sparc_md_end () - -#endif - -/* end of tc-sparc.h */ diff --git a/contrib/binutils/gas/config/tc-tic30.c b/contrib/binutils/gas/config/tc-tic30.c deleted file mode 100644 index f78c6f81fe14..000000000000 --- a/contrib/binutils/gas/config/tc-tic30.c +++ /dev/null @@ -1,1909 +0,0 @@ -/* tc-c30.c -- Assembly code for the Texas Instruments TMS320C30 - Copyright (C) 1998 Free Software Foundation. - Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au) - - 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 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. */ - -/* - Texas Instruments TMS320C30 machine specific gas. - Written by Steven Haworth (steve@pm.cse.rmit.edu.au). - Bugs & suggestions are completely welcome. This is free software. - Please help us make it better. - */ - -#include "as.h" -#include "opcode/tic30.h" - -/* put here all non-digit non-letter charcters that may occur in an operand */ -static char operand_special_chars[] = "%$-+(,)*._~/<>&^!:[@]"; -static char *ordinal_names[] = -{"first", "second", "third", "fourth", "fifth"}; - -const int md_reloc_size = 0; -int md_long_jump_size = 0; -int md_short_jump_size = 0; - -const char comment_chars[] = ";"; -const char line_comment_chars[] = "*"; -const char line_separator_chars[] = ""; - -const char *md_shortopts = ""; -struct option md_longopts[] = -{ - {NULL, no_argument, NULL, 0} -}; - -size_t md_longopts_size = sizeof (md_longopts); - -/* Chars that mean this number is a floating point constant */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ -const char FLT_CHARS[] = "fFdDxX"; - -/* Chars that can be used to separate mant from exp in floating point nums */ -const char EXP_CHARS[] = "eE"; - -/* tables for lexical analysis */ -static char opcode_chars[256]; -static char register_chars[256]; -static char operand_chars[256]; -static char space_chars[256]; -static char identifier_chars[256]; -static char digit_chars[256]; - -/* lexical macros */ -#define is_opcode_char(x) (opcode_chars[(unsigned char) x]) -#define is_operand_char(x) (operand_chars[(unsigned char) x]) -#define is_register_char(x) (register_chars[(unsigned char) x]) -#define is_space_char(x) (space_chars[(unsigned char) x]) -#define is_identifier_char(x) (identifier_chars[(unsigned char) x]) -#define is_digit_char(x) (digit_chars[(unsigned char) x]) - -const pseudo_typeS md_pseudo_table[] = -{ - {0, 0, 0} -}; - -#undef USE_STDOUT -#define USE_STDOUT 1 - -#ifdef USE_STDARG - -#include <stdarg.h> - -int -debug (const char *string,...) -{ - if (flag_debug) - { - va_list argptr; - char str[100]; - - va_start (argptr, string); - vsprintf (str, string, argptr); - if (str[0] == '\0') - return (0); - va_end (argptr); - fputs (str, USE_STDOUT ? stdout : stderr); - return strlen (str); - } - else - return 0; -} -#else -int -debug (string, va_alist) - const char *string; - va_dcl -{ - if (flag_debug) - { - va_list argptr; - char str[100]; - int cnt; - - va_start (argptr, string); - cnt = vsprintf (str, string, argptr); - if (str[0] == NULL) - return (0); - va_end (argptr); - fputs (str, USE_STDOUT ? stdout : stderr); - return (cnt); - } - else - return 0; -} -#endif - -/* hash table for opcode lookup */ -static struct hash_control *op_hash; -/* hash table for parallel opcode lookup */ -static struct hash_control *parop_hash; -/* hash table for register lookup */ -static struct hash_control *reg_hash; -/* hash table for indirect addressing lookup */ -static struct hash_control *ind_hash; - -void -md_begin () -{ - const char *hash_err; - debug ("In md_begin()\n"); - op_hash = hash_new (); - { - const template *current_optab = tic30_optab; - for (; current_optab < tic30_optab_end; current_optab++) - { - hash_err = hash_insert (op_hash, current_optab->name, (char *) current_optab); - if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_optab->name, hash_err); - } - } - parop_hash = hash_new (); - { - const partemplate *current_parop = tic30_paroptab; - for (; current_parop < tic30_paroptab_end; current_parop++) - { - hash_err = hash_insert (parop_hash, current_parop->name, (char *) current_parop); - if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_parop->name, hash_err); - } - } - reg_hash = hash_new (); - { - const reg *current_reg = tic30_regtab; - for (; current_reg < tic30_regtab_end; current_reg++) - { - hash_err = hash_insert (reg_hash, current_reg->name, (char *) current_reg); - if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_reg->name, hash_err); - } - } - ind_hash = hash_new (); - { - const ind_addr_type *current_ind = tic30_indaddr_tab; - for (; current_ind < tic30_indaddrtab_end; current_ind++) - { - hash_err = hash_insert (ind_hash, current_ind->syntax, (char *) current_ind); - if (hash_err) - as_fatal ("Internal Error: Can't Hash %s: %s", current_ind->syntax, hash_err); - } - } - /* fill in lexical tables: opcode_chars, operand_chars, space_chars */ - { - register int c; - register char *p; - - for (c = 0; c < 256; c++) - { - if (islower (c) || isdigit (c)) - { - opcode_chars[c] = c; - register_chars[c] = c; - } - else if (isupper (c)) - { - opcode_chars[c] = tolower (c); - register_chars[c] = opcode_chars[c]; - } - else if (c == ')' || c == '(') - { - register_chars[c] = c; - } - if (isupper (c) || islower (c) || isdigit (c)) - operand_chars[c] = c; - if (isdigit (c) || c == '-') - digit_chars[c] = c; - if (isalpha (c) || c == '_' || c == '.' || isdigit (c)) - identifier_chars[c] = c; - if (c == ' ' || c == '\t') - space_chars[c] = c; - if (c == '_') - opcode_chars[c] = c; - } - for (p = operand_special_chars; *p != '\0'; p++) - operand_chars[(unsigned char) *p] = *p; - } -} - -/* Address Mode OR values */ -#define AM_Register 0x00000000 -#define AM_Direct 0x00200000 -#define AM_Indirect 0x00400000 -#define AM_Immediate 0x00600000 -#define AM_NotReq 0xFFFFFFFF - -/* PC Relative OR values */ -#define PC_Register 0x00000000 -#define PC_Relative 0x02000000 - -typedef struct -{ - unsigned op_type; - struct - { - int resolved; - unsigned address; - char *label; - expressionS direct_expr; - } - direct; - struct - { - unsigned mod; - int ARnum; - unsigned char disp; - } - indirect; - struct - { - unsigned opcode; - } - reg; - struct - { - int resolved; - int decimal_found; - float f_number; - int s_number; - unsigned int u_number; - char *label; - expressionS imm_expr; - } - immediate; -} -operand; - -int tic30_parallel_insn PARAMS ((char *)); -operand *tic30_operand PARAMS ((char *)); -char *tic30_find_parallel_insn PARAMS ((char *, char *)); - -template *opcode; - -struct tic30_insn - { - template *tm; /* Template of current instruction */ - unsigned opcode; /* Final opcode */ - int operands; /* Number of given operands */ - /* Type of operand given in instruction */ - operand *operand_type[MAX_OPERANDS]; - unsigned addressing_mode; /* Final addressing mode of instruction */ - }; - -struct tic30_insn insn; -static int found_parallel_insn; - -void -md_assemble (line) - char *line; -{ - template *opcode; - char *current_posn; - char *token_start; - char save_char; - int count; - - debug ("In md_assemble() with argument %s\n", line); - memset (&insn, '\0', sizeof (insn)); - if (found_parallel_insn) - { - debug ("Line is second part of parallel instruction\n\n"); - found_parallel_insn = 0; - return; - } - if ((current_posn = tic30_find_parallel_insn (line, input_line_pointer + 1)) == NULL) - current_posn = line; - else - found_parallel_insn = 1; - while (is_space_char (*current_posn)) - current_posn++; - token_start = current_posn; - if (!is_opcode_char (*current_posn)) - { - as_bad ("Invalid character %s in opcode", output_invalid (*current_posn)); - return; - } - /* Check if instruction is a parallel instruction by seeing if the first - character is a q. */ - if (*token_start == 'q') - { - if (tic30_parallel_insn (token_start)) - { - if (found_parallel_insn) - free (token_start); - return; - } - } - while (is_opcode_char (*current_posn)) - current_posn++; - { /* Find instruction */ - save_char = *current_posn; - *current_posn = '\0'; - opcode = (template *) hash_find (op_hash, token_start); - if (opcode) - { - debug ("Found instruction %s\n", opcode->name); - insn.tm = opcode; - } - else - { - debug ("Didn't find insn\n"); - as_bad ("Unknown TMS320C30 instruction: %s", token_start); - return; - } - *current_posn = save_char; - } - if (*current_posn != END_OF_INSN) - { /* Find operands */ - int paren_not_balanced; - int expecting_operand = 0; - int this_operand; - do - { - /* skip optional white space before operand */ - while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN) - { - if (!is_space_char (*current_posn)) - { - as_bad ("Invalid character %s before %s operand", - output_invalid (*current_posn), - ordinal_names[insn.operands]); - return; - } - current_posn++; - } - token_start = current_posn; /* after white space */ - paren_not_balanced = 0; - while (paren_not_balanced || *current_posn != ',') - { - if (*current_posn == END_OF_INSN) - { - if (paren_not_balanced) - { - as_bad ("Unbalanced parenthesis in %s operand.", - ordinal_names[insn.operands]); - return; - } - else - break; /* we are done */ - } - else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn)) - { - as_bad ("Invalid character %s in %s operand", - output_invalid (*current_posn), - ordinal_names[insn.operands]); - return; - } - if (*current_posn == '(') - ++paren_not_balanced; - if (*current_posn == ')') - --paren_not_balanced; - current_posn++; - } - if (current_posn != token_start) - { /* yes, we've read in another operand */ - this_operand = insn.operands++; - if (insn.operands > MAX_OPERANDS) - { - as_bad ("Spurious operands; (%d operands/instruction max)", - MAX_OPERANDS); - return; - } - /* now parse operand adding info to 'insn' as we go along */ - save_char = *current_posn; - *current_posn = '\0'; - insn.operand_type[this_operand] = tic30_operand (token_start); - *current_posn = save_char; - if (insn.operand_type[this_operand] == NULL) - return; - } - else - { - if (expecting_operand) - { - as_bad ("Expecting operand after ','; got nothing"); - return; - } - if (*current_posn == ',') - { - as_bad ("Expecting operand before ','; got nothing"); - return; - } - } - /* now *current_posn must be either ',' or END_OF_INSN */ - if (*current_posn == ',') - { - if (*++current_posn == END_OF_INSN) - { /* just skip it, if it's \n complain */ - as_bad ("Expecting operand after ','; got nothing"); - return; - } - expecting_operand = 1; - } - } - while (*current_posn != END_OF_INSN); /* until we get end of insn */ - } - debug ("Number of operands found: %d\n", insn.operands); - /* Check that number of operands is correct */ - if (insn.operands != insn.tm->operands) - { - int i; - int numops = insn.tm->operands; - /* If operands are not the same, then see if any of the operands are not - required. Then recheck with number of given operands. If they are still not - the same, then give an error, otherwise carry on. */ - for (i = 0; i < insn.tm->operands; i++) - if (insn.tm->operand_types[i] & NotReq) - numops--; - if (insn.operands != numops) - { - as_bad ("Incorrect number of operands given"); - return; - } - } - insn.addressing_mode = AM_NotReq; - for (count = 0; count < insn.operands; count++) - { - if (insn.operand_type[count]->op_type & insn.tm->operand_types[count]) - { - debug ("Operand %d matches\n", count + 1); - /* If instruction has two operands and has an AddressMode modifier then set - addressing mode type for instruction */ - if (insn.tm->opcode_modifier == AddressMode) - { - int addr_insn = 0; - /* Store instruction uses the second operand for the address mode. */ - if ((insn.tm->operand_types[1] & (Indirect | Direct)) == (Indirect | Direct)) - addr_insn = 1; - if (insn.operand_type[addr_insn]->op_type & (AllReg)) - insn.addressing_mode = AM_Register; - else if (insn.operand_type[addr_insn]->op_type & Direct) - insn.addressing_mode = AM_Direct; - else if (insn.operand_type[addr_insn]->op_type & Indirect) - insn.addressing_mode = AM_Indirect; - else - insn.addressing_mode = AM_Immediate; - } - } - else - { - as_bad ("The %s operand doesn't match", ordinal_names[count]); - return; - } - } - /* Now set the addressing mode for 3 operand instructions. */ - if ((insn.tm->operand_types[0] & op3T1) && (insn.tm->operand_types[1] & op3T2)) - { - /* Set the addressing mode to the values used for 2 operand instructions in the - G addressing field of the opcode. */ - char *p; - switch (insn.operand_type[0]->op_type) - { - case Rn: - case ARn: - case DPReg: - case OtherReg: - if (insn.operand_type[1]->op_type & (AllReg)) - insn.addressing_mode = AM_Register; - else if (insn.operand_type[1]->op_type & Indirect) - insn.addressing_mode = AM_Direct; - else - { - /* Shouldn't make it to this stage */ - as_bad ("Incompatible first and second operands in instruction"); - return; - } - break; - case Indirect: - if (insn.operand_type[1]->op_type & (AllReg)) - insn.addressing_mode = AM_Indirect; - else if (insn.operand_type[1]->op_type & Indirect) - insn.addressing_mode = AM_Immediate; - else - { - /* Shouldn't make it to this stage */ - as_bad ("Incompatible first and second operands in instruction"); - return; - } - break; - } - /* Now make up the opcode for the 3 operand instructions. As in parallel - instructions, there will be no unresolved values, so they can be fully formed - and added to the frag table. */ - insn.opcode = insn.tm->base_opcode; - if (insn.operand_type[0]->op_type & Indirect) - { - insn.opcode |= (insn.operand_type[0]->indirect.ARnum); - insn.opcode |= (insn.operand_type[0]->indirect.mod << 3); - } - else - insn.opcode |= (insn.operand_type[0]->reg.opcode); - if (insn.operand_type[1]->op_type & Indirect) - { - insn.opcode |= (insn.operand_type[1]->indirect.ARnum << 8); - insn.opcode |= (insn.operand_type[1]->indirect.mod << 11); - } - else - insn.opcode |= (insn.operand_type[1]->reg.opcode << 8); - if (insn.operands == 3) - insn.opcode |= (insn.operand_type[2]->reg.opcode << 16); - insn.opcode |= insn.addressing_mode; - p = frag_more (INSN_SIZE); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { /* Not a three operand instruction */ - char *p; - int am_insn = -1; - insn.opcode = insn.tm->base_opcode; - /* Create frag for instruction - all instructions are 4 bytes long. */ - p = frag_more (INSN_SIZE); - if ((insn.operands > 0) && (insn.tm->opcode_modifier == AddressMode)) - { - insn.opcode |= insn.addressing_mode; - if (insn.addressing_mode == AM_Indirect) - { - /* Determine which operand gives the addressing mode */ - if (insn.operand_type[0]->op_type & Indirect) - am_insn = 0; - if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Indirect)) - am_insn = 1; - insn.opcode |= (insn.operand_type[am_insn]->indirect.disp); - insn.opcode |= (insn.operand_type[am_insn]->indirect.ARnum << 8); - insn.opcode |= (insn.operand_type[am_insn]->indirect.mod << 11); - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.addressing_mode == AM_Register) - { - insn.opcode |= (insn.operand_type[0]->reg.opcode); - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.addressing_mode == AM_Direct) - { - if (insn.operand_type[0]->op_type & Direct) - am_insn = 0; - if ((insn.operands > 1) && (insn.operand_type[1]->op_type & Direct)) - am_insn = 1; - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[!am_insn]->reg.opcode << 16); - if (insn.operand_type[am_insn]->direct.resolved == 1) - { - /* Resolved values can be placed straight into instruction word, and output */ - insn.opcode |= (insn.operand_type[am_insn]->direct.address & 0x0000FFFF); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { /* Unresolved direct addressing mode instruction */ - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[am_insn]->direct.direct_expr, 0, 0); - } - } - else if (insn.addressing_mode == AM_Immediate) - { - if (insn.operand_type[0]->immediate.resolved == 1) - { - char *keeploc; - int size; - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); - switch (insn.tm->imm_arg_type) - { - case Imm_Float: - debug ("Floating point first operand\n"); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - keeploc = input_line_pointer; - input_line_pointer = insn.operand_type[0]->immediate.label; - if (md_atof ('f', p + 2, &size) != 0) - { - as_bad ("invalid short form floating point immediate operand"); - return; - } - input_line_pointer = keeploc; - break; - case Imm_UInt: - debug ("Unsigned int first operand\n"); - if (insn.operand_type[0]->immediate.decimal_found) - as_warn ("rounding down first operand float to unsigned int"); - if (insn.operand_type[0]->immediate.u_number > 0xFFFF) - as_warn ("only lower 16-bits of first operand are used"); - insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x0000FFFFL); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - break; - case Imm_SInt: - debug ("Int first operand\n"); - if (insn.operand_type[0]->immediate.decimal_found) - as_warn ("rounding down first operand float to signed int"); - if (insn.operand_type[0]->immediate.s_number < -32768 || - insn.operand_type[0]->immediate.s_number > 32767) - { - as_bad ("first operand is too large for 16-bit signed int"); - return; - } - insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFFL); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - break; - } - } - else - { /* Unresolved immediate label */ - if (insn.operands > 1) - insn.opcode |= (insn.operand_type[1]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 0, 0); - } - } - } - else if (insn.tm->opcode_modifier == PCRel) - { - /* Conditional Branch and Call instructions */ - if ((insn.tm->operand_types[0] & (AllReg | Disp)) == (AllReg | Disp)) - { - if (insn.operand_type[0]->op_type & (AllReg)) - { - insn.opcode |= (insn.operand_type[0]->reg.opcode); - insn.opcode |= PC_Register; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - insn.opcode |= PC_Relative; - if (insn.operand_type[0]->immediate.resolved == 1) - { - insn.opcode |= (insn.operand_type[0]->immediate.s_number & 0x0000FFFF); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - (frag_now->fr_literal), 2, &insn.operand_type[0]->immediate.imm_expr, 1, 0); - } - } - } - else if ((insn.tm->operand_types[0] & ARn) == ARn) - { - /* Decrement and Branch instructions */ - insn.opcode |= ((insn.operand_type[0]->reg.opcode - 0x08) << 22); - if (insn.operand_type[1]->op_type & (AllReg)) - { - insn.opcode |= (insn.operand_type[1]->reg.opcode); - insn.opcode |= PC_Register; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.operand_type[1]->immediate.resolved == 1) - { - if (insn.operand_type[0]->immediate.decimal_found) - { - as_bad ("first operand is floating point"); - return; - } - if (insn.operand_type[0]->immediate.s_number < -32768 || - insn.operand_type[0]->immediate.s_number > 32767) - { - as_bad ("first operand is too large for 16-bit signed int"); - return; - } - insn.opcode |= (insn.operand_type[1]->immediate.s_number); - insn.opcode |= PC_Relative; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - insn.opcode |= PC_Relative; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 2 - frag_now->fr_literal, 2, &insn.operand_type[1]->immediate.imm_expr, 1, 0); - } - } - } - else if (insn.tm->operand_types[0] == IVector) - { - /* Trap instructions */ - if (insn.operand_type[0]->op_type & IVector) - insn.opcode |= (insn.operand_type[0]->immediate.u_number); - else - { /* Shouldn't get here */ - as_bad ("interrupt vector for trap instruction out of range"); - return; - } - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.tm->opcode_modifier == StackOp || insn.tm->opcode_modifier == Rotate) - { - /* Push, Pop and Rotate instructions */ - insn.opcode |= (insn.operand_type[0]->reg.opcode << 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if ((insn.tm->operand_types[0] & (Abs24 | Direct)) == (Abs24 | Direct)) - { - /* LDP Instruction needs to be tested for before the next section */ - if (insn.operand_type[0]->op_type & Direct) - { - if (insn.operand_type[0]->direct.resolved == 1) - { - /* Direct addressing uses lower 8 bits of direct address */ - insn.opcode |= (insn.operand_type[0]->direct.address & 0x00FF0000) >> 16; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - fixS *fix; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->direct.direct_expr, 0, 0); - /* Ensure that the assembler doesn't complain about fitting a 24-bit - address into 8 bits. */ - fix->fx_no_overflow = 1; - } - } - else - { - if (insn.operand_type[0]->immediate.resolved == 1) - { - /* Immediate addressing uses upper 8 bits of address */ - if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) - { - as_bad ("LDP instruction needs a 24-bit operand"); - return; - } - insn.opcode |= ((insn.operand_type[0]->immediate.u_number & 0x00FF0000) >> 16); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - fixS *fix; - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix = fix_new_exp (frag_now, p + 3 - (frag_now->fr_literal), 1, &insn.operand_type[0]->immediate.imm_expr, 0, 0); - fix->fx_no_overflow = 1; - } - } - } - else if (insn.tm->operand_types[0] & (Imm24)) - { - /* Unconditional Branch and Call instructions */ - if (insn.operand_type[0]->immediate.resolved == 1) - { - if (insn.operand_type[0]->immediate.u_number > 0x00FFFFFF) - as_warn ("first operand is too large for a 24-bit displacement"); - insn.opcode |= (insn.operand_type[0]->immediate.u_number & 0x00FFFFFF); - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else - { - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - fix_new_exp (frag_now, p + 1 - (frag_now->fr_literal), 3, &insn.operand_type[0]->immediate.imm_expr, 0, 0); - } - } - else if (insn.tm->operand_types[0] & NotReq) - { - /* Check for NOP instruction without arguments. */ - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - else if (insn.tm->operands == 0) - { - /* Check for instructions without operands. */ - md_number_to_chars (p, (valueT) insn.opcode, INSN_SIZE); - } - } - debug ("Addressing mode: %08X\n", insn.addressing_mode); - { - int i; - for (i = 0; i < insn.operands; i++) - { - if (insn.operand_type[i]->immediate.label) - free (insn.operand_type[i]->immediate.label); - free (insn.operand_type[i]); - } - } - debug ("Final opcode: %08X\n", insn.opcode); - debug ("\n"); -} - -struct tic30_par_insn -{ - partemplate *tm; /* Template of current parallel instruction */ - int operands[2]; /* Number of given operands for each insn */ - /* Type of operand given in instruction */ - operand *operand_type[2][MAX_OPERANDS]; - int swap_operands; /* Whether to swap operands around. */ - unsigned p_field; /* Value of p field in multiply add/sub instructions */ - unsigned opcode; /* Final opcode */ -}; - -struct tic30_par_insn p_insn; - -int -tic30_parallel_insn (char *token) -{ - static partemplate *p_opcode; - char *current_posn = token; - char *token_start; - char save_char; - - debug ("In tic30_parallel_insn with %s\n", token); - memset (&p_insn, '\0', sizeof (p_insn)); - while (is_opcode_char (*current_posn)) - current_posn++; - { /* Find instruction */ - save_char = *current_posn; - *current_posn = '\0'; - p_opcode = (partemplate *) hash_find (parop_hash, token); - if (p_opcode) - { - debug ("Found instruction %s\n", p_opcode->name); - p_insn.tm = p_opcode; - } - else - { - char first_opcode[6] = - {0}; - char second_opcode[6] = - {0}; - int i; - int current_opcode = -1; - int char_ptr = 0; - - for (i = 0; i < strlen (token); i++) - { - char ch = *(token + i); - if (ch == '_' && current_opcode == -1) - { - current_opcode = 0; - continue; - } - if (ch == '_' && current_opcode == 0) - { - current_opcode = 1; - char_ptr = 0; - continue; - } - switch (current_opcode) - { - case 0: - first_opcode[char_ptr++] = ch; - break; - case 1: - second_opcode[char_ptr++] = ch; - break; - } - } - debug ("first_opcode = %s\n", first_opcode); - debug ("second_opcode = %s\n", second_opcode); - sprintf (token, "q_%s_%s", second_opcode, first_opcode); - p_opcode = (partemplate *) hash_find (parop_hash, token); - if (p_opcode) - { - debug ("Found instruction %s\n", p_opcode->name); - p_insn.tm = p_opcode; - p_insn.swap_operands = 1; - } - else - return 0; - } - *current_posn = save_char; - } - { /* Find operands */ - int paren_not_balanced; - int expecting_operand = 0; - int found_separator = 0; - do - { - /* skip optional white space before operand */ - while (!is_operand_char (*current_posn) && *current_posn != END_OF_INSN) - { - if (!is_space_char (*current_posn) && *current_posn != PARALLEL_SEPARATOR) - { - as_bad ("Invalid character %s before %s operand", - output_invalid (*current_posn), - ordinal_names[insn.operands]); - return 1; - } - if (*current_posn == PARALLEL_SEPARATOR) - found_separator = 1; - current_posn++; - } - token_start = current_posn; /* after white space */ - paren_not_balanced = 0; - while (paren_not_balanced || *current_posn != ',') - { - if (*current_posn == END_OF_INSN) - { - if (paren_not_balanced) - { - as_bad ("Unbalanced parenthesis in %s operand.", - ordinal_names[insn.operands]); - return 1; - } - else - break; /* we are done */ - } - else if (*current_posn == PARALLEL_SEPARATOR) - { - while (is_space_char (*(current_posn - 1))) - current_posn--; - break; - } - else if (!is_operand_char (*current_posn) && !is_space_char (*current_posn)) - { - as_bad ("Invalid character %s in %s operand", - output_invalid (*current_posn), - ordinal_names[insn.operands]); - return 1; - } - if (*current_posn == '(') - ++paren_not_balanced; - if (*current_posn == ')') - --paren_not_balanced; - current_posn++; - } - if (current_posn != token_start) - { /* yes, we've read in another operand */ - p_insn.operands[found_separator]++; - if (p_insn.operands[found_separator] > MAX_OPERANDS) - { - as_bad ("Spurious operands; (%d operands/instruction max)", - MAX_OPERANDS); - return 1; - } - /* now parse operand adding info to 'insn' as we go along */ - save_char = *current_posn; - *current_posn = '\0'; - p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1] = - tic30_operand (token_start); - *current_posn = save_char; - if (!p_insn.operand_type[found_separator][p_insn.operands[found_separator] - 1]) - return 1; - } - else - { - if (expecting_operand) - { - as_bad ("Expecting operand after ','; got nothing"); - return 1; - } - if (*current_posn == ',') - { - as_bad ("Expecting operand before ','; got nothing"); - return 1; - } - } - /* now *current_posn must be either ',' or END_OF_INSN */ - if (*current_posn == ',') - { - if (*++current_posn == END_OF_INSN) - { /* just skip it, if it's \n complain */ - as_bad ("Expecting operand after ','; got nothing"); - return 1; - } - expecting_operand = 1; - } - } - while (*current_posn != END_OF_INSN); /* until we get end of insn */ - } - if (p_insn.swap_operands) - { - int temp_num, i; - operand *temp_op; - - temp_num = p_insn.operands[0]; - p_insn.operands[0] = p_insn.operands[1]; - p_insn.operands[1] = temp_num; - for (i = 0; i < MAX_OPERANDS; i++) - { - temp_op = p_insn.operand_type[0][i]; - p_insn.operand_type[0][i] = p_insn.operand_type[1][i]; - p_insn.operand_type[1][i] = temp_op; - } - } - if (p_insn.operands[0] != p_insn.tm->operands_1) - { - as_bad ("incorrect number of operands given in the first instruction"); - return 1; - } - if (p_insn.operands[1] != p_insn.tm->operands_2) - { - as_bad ("incorrect number of operands given in the second instruction"); - return 1; - } - debug ("Number of operands in first insn: %d\n", p_insn.operands[0]); - debug ("Number of operands in second insn: %d\n", p_insn.operands[1]); - { /* Now check if operands are correct */ - int count; - int num_rn = 0; - int num_ind = 0; - for (count = 0; count < 2; count++) - { - int i; - for (i = 0; i < p_insn.operands[count]; i++) - { - if ((p_insn.operand_type[count][i]->op_type & - p_insn.tm->operand_types[count][i]) == 0) - { - as_bad ("%s instruction, operand %d doesn't match", ordinal_names[count], i + 1); - return 1; - } - /* Get number of R register and indirect reference contained within the first - two operands of each instruction. This is required for the multiply - parallel instructions which require two R registers and two indirect - references, but not in any particular place. */ - if ((p_insn.operand_type[count][i]->op_type & Rn) && i < 2) - num_rn++; - else if ((p_insn.operand_type[count][i]->op_type & Indirect) && i < 2) - num_ind++; - } - } - if ((p_insn.tm->operand_types[0][0] & (Indirect | Rn)) == (Indirect | Rn)) - { - /* Check for the multiply instructions */ - if (num_rn != 2) - { - as_bad ("incorrect format for multiply parallel instruction"); - return 1; - } - if (num_ind != 2) - { /* Shouldn't get here */ - as_bad ("incorrect format for multiply parallel instruction"); - return 1; - } - if ((p_insn.operand_type[0][2]->reg.opcode != 0x00) && - (p_insn.operand_type[0][2]->reg.opcode != 0x01)) - { - as_bad ("destination for multiply can only be R0 or R1"); - return 1; - } - if ((p_insn.operand_type[1][2]->reg.opcode != 0x02) && - (p_insn.operand_type[1][2]->reg.opcode != 0x03)) - { - as_bad ("destination for add/subtract can only be R2 or R3"); - return 1; - } - /* Now determine the P field for the instruction */ - if (p_insn.operand_type[0][0]->op_type & Indirect) - { - if (p_insn.operand_type[0][1]->op_type & Indirect) - p_insn.p_field = 0x00000000; /* Ind * Ind, Rn +/- Rn */ - else if (p_insn.operand_type[1][0]->op_type & Indirect) - p_insn.p_field = 0x01000000; /* Ind * Rn, Ind +/- Rn */ - else - p_insn.p_field = 0x03000000; /* Ind * Rn, Rn +/- Ind */ - } - else - { - if (p_insn.operand_type[0][1]->op_type & Rn) - p_insn.p_field = 0x02000000; /* Rn * Rn, Ind +/- Ind */ - else if (p_insn.operand_type[1][0]->op_type & Indirect) - { - operand *temp; - p_insn.p_field = 0x01000000; /* Rn * Ind, Ind +/- Rn */ - /* Need to swap the two multiply operands around so that everything is in - its place for the opcode makeup ie so Ind * Rn, Ind +/- Rn */ - temp = p_insn.operand_type[0][0]; - p_insn.operand_type[0][0] = p_insn.operand_type[0][1]; - p_insn.operand_type[0][1] = temp; - } - else - { - operand *temp; - p_insn.p_field = 0x03000000; /* Rn * Ind, Rn +/- Ind */ - temp = p_insn.operand_type[0][0]; - p_insn.operand_type[0][0] = p_insn.operand_type[0][1]; - p_insn.operand_type[0][1] = temp; - } - } - } - } - debug ("P field: %08X\n", p_insn.p_field); - /* Finalise opcode. This is easier for parallel instructions as they have to be - fully resolved, there are no memory addresses allowed, except through indirect - addressing, so there are no labels to resolve. */ - { - p_insn.opcode = p_insn.tm->base_opcode; - switch (p_insn.tm->oporder) - { - case OO_4op1: - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); - break; - case OO_4op2: - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 19); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 22); - if (p_insn.operand_type[1][1]->reg.opcode == p_insn.operand_type[0][1]->reg.opcode) - as_warn ("loading the same register in parallel operation"); - break; - case OO_4op3: - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 22); - break; - case OO_5op1: - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); - p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); - break; - case OO_5op2: - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); - p_insn.opcode |= (p_insn.operand_type[0][2]->reg.opcode << 22); - break; - case OO_PField: - p_insn.opcode |= p_insn.p_field; - if (p_insn.operand_type[0][2]->reg.opcode == 0x01) - p_insn.opcode |= 0x00800000; - if (p_insn.operand_type[1][2]->reg.opcode == 0x03) - p_insn.opcode |= 0x00400000; - switch (p_insn.p_field) - { - case 0x00000000: - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[0][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 19); - break; - case 0x01000000: - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][1]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); - break; - case 0x02000000: - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[1][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][0]->reg.opcode << 19); - break; - case 0x03000000: - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.ARnum); - p_insn.opcode |= (p_insn.operand_type[1][1]->indirect.mod << 3); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.ARnum << 8); - p_insn.opcode |= (p_insn.operand_type[0][0]->indirect.mod << 11); - p_insn.opcode |= (p_insn.operand_type[1][0]->reg.opcode << 16); - p_insn.opcode |= (p_insn.operand_type[0][1]->reg.opcode << 19); - break; - } - break; - } - } /* Opcode is finalised at this point for all parallel instructions. */ - { /* Output opcode */ - char *p; - p = frag_more (INSN_SIZE); - md_number_to_chars (p, (valueT) p_insn.opcode, INSN_SIZE); - } - { - int i, j; - for (i = 0; i < 2; i++) - for (j = 0; j < p_insn.operands[i]; j++) - free (p_insn.operand_type[i][j]); - } - debug ("Final opcode: %08X\n", p_insn.opcode); - debug ("\n"); - return 1; -} - -operand * -tic30_operand (token) - char *token; -{ - int count; - char ind_buffer[strlen (token)]; - operand *current_op; - - debug ("In tic30_operand with %s\n", token); - current_op = (operand *) malloc (sizeof (operand)); - memset (current_op, '\0', sizeof (operand)); - if (*token == DIRECT_REFERENCE) - { - char *token_posn = token + 1; - int direct_label = 0; - debug ("Found direct reference\n"); - while (*token_posn) - { - if (!is_digit_char (*token_posn)) - direct_label = 1; - token_posn++; - } - if (direct_label) - { - char *save_input_line_pointer; - segT retval; - debug ("Direct reference is a label\n"); - current_op->direct.label = token + 1; - save_input_line_pointer = input_line_pointer; - input_line_pointer = token + 1; - debug ("Current input_line_pointer: %s\n", input_line_pointer); - retval = expression (¤t_op->direct.direct_expr); - debug ("Expression type: %d\n", current_op->direct.direct_expr.X_op); - debug ("Expression addnum: %d\n", current_op->direct.direct_expr.X_add_number); - debug ("Segment: %d\n", retval); - input_line_pointer = save_input_line_pointer; - if (current_op->direct.direct_expr.X_op == O_constant) - { - current_op->direct.address = current_op->direct.direct_expr.X_add_number; - current_op->direct.resolved = 1; - } - } - else - { - debug ("Direct reference is a number\n"); - current_op->direct.address = atoi (token + 1); - current_op->direct.resolved = 1; - } - current_op->op_type = Direct; - } - else if (*token == INDIRECT_REFERENCE) - { /* Indirect reference operand */ - int found_ar = 0; - int found_disp = 0; - int ar_number = -1; - int disp_number = 0; - int buffer_posn = 1; - ind_addr_type *ind_addr_op; - debug ("Found indirect reference\n"); - ind_buffer[0] = *token; - for (count = 1; count < strlen (token); count++) - { /* Strip operand */ - ind_buffer[buffer_posn] = tolower (*(token + count)); - if ((*(token + count - 1) == 'a' || *(token + count - 1) == 'A') && - (*(token + count) == 'r' || *(token + count) == 'R')) - { - /* AR reference is found, so get its number and remove it from the buffer - so it can pass through hash_find() */ - if (found_ar) - { - as_bad ("More than one AR register found in indirect reference"); - return NULL; - } - if (*(token + count + 1) < '0' || *(token + count + 1) > '7') - { - as_bad ("Illegal AR register in indirect reference"); - return NULL; - } - ar_number = *(token + count + 1) - '0'; - found_ar = 1; - count++; - } - if (*(token + count) == '(') - { - /* Parenthesis found, so check if a displacement value is inside. If so, get - the value and remove it from the buffer. */ - if (is_digit_char (*(token + count + 1))) - { - char disp[10]; - int disp_posn = 0; - - if (found_disp) - { - as_bad ("More than one displacement found in indirect reference"); - return NULL; - } - count++; - while (*(token + count) != ')') - { - if (!is_digit_char (*(token + count))) - { - as_bad ("Invalid displacement in indirect reference"); - return NULL; - } - disp[disp_posn++] = *(token + (count++)); - } - disp[disp_posn] = '\0'; - disp_number = atoi (disp); - count--; - found_disp = 1; - } - } - buffer_posn++; - } - ind_buffer[buffer_posn] = '\0'; - if (!found_ar) - { - as_bad ("AR register not found in indirect reference"); - return NULL; - } - ind_addr_op = (ind_addr_type *) hash_find (ind_hash, ind_buffer); - if (ind_addr_op) - { - debug ("Found indirect reference: %s\n", ind_addr_op->syntax); - if (ind_addr_op->displacement == IMPLIED_DISP) - { - found_disp = 1; - disp_number = 1; - } - else if ((ind_addr_op->displacement == DISP_REQUIRED) && !found_disp) - { - /* Maybe an implied displacement of 1 again */ - as_bad ("required displacement wasn't given in indirect reference"); - return 0; - } - } - else - { - as_bad ("illegal indirect reference"); - return NULL; - } - if (found_disp && (disp_number < 0 || disp_number > 255)) - { - as_bad ("displacement must be an unsigned 8-bit number"); - return NULL; - } - current_op->indirect.mod = ind_addr_op->modfield; - current_op->indirect.disp = disp_number; - current_op->indirect.ARnum = ar_number; - current_op->op_type = Indirect; - } - else - { - reg *regop = (reg *) hash_find (reg_hash, token); - if (regop) - { - debug ("Found register operand: %s\n", regop->name); - if (regop->regtype == REG_ARn) - current_op->op_type = ARn; - else if (regop->regtype == REG_Rn) - current_op->op_type = Rn; - else if (regop->regtype == REG_DP) - current_op->op_type = DPReg; - else - current_op->op_type = OtherReg; - current_op->reg.opcode = regop->opcode; - } - else - { - if (!is_digit_char (*token) || *(token + 1) == 'x' || strchr (token, 'h')) - { - char *save_input_line_pointer; - segT retval; - debug ("Probably a label: %s\n", token); - current_op->immediate.label = (char *) malloc (strlen (token) + 1); - strcpy (current_op->immediate.label, token); - current_op->immediate.label[strlen (token)] = '\0'; - save_input_line_pointer = input_line_pointer; - input_line_pointer = token; - debug ("Current input_line_pointer: %s\n", input_line_pointer); - retval = expression (¤t_op->immediate.imm_expr); - debug ("Expression type: %d\n", current_op->immediate.imm_expr.X_op); - debug ("Expression addnum: %d\n", current_op->immediate.imm_expr.X_add_number); - debug ("Segment: %d\n", retval); - input_line_pointer = save_input_line_pointer; - if (current_op->immediate.imm_expr.X_op == O_constant) - { - current_op->immediate.s_number = current_op->immediate.imm_expr.X_add_number; - current_op->immediate.u_number = (unsigned int) current_op->immediate.imm_expr.X_add_number; - current_op->immediate.resolved = 1; - } - } - else - { - unsigned count; - debug ("Found a number or displacement\n"); - for (count = 0; count < strlen (token); count++) - if (*(token + count) == '.') - current_op->immediate.decimal_found = 1; - current_op->immediate.label = (char *) malloc (strlen (token) + 1); - strcpy (current_op->immediate.label, token); - current_op->immediate.label[strlen (token)] = '\0'; - current_op->immediate.f_number = (float) atof (token); - current_op->immediate.s_number = (int) atoi (token); - current_op->immediate.u_number = (unsigned int) atoi (token); - current_op->immediate.resolved = 1; - } - current_op->op_type = Disp | Abs24 | Imm16 | Imm24; - if (current_op->immediate.u_number >= 0 && current_op->immediate.u_number <= 31) - current_op->op_type |= IVector; - } - } - return current_op; -} - -/* next_line points to the next line after the current instruction (current_line). - Search for the parallel bars, and if found, merge two lines into internal syntax - for a parallel instruction: - q_[INSN1]_[INSN2] [OPERANDS1] | [OPERANDS2] - By this stage, all comments are scrubbed, and only the bare lines are given. - */ - -#define NONE 0 -#define START_OPCODE 1 -#define END_OPCODE 2 -#define START_OPERANDS 3 -#define END_OPERANDS 4 - -char * -tic30_find_parallel_insn (current_line, next_line) - char *current_line; - char *next_line; -{ - int found_parallel = 0; - char first_opcode[256]; - char second_opcode[256]; - char first_operands[256]; - char second_operands[256]; - char *parallel_insn; - - debug ("In tic30_find_parallel_insn()\n"); - while (!is_end_of_line[(int) *next_line]) - { - if (*next_line == PARALLEL_SEPARATOR && *(next_line + 1) == PARALLEL_SEPARATOR) - { - found_parallel = 1; - next_line++; - break; - } - next_line++; - } - if (!found_parallel) - return NULL; - debug ("Found a parallel instruction\n"); - { - int i; - char *opcode, *operands, *line; - - for (i = 0; i < 2; i++) - { - if (i == 0) - { - opcode = &first_opcode[0]; - operands = &first_operands[0]; - line = current_line; - } - else - { - opcode = &second_opcode[0]; - operands = &second_operands[0]; - line = next_line; - } - { - int search_status = NONE; - int char_ptr = 0; - char c; - - while (!is_end_of_line[(int) (c = *line)] && *line) - { - if (is_opcode_char (c) && search_status == NONE) - { - opcode[char_ptr++] = tolower (c); - search_status = START_OPCODE; - } - else if (is_opcode_char (c) && search_status == START_OPCODE) - { - opcode[char_ptr++] = tolower (c); - } - else if (!is_opcode_char (c) && search_status == START_OPCODE) - { - opcode[char_ptr] = '\0'; - char_ptr = 0; - search_status = END_OPCODE; - } - else if (is_operand_char (c) && search_status == START_OPERANDS) - { - operands[char_ptr++] = c; - } - if (is_operand_char (c) && search_status == END_OPCODE) - { - operands[char_ptr++] = c; - search_status = START_OPERANDS; - } - line++; - } - if (search_status != START_OPERANDS) - return NULL; - operands[char_ptr] = '\0'; - } - } - } - parallel_insn = (char *) malloc (strlen (first_opcode) + strlen (first_operands) + - strlen (second_opcode) + strlen (second_operands) + 8); - sprintf (parallel_insn, "q_%s_%s %s | %s", first_opcode, second_opcode, first_operands, second_operands); - debug ("parallel insn = %s\n", parallel_insn); - return parallel_insn; -} - -#undef NONE -#undef START_OPCODE -#undef END_OPCODE -#undef START_OPERANDS -#undef END_OPERANDS - -/* In order to get gas to ignore any | chars at the start of a line, - this function returns true if a | is found in a line. */ - -int -tic30_unrecognized_line (c) - int c; -{ - debug ("In tc_unrecognized_line\n"); - return (c == PARALLEL_SEPARATOR); -} - -int -md_estimate_size_before_relax (fragP, segment) - fragS *fragP; - segT segment; -{ - debug ("In md_estimate_size_before_relax()\n"); - return 0; -} - -void -md_convert_frag (abfd, sec, fragP) - bfd *abfd; - segT sec; - register fragS *fragP; -{ - debug ("In md_convert_frag()\n"); -} - -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; -{ - debug ("In md_create_short_jump()\n"); -} - -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; -{ - debug ("In md_create_long_jump()\n"); -} - -int -md_apply_fix (fixP, valP) - fixS *fixP; - valueT *valP; -{ - valueT value = *valP; - - debug ("In md_apply_fix() with value = %ld\n", (long) value); - debug ("Values in fixP\n"); - debug ("fx_size = %d\n", fixP->fx_size); - debug ("fx_pcrel = %d\n", fixP->fx_pcrel); - debug ("fx_where = %d\n", fixP->fx_where); - debug ("fx_offset = %d\n", (int) fixP->fx_offset); - { - char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; - value /= INSN_SIZE; - if (fixP->fx_size == 1) - { /* Special fix for LDP instruction. */ - value = (value & 0x00FF0000) >> 16; - } - debug ("new value = %ld\n", (long) value); - md_number_to_chars (buf, value, fixP->fx_size); - } - return 1; -} - -int -md_parse_option (c, arg) - int c; - char *arg; -{ - int i; - - debug ("In md_parse_option()\n"); - for (i = 0; i < c; i++) - { - printf ("%c\n", arg[c]); - } - return 0; -} - -void -md_show_usage (stream) - FILE *stream; -{ - debug ("In md_show_usage()\n"); -} - -symbolS * -md_undefined_symbol (name) - char *name; -{ - debug ("In md_undefined_symbol()\n"); - return (symbolS *) 0; -} - -valueT -md_section_align (segment, size) - segT segment; - valueT size; -{ - debug ("In md_section_align() segment = %d and size = %d\n", segment, size); - size = (size + 3) / 4; - size *= 4; - debug ("New size value = %d\n", size); - return size; -} - -long -md_pcrel_from (fixP) - fixS *fixP; -{ - int offset; - - debug ("In md_pcrel_from()\n"); - debug ("fx_where = %d\n", fixP->fx_where); - debug ("fx_size = %d\n", fixP->fx_size); - /* Find the opcode that represents the current instruction in the fr_literal - storage area, and check bit 21. Bit 21 contains whether the current instruction - is a delayed one or not, and then set the offset value appropriately. */ - if (fixP->fx_frag->fr_literal[fixP->fx_where - fixP->fx_size + 1] & 0x20) - offset = 3; - else - offset = 1; - debug ("offset = %d\n", offset); - /* PC Relative instructions have a format: - displacement = Label - (PC + offset) - This function returns PC + offset where: - fx_where - fx_size = PC - INSN_SIZE * offset = offset number of instructions - */ - return fixP->fx_where - fixP->fx_size + (INSN_SIZE * offset); -} - -char * -md_atof (what_statement_type, literalP, sizeP) - int what_statement_type; - char *literalP; - int *sizeP; -{ - int prec; - char *token; - char keepval; - unsigned long value; - /* char *atof_ieee (); */ - float float_value; - debug ("In md_atof()\n"); - debug ("precision = %c\n", what_statement_type); - debug ("literal = %s\n", literalP); - debug ("line = "); - token = input_line_pointer; - while (!is_end_of_line[(unsigned) *input_line_pointer] && (*input_line_pointer) && (*input_line_pointer != ',')) - { - debug ("%c", *input_line_pointer); - input_line_pointer++; - } - keepval = *input_line_pointer; - *input_line_pointer = '\0'; - debug ("\n"); - float_value = (float) atof (token); - *input_line_pointer = keepval; - debug ("float_value = %f\n", float_value); - switch (what_statement_type) - { - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - prec = 4; - break; - - default: - *sizeP = 0; - return "Bad call to MD_ATOF()"; - } - if (float_value == 0.0) - { - value = (prec == 2) ? 0x00008000L : 0x80000000L; - } - else - { - unsigned long exp, sign, mant, tmsfloat; - tmsfloat = *((long *) &float_value); - sign = tmsfloat & 0x80000000; - mant = tmsfloat & 0x007FFFFF; - exp = tmsfloat & 0x7F800000; - exp <<= 1; - if (exp == 0xFF000000) - { - if (mant == 0) - value = 0x7F7FFFFF; - else if (sign == 0) - value = 0x7F7FFFFF; - else - value = 0x7F800000; - } - else - { - exp -= 0x7F000000; - if (sign) - { - mant = mant & 0x007FFFFF; - mant = -mant; - mant = mant & 0x00FFFFFF; - if (mant == 0) - { - mant |= 0x00800000; - exp = (long) exp - 0x01000000; - } - } - tmsfloat = exp | mant; - value = tmsfloat; - } - if (prec == 2) - { - long exp, mant; - - if (tmsfloat == 0x80000000) - { - value = 0x8000; - } - else - { - value = 0; - exp = (tmsfloat & 0xFF000000); - exp >>= 24; - mant = tmsfloat & 0x007FFFFF; - if (tmsfloat & 0x00800000) - { - mant |= 0xFF000000; - mant += 0x00000800; - mant >>= 12; - mant |= 0x00000800; - mant &= 0x0FFF; - if (exp > 7) - value = 0x7800; - } - else - { - mant |= 0x00800000; - mant += 0x00000800; - exp += (mant >> 24); - mant >>= 12; - mant &= 0x07FF; - if (exp > 7) - value = 0x77FF; - } - if (exp < -8) - value = 0x8000; - if (value == 0) - { - mant = (exp << 12) | mant; - value = mant & 0xFFFF; - } - } - } - } - md_number_to_chars (literalP, value, prec); - *sizeP = prec; - return 0; -} - -void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; -{ - debug ("In md_number_to_chars()\n"); - number_to_chars_bigendian (buf, val, n); - /* number_to_chars_littleendian(buf,val,n); */ -} - -#define F(SZ,PCREL) (((SZ) << 1) + (PCREL)) -#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break - -arelent * -tc_gen_reloc (section, fixP) - asection *section; - fixS *fixP; -{ - arelent *rel; - bfd_reloc_code_real_type code = 0; - - debug ("In tc_gen_reloc()\n"); - debug ("fixP.size = %d\n", fixP->fx_size); - debug ("fixP.pcrel = %d\n", fixP->fx_pcrel); - debug ("addsy.name = %s\n", S_GET_NAME (fixP->fx_addsy)); - switch (F (fixP->fx_size, fixP->fx_pcrel)) - { - MAP (1, 0, BFD_RELOC_TIC30_LDP); - MAP (2, 0, BFD_RELOC_16); - MAP (3, 0, BFD_RELOC_24); - MAP (2, 1, BFD_RELOC_16_PCREL); - MAP (4, 0, BFD_RELOC_32); - default: - as_bad ("Can not do %d byte %srelocation", fixP->fx_size, - fixP->fx_pcrel ? "pc-relative " : ""); - } -#undef MAP -#undef F - - rel = (arelent *) xmalloc (sizeof (arelent)); - assert (rel != 0); - rel->sym_ptr_ptr = &fixP->fx_addsy->bsym; - rel->address = fixP->fx_frag->fr_address + fixP->fx_where; - if (fixP->fx_pcrel) - rel->addend = fixP->fx_addnumber; - else - rel->addend = 0; - rel->howto = bfd_reloc_type_lookup (stdoutput, code); - if (!rel->howto) - { - const char *name; - name = S_GET_NAME (fixP->fx_addsy); - if (name == NULL) - name = "<unknown>"; - as_fatal ("Cannot generate relocation type for symbol %s, code %s", name, bfd_get_reloc_code_name (code)); - } - return rel; -} - -void -tc_aout_pre_write_hook () -{ - debug ("In tc_aout_pre_write_hook()\n"); -} - -void -md_operand (expressionP) - expressionS *expressionP; -{ - debug ("In md_operand()\n"); -} - -char output_invalid_buf[8]; - -char * -output_invalid (c) - char c; -{ - if (isprint (c)) - sprintf (output_invalid_buf, "'%c'", c); - else - sprintf (output_invalid_buf, "(0x%x)", (unsigned) c); - return output_invalid_buf; -} diff --git a/contrib/binutils/gas/config/tc-tic30.h b/contrib/binutils/gas/config/tc-tic30.h deleted file mode 100644 index 2fb9cb6f31cb..000000000000 --- a/contrib/binutils/gas/config/tc-tic30.h +++ /dev/null @@ -1,53 +0,0 @@ -/* tc-tic30.h -- Header file for tc-tic30.c - Copyright (C) 1998 Free Software Foundation. - Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au) - - 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 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. */ - -#ifndef _TC_TIC30_H_ -#define _TC_TIC30_H_ - -#define TC_TIC30 1 - -#ifdef OBJ_AOUT -#define TARGET_FORMAT "a.out-tic30" -#endif - -#define TARGET_ARCH bfd_arch_tic30 -#define TARGET_BYTES_BIG_ENDIAN 1 - -char *output_invalid PARAMS ((int c)); - -#define END_OF_INSN '\0' -#define MAX_OPERANDS 6 -#define DIRECT_REFERENCE '@' -#define INDIRECT_REFERENCE '*' -#define PARALLEL_SEPARATOR '|' -#define INSN_SIZE 4 - -/* Define this to 1 if you want the debug output to be on stdout, - otherwise stderr will be used. If stderr is used, there will be a - better synchronisation with the as_bad outputs, but you can't - capture the output. */ -#define USE_STDOUT 0 - -#define tc_unrecognized_line tic30_unrecognized_line - -extern int tic30_unrecognized_line PARAMS ((int)); - -#endif diff --git a/contrib/binutils/gas/config/tc-v850.c b/contrib/binutils/gas/config/tc-v850.c deleted file mode 100644 index 18ec1142f5d8..000000000000 --- a/contrib/binutils/gas/config/tc-v850.c +++ /dev/null @@ -1,1902 +0,0 @@ -/* tc-v850.c -- Assembler code for the NEC V850 - Copyright (C) 1996, 1997, 1998 Free Software Foundation. - - 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 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. */ - -#include <stdio.h> -#include <ctype.h> -#include "as.h" -#include "subsegs.h" -#include "opcode/v850.h" - -#define AREA_ZDA 0 -#define AREA_SDA 1 -#define AREA_TDA 2 - -/* sign-extend a 16-bit number */ -#define SEXT16(x) ((((x) & 0xffff) ^ (~ 0x7fff)) + 0x8000) - -/* Temporarily holds the reloc in a cons expression. */ -static bfd_reloc_code_real_type hold_cons_reloc; - -/* Set to TRUE if we want to be pedantic about signed overflows. */ -static boolean warn_signed_overflows = FALSE; -static boolean warn_unsigned_overflows = FALSE; - -/* Indicates the target BFD machine number. */ -static int machine = -1; - -/* Indicates the target processor(s) for the assemble. */ -static unsigned int processor_mask = -1; - - -/* Structure to hold information about predefined registers. */ -struct reg_name -{ - const char * name; - int value; -}; - -/* Generic assembler global variables which must be defined by all targets. */ - -/* Characters which always start a comment. */ -const char comment_chars[] = "#"; - -/* Characters which start a comment at the beginning of a line. */ -const char line_comment_chars[] = ";#"; - -/* Characters which may be used to separate multiple commands on a - single line. */ -const char line_separator_chars[] = ";"; - -/* Characters which are used to indicate an exponent in a floating - point number. */ -const char EXP_CHARS[] = "eE"; - -/* Characters which mean that a number is a floating point constant, - as in 0d1.0. */ -const char FLT_CHARS[] = "dD"; - - -const relax_typeS md_relax_table[] = -{ - /* Conditional branches. */ - {0xff, -0x100, 2, 1}, - {0x1fffff, -0x200000, 6, 0}, - /* Unconditional branches. */ - {0xff, -0x100, 2, 3}, - {0x1fffff, -0x200000, 4, 0}, -}; - - -static segT sdata_section = NULL; -static segT tdata_section = NULL; -static segT zdata_section = NULL; -static segT sbss_section = NULL; -static segT tbss_section = NULL; -static segT zbss_section = NULL; -static segT rosdata_section = NULL; -static segT rozdata_section = NULL; -static segT scommon_section = NULL; -static segT tcommon_section = NULL; -static segT zcommon_section = NULL; - -/* fixups */ -#define MAX_INSN_FIXUPS (5) -struct v850_fixup -{ - expressionS exp; - int opindex; - bfd_reloc_code_real_type reloc; -}; - -struct v850_fixup fixups [MAX_INSN_FIXUPS]; -static int fc; - - -void -v850_sdata (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (sdata_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - -void -v850_tdata (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (tdata_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - -void -v850_zdata (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (zdata_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - -void -v850_sbss (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (sbss_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - -void -v850_tbss (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (tbss_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - -void -v850_zbss (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (zbss_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - -void -v850_rosdata (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (rosdata_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - -void -v850_rozdata (int ignore) -{ - obj_elf_section_change_hook(); - - subseg_set (rozdata_section, (subsegT) get_absolute_expression ()); - - demand_empty_rest_of_line (); -} - - -void -v850_bss (int ignore) -{ - register int temp = get_absolute_expression (); - - obj_elf_section_change_hook(); - - subseg_set (bss_section, (subsegT) temp); - - demand_empty_rest_of_line (); -} - -void -v850_offset (int ignore) -{ - int temp = get_absolute_expression (); - - temp -= frag_now_fix(); - - if (temp > 0) - (void) frag_more (temp); - - demand_empty_rest_of_line (); -} - -/* Copied from obj_elf_common() in gas/config/obj-elf.c */ -static void -v850_comm (area) - int area; -{ - char * name; - char c; - char * p; - int temp; - int size; - symbolS * symbolP; - int have_align; - - name = input_line_pointer; - c = get_symbol_end (); - /* just after name is now '\0' */ - p = input_line_pointer; - *p = c; - SKIP_WHITESPACE (); - if (*input_line_pointer != ',') - { - as_bad ("Expected comma after symbol-name"); - ignore_rest_of_line (); - return; - } - input_line_pointer++; /* skip ',' */ - if ((temp = get_absolute_expression ()) < 0) - { - as_bad (".COMMon length (%d.) <0! Ignored.", temp); - ignore_rest_of_line (); - return; - } - size = temp; - *p = 0; - symbolP = symbol_find_or_make (name); - *p = c; - if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) - { - as_bad ("Ignoring attempt to re-define symbol"); - ignore_rest_of_line (); - return; - } - if (S_GET_VALUE (symbolP) != 0) - { - if (S_GET_VALUE (symbolP) != size) - { - as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.", - S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size); - } - } - know (symbolP->sy_frag == &zero_address_frag); - if (*input_line_pointer != ',') - have_align = 0; - else - { - have_align = 1; - input_line_pointer++; - SKIP_WHITESPACE (); - } - if (! have_align || *input_line_pointer != '"') - { - if (! have_align) - temp = 0; - else - { - temp = get_absolute_expression (); - if (temp < 0) - { - temp = 0; - as_warn ("Common alignment negative; 0 assumed"); - } - } - if (symbolP->local) - { - segT old_sec; - int old_subsec; - char * pfrag; - int align; - - /* allocate_bss: */ - old_sec = now_seg; - old_subsec = now_subseg; - if (temp) - { - /* convert to a power of 2 alignment */ - for (align = 0; (temp & 1) == 0; temp >>= 1, ++align); - if (temp != 1) - { - as_bad ("Common alignment not a power of 2"); - ignore_rest_of_line (); - return; - } - } - else - align = 0; - switch (area) - { - case AREA_SDA: - record_alignment (sbss_section, align); - obj_elf_section_change_hook(); - subseg_set (sbss_section, 0); - break; - - case AREA_ZDA: - record_alignment (zbss_section, align); - obj_elf_section_change_hook(); - subseg_set (zbss_section, 0); - break; - - case AREA_TDA: - record_alignment (tbss_section, align); - obj_elf_section_change_hook(); - subseg_set (tbss_section, 0); - break; - - default: - abort(); - } - - if (align) - frag_align (align, 0, 0); - - switch (area) - { - case AREA_SDA: - if (S_GET_SEGMENT (symbolP) == sbss_section) - symbolP->sy_frag->fr_symbol = 0; - break; - - case AREA_ZDA: - if (S_GET_SEGMENT (symbolP) == zbss_section) - symbolP->sy_frag->fr_symbol = 0; - break; - - case AREA_TDA: - if (S_GET_SEGMENT (symbolP) == tbss_section) - symbolP->sy_frag->fr_symbol = 0; - break; - - default: - abort(); - } - - symbolP->sy_frag = frag_now; - pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, - (offsetT) size, (char *) 0); - *pfrag = 0; - S_SET_SIZE (symbolP, size); - - switch (area) - { - case AREA_SDA: S_SET_SEGMENT (symbolP, sbss_section); break; - case AREA_ZDA: S_SET_SEGMENT (symbolP, zbss_section); break; - case AREA_TDA: S_SET_SEGMENT (symbolP, tbss_section); break; - default: - abort(); - } - - S_CLEAR_EXTERNAL (symbolP); - obj_elf_section_change_hook(); - subseg_set (old_sec, old_subsec); - } - else - { - allocate_common: - S_SET_VALUE (symbolP, (valueT) size); - S_SET_ALIGN (symbolP, temp); - S_SET_EXTERNAL (symbolP); - - switch (area) - { - case AREA_SDA: S_SET_SEGMENT (symbolP, scommon_section); break; - case AREA_ZDA: S_SET_SEGMENT (symbolP, zcommon_section); break; - case AREA_TDA: S_SET_SEGMENT (symbolP, tcommon_section); break; - default: - abort(); - } - } - } - else - { - input_line_pointer++; - /* @@ Some use the dot, some don't. Can we get some consistency?? */ - if (*input_line_pointer == '.') - input_line_pointer++; - /* @@ Some say data, some say bss. */ - if (strncmp (input_line_pointer, "bss\"", 4) - && strncmp (input_line_pointer, "data\"", 5)) - { - while (*--input_line_pointer != '"') - ; - input_line_pointer--; - goto bad_common_segment; - } - while (*input_line_pointer++ != '"') - ; - goto allocate_common; - } - - symbolP->bsym->flags |= BSF_OBJECT; - - demand_empty_rest_of_line (); - return; - - { - bad_common_segment: - p = input_line_pointer; - while (*p && *p != '\n') - p++; - c = *p; - *p = '\0'; - as_bad ("bad .common segment %s", input_line_pointer + 1); - *p = c; - input_line_pointer = p; - ignore_rest_of_line (); - return; - } -} - -void -set_machine (int number) -{ - machine = number; - bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine); - - switch (machine) - { - case 0: processor_mask = PROCESSOR_V850; break; - } -} - -/* The target specific pseudo-ops which we support. */ -const pseudo_typeS md_pseudo_table[] = -{ - {"sdata", v850_sdata, 0}, - {"tdata", v850_tdata, 0}, - {"zdata", v850_zdata, 0}, - {"sbss", v850_sbss, 0}, - {"tbss", v850_tbss, 0}, - {"zbss", v850_zbss, 0}, - {"rosdata", v850_rosdata, 0}, - {"rozdata", v850_rozdata, 0}, - {"bss", v850_bss, 0}, - {"offset", v850_offset, 0}, - {"word", cons, 4}, - {"zcomm", v850_comm, AREA_ZDA}, - {"scomm", v850_comm, AREA_SDA}, - {"tcomm", v850_comm, AREA_TDA}, - {"v850", set_machine, 0}, - { NULL, NULL, 0} -}; - -/* Opcode hash table. */ -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 */ - { "r0", 0 }, - { "r1", 1 }, - { "r10", 10 }, - { "r11", 11 }, - { "r12", 12 }, - { "r13", 13 }, - { "r14", 14 }, - { "r15", 15 }, - { "r16", 16 }, - { "r17", 17 }, - { "r18", 18 }, - { "r19", 19 }, - { "r2", 2 }, - { "r20", 20 }, - { "r21", 21 }, - { "r22", 22 }, - { "r23", 23 }, - { "r24", 24 }, - { "r25", 25 }, - { "r26", 26 }, - { "r27", 27 }, - { "r28", 28 }, - { "r29", 29 }, - { "r3", 3 }, - { "r30", 30 }, - { "r31", 31 }, - { "r4", 4 }, - { "r5", 5 }, - { "r6", 6 }, - { "r7", 7 }, - { "r8", 8 }, - { "r9", 9 }, - { "sp", 3 }, /* sp - stack ptr */ - { "tp", 5 }, /* tp - text ptr */ - { "zero", 0 }, -}; -#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct reg_name)) - - -static const struct reg_name system_registers[] = -{ - { "ecr", 4 }, - { "eipc", 0 }, - { "eipsw", 1 }, - { "fepc", 2 }, - { "fepsw", 3 }, - { "psw", 5 }, -}; -#define SYSREG_NAME_CNT (sizeof (system_registers) / sizeof (struct reg_name)) - - -static const struct reg_name cc_names[] = -{ - { "c", 0x1 }, - { "e", 0x2 }, - { "ge", 0xe }, - { "gt", 0xf }, - { "h", 0xb }, - { "l", 0x1 }, - { "le", 0x7 }, - { "lt", 0x6 }, - { "n", 0x4 }, - { "nc", 0x9 }, - { "ne", 0xa }, - { "nh", 0x3 }, - { "nl", 0x9 }, - { "ns", 0xc }, - { "nv", 0x8 }, - { "nz", 0xa }, - { "p", 0xc }, - { "s", 0x4 }, - { "sa", 0xd }, - { "t", 0x5 }, - { "v", 0x0 }, - { "z", 0x2 }, -}; -#define CC_NAME_CNT (sizeof (cc_names) / sizeof (struct reg_name)) - -/* reg_name_search does a binary search of the given register table - to see if "name" is a valid regiter name. Returns the register - number from the array on success, or -1 on failure. */ - -static int -reg_name_search (regs, regcount, name, accept_numbers) - const struct reg_name * regs; - int regcount; - const char * name; - boolean accept_numbers; -{ - int middle, low, high; - int cmp; - symbolS * symbolP; - - /* If the register name is a symbol, then evaluate it. */ - if ((symbolP = symbol_find (name)) != NULL) - { - /* 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 (symbolP->sy_value.X_op == O_symbol) - { - name = S_GET_NAME (symbolP->sy_value.X_add_symbol); - } - else if (accept_numbers) - { - int reg = S_GET_VALUE (symbolP); - - if (reg >= 0 && reg <= 31) - return reg; - } - } - - low = 0; - high = regcount - 1; - - do - { - middle = (low + high) / 2; - cmp = strcasecmp (name, regs[middle].name); - if (cmp < 0) - high = middle - 1; - else if (cmp > 0) - low = middle + 1; - else - return regs[middle].value; - } - while (low <= high); - return -1; -} - - -/* Summary of register_name(). - * - * in: Input_line_pointer points to 1st char of operand. - * - * out: A 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 boolean -register_name (expressionP) - expressionS * expressionP; -{ - int reg_number; - char * name; - char * start; - char c; - - /* Find the spelling of the operand */ - start = name = input_line_pointer; - - c = get_symbol_end (); - - reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, - name, FALSE); - - * input_line_pointer = c; /* put back the delimiting char */ - - /* look to see if it's in the register table */ - if (reg_number >= 0) - { - expressionP->X_op = O_register; - expressionP->X_add_number = reg_number; - - /* make the rest nice */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - - return true; - } - else - { - /* reset the line as if we had not done anything */ - input_line_pointer = start; - - return false; - } -} - -/* Summary of system_register_name(). - * - * in: Input_line_pointer points to 1st char of operand. - * expressionP points to an expression structure to be filled in. - * accept_numbers is true iff numerical register names may be used. - * - * out: A expressionS structure in expressionP. - * 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 boolean -system_register_name (expressionP, accept_numbers - ) - expressionS * expressionP; - boolean accept_numbers; -{ - int reg_number; - char * name; - char * start; - char c; - - /* Find the spelling of the operand */ - start = name = input_line_pointer; - - c = get_symbol_end (); - reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name, - accept_numbers); - - * input_line_pointer = c; /* put back the delimiting char */ - - if (reg_number < 0 - && accept_numbers) - { - input_line_pointer = start; /* reset input_line pointer */ - - if (isdigit (* input_line_pointer)) - { - reg_number = strtol (input_line_pointer, & input_line_pointer, 10); - - /* Make sure that the register number is allowable. */ - if ( reg_number < 0 - || reg_number > 5 - ) - { - reg_number = -1; - } - } - } - - /* look to see if it's in the register table */ - if (reg_number >= 0) - { - expressionP->X_op = O_register; - expressionP->X_add_number = reg_number; - - /* make the rest nice */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - - return true; - } - else - { - /* reset the line as if we had not done anything */ - input_line_pointer = start; - - return false; - } -} - -/* Summary of cc_name(). - * - * in: Input_line_pointer points to 1st char of operand. - * - * out: A 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 boolean -cc_name (expressionP) - expressionS * expressionP; -{ - int reg_number; - char * name; - char * start; - char c; - - /* Find the spelling of the operand */ - start = name = input_line_pointer; - - c = get_symbol_end (); - reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE); - - * input_line_pointer = c; /* put back the delimiting char */ - - /* look to see if it's in the register table */ - if (reg_number >= 0) - { - expressionP->X_op = O_constant; - expressionP->X_add_number = reg_number; - - /* make the rest nice */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - - return true; - } - else - { - /* reset the line as if we had not done anything */ - input_line_pointer = start; - - return false; - } -} - -static void -skip_white_space (void) -{ - while ( * input_line_pointer == ' ' - || * input_line_pointer == '\t') - ++ input_line_pointer; -} - - -CONST char * md_shortopts = "m:"; - -struct option md_longopts[] = -{ - {NULL, no_argument, NULL, 0} -}; -size_t md_longopts_size = sizeof md_longopts; - - -void -md_show_usage (stream) - FILE * stream; -{ - fprintf (stream, "V850 options:\n"); - fprintf (stream, "\t-mwarn-signed-overflow Warn if signed immediate values overflow\n"); - fprintf (stream, "\t-mwarn-unsigned-overflow Warn if unsigned immediate values overflow\n"); - fprintf (stream, "\t-mv850 The code is targeted at the v850\n"); -} - -int -md_parse_option (c, arg) - int c; - char * arg; -{ - if (c != 'm') - { - fprintf (stderr, "unknown command line option: -%c%s\n", c, arg); - return 0; - } - - if (strcmp (arg, "warn-signed-overflow") == 0) - { - warn_signed_overflows = TRUE; - } - else if (strcmp (arg, "warn-unsigned-overflow") == 0) - { - warn_unsigned_overflows = TRUE; - } - else if (strcmp (arg, "v850") == 0) - { - machine = 0; - processor_mask = PROCESSOR_V850; - } - else - { - fprintf (stderr, "unknown command line option: -%c%s\n", c, arg); - return 0; - } - - return 1; -} - -symbolS * -md_undefined_symbol (name) - char * name; -{ - return 0; -} - -char * -md_atof (type, litp, sizep) - int type; - char * litp; - int * sizep; -{ - int prec; - LITTLENUM_TYPE words[4]; - char * t; - int i; - - 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 * 2; - - for (i = prec - 1; i >= 0; i--) - { - md_number_to_chars (litp, (valueT) words[i], 2); - litp += 2; - } - - return NULL; -} - - -/* Very gross. */ -void -md_convert_frag (abfd, sec, fragP) - bfd * abfd; - asection * sec; - fragS * fragP; -{ - subseg_change (sec, 0); - - /* In range conditional or unconditional branch. */ - if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2) - { - fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, - fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode); - fragP->fr_var = 0; - fragP->fr_fix += 2; - } - /* Out of range conditional branch. Emit a branch around a jump. */ - else if (fragP->fr_subtype == 1) - { - unsigned char *buffer = - (unsigned char *) (fragP->fr_fix + fragP->fr_literal); - - /* Reverse the condition of the first branch. */ - buffer[0] ^= 0x08; - /* Mask off all the displacement bits. */ - buffer[0] &= 0x8f; - buffer[1] &= 0x07; - /* Now set the displacement bits so that we branch - around the unconditional branch. */ - buffer[0] |= 0x30; - - /* Now create the unconditional branch + fixup to the final - target. */ - md_number_to_chars (buffer + 2, 0x00000780, 4); - fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, - fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int) fragP->fr_opcode - + 1); - fragP->fr_var = 0; - fragP->fr_fix += 6; - } - /* Out of range unconditional branch. Emit a jump. */ - else if (fragP->fr_subtype == 3) - { - md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4); - fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, - fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int) fragP->fr_opcode - + 1); - fragP->fr_var = 0; - fragP->fr_fix += 4; - } - else - abort (); -} - -valueT -md_section_align (seg, addr) - asection * seg; - valueT addr; -{ - int align = bfd_get_section_alignment (stdoutput, seg); - return ((addr + (1 << align) - 1) & (-1 << align)); -} - -void -md_begin () -{ - char * prev_name = ""; - register const struct v850_opcode * op; - flagword applicable; - - if (strncmp (TARGET_CPU, "v850", 4) == 0) - { - if (machine == -1) - machine = 0; - - if (processor_mask == -1) - processor_mask = PROCESSOR_V850; - } - else - as_bad ("Unable to determine default target processor from string: %s", - TARGET_CPU); - - v850_hash = hash_new(); - - /* Insert unique names into hash table. The V850 instruction set - has many identical opcode names that have different opcodes based - on the operands. This hash table then provides a quick index to - the first opcode with a particular name in the opcode table. */ - - op = v850_opcodes; - while (op->name) - { - if (strcmp (prev_name, op->name)) - { - prev_name = (char *) op->name; - hash_insert (v850_hash, op->name, (char *) op); - } - op++; - } - - bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine); - - applicable = bfd_applicable_section_flags (stdoutput); - - sdata_section = subseg_new (".sdata", 0); - bfd_set_section_flags (stdoutput, sdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS)); - - tdata_section = subseg_new (".tdata", 0); - bfd_set_section_flags (stdoutput, tdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS)); - - zdata_section = subseg_new (".zdata", 0); - bfd_set_section_flags (stdoutput, zdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS)); - - sbss_section = subseg_new (".sbss", 0); - bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC); - seg_info (sbss_section)->bss = 1; - - tbss_section = subseg_new (".tbss", 0); - bfd_set_section_flags (stdoutput, tbss_section, applicable & SEC_ALLOC); - seg_info (tbss_section)->bss = 1; - - zbss_section = subseg_new (".zbss", 0); - bfd_set_section_flags (stdoutput, zbss_section, applicable & SEC_ALLOC); - seg_info (zbss_section)->bss = 1; - - rosdata_section = subseg_new (".rosdata", 0); - bfd_set_section_flags (stdoutput, rosdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY)); - - rozdata_section = subseg_new (".rozdata", 0); - bfd_set_section_flags (stdoutput, rozdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY)); - - scommon_section = subseg_new (".scommon", 0); - bfd_set_section_flags (stdoutput, scommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON)); - - zcommon_section = subseg_new (".zcommon", 0); - bfd_set_section_flags (stdoutput, zcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON)); - - tcommon_section = subseg_new (".tcommon", 0); - bfd_set_section_flags (stdoutput, tcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON)); - -} - - - -static bfd_reloc_code_real_type -handle_sdaoff (const struct v850_operand * operand) -{ - if (operand == NULL) return BFD_RELOC_V850_SDA_16_16_OFFSET; - if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_SDA_15_16_OFFSET; - - if ( operand->bits != 16 - || operand->shift != 16) - { - as_bad ("sdaoff() relocation used on an instruction which does not support it"); - return BFD_RELOC_64; /* Used to indicate an error condition. */ - } - - return BFD_RELOC_V850_SDA_16_16_OFFSET; -} - -static bfd_reloc_code_real_type -handle_zdaoff (const struct v850_operand * operand) -{ - if (operand == NULL) return BFD_RELOC_V850_ZDA_16_16_OFFSET; - if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_ZDA_15_16_OFFSET; - - if ( operand->bits != 16 - || operand->shift != 16) - { - as_bad ("zdaoff() relocation used on an instruction which does not support it"); - return BFD_RELOC_64; /* Used to indicate an error condition. */ - } - - return BFD_RELOC_V850_ZDA_16_16_OFFSET; -} - -static bfd_reloc_code_real_type -handle_tdaoff (const struct v850_operand * operand) -{ - if (operand == NULL) return BFD_RELOC_V850_TDA_7_7_OFFSET; /* data item, not an instruction. */ - if (operand->bits == 6 && operand->shift == 1) return BFD_RELOC_V850_TDA_6_8_OFFSET; /* sld.w/sst.w, operand: D8_6 */ - if (operand->bits == 16 && operand->shift == 16) return BFD_RELOC_V850_TDA_16_16_OFFSET; /* set1 & chums, operands: D16 */ - - if (operand->bits != 7) - { - as_bad ("tdaoff() relocation used on an instruction which does not support it"); - return BFD_RELOC_64; /* Used to indicate an error condition. */ - } - - 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, opreand: 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 (const struct v850_operand * operand) -{ - boolean paren_skipped = false; - - - /* Skip leading opening parenthesis. */ - if (* input_line_pointer == '(') - { - ++ input_line_pointer; - paren_skipped = true; - } - -#define CHECK_(name, reloc) \ - if (strncmp (input_line_pointer, name##"(", strlen (name) + 1) == 0) \ - { \ - input_line_pointer += strlen (name); \ - return reloc; \ - } - - CHECK_ ("hi0", BFD_RELOC_HI16); - CHECK_ ("hi", BFD_RELOC_HI16_S); - CHECK_ ("lo", BFD_RELOC_LO16); - CHECK_ ("sdaoff", handle_sdaoff (operand)); - CHECK_ ("zdaoff", handle_zdaoff (operand)); - CHECK_ ("tdaoff", handle_tdaoff (operand)); - - - /* Restore skipped parenthesis. */ - if (paren_skipped) - -- input_line_pointer; - - return BFD_RELOC_UNUSED; -} - -/* Insert an operand value into an instruction. */ - -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; -{ - if (operand->insert) - { - const char * message = NULL; - - insn = operand->insert (insn, val, & message); - if (message != NULL) - { - if ((operand->flags & V850_OPERAND_SIGNED) - && ! warn_signed_overflows - && strstr (message, "out of range") != NULL) - { - /* skip warning... */ - } - else if ((operand->flags & V850_OPERAND_SIGNED) == 0 - && ! warn_unsigned_overflows - && strstr (message, "out of range") != NULL) - { - /* skip warning... */ - } - else if (str) - { - if (file == (char *) NULL) - as_warn ("%s: %s", str, message); - else - as_warn_where (file, line, "%s: %s", str, message); - } - else - { - if (file == (char *) NULL) - as_warn (message); - else - as_warn_where (file, line, message); - } - } - } - else - { - if (operand->bits != 32) - { - long min, max; - offsetT test; - - if ((operand->flags & V850_OPERAND_SIGNED) != 0) - { - if (! warn_signed_overflows) - max = (1 << operand->bits) - 1; - else - max = (1 << (operand->bits - 1)) - 1; - - min = - (1 << (operand->bits - 1)); - } - else - { - max = (1 << operand->bits) - 1; - - if (! warn_unsigned_overflows) - min = - (1 << (operand->bits - 1)); - else - min = 0; - } - - if (val < (offsetT) min || val > (offsetT) max) - { - const char * err = "operand out of range (%s not between %ld and %ld)"; - char buf[100]; - - /* Restore min and mix to expected values for decimal ranges. */ - if ((operand->flags & V850_OPERAND_SIGNED) - && ! warn_signed_overflows) - max = (1 << (operand->bits - 1)) - 1; - - if (! (operand->flags & V850_OPERAND_SIGNED) - && ! warn_unsigned_overflows) - min = 0; - - if (str) - { - sprintf (buf, "%s: ", str); - - sprint_value (buf + strlen (buf), val); - } - else - sprint_value (buf, val); - - if (file == (char *) NULL) - as_warn (err, buf, min, max); - else - as_warn_where (file, line, err, buf, min, max); - } - } - - insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift); - } - - return insn; -} - - -static char copy_of_instruction [128]; - -void -md_assemble (str) - char * str; -{ - char * s; - char * start_of_operands; - struct v850_opcode * opcode; - struct v850_opcode * next_opcode; - const unsigned char * opindex_ptr; - int next_opindex; - int relaxable; - unsigned long insn; - unsigned long insn_size; - char * f; - int i; - int match; - boolean extra_data_after_insn = false; - unsigned extra_data_len; - unsigned long extra_data; - char * saved_input_line_pointer; - - - strncpy (copy_of_instruction, str, sizeof (copy_of_instruction) - 1); - - /* Get the opcode. */ - for (s = str; *s != '\0' && ! isspace (*s); s++) - continue; - - if (*s != '\0') - *s++ = '\0'; - - /* find the first opcode with the proper name */ - opcode = (struct v850_opcode *) hash_find (v850_hash, str); - if (opcode == NULL) - { - as_bad ("Unrecognized opcode: `%s'", str); - ignore_rest_of_line (); - return; - } - - str = s; - while (isspace (* str)) - ++ str; - - start_of_operands = str; - - saved_input_line_pointer = input_line_pointer; - - for (;;) - { - const char * errmsg = NULL; - - match = 0; - - if ((opcode->processors & processor_mask) == 0) - { - errmsg = "Target processor does not support this instruction."; - goto error; - } - - relaxable = 0; - fc = 0; - next_opindex = 0; - insn = opcode->opcode; - extra_data_after_insn = false; - - input_line_pointer = str = start_of_operands; - - for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr ++) - { - const struct v850_operand * operand; - char * hold; - expressionS ex; - bfd_reloc_code_real_type reloc; - - if (next_opindex == 0) - { - operand = & v850_operands[ * opindex_ptr ]; - } - else - { - operand = & v850_operands[ next_opindex ]; - next_opindex = 0; - } - - errmsg = NULL; - - while (*str == ' ' || *str == ',' || *str == '[' || *str == ']') - ++ str; - - if (operand->flags & V850_OPERAND_RELAX) - relaxable = 1; - - /* Gather the operand. */ - hold = input_line_pointer; - input_line_pointer = str; - - /* lo(), hi(), hi0(), etc... */ - if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED) - { - /* This is a fake reloc, used to indicate an error condition. */ - if (reloc == BFD_RELOC_64) - { - match = 1; - goto error; - } - - expression (& ex); - - if (ex.X_op == O_constant) - { - switch (reloc) - { - case BFD_RELOC_V850_ZDA_16_16_OFFSET: - /* To cope with "not1 7, zdaoff(0xfffff006)[r0]" - and the like. */ - /* Fall through. */ - - case BFD_RELOC_LO16: - { - /* Truncate, then sign extend the value. */ - ex.X_add_number = SEXT16 (ex.X_add_number); - break; - } - - case BFD_RELOC_HI16: - { - /* Truncate, then sign extend the value. */ - ex.X_add_number = SEXT16 (ex.X_add_number >> 16); - break; - } - - case BFD_RELOC_HI16_S: - { - /* Truncate, then sign extend the value. */ - int temp = (ex.X_add_number >> 16) & 0xffff; - - temp += (ex.X_add_number >> 15) & 1; - - ex.X_add_number = SEXT16 (temp); - break; - } - - - default: - fprintf (stderr, "reloc: %d\n", reloc); - as_bad ("AAARG -> unhandled constant reloc"); - break; - } - - insn = v850_insert_operand (insn, operand, ex.X_add_number, - (char *) NULL, 0, - copy_of_instruction); - } - else - { - - if (fc > MAX_INSN_FIXUPS) - as_fatal ("too many fixups"); - - fixups[ fc ].exp = ex; - fixups[ fc ].opindex = * opindex_ptr; - fixups[ fc ].reloc = reloc; - fc++; - } - } - else - { - errmsg = NULL; - - if ((operand->flags & V850_OPERAND_REG) != 0) - { - if (!register_name (& ex)) - { - errmsg = "invalid register name"; - } - else if ((operand->flags & V850_NOT_R0) - && ex.X_add_number == 0) - { - errmsg = "register r0 cannot be used here"; - - /* Force an error message to be generated by - skipping over any following potential matches - for this opcode. */ - opcode += 3; - } - } - else if ((operand->flags & V850_OPERAND_SRG) != 0) - { - if (!system_register_name (& ex, true - )) - { - errmsg = "invalid system register name"; - } - } - else if ((operand->flags & V850_OPERAND_EP) != 0) - { - char * start = input_line_pointer; - char c = get_symbol_end (); - - if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0) - { - /* Put things back the way we found them. */ - *input_line_pointer = c; - input_line_pointer = start; - errmsg = "expected EP register"; - goto error; - } - - *input_line_pointer = c; - str = input_line_pointer; - input_line_pointer = hold; - - while ( *str == ' ' || *str == ',' || *str == '[' - || *str == ']') - ++ str; - continue; - } - else if ((operand->flags & V850_OPERAND_CC) != 0) - { - if (!cc_name (& ex)) - { - errmsg = "invalid condition code name"; - } - } - else if (register_name (& ex) - && (operand->flags & V850_OPERAND_REG) == 0) - { - /* It is possible that an alias has been defined that - matches a register name. For example the code may - include a ".set ZERO, 0" directive, which matches - the register name "zero". Attempt to reparse the - field as an expression, and only complain if we - cannot generate a constant. */ - - input_line_pointer = str; - - expression (& ex); - - if (ex.X_op != O_constant) - { - /* If this register is actually occuring too early on - the parsing of the instruction, (because another - field is missing) then report this. */ - if (opindex_ptr[1] != 0 - && (v850_operands [opindex_ptr [1]].flags & V850_OPERAND_REG)) - errmsg = "syntax error: value is missing before the register name"; - else - errmsg = "syntax error: register not expected"; - } - } - else if (system_register_name (& ex, false - ) - && (operand->flags & V850_OPERAND_SRG) == 0) - { - 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"; - } - else - { - expression (& ex); - } - - if (errmsg) - goto error; - -/* fprintf (stderr, " insn: %x, operand %d, op: %d, add_number: %d\n", insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number); */ - - switch (ex.X_op) - { - case O_illegal: - errmsg = "illegal operand"; - goto error; - case O_absent: - errmsg = "missing operand"; - goto error; - case O_register: - if ((operand->flags & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0) - { - errmsg = "invalid operand"; - goto error; - } - insn = v850_insert_operand (insn, operand, ex.X_add_number, - (char *) 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); - break; - - default: - /* We need to generate a fixup for this expression. */ - if (fc >= MAX_INSN_FIXUPS) - as_fatal ("too many fixups"); - - fixups[ fc ].exp = ex; - fixups[ fc ].opindex = * opindex_ptr; - fixups[ fc ].reloc = BFD_RELOC_UNUSED; - ++fc; - break; - } - } - - str = input_line_pointer; - input_line_pointer = hold; - - while (*str == ' ' || *str == ',' || *str == '[' || *str == ']' - || *str == ')') - ++str; - } - match = 1; - - error: - if (match == 0) - { - next_opcode = opcode + 1; - if (next_opcode->name != NULL - && strcmp (next_opcode->name, opcode->name) == 0) - { - opcode = next_opcode; - - /* Skip versions that are not supported by the target - processor. */ - if ((opcode->processors & processor_mask) == 0) - goto error; - - continue; - } - - as_bad ("%s: %s", copy_of_instruction, errmsg); - - if (* input_line_pointer == ']') - ++ input_line_pointer; - - ignore_rest_of_line (); - input_line_pointer = saved_input_line_pointer; - return; - } - break; - } - - while (isspace (*str)) - ++str; - - if (*str != '\0') - as_bad ("junk at end of line: `%s'", str); - - input_line_pointer = str; - - /* Write out the instruction. */ - - if (relaxable && fc > 0) - { - insn_size = 2; - fc = 0; - - if (!strcmp (opcode->name, "br")) - { - f = frag_var (rs_machine_dependent, 4, 2, 2, - fixups[0].exp.X_add_symbol, - fixups[0].exp.X_add_number, - (char *)fixups[0].opindex); - md_number_to_chars (f, insn, insn_size); - md_number_to_chars (f + 2, 0, 2); - } - else - { - f = frag_var (rs_machine_dependent, 6, 4, 0, - fixups[0].exp.X_add_symbol, - fixups[0].exp.X_add_number, - (char *)fixups[0].opindex); - md_number_to_chars (f, insn, insn_size); - md_number_to_chars (f + 2, 0, 4); - } - } - else - { - /* Four byte insns have an opcode with the two high bits on. */ - if ((insn & 0x0600) == 0x0600) - insn_size = 4; - else - insn_size = 2; - - - f = frag_more (insn_size); - - md_number_to_chars (f, insn, insn_size); - - if (extra_data_after_insn) - { - f = frag_more (extra_data_len); - - md_number_to_chars (f, extra_data, extra_data_len); - - extra_data_after_insn = false; - } - } - - /* Create any fixups. At this point we do not use a - bfd_reloc_code_real_type, but instead just use the - BFD_RELOC_UNUSED plus 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_fix. */ - for (i = 0; i < fc; i++) - { - const struct v850_operand * operand; - bfd_reloc_code_real_type reloc; - - operand = & v850_operands[ fixups[i].opindex ]; - - reloc = fixups[i].reloc; - - if (reloc != BFD_RELOC_UNUSED) - { - reloc_howto_type * reloc_howto = bfd_reloc_type_lookup (stdoutput, - reloc); - int size; - int address; - fixS * fixP; - - if (!reloc_howto) - abort(); - - size = bfd_get_reloc_size (reloc_howto); - - /* XXX This will abort on an R_V850_8 reloc - - is this reloc actually used ? */ - if (size != 2 && size != 4) - abort(); - - address = (f - frag_now->fr_literal) + insn_size - size; - - if (reloc == BFD_RELOC_32) - { - address += 2; - } - - fixP = fix_new_exp (frag_now, address, size, - & fixups[i].exp, - reloc_howto->pc_relative, - reloc); - - switch (reloc) - { - case BFD_RELOC_LO16: - case BFD_RELOC_HI16: - case BFD_RELOC_HI16_S: - fixP->fx_no_overflow = 1; - break; - } - } - else - { - fix_new_exp ( - frag_now, - f - frag_now->fr_literal, 4, - & fixups[i].exp, - 1 /* FIXME: V850_OPERAND_RELATIVE ??? */, - (bfd_reloc_code_real_type) (fixups[i].opindex - + (int) BFD_RELOC_UNUSED) - ); - } - } - - input_line_pointer = saved_input_line_pointer; -} - - -/* 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; - fixS * fixp; -{ - arelent * reloc; - - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = & fixp->fx_addsy->bsym; - 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); - - xfree (reloc); - - return NULL; - } - - reloc->addend = fixp->fx_addnumber; - - return reloc; -} - -/* Assume everything will fit in two bytes, then expand as necessary. */ -int -md_estimate_size_before_relax (fragp, seg) - fragS * fragp; - asection * seg; -{ - if (fragp->fr_subtype == 0) - fragp->fr_var = 4; - else if (fragp->fr_subtype == 2) - fragp->fr_var = 2; - else - abort (); - return 2; -} - -long -md_pcrel_from (fixp) - fixS * fixp; -{ - /* If the symbol is undefined, or in a section other than our own, - then let the linker figure it out. */ - if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy)) - { - /* The symbol is undefined. Let the linker figure it out. */ - return 0; - } - return fixp->fx_frag->fr_address + fixp->fx_where; -} - -int -md_apply_fix3 (fixp, valuep, seg) - fixS * fixp; - valueT * valuep; - segT seg; -{ - valueT value; - char * where; - - if (fixp->fx_addsy == (symbolS *) NULL) - { - value = * valuep; - fixp->fx_done = 1; - } - else if (fixp->fx_pcrel) - value = * valuep; - else - { - value = fixp->fx_offset; - if (fixp->fx_subsy != (symbolS *) NULL) - { - 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"); - } - } - } - - if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED) - { - int opindex; - const struct v850_operand * operand; - unsigned long insn; - - opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED; - operand = & v850_operands[ opindex ]; - - /* Fetch the instruction, insert the fully resolved operand - value, and stuff the instruction back again. - - Note the instruction has been stored in little endian - format! */ - where = fixp->fx_frag->fr_literal + fixp->fx_where; - - insn = bfd_getl32 ((unsigned char *) where); - insn = v850_insert_operand (insn, operand, (offsetT) value, - fixp->fx_file, fixp->fx_line, NULL); - bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); - - if (fixp->fx_done) - { - /* Nothing else to do here. */ - return 1; - } - - /* Determine a BFD reloc value based on the operand information. - We are only prepared to turn a few of the operands into relocs. */ - - if (operand->bits == 22) - fixp->fx_r_type = BFD_RELOC_V850_22_PCREL; - else if (operand->bits == 9) - fixp->fx_r_type = BFD_RELOC_V850_9_PCREL; - else - { - /* fprintf (stderr, "bits: %d, insn: %x\n", operand->bits, insn); */ - - as_bad_where(fixp->fx_file, fixp->fx_line, - "unresolved expression that must be resolved"); - fixp->fx_done = 1; - return 1; - } - } - else if (fixp->fx_done) - { - /* We still have to insert the value into memory! */ - where = fixp->fx_frag->fr_literal + fixp->fx_where; - - if (fixp->fx_size == 1) - *where = value & 0xff; - else if (fixp->fx_size == 2) - bfd_putl16 (value & 0xffff, (unsigned char *) where); - else if (fixp->fx_size == 4) - bfd_putl32 (value, (unsigned char *) where); - } - - fixp->fx_addnumber = value; - return 1; -} - - -/* Parse a cons expression. We have to handle hi(), lo(), etc - on the v850. */ -void -parse_cons_expression_v850 (exp) - expressionS *exp; -{ - /* See if there's a reloc prefix like hi() we have to handle. */ - hold_cons_reloc = v850_reloc_prefix (NULL); - - /* Do normal expression parsing. */ - expression (exp); -} - -/* Create a fixup for a cons expression. If parse_cons_expression_v850 - found a reloc prefix, then we use that reloc, else we choose an - 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; -{ - if (hold_cons_reloc == BFD_RELOC_UNUSED) - { - if (size == 4) - hold_cons_reloc = BFD_RELOC_32; - if (size == 2) - hold_cons_reloc = BFD_RELOC_16; - if (size == 1) - hold_cons_reloc = BFD_RELOC_8; - } - - if (exp != NULL) - fix_new_exp (frag, where, size, exp, 0, hold_cons_reloc); - else - fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc); -} diff --git a/contrib/binutils/gas/config/tc-v850.h b/contrib/binutils/gas/config/tc-v850.h deleted file mode 100644 index f03136675445..000000000000 --- a/contrib/binutils/gas/config/tc-v850.h +++ /dev/null @@ -1,80 +0,0 @@ -/* tc-v850.h -- Header file for tc-v850.c. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. - - 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 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. */ - -#define TC_V850 - -#include <elf/v850.h> - -#define TARGET_BYTES_BIG_ENDIAN 0 - -#ifndef BFD_ASSEMBLER - #error V850 support requires BFD_ASSEMBLER -#endif - -/* The target BFD architecture. */ -#define TARGET_ARCH bfd_arch_v850 - -/* The target BFD format. */ -#define TARGET_FORMAT "elf32-v850" - - -#define MD_APPLY_FIX3 -#define md_operand(x) - -/* Permit temporary numeric labels. */ -#define LOCAL_LABELS_FB 1 - -#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ - -/* We don't need to handle .word strangely. */ -#define WORKING_DOT_WORD - -#define md_number_to_chars number_to_chars_littleendian - -/* 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) -#define TC_CONS_FIX_NEW cons_fix_new_v850 -extern const struct relax_type md_relax_table[]; -#define TC_GENERIC_RELAX_TABLE md_relax_table - - -/* This section must be in the small data area (pointed to by GP). */ -#define SHF_V850_GPREL 0x10000000 -/* This section must be in the tiny data area (pointed to by EP). */ -#define SHF_V850_EPREL 0x20000000 -/* This section must be in the zero data area (pointed to by R0). */ -#define SHF_V850_R0REL 0x40000000 - -#define ELF_TC_SPECIAL_SECTIONS \ - { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \ - { ".rosdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_GPREL }, \ - { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \ - { ".scommon", SHT_V850_SCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \ - { ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \ - { ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \ - { ".tcommon", SHT_V850_TCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \ - { ".zdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \ - { ".rozdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_R0REL }, \ - { ".zbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \ - { ".zcommon", SHT_V850_ZCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \ - { ".call_table_data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \ - { ".call_table_text", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR }, - diff --git a/contrib/binutils/gas/config/tc-z8k.c b/contrib/binutils/gas/config/tc-z8k.c deleted file mode 100644 index 909dd925343f..000000000000 --- a/contrib/binutils/gas/config/tc-z8k.c +++ /dev/null @@ -1,1613 +0,0 @@ -/* tc-z8k.c -- Assemble code for the Zilog Z800n - Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation. - - 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 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. */ - -/* - Written By Steve Chamberlain - sac@cygnus.com - */ -#define DEFINE_TABLE -#include <stdio.h> - -#include "opcodes/z8k-opc.h" - -#include "as.h" -#include "bfd.h" -#include <ctype.h> - -const char comment_chars[] = -{'!', 0}; -const char line_separator_chars[] = -{';', 0}; -const char line_comment_chars[] = -{'#', 0}; - -extern int machine; -extern int coff_flags; -int segmented_mode; -const int md_reloc_size; - -/* 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 - */ - -void cons (); - -void -s_segm () -{ - segmented_mode = 1; - machine = bfd_mach_z8001; - coff_flags = F_Z8001; -} - -void -s_unseg () -{ - segmented_mode = 0; - machine = bfd_mach_z8002; - coff_flags = F_Z8002; -} - -static -void -even () -{ - frag_align (1, 0, 0); - record_alignment (now_seg, 1); -} - -void obj_coff_section (); - -int -tohex (c) - int c; -{ - if (isdigit (c)) - return c - '0'; - if (islower (c)) - return c - 'a' + 10; - return c - 'A' + 10; -} - -void -sval () -{ - - SKIP_WHITESPACE (); - if (*input_line_pointer == '\'') - { - int c; - input_line_pointer++; - c = *input_line_pointer++; - while (c != '\'') - { - if (c == '%') - { - c = (tohex (input_line_pointer[0]) << 4) - | tohex (input_line_pointer[1]); - input_line_pointer += 2; - } - FRAG_APPEND_1_CHAR (c); - c = *input_line_pointer++; - } - demand_empty_rest_of_line (); - } - -} -const pseudo_typeS md_pseudo_table[] = -{ - {"int", cons, 2}, - {"data.b", cons, 1}, - {"data.w", cons, 2}, - {"data.l", cons, 4}, - {"form", listing_psize, 0}, - {"heading", listing_title, 0}, - {"import", s_ignore, 0}, - {"page", listing_eject, 0}, - {"program", s_ignore, 0}, - {"z8001", s_segm, 0}, - {"z8002", s_unseg, 0}, - - - {"segm", s_segm, 0}, - {"unsegm", s_unseg, 0}, - {"unseg", s_unseg, 0}, - {"name", s_app_file, 0}, - {"global", s_globl, 0}, - {"wval", cons, 2}, - {"lval", cons, 4}, - {"bval", cons, 1}, - {"sval", sval, 0}, - {"rsect", obj_coff_section, 0}, - {"sect", obj_coff_section, 0}, - {"block", s_space, 0}, - {"even", even, 0}, - {0, 0, 0} -}; - -const char EXP_CHARS[] = "eE"; - -/* Chars that mean this number is a floating point constant */ -/* As in 0f12.456 */ -/* or 0d1.2345e12 */ -const char FLT_CHARS[] = "rRsSfFdDxXpP"; - -static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ - -void -md_begin () -{ - opcode_entry_type *opcode; - char *prev_name = ""; - int idx = 0; - - opcode_hash_control = hash_new (); - - for (opcode = z8k_table; opcode->name; opcode++) - { - /* Only enter unique codes into the table */ - char *src = opcode->name; - - if (strcmp (opcode->name, prev_name)) - { - hash_insert (opcode_hash_control, opcode->name, (char *) opcode); - idx++; - } - opcode->idx = idx; - prev_name = opcode->name; - } - - /* default to z8002 */ - s_unseg (); - - /* insert the pseudo ops too */ - for (idx = 0; md_pseudo_table[idx].poc_name; idx++) - { - opcode_entry_type *fake_opcode; - fake_opcode = (opcode_entry_type *) malloc (sizeof (opcode_entry_type)); - fake_opcode->name = md_pseudo_table[idx].poc_name, - fake_opcode->func = (void *) (md_pseudo_table + idx); - fake_opcode->opcode = 250; - hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode); - } - - linkrelax = 1; -} - -struct z8k_exp -{ - char *e_beg; - char *e_end; - expressionS e_exp; -}; -typedef struct z8k_op -{ - char regsize; /* 'b','w','r','q' */ - unsigned int reg; /* 0..15 */ - - int mode; - - unsigned int x_reg; /* any other register associated with the mode */ - expressionS exp; /* any expression */ -} - -op_type; - -static expressionS *da_operand; -static expressionS *imm_operand; - -int reg[16]; -int the_cc; -int the_ctrl; -int the_flags; -int the_interrupt; - -char * -DEFUN (whatreg, (reg, src), - int *reg AND - char *src) -{ - if (isdigit (src[1])) - { - *reg = (src[0] - '0') * 10 + src[1] - '0'; - return src + 2; - } - else - { - *reg = (src[0] - '0'); - return src + 1; - } -} - -/* - parse operands - - rh0-rh7, rl0-rl7 - r0-r15 - rr0-rr14 - rq0--rq12 - WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp - r0l,r0h,..r7l,r7h - @WREG - @WREG+ - @-WREG - #const - - */ - -/* try and parse a reg name, returns number of chars consumed */ -char * -DEFUN (parse_reg, (src, mode, reg), - char *src AND - int *mode AND - unsigned int *reg) -{ - char *res = 0; - char regno; - - if (src[0] == 's' && src[1] == 'p') - { - if (segmented_mode) - { - *mode = CLASS_REG_LONG; - *reg = 14; - } - else - { - *mode = CLASS_REG_WORD; - *reg = 15; - } - return src + 2; - } - if (src[0] == 'r') - { - if (src[1] == 'r') - { - *mode = CLASS_REG_LONG; - res = whatreg (reg, src + 2); - regno = *reg; - if (regno > 14) - as_warn ("register rr%d, out of range.",regno); - } - else if (src[1] == 'h') - { - *mode = CLASS_REG_BYTE; - res = whatreg (reg, src + 2); - regno = *reg; - if (regno > 7) - as_warn ("register rh%d, out of range.",regno); - } - else if (src[1] == 'l') - { - *mode = CLASS_REG_BYTE; - res = whatreg (reg, src + 2); - regno = *reg; - if (regno > 7) - as_warn ("register rl%d, out of range.",regno); - *reg += 8; - } - else if (src[1] == 'q') - { - *mode = CLASS_REG_QUAD; - res = whatreg (reg, src + 2); - regno = *reg; - if (regno > 12) - as_warn ("register rq%d, out of range.",regno); - } - else - { - *mode = CLASS_REG_WORD; - res = whatreg (reg, src + 1); - regno = *reg; - if (regno > 15) - as_warn ("register r%d, out of range.",regno); - } - } - return res; - -} - -char * -DEFUN (parse_exp, (s, op), - char *s AND - expressionS * op) -{ - char *save = input_line_pointer; - char *new; - - input_line_pointer = s; - expression (op); - if (op->X_op == O_absent) - as_bad ("missing operand"); - new = input_line_pointer; - input_line_pointer = save; - return new; -} - -/* The many forms of operand: - - <rb> - <r> - <rr> - <rq> - @r - #exp - exp - exp(r) - r(#exp) - r(r) - - - - */ - -static -char * -DEFUN (checkfor, (ptr, what), - char *ptr AND - char what) -{ - if (*ptr == what) - ptr++; - else - { - as_bad ("expected %c", what); - } - return ptr; -} - -/* Make sure the mode supplied is the size of a word */ -static void -DEFUN (regword, (mode, string), - int mode AND - char *string) -{ - int ok; - - ok = CLASS_REG_WORD; - if (ok != mode) - { - as_bad ("register is wrong size for a word %s", string); - } -} - -/* Make sure the mode supplied is the size of an address */ -static void -DEFUN (regaddr, (mode, string), - int mode AND - char *string) -{ - int ok; - - ok = segmented_mode ? CLASS_REG_LONG : CLASS_REG_WORD; - if (ok != mode) - { - as_bad ("register is wrong size for address %s", string); - } -} - -struct ctrl_names -{ - int value; - char *name; -}; - -struct ctrl_names ctrl_table[] = -{ - 0x2, "fcw", - 0X3, "refresh", - 0x4, "psapseg", - 0x5, "psapoff", - 0x5, "psap", - 0x6, "nspseg", - 0x7, "nspoff", - 0x7, "nsp", - 0, 0 -}; - -static void -DEFUN (get_ctrl_operand, (ptr, mode, dst), - char **ptr AND - struct z8k_op *mode AND - unsigned int dst) -{ - char *src = *ptr; - int r; - int i; - - while (*src == ' ') - src++; - - mode->mode = CLASS_CTRL; - for (i = 0; ctrl_table[i].name; i++) - { - int j; - - for (j = 0; ctrl_table[i].name[j]; j++) - { - if (ctrl_table[i].name[j] != src[j]) - goto fail; - } - the_ctrl = ctrl_table[i].value; - *ptr = src + j; - return; - fail:; - } - the_ctrl = 0; - return; -} - -struct flag_names -{ - int value; - char *name; - -}; - -struct flag_names flag_table[] = -{ - 0x1, "p", - 0x1, "v", - 0x2, "s", - 0x4, "z", - 0x8, "c", - 0x0, "+", - 0, 0 -}; - -static void -DEFUN (get_flags_operand, (ptr, mode, dst), - char **ptr AND - struct z8k_op *mode AND - unsigned int dst) -{ - char *src = *ptr; - int r; - int i; - int j; - - while (*src == ' ') - src++; - - mode->mode = CLASS_FLAGS; - the_flags = 0; - for (j = 0; j <= 9; j++) - { - if (!src[j]) - goto done; - for (i = 0; flag_table[i].name; i++) - { - if (flag_table[i].name[0] == src[j]) - { - the_flags = the_flags | flag_table[i].value; - goto match; - } - } - goto done; - match: - ; - } - done: - *ptr = src + j; - return; -} - - -struct interrupt_names -{ - int value; - char *name; - -}; - -struct interrupt_names intr_table[] = -{ - 0x1, "nvi", - 0x2, "vi", - 0x3, "both", - 0x3, "all", - 0, 0 -}; - -static void -DEFUN (get_interrupt_operand, (ptr, mode, dst), - char **ptr AND - struct z8k_op *mode AND - unsigned int dst) -{ - char *src = *ptr; - int r; - int i; - - while (*src == ' ') - src++; - - mode->mode = CLASS_IMM; - for (i = 0; intr_table[i].name; i++) - { - int j; - - for (j = 0; intr_table[i].name[j]; j++) - { - if (intr_table[i].name[j] != src[j]) - goto fail; - } - the_interrupt = intr_table[i].value; - *ptr = src + j; - return; - fail:; - } - the_interrupt = 0x0; - return; -} - -struct cc_names -{ - int value; - char *name; - -}; - -struct cc_names table[] = -{ - 0x0, "f", - 0x1, "lt", - 0x2, "le", - 0x3, "ule", - 0x4, "ov", - 0x4, "pe", - 0x5, "mi", - 0x6, "eq", - 0x6, "z", - 0x7, "c", - 0x7, "ult", - 0x8, "t", - 0x9, "ge", - 0xa, "gt", - 0xb, "ugt", - 0xc, "nov", - 0xc, "po", - 0xd, "pl", - 0xe, "ne", - 0xe, "nz", - 0xf, "nc", - 0xf, "uge", - 0, 0 -}; - -static void -DEFUN (get_cc_operand, (ptr, mode, dst), - char **ptr AND - struct z8k_op *mode AND - unsigned int dst) -{ - char *src = *ptr; - int r; - int i; - - while (*src == ' ') - src++; - - mode->mode = CLASS_CC; - for (i = 0; table[i].name; i++) - { - int j; - - for (j = 0; table[i].name[j]; j++) - { - if (table[i].name[j] != src[j]) - goto fail; - } - the_cc = table[i].value; - *ptr = src + j; - return; - fail:; - } - the_cc = 0x8; -} - -static void -get_operand (ptr, mode, dst) - char **ptr; - struct z8k_op *mode; - unsigned int dst; -{ - char *src = *ptr; - char *end; - unsigned int num; - unsigned int len; - unsigned int size; - - mode->mode = 0; - - while (*src == ' ') - src++; - if (*src == '#') - { - mode->mode = CLASS_IMM; - imm_operand = &(mode->exp); - src = parse_exp (src + 1, &(mode->exp)); - } - else if (*src == '@') - { - int d; - - mode->mode = CLASS_IR; - src = parse_reg (src + 1, &d, &mode->reg); - } - else - { - int regn; - - end = parse_reg (src, &mode->mode, ®n); - - if (end) - { - int nw, nr; - - src = end; - if (*src == '(') - { - src++; - end = parse_reg (src, &nw, &nr); - if (end) - { - /* Got Ra(Rb) */ - src = end; - - if (*src != ')') - { - as_bad ("Missing ) in ra(rb)"); - } - else - { - src++; - } - - regaddr (mode->mode, "ra(rb) ra"); -/* regword (mode->mode, "ra(rb) rb");*/ - mode->mode = CLASS_BX; - mode->reg = regn; - mode->x_reg = nr; - reg[ARG_RX] = nr; - } - else - { - /* Got Ra(disp) */ - if (*src == '#') - src++; - src = parse_exp (src, &(mode->exp)); - src = checkfor (src, ')'); - mode->mode = CLASS_BA; - mode->reg = regn; - mode->x_reg = 0; - imm_operand = &(mode->exp); - } - } - else - { - mode->reg = regn; - mode->x_reg = 0; - } - } - else - { - /* No initial reg */ - src = parse_exp (src, &(mode->exp)); - if (*src == '(') - { - src++; - end = parse_reg (src, &(mode->mode), ®n); - regword (mode->mode, "addr(Ra) ra"); - mode->mode = CLASS_X; - mode->reg = regn; - mode->x_reg = 0; - da_operand = &(mode->exp); - src = checkfor (end, ')'); - } - else - { - /* Just an address */ - mode->mode = CLASS_DA; - mode->reg = 0; - mode->x_reg = 0; - da_operand = &(mode->exp); - } - } - } - *ptr = src; -} - -static -char * -get_operands (opcode, op_end, operand) - opcode_entry_type *opcode; - char *op_end; - op_type *operand; -{ - char *ptr = op_end; -char *savptr; - switch (opcode->noperands) - { - case 0: - operand[0].mode = 0; - operand[1].mode = 0; - break; - - case 1: - ptr++; - if (opcode->arg_info[0] == CLASS_CC) - { - get_cc_operand (&ptr, operand + 0, 0); - } - else if (opcode->arg_info[0] == CLASS_FLAGS) - { - get_flags_operand (&ptr, operand + 0, 0); - } - else if (opcode->arg_info[0] == (CLASS_IMM +(ARG_IMM2))) - { - get_interrupt_operand (&ptr, operand + 0, 0); - } - else - { - get_operand (&ptr, operand + 0, 0); - } - operand[1].mode = 0; - break; - - case 2: - ptr++; - savptr = ptr; - if (opcode->arg_info[0] == CLASS_CC) - { - get_cc_operand (&ptr, operand + 0, 0); - } - else if (opcode->arg_info[0] == CLASS_CTRL) - { - get_ctrl_operand (&ptr, operand + 0, 0); - if (the_ctrl == 0) - { - ptr = savptr; - get_operand (&ptr, operand + 0, 0); - if (ptr == 0) - return; - if (*ptr == ',') - ptr++; - get_ctrl_operand (&ptr, operand + 1, 1); - return ptr; - } - } - else - { - get_operand (&ptr, operand + 0, 0); - } - if (ptr == 0) - return; - if (*ptr == ',') - ptr++; - get_operand (&ptr, operand + 1, 1); - break; - - case 3: - ptr++; - get_operand (&ptr, operand + 0, 0); - if (*ptr == ',') - ptr++; - get_operand (&ptr, operand + 1, 1); - if (*ptr == ',') - ptr++; - get_operand (&ptr, operand + 2, 2); - break; - - case 4: - ptr++; - get_operand (&ptr, operand + 0, 0); - if (*ptr == ',') - ptr++; - get_operand (&ptr, operand + 1, 1); - if (*ptr == ',') - ptr++; - get_operand (&ptr, operand + 2, 2); - if (*ptr == ',') - ptr++; - get_cc_operand (&ptr, operand + 3, 3); - break; - default: - abort (); - } - - return ptr; -} - -/* Passed a pointer to a list of opcodes which use different - addressing modes, return the opcode which matches the opcodes - provided - */ - -static -opcode_entry_type * -DEFUN (get_specific, (opcode, operands), - opcode_entry_type * opcode AND - op_type * operands) - -{ - opcode_entry_type *this_try = opcode; - int found = 0; - unsigned int noperands = opcode->noperands; - - unsigned int dispreg; - unsigned int this_index = opcode->idx; - - while (this_index == opcode->idx && !found) - { - unsigned int i; - - this_try = opcode++; - for (i = 0; i < noperands; i++) - { - int mode = operands[i].mode; - - if ((mode & CLASS_MASK) != (this_try->arg_info[i] & CLASS_MASK)) - { - /* it could be an pc rel operand, if this is a da mode and - we like disps, then insert it */ - - if (mode == CLASS_DA && this_try->arg_info[i] == CLASS_DISP) - { - /* This is the case */ - operands[i].mode = CLASS_DISP; - } - else if (mode == CLASS_BA && this_try->arg_info[i]) - { - /* Can't think of a way to turn what we've been given into - something that's ok */ - goto fail; - } - else if (this_try->arg_info[i] & CLASS_PR) - { - if (mode == CLASS_REG_LONG && segmented_mode) - { - /* ok */ - } - else if (mode == CLASS_REG_WORD && !segmented_mode) - { - /* ok */ - } - else - goto fail; - } - else - goto fail; - } - switch (mode & CLASS_MASK) - { - default: - break; - case CLASS_X: - case CLASS_IR: - case CLASS_BA: - case CLASS_BX: - case CLASS_DISP: - case CLASS_REG: - case CLASS_REG_WORD: - case CLASS_REG_BYTE: - case CLASS_REG_QUAD: - case CLASS_REG_LONG: - case CLASS_REGN0: - reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg; - break; - } - } - - found = 1; - fail:; - } - if (found) - return this_try; - else - return 0; -} - -static void -DEFUN (check_operand, (operand, width, string), - struct z8k_op *operand AND - unsigned int width AND - char *string) -{ - if (operand->exp.X_add_symbol == 0 - && operand->exp.X_op_symbol == 0) - { - - /* No symbol involved, let's look at offset, it's dangerous if any of - the high bits are not 0 or ff's, find out by oring or anding with - the width and seeing if the answer is 0 or all fs*/ - if ((operand->exp.X_add_number & ~width) != 0 && - (operand->exp.X_add_number | width) != (~0)) - { - as_warn ("operand %s0x%x out of range.", string, operand->exp.X_add_number); - } - } - -} - -static char buffer[20]; - -static void -DEFUN (newfix, (ptr, type, operand), - int ptr AND - int type AND - expressionS * operand) -{ - if (operand->X_add_symbol - || operand->X_op_symbol - || operand->X_add_number) - { - fix_new_exp (frag_now, - ptr, - 1, - operand, - 0, - type); - } -} - -static char * -DEFUN (apply_fix, (ptr, type, operand, size), - char *ptr AND - int type AND - expressionS * operand AND - int size) -{ - int n = operand->X_add_number; - - operand->X_add_number = n; - newfix ((ptr - buffer) / 2, type, operand); -#if 1 - switch (size) - { - case 8: /* 8 nibbles == 32 bits */ - *ptr++ = n >> 28; - *ptr++ = n >> 24; - *ptr++ = n >> 20; - *ptr++ = n >> 16; - case 4: /* 4 niblles == 16 bits */ - *ptr++ = n >> 12; - *ptr++ = n >> 8; - case 2: - *ptr++ = n >> 4; - case 1: - *ptr++ = n >> 0; - break; - } -#endif - return ptr; - -} - -/* Now we know what sort of opcodes it is, lets build the bytes - - */ -#define INSERT(x,y) *x++ = y>>24; *x++ = y>> 16; *x++=y>>8; *x++ =y; -static void -build_bytes (this_try, operand) - opcode_entry_type * this_try; - struct z8k_op *operand; -{ - unsigned int i; - - int length; - char *output; - char *output_ptr = buffer; - char part; - int c; - char high; - int nib; - int nibble; - unsigned int *class_ptr; - - frag_wane (frag_now); - frag_new (0); - - memset (buffer, 20, 0); - class_ptr = this_try->byte_info; -top:; - - for (nibble = 0; c = *class_ptr++; nibble++) - { - - switch (c & CLASS_MASK) - { - default: - - abort (); - case CLASS_ADDRESS: - /* Direct address, we don't cope with the SS mode right now */ - if (segmented_mode) - { - da_operand->X_add_number |= 0x80000000; - output_ptr = apply_fix (output_ptr, R_IMM32, da_operand, 8); - } - else - { - output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4); - } - da_operand = 0; - break; - case CLASS_DISP8: - /* pc rel 8 bit */ - output_ptr = apply_fix (output_ptr, R_JR, da_operand, 2); - da_operand = 0; - break; - - case CLASS_0DISP7: - /* pc rel 7 bit */ - *output_ptr = 0; - output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2); - da_operand = 0; - break; - - case CLASS_1DISP7: - /* pc rel 7 bit */ - *output_ptr = 0x80; - output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2); - output_ptr[-2] = 0x8; - da_operand = 0; - break; - - case CLASS_BIT_1OR2: - *output_ptr = c & 0xf; - if (imm_operand) - { - if (imm_operand->X_add_number == 2) - { - *output_ptr |= 2; - } - else if (imm_operand->X_add_number != 1) - { - as_bad ("immediate must be 1 or 2"); - } - } - else - { - as_bad ("immediate 1 or 2 expected"); - } - output_ptr++; - break; - case CLASS_CC: - *output_ptr++ = the_cc; - break; - case CLASS_0CCC: - *output_ptr++ = the_ctrl; - break; - case CLASS_1CCC: - *output_ptr++ = the_ctrl | 0x8; - break; - case CLASS_00II: - *output_ptr++ = (~the_interrupt & 0x3); - break; - case CLASS_01II: - *output_ptr++ = (~the_interrupt & 0x3) | 0x4; - break; - case CLASS_FLAGS: - *output_ptr++ = the_flags; - break; - case CLASS_BIT: - *output_ptr++ = c & 0xf; - break; - case CLASS_REGN0: - if (reg[c & 0xf] == 0) - { - as_bad ("can't use R0 here"); - } - case CLASS_REG: - case CLASS_REG_BYTE: - case CLASS_REG_WORD: - case CLASS_REG_LONG: - case CLASS_REG_QUAD: - /* Insert bit mattern of - right reg */ - *output_ptr++ = reg[c & 0xf]; - break; - case CLASS_DISP: - output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4); - da_operand = 0; - break; - - case CLASS_IMM: - { - nib = 0; - switch (c & ARG_MASK) - { - case ARG_IMM4: - output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); - break; - case ARG_IMM4M1: - imm_operand->X_add_number--; - output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); - break; - case ARG_IMMNMINUS1: - imm_operand->X_add_number--; - output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); - break; - case ARG_NIM8: - imm_operand->X_add_number = -imm_operand->X_add_number; - case ARG_IMM8: - output_ptr = apply_fix (output_ptr, R_IMM8, imm_operand, 2); - break; - case ARG_IMM16: - output_ptr = apply_fix (output_ptr, R_IMM16, imm_operand, 4); - break; - - case ARG_IMM32: - output_ptr = apply_fix (output_ptr, R_IMM32, imm_operand, 8); - break; - - default: - abort (); - } - } - } - } - - /* Copy from the nibble buffer into the frag */ - - { - int length = (output_ptr - buffer) / 2; - char *src = buffer; - char *fragp = frag_more (length); - - while (src < output_ptr) - { - *fragp = (src[0] << 4) | src[1]; - src += 2; - fragp++; - } - - } - -} - -/* This is the guts of the machine-dependent assembler. STR points to a - machine dependent instruction. This funciton is supposed to emit - the frags/bytes it assembles to. - */ - -void -DEFUN (md_assemble, (str), - char *str) -{ - char *op_start; - char *op_end; - unsigned int i; - struct z8k_op operand[3]; - opcode_entry_type *opcode; - opcode_entry_type *prev_opcode; - - char *dot = 0; - char c; - - /* Drop leading whitespace */ - while (*str == ' ') - str++; - - /* find the op code end */ - for (op_start = op_end = str; - *op_end != 0 && *op_end != ' '; - op_end++) - { - } - - ; - - if (op_end == op_start) - { - as_bad ("can't find opcode "); - } - c = *op_end; - - *op_end = 0; - - opcode = (opcode_entry_type *) hash_find (opcode_hash_control, - op_start); - - - if (opcode == NULL) - { - as_bad ("unknown opcode"); - return; - } - - if (opcode->opcode == 250) - { - /* was really a pseudo op */ - - pseudo_typeS *p; - char oc; - - char *old = input_line_pointer; - *op_end = c; - - - input_line_pointer = op_end; - - oc = *old; - *old = '\n'; - while (*input_line_pointer == ' ') - input_line_pointer++; - p = (pseudo_typeS *) (opcode->func); - - (p->poc_handler) (p->poc_val); - input_line_pointer = old; - *old = oc; - } - else - { - input_line_pointer = get_operands (opcode, op_end, - operand); - prev_opcode = opcode; - - opcode = get_specific (opcode, operand); - - if (opcode == 0) - { - /* Couldn't find an opcode which matched the operands */ - char *where = frag_more (2); - - where[0] = 0x0; - where[1] = 0x0; - - as_bad ("Can't find opcode to match operands"); - return; - } - - build_bytes (opcode, operand); - } -} - -void -DEFUN (tc_crawl_symbol_chain, (headers), - object_headers * headers) -{ - printf ("call to tc_crawl_symbol_chain \n"); -} - -symbolS * -DEFUN (md_undefined_symbol, (name), - char *name) -{ - return 0; -} - -void -DEFUN (tc_headers_hook, (headers), - object_headers * headers) -{ - printf ("call to tc_headers_hook \n"); -} - -/* Various routines to kill one day */ -/* 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. - */ -char * -md_atof (type, litP, sizeP) - char type; - char *litP; - int *sizeP; -{ - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - char *atof_ieee (); - - switch (type) - { - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - 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--;) - { - md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - return 0; -} - -CONST char *md_shortopts = "z:"; -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; -{ - switch (c) - { - case 'z': - if (!strcmp (arg, "8001")) - s_segm (); - else if (!strcmp (arg, "8002")) - s_unseg (); - else - { - as_bad ("invalid architecture -z%s", arg); - return 0; - } - break; - - default: - return 0; - } - - return 1; -} - -void -md_show_usage (stream) - FILE *stream; -{ - fprintf(stream, "\ -Z8K options:\n\ --z8001 generate segmented code\n\ --z8002 generate unsegmented code\n"); -} - -int md_short_jump_size; - -void -tc_aout_fix_to_chars () -{ - printf ("call to tc_aout_fix_to_chars \n"); - abort (); -} - -void -md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) - char *ptr; - addressT from_addr; - addressT to_addr; - fragS *frag; - symbolS *to_symbol; -{ - as_fatal ("failed sanity check."); -} - -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; -{ - as_fatal ("failed sanity check."); -} - -void -md_convert_frag (headers, seg, fragP) - object_headers *headers; - segT seg; - fragS *fragP; -{ - printf ("call to md_convert_frag \n"); - abort (); -} - -valueT -DEFUN (md_section_align, (seg, size), - segT seg AND - valueT size) -{ - return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); - -} - -void -md_apply_fix (fixP, val) - fixS *fixP; - long val; -{ - char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; - - switch (fixP->fx_r_type) - { - case R_IMM4L: - buf[0] = (buf[0] & 0xf0) | ((buf[0] + val) & 0xf); - break; - - case R_JR: - - *buf++ = val; - /* if (val != 0) abort();*/ - break; - - case R_DISP7: - - *buf++ += val; - /* if (val != 0) abort();*/ - break; - - case R_IMM8: - buf[0] += val; - break; - case R_IMM16: - *buf++ = (val >> 8); - *buf++ = val; - break; - case R_IMM32: - *buf++ = (val >> 24); - *buf++ = (val >> 16); - *buf++ = (val >> 8); - *buf++ = val; - break; -#if 0 - case R_DA | R_SEG: - *buf++ = (val >> 16); - *buf++ = 0x00; - *buf++ = (val >> 8); - *buf++ = val; - break; -#endif - - case 0: - md_number_to_chars (buf, val, fixP->fx_size); - break; - - default: - abort (); - - } -} - -int md_long_jump_size; -int -md_estimate_size_before_relax (fragP, segment_type) - register fragS *fragP; - register segT segment_type; -{ - printf ("call tomd_estimate_size_before_relax \n"); - abort (); -} - -/* Put number into target byte order */ - -void -DEFUN (md_number_to_chars, (ptr, use, nbytes), - char *ptr AND - valueT use AND - int nbytes) -{ - number_to_chars_bigendian (ptr, use, nbytes); -} -long -md_pcrel_from (fixP) - fixS *fixP; -{ - abort (); -} - -void -tc_coff_symbol_emit_hook (s) - struct symbol *s; -{ -} - -void -tc_reloc_mangle (fix_ptr, intr, base) - fixS *fix_ptr; - struct internal_reloc *intr; - bfd_vma base; - -{ - symbolS *symbol_ptr; - - if (fix_ptr->fx_addsy && - fix_ptr->fx_subsy) - { - symbolS *add = fix_ptr->fx_addsy; - symbolS *sub = fix_ptr->fx_subsy; - if (S_GET_SEGMENT(add) != S_GET_SEGMENT(sub)) - { - as_bad("Can't subtract symbols in different sections %s %s", - S_GET_NAME(add), S_GET_NAME(sub)); - } - else { - int diff = S_GET_VALUE(add) - S_GET_VALUE(sub); - fix_ptr->fx_addsy = 0; - fix_ptr->fx_subsy = 0; - fix_ptr->fx_offset += diff; - } - } - symbol_ptr = fix_ptr->fx_addsy; - - /* If this relocation is attached to a symbol then it's ok - to output it */ - if (fix_ptr->fx_r_type == 0) - { - /* cons likes to create reloc32's whatever the size of the reloc.. */ - switch (fix_ptr->fx_size) - { - case 2: - intr->r_type = R_IMM16; - break; - case 1: - intr->r_type = R_IMM8; - break; - case 4: - intr->r_type = R_IMM32; - break; - default: - abort (); - } - - } - else - { - 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; - - if (symbol_ptr) - intr->r_symndx = symbol_ptr->sy_number; - else - intr->r_symndx = -1; -} - diff --git a/contrib/binutils/gas/config/tc-z8k.h b/contrib/binutils/gas/config/tc-z8k.h deleted file mode 100644 index 1a585026f215..000000000000 --- a/contrib/binutils/gas/config/tc-z8k.h +++ /dev/null @@ -1,46 +0,0 @@ -/* This file is tc-z8k.h - Copyright (C) 1987-1992, 93, 95, 1997 Free Software Foundation, Inc. - - 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 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. */ - - -#define TC_Z8K -#define TARGET_BYTES_BIG_ENDIAN 1 - -#ifndef BFD_ASSEMBLER -#define LOCAL_LABEL(x) 0 -#endif - -/* This macro translates between an internal fix and an coff reloc type */ -#define TC_COFF_FIX2RTYPE(fixP) abort(); - -#define BFD_ARCH bfd_arch_z8k -#define COFF_MAGIC 0x8000 -#define TC_COUNT_RELOC(x) (1) -#define IGNORE_NONSTANDARD_ESCAPES - -#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c) - -#define DO_NOT_STRIP 0 -#define LISTING_HEADER "Zilog Z8000 GAS " -#define NEED_FX_R_TYPE 1 -#define RELOC_32 1234 - -#define md_operand(x) - -/* end of tc-z8k.h */ diff --git a/contrib/binutils/gas/config/te-386bsd.h b/contrib/binutils/gas/config/te-386bsd.h deleted file mode 100644 index dbff99027eaf..000000000000 --- a/contrib/binutils/gas/config/te-386bsd.h +++ /dev/null @@ -1,31 +0,0 @@ -/* te-386bsd.h -- 386BSD target environment declarations. - Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc. - - 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 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. */ - -#define TE_386BSD 1 - -#include "obj-format.h" - -/* - * Local Variables: - * comment-column: 0 - * fill-column: 131 - * End: - */ - -/* end of te-sun3.h */ diff --git a/contrib/binutils/gas/config/te-aux.h b/contrib/binutils/gas/config/te-aux.h deleted file mode 100644 index da6fa0164cf1..000000000000 --- a/contrib/binutils/gas/config/te-aux.h +++ /dev/null @@ -1,17 +0,0 @@ -#define TE_AUX - -/* From obj-coff.h: - This internal_lineno crap is to stop namespace pollution from the - bfd internal coff headerfile. */ -#define internal_lineno bfd_internal_lineno -#include "coff/aux-coff.h" /* override bits in coff/internal.h */ -#undef internal_lineno - -#define COFF_NOLOAD_PROBLEM -#define KEEP_RELOC_INFO - -#include "obj-format.h" - -#ifndef LOCAL_LABELS_FB -#define LOCAL_LABELS_FB 1 -#endif diff --git a/contrib/binutils/gas/config/te-freebsd.h b/contrib/binutils/gas/config/te-freebsd.h deleted file mode 100644 index 13142359dcd7..000000000000 --- a/contrib/binutils/gas/config/te-freebsd.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Target environment for FreeBSD. It is the same as the generic - * target, except it arranges to suppress the use of "/" as a comment - * character. Some code in the FreeBSD kernel uses "/" to mean - * division. (What a concept.) - */ -#define TE_FreeBSD 1 -#include "te-generic.h" diff --git a/contrib/binutils/gas/config/te-generic.h b/contrib/binutils/gas/config/te-generic.h deleted file mode 100644 index b8eda4505fb7..000000000000 --- a/contrib/binutils/gas/config/te-generic.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is te-generic.h and is intended to be a template for - * target environment specific header files. - * - * It is my intent that this file will evolve into a file suitable for config, - * compile, and copying as an aid for testing and porting. xoxorich. - */ - -/* Added these, because if we don't know what we're targetting we may - need an assembler version of libgcc, and that will use local - labels. */ -#define LOCAL_LABELS_DOLLAR 1 -#define LOCAL_LABELS_FB 1 - -/* these define interfaces */ -#ifdef OBJ_HEADER -#include OBJ_HEADER -#else -#include "obj-format.h" -#endif - -/* end of te-generic.h */ diff --git a/contrib/binutils/gas/config/te-linux.h b/contrib/binutils/gas/config/te-linux.h deleted file mode 100644 index c235a7ab8a8a..000000000000 --- a/contrib/binutils/gas/config/te-linux.h +++ /dev/null @@ -1,4 +0,0 @@ -#define TE_LINUX -#define LOCAL_LABELS_FB 1 - -#include "obj-format.h" diff --git a/contrib/binutils/gas/config/te-multi.h b/contrib/binutils/gas/config/te-multi.h deleted file mode 100644 index b8eda4505fb7..000000000000 --- a/contrib/binutils/gas/config/te-multi.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is te-generic.h and is intended to be a template for - * target environment specific header files. - * - * It is my intent that this file will evolve into a file suitable for config, - * compile, and copying as an aid for testing and porting. xoxorich. - */ - -/* Added these, because if we don't know what we're targetting we may - need an assembler version of libgcc, and that will use local - labels. */ -#define LOCAL_LABELS_DOLLAR 1 -#define LOCAL_LABELS_FB 1 - -/* these define interfaces */ -#ifdef OBJ_HEADER -#include OBJ_HEADER -#else -#include "obj-format.h" -#endif - -/* end of te-generic.h */ diff --git a/contrib/binutils/gas/config/te-nbsd.h b/contrib/binutils/gas/config/te-nbsd.h deleted file mode 100644 index cee4600077b2..000000000000 --- a/contrib/binutils/gas/config/te-nbsd.h +++ /dev/null @@ -1,23 +0,0 @@ -/* te-nbsd.h -- NetBSD target environment declarations. - Copyright (C) 1987, 90, 91, 92, 94, 95, 1998 Free Software Foundation, Inc. - - 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 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. */ - -#define TE_NetBSD 1 -#define LOCAL_LABELS_FB 1 -#include "obj-format.h" diff --git a/contrib/binutils/gas/config/te-pe.h b/contrib/binutils/gas/config/te-pe.h deleted file mode 100644 index 1c1f0b27bc1d..000000000000 --- a/contrib/binutils/gas/config/te-pe.h +++ /dev/null @@ -1,7 +0,0 @@ -#define TE_PE -#define LEX_AT 1 /* can have @'s inside labels */ - -/* The PE format supports long section names. */ -#define COFF_LONG_SECTION_NAMES - -#include "obj-format.h" diff --git a/contrib/binutils/gas/config/te-svr4.h b/contrib/binutils/gas/config/te-svr4.h deleted file mode 100644 index 7217ee119e62..000000000000 --- a/contrib/binutils/gas/config/te-svr4.h +++ /dev/null @@ -1,4 +0,0 @@ -#define TE_SVR4 -#define LOCAL_LABELS_FB 1 - -#include "obj-format.h" diff --git a/contrib/binutils/gas/config/te-sysv32.h b/contrib/binutils/gas/config/te-sysv32.h deleted file mode 100644 index 923e6e5799f2..000000000000 --- a/contrib/binutils/gas/config/te-sysv32.h +++ /dev/null @@ -1,6 +0,0 @@ -/* Remove leading underscore from the gcc generated symbol names */ -#define STRIP_UNDERSCORE - -#include "obj-format.h" - -/* end of te-sysv32.h */ |