forked from KolibriOS/kolibrios
binutils: build AS.
git-svn-id: svn://kolibrios.org@5222 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
ecd34cd9d9
commit
5490489cbb
45
contrib/toolchain/binutils/gas/Makefile
Normal file
45
contrib/toolchain/binutils/gas/Makefile
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
LIB_DIR:= $(SDK_DIR)/lib
|
||||
|
||||
CFLAGS_OPT = -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -U_MSC_VER -O2
|
||||
CFLAGS_OPT+= -fomit-frame-pointer -fno-ident -mno-ms-bitfields
|
||||
CFLAGS_OPT+= -W -Wall -Wmissing-prototypes -Wno-format
|
||||
CFLAGS = -c $(CFLAGS_OPT)
|
||||
|
||||
INCLUDES= -I. -I../bfd -I./config -I../include -I../
|
||||
INCLUDES+= -I$(SDK_DIR)/sources/newlib/libc/include -I$(SDK_DIR)/sources/zlib
|
||||
|
||||
DEFINES= -DHAVE_CONFIG_H -DLOCALEDIR='"/home/autobuild/tools/win32/share/locale"'
|
||||
|
||||
LIBS= -lopcodes -lbfd -liberty -lz -lgcc -lc.dll -lapp
|
||||
|
||||
LIBPATH:= -L$(LIB_DIR) -L/home/autobuild/tools/win32/mingw32/lib
|
||||
|
||||
LDFLAGS = -static -nostdlib --stack 12582912 -T$(SDK_DIR)/sources/newlib/app.lds --image-base 0
|
||||
|
||||
|
||||
SRCS = \
|
||||
app.c as.c atof-generic.c compress-debug.c \
|
||||
cond.c depend.c dwarf2dbg.c dw2gencfi.c ecoff.c \
|
||||
ehopt.c expr.c flonum-copy.c flonum-konst.c \
|
||||
flonum-mult.c frags.c hash.c input-file.c \
|
||||
input-scrub.c listing.c literal.c macro.c \
|
||||
messages.c output-file.c read.c remap.c sb.c \
|
||||
stabs.c subsegs.c symbols.c write.c \
|
||||
config/atof-ieee.c config/obj-coff.c \
|
||||
config/tc-i386.c
|
||||
|
||||
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
|
||||
|
||||
# targets
|
||||
|
||||
all: as
|
||||
|
||||
as: $(OBJS) Makefile
|
||||
$(LD) $(LDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LIBS)
|
||||
kos32-objcopy $@ -O binary
|
||||
|
||||
%.o : %.c Makefile
|
||||
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
|
||||
|
||||
|
1473
contrib/toolchain/binutils/gas/app.c
Normal file
1473
contrib/toolchain/binutils/gas/app.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
contrib/toolchain/binutils/gas/as
Normal file
BIN
contrib/toolchain/binutils/gas/as
Normal file
Binary file not shown.
1326
contrib/toolchain/binutils/gas/as.c
Normal file
1326
contrib/toolchain/binutils/gas/as.c
Normal file
File diff suppressed because it is too large
Load Diff
634
contrib/toolchain/binutils/gas/as.h
Normal file
634
contrib/toolchain/binutils/gas/as.h
Normal file
@ -0,0 +1,634 @@
|
||||
/* as.h - global header file
|
||||
Copyright 1987-2013 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GAS
|
||||
#define GAS 1
|
||||
/* I think this stuff is largely out of date. xoxorich.
|
||||
|
||||
CAPITALISED names are #defined.
|
||||
"lowercaseH" is #defined if "lowercase.h" has been #include-d.
|
||||
"lowercaseT" is a typedef of "lowercase" objects.
|
||||
"lowercaseP" is type "pointer to object of type 'lowercase'".
|
||||
"lowercaseS" is typedef struct ... lowercaseS.
|
||||
|
||||
#define DEBUG to enable all the "know" assertion tests.
|
||||
#define SUSPECT when debugging hash code.
|
||||
#define COMMON as "extern" for all modules except one, where you #define
|
||||
COMMON as "".
|
||||
If TEST is #defined, then we are testing a module: #define COMMON as "". */
|
||||
|
||||
#include "alloca-conf.h"
|
||||
|
||||
/* Now, tend to the rest of the configuration. */
|
||||
|
||||
/* System include files first... */
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef STRING_WITH_STRINGS
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#else
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
/* for size_t, pid_t */
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "getopt.h"
|
||||
/* The first getopt value for machine-independent long options.
|
||||
150 isn't special; it's just an arbitrary non-ASCII char value. */
|
||||
#define OPTION_STD_BASE 150
|
||||
/* The first getopt value for machine-dependent long options.
|
||||
190 gives the standard options room to grow. */
|
||||
#define OPTION_MD_BASE 190
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
|
||||
#define __PRETTY_FUNCTION__ ((char *) NULL)
|
||||
#endif
|
||||
#define gas_assert(P) \
|
||||
((void) ((P) ? 0 : (as_assert (__FILE__, __LINE__, __PRETTY_FUNCTION__), 0)))
|
||||
#undef abort
|
||||
#define abort() as_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||||
|
||||
/* Now GNU header files... */
|
||||
#include "ansidecl.h"
|
||||
#include "bfd.h"
|
||||
#include "libiberty.h"
|
||||
|
||||
/* Define the standard progress macros. */
|
||||
#include "progress.h"
|
||||
|
||||
/* This doesn't get taken care of anywhere. */
|
||||
#ifndef __MWERKS__ /* Metrowerks C chokes on the "defined (inline)" */
|
||||
#if !defined (__GNUC__) && !defined (inline)
|
||||
#define inline
|
||||
#endif
|
||||
#endif /* !__MWERKS__ */
|
||||
|
||||
/* Other stuff from config.h. */
|
||||
#ifdef NEED_DECLARATION_ENVIRON
|
||||
extern char **environ;
|
||||
#endif
|
||||
#ifdef NEED_DECLARATION_ERRNO
|
||||
extern int errno;
|
||||
#endif
|
||||
#ifdef NEED_DECLARATION_FFS
|
||||
extern int ffs (int);
|
||||
#endif
|
||||
#ifdef NEED_DECLARATION_FREE
|
||||
extern void free ();
|
||||
#endif
|
||||
#ifdef NEED_DECLARATION_MALLOC
|
||||
extern void *malloc ();
|
||||
extern void *realloc ();
|
||||
#endif
|
||||
#ifdef NEED_DECLARATION_STRSTR
|
||||
extern char *strstr ();
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_MEMPCPY
|
||||
void *mempcpy(void *, const void *, size_t);
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_VSNPRINTF
|
||||
extern int vsnprintf(char *, size_t, const char *, va_list);
|
||||
#endif
|
||||
|
||||
/* This is needed for VMS. */
|
||||
#if ! defined (HAVE_UNLINK) && defined (HAVE_REMOVE)
|
||||
#define unlink remove
|
||||
#endif
|
||||
|
||||
/* Hack to make "gcc -Wall" not complain about obstack macros. */
|
||||
#if !defined (memcpy) && !defined (bcopy)
|
||||
#define bcopy(src,dest,size) memcpy (dest, src, size)
|
||||
#endif
|
||||
|
||||
/* Make Saber happier on obstack.h. */
|
||||
#ifdef SABER
|
||||
#undef __PTR_TO_INT
|
||||
#define __PTR_TO_INT(P) ((int) (P))
|
||||
#undef __INT_TO_PTR
|
||||
#define __INT_TO_PTR(P) ((char *) (P))
|
||||
#endif
|
||||
|
||||
#ifndef __LINE__
|
||||
#define __LINE__ "unknown"
|
||||
#endif /* __LINE__ */
|
||||
|
||||
#ifndef __FILE__
|
||||
#define __FILE__ "unknown"
|
||||
#endif /* __FILE__ */
|
||||
|
||||
#ifndef FOPEN_WB
|
||||
#ifdef USE_BINARY_FOPEN
|
||||
#include "fopen-bin.h"
|
||||
#else
|
||||
#include "fopen-same.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free xfree
|
||||
|
||||
#define xfree free
|
||||
|
||||
#include "asintl.h"
|
||||
|
||||
#define BAD_CASE(val) \
|
||||
{ \
|
||||
as_fatal (_("Case value %ld unexpected at line %d of file \"%s\"\n"), \
|
||||
(long) val, __LINE__, __FILE__); \
|
||||
}
|
||||
|
||||
#include "flonum.h"
|
||||
|
||||
/* These are assembler-wide concepts */
|
||||
|
||||
extern bfd *stdoutput;
|
||||
typedef bfd_vma addressT;
|
||||
typedef bfd_signed_vma offsetT;
|
||||
|
||||
/* Type of symbol value, etc. For use in prototypes. */
|
||||
typedef addressT valueT;
|
||||
|
||||
#ifndef COMMON
|
||||
#ifdef TEST
|
||||
#define COMMON /* Declare our COMMONs storage here. */
|
||||
#else
|
||||
#define COMMON extern /* Our commons live elsewhere. */
|
||||
#endif
|
||||
#endif
|
||||
/* COMMON now defined */
|
||||
|
||||
#ifndef ENABLE_CHECKING
|
||||
#define ENABLE_CHECKING 0
|
||||
#endif
|
||||
|
||||
#if ENABLE_CHECKING || defined (DEBUG)
|
||||
#ifndef know
|
||||
#define know(p) gas_assert(p) /* Verify our assumptions! */
|
||||
#endif /* not yet defined */
|
||||
#else
|
||||
#define know(p) do {} while (0) /* know() checks are no-op.ed */
|
||||
#endif
|
||||
|
||||
/* input_scrub.c */
|
||||
|
||||
/* Supplies sanitised buffers to read.c.
|
||||
Also understands printing line-number part of error messages. */
|
||||
|
||||
/* subsegs.c Sub-segments. Also, segment(=expression type)s.*/
|
||||
|
||||
typedef asection *segT;
|
||||
#define SEG_NORMAL(SEG) ( (SEG) != absolute_section \
|
||||
&& (SEG) != undefined_section \
|
||||
&& (SEG) != reg_section \
|
||||
&& (SEG) != expr_section)
|
||||
typedef int subsegT;
|
||||
|
||||
/* What subseg we are accessing now? */
|
||||
COMMON subsegT now_subseg;
|
||||
|
||||
/* Segment our instructions emit to. */
|
||||
COMMON segT now_seg;
|
||||
|
||||
#define segment_name(SEG) bfd_get_section_name (stdoutput, SEG)
|
||||
|
||||
extern segT reg_section, expr_section;
|
||||
/* Shouldn't these be eliminated someday? */
|
||||
extern segT text_section, data_section, bss_section;
|
||||
#define absolute_section bfd_abs_section_ptr
|
||||
#define undefined_section bfd_und_section_ptr
|
||||
|
||||
enum _relax_state
|
||||
{
|
||||
/* Dummy frag used by listing code. */
|
||||
rs_dummy = 0,
|
||||
|
||||
/* Variable chars to be repeated fr_offset times.
|
||||
Fr_symbol unused. Used with fr_offset == 0 for a
|
||||
constant length frag. */
|
||||
rs_fill,
|
||||
|
||||
/* Align. The fr_offset field holds the power of 2 to which to
|
||||
align. The fr_var field holds the number of characters in the
|
||||
fill pattern. The fr_subtype field holds the maximum number of
|
||||
bytes to skip when aligning, or 0 if there is no maximum. */
|
||||
rs_align,
|
||||
|
||||
/* Align code. The fr_offset field holds the power of 2 to which
|
||||
to align. This type is only generated by machine specific
|
||||
code, which is normally responsible for handling the fill
|
||||
pattern. The fr_subtype field holds the maximum number of
|
||||
bytes to skip when aligning, or 0 if there is no maximum. */
|
||||
rs_align_code,
|
||||
|
||||
/* Test for alignment. Like rs_align, but used by several targets
|
||||
to warn if data is not properly aligned. */
|
||||
rs_align_test,
|
||||
|
||||
/* Org: Fr_offset, fr_symbol: address. 1 variable char: fill
|
||||
character. */
|
||||
rs_org,
|
||||
|
||||
#ifndef WORKING_DOT_WORD
|
||||
/* JF: gunpoint */
|
||||
rs_broken_word,
|
||||
#endif
|
||||
|
||||
/* Machine specific relaxable (or similarly alterable) instruction. */
|
||||
rs_machine_dependent,
|
||||
|
||||
/* .space directive with expression operand that needs to be computed
|
||||
later. Similar to rs_org, but different.
|
||||
fr_symbol: operand
|
||||
1 variable char: fill character */
|
||||
rs_space,
|
||||
|
||||
/* A DWARF leb128 value; only ELF uses this. The subtype is 0 for
|
||||
unsigned, 1 for signed. */
|
||||
rs_leb128,
|
||||
|
||||
/* Exception frame information which we may be able to optimize. */
|
||||
rs_cfa,
|
||||
|
||||
/* Cross-fragment dwarf2 line number optimization. */
|
||||
rs_dwarf2dbg
|
||||
};
|
||||
|
||||
typedef enum _relax_state relax_stateT;
|
||||
|
||||
/* This type is used in prototypes, so it can't be a type that will be
|
||||
widened for argument passing. */
|
||||
typedef unsigned int relax_substateT;
|
||||
|
||||
/* Enough bits for address, but still an integer type.
|
||||
Could be a problem, cross-assembling for 64-bit machines. */
|
||||
typedef addressT relax_addressT;
|
||||
|
||||
struct relax_type
|
||||
{
|
||||
/* Forward reach. Signed number. > 0. */
|
||||
offsetT rlx_forward;
|
||||
/* Backward reach. Signed number. < 0. */
|
||||
offsetT rlx_backward;
|
||||
|
||||
/* Bytes length of this address. */
|
||||
unsigned char rlx_length;
|
||||
|
||||
/* Next longer relax-state. 0 means there is no 'next' relax-state. */
|
||||
relax_substateT rlx_more;
|
||||
};
|
||||
|
||||
typedef struct relax_type relax_typeS;
|
||||
|
||||
/* main program "as.c" (command arguments etc). */
|
||||
|
||||
COMMON unsigned char flag_no_comments; /* -f */
|
||||
COMMON unsigned char flag_debug; /* -D */
|
||||
COMMON unsigned char flag_signed_overflow_ok; /* -J */
|
||||
#ifndef WORKING_DOT_WORD
|
||||
COMMON unsigned char flag_warn_displacement; /* -K */
|
||||
#endif
|
||||
|
||||
/* True if local symbols should be retained. */
|
||||
COMMON int flag_keep_locals; /* -L */
|
||||
|
||||
/* True if we are assembling in MRI mode. */
|
||||
COMMON int flag_mri;
|
||||
|
||||
/* Should the data section be made read-only and appended to the text
|
||||
section? */
|
||||
COMMON unsigned char flag_readonly_data_in_text; /* -R */
|
||||
|
||||
/* True if warnings should be inhibited. */
|
||||
COMMON int flag_no_warnings; /* -W */
|
||||
|
||||
/* True if warnings count as errors. */
|
||||
COMMON int flag_fatal_warnings; /* --fatal-warnings */
|
||||
|
||||
/* True if we should attempt to generate output even if non-fatal errors
|
||||
are detected. */
|
||||
COMMON unsigned char flag_always_generate_output; /* -Z */
|
||||
|
||||
/* This is true if the assembler should output time and space usage. */
|
||||
COMMON unsigned char flag_print_statistics;
|
||||
|
||||
/* True if local absolute symbols are to be stripped. */
|
||||
COMMON int flag_strip_local_absolute;
|
||||
|
||||
/* True if we should generate a traditional format object file. */
|
||||
COMMON int flag_traditional_format;
|
||||
|
||||
/* TRUE if debug sections should be compressed. */
|
||||
COMMON int flag_compress_debug;
|
||||
|
||||
/* TRUE if .note.GNU-stack section with SEC_CODE should be created */
|
||||
COMMON int flag_execstack;
|
||||
|
||||
/* TRUE if .note.GNU-stack section with SEC_CODE should be created */
|
||||
COMMON int flag_noexecstack;
|
||||
|
||||
/* name of emitted object file */
|
||||
COMMON char *out_file_name;
|
||||
|
||||
/* name of file defining extensions to the basic instruction set */
|
||||
COMMON char *insttbl_file_name;
|
||||
|
||||
/* TRUE if we need a second pass. */
|
||||
COMMON int need_pass_2;
|
||||
|
||||
/* TRUE if we should do no relaxing, and
|
||||
leave lots of padding. */
|
||||
COMMON int linkrelax;
|
||||
|
||||
/* TRUE if we should produce a listing. */
|
||||
extern int listing;
|
||||
|
||||
/* Type of debugging information we should generate. We currently support
|
||||
stabs, ECOFF, and DWARF2.
|
||||
|
||||
NOTE! This means debug information about the assembly source code itself
|
||||
and _not_ about possible debug information from a high-level language.
|
||||
This is especially relevant to DWARF2, since the compiler may emit line
|
||||
number directives that the assembler resolves. */
|
||||
|
||||
enum debug_info_type
|
||||
{
|
||||
DEBUG_UNSPECIFIED,
|
||||
DEBUG_NONE,
|
||||
DEBUG_STABS,
|
||||
DEBUG_ECOFF,
|
||||
DEBUG_DWARF,
|
||||
DEBUG_DWARF2
|
||||
};
|
||||
|
||||
extern enum debug_info_type debug_type;
|
||||
extern int use_gnu_debug_info_extensions;
|
||||
COMMON bfd_boolean flag_dwarf_sections;
|
||||
|
||||
/* Maximum level of macro nesting. */
|
||||
extern int max_macro_nest;
|
||||
|
||||
/* Verbosity level. */
|
||||
extern int verbose;
|
||||
|
||||
/* Obstack chunk size. Keep large for efficient space use, make small to
|
||||
increase malloc calls for monitoring memory allocation. */
|
||||
extern int chunksize;
|
||||
|
||||
struct _pseudo_type
|
||||
{
|
||||
/* assembler mnemonic, lower case, no '.' */
|
||||
const char *poc_name;
|
||||
/* Do the work */
|
||||
void (*poc_handler) (int);
|
||||
/* Value to pass to handler */
|
||||
int poc_val;
|
||||
};
|
||||
|
||||
typedef struct _pseudo_type pseudo_typeS;
|
||||
|
||||
#if (__GNUC__ >= 2) && !defined(VMS)
|
||||
/* for use with -Wformat */
|
||||
|
||||
#if __GNUC__ == 2 && __GNUC_MINOR__ < 6
|
||||
/* Support for double underscores in attribute names was added in gcc
|
||||
2.6, so avoid them if we are using an earlier version. */
|
||||
#define __printf__ printf
|
||||
#define __format__ format
|
||||
#endif
|
||||
|
||||
#define PRINTF_LIKE(FCN) \
|
||||
void FCN (const char *format, ...) \
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)))
|
||||
#define PRINTF_WHERE_LIKE(FCN) \
|
||||
void FCN (char *file, unsigned int line, const char *format, ...) \
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)))
|
||||
|
||||
#else /* __GNUC__ < 2 || defined(VMS) */
|
||||
|
||||
#define PRINTF_LIKE(FCN) void FCN (const char *format, ...)
|
||||
#define PRINTF_WHERE_LIKE(FCN) void FCN (char *file, \
|
||||
unsigned int line, \
|
||||
const char *format, ...)
|
||||
|
||||
#endif /* __GNUC__ < 2 || defined(VMS) */
|
||||
|
||||
PRINTF_LIKE (as_bad);
|
||||
PRINTF_LIKE (as_fatal) ATTRIBUTE_NORETURN;
|
||||
PRINTF_LIKE (as_tsktsk);
|
||||
PRINTF_LIKE (as_warn);
|
||||
PRINTF_WHERE_LIKE (as_bad_where);
|
||||
PRINTF_WHERE_LIKE (as_warn_where);
|
||||
|
||||
void as_assert (const char *, int, const char *);
|
||||
void as_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
|
||||
void sprint_value (char *, addressT);
|
||||
int had_errors (void);
|
||||
int had_warnings (void);
|
||||
void as_warn_value_out_of_range (char *, offsetT, offsetT, offsetT, char *, unsigned);
|
||||
void as_bad_value_out_of_range (char *, offsetT, offsetT, offsetT, char *, unsigned);
|
||||
void print_version_id (void);
|
||||
char * app_push (void);
|
||||
char * atof_ieee (char *, int, LITTLENUM_TYPE *);
|
||||
char * ieee_md_atof (int, char *, int *, bfd_boolean);
|
||||
char * vax_md_atof (int, char *, int *);
|
||||
char * input_scrub_include_file (char *, char *);
|
||||
void input_scrub_insert_line (const char *);
|
||||
void input_scrub_insert_file (char *);
|
||||
char * input_scrub_new_file (char *);
|
||||
char * input_scrub_next_buffer (char **bufp);
|
||||
size_t do_scrub_chars (size_t (*get) (char *, size_t), char *, size_t);
|
||||
int gen_to_words (LITTLENUM_TYPE *, int, long);
|
||||
int had_err (void);
|
||||
int ignore_input (void);
|
||||
void cond_finish_check (int);
|
||||
void cond_exit_macro (int);
|
||||
int seen_at_least_1_file (void);
|
||||
void app_pop (char *);
|
||||
void as_where (char **, unsigned int *);
|
||||
void bump_line_counters (void);
|
||||
void do_scrub_begin (int);
|
||||
void input_scrub_begin (void);
|
||||
void input_scrub_close (void);
|
||||
void input_scrub_end (void);
|
||||
int new_logical_line (char *, int);
|
||||
int new_logical_line_flags (char *, int, int);
|
||||
void subsegs_begin (void);
|
||||
void subseg_change (segT, int);
|
||||
segT subseg_new (const char *, subsegT);
|
||||
segT subseg_force_new (const char *, subsegT);
|
||||
void subseg_set (segT, subsegT);
|
||||
int subseg_text_p (segT);
|
||||
int seg_not_empty_p (segT);
|
||||
void start_dependencies (char *);
|
||||
void register_dependency (char *);
|
||||
void print_dependencies (void);
|
||||
segT subseg_get (const char *, int);
|
||||
|
||||
const char *remap_debug_filename (const char *);
|
||||
void add_debug_prefix_map (const char *);
|
||||
|
||||
struct expressionS;
|
||||
struct fix;
|
||||
typedef struct symbol symbolS;
|
||||
typedef struct frag fragS;
|
||||
|
||||
/* literal.c */
|
||||
valueT add_to_literal_pool (symbolS *, valueT, segT, int);
|
||||
|
||||
int check_eh_frame (struct expressionS *, unsigned int *);
|
||||
int eh_frame_estimate_size_before_relax (fragS *);
|
||||
int eh_frame_relax_frag (fragS *);
|
||||
void eh_frame_convert_frag (fragS *);
|
||||
int generic_force_reloc (struct fix *);
|
||||
|
||||
#include "expr.h" /* Before targ-*.h */
|
||||
|
||||
/* This one starts the chain of target dependant headers. */
|
||||
#include "targ-env.h"
|
||||
|
||||
#ifdef OBJ_MAYBE_ELF
|
||||
#define IS_ELF (OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||
#else
|
||||
#ifdef OBJ_ELF
|
||||
#define IS_ELF 1
|
||||
#else
|
||||
#define IS_ELF 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "write.h"
|
||||
#include "frags.h"
|
||||
#include "hash.h"
|
||||
#include "read.h"
|
||||
#include "symbols.h"
|
||||
|
||||
#include "tc.h"
|
||||
#include "obj.h"
|
||||
|
||||
#ifdef USE_EMULATIONS
|
||||
#include "emul.h"
|
||||
#endif
|
||||
#include "listing.h"
|
||||
|
||||
#ifdef H_TICK_HEX
|
||||
extern int enable_h_tick_hex;
|
||||
#endif
|
||||
|
||||
#ifdef TC_M68K
|
||||
/* True if we are assembling in m68k MRI mode. */
|
||||
COMMON int flag_m68k_mri;
|
||||
#define DOLLAR_AMBIGU flag_m68k_mri
|
||||
#else
|
||||
#define flag_m68k_mri 0
|
||||
#endif
|
||||
|
||||
#ifdef WARN_COMMENTS
|
||||
COMMON int warn_comment;
|
||||
COMMON unsigned int found_comment;
|
||||
COMMON char * found_comment_file;
|
||||
#endif
|
||||
|
||||
#if defined OBJ_ELF || defined OBJ_MAYBE_ELF
|
||||
/* If .size directive failure should be error or warning. */
|
||||
COMMON enum
|
||||
{
|
||||
size_check_error = 0,
|
||||
size_check_warning
|
||||
}
|
||||
flag_size_check;
|
||||
#endif
|
||||
|
||||
#ifndef DOLLAR_AMBIGU
|
||||
#define DOLLAR_AMBIGU 0
|
||||
#endif
|
||||
|
||||
#ifndef NUMBERS_WITH_SUFFIX
|
||||
#define NUMBERS_WITH_SUFFIX 0
|
||||
#endif
|
||||
|
||||
#ifndef LOCAL_LABELS_DOLLAR
|
||||
#define LOCAL_LABELS_DOLLAR 0
|
||||
#endif
|
||||
|
||||
#ifndef LOCAL_LABELS_FB
|
||||
#define LOCAL_LABELS_FB 0
|
||||
#endif
|
||||
|
||||
#ifndef LABELS_WITHOUT_COLONS
|
||||
#define LABELS_WITHOUT_COLONS 0
|
||||
#endif
|
||||
|
||||
#ifndef NO_PSEUDO_DOT
|
||||
#define NO_PSEUDO_DOT 0
|
||||
#endif
|
||||
|
||||
#ifndef TEXT_SECTION_NAME
|
||||
#define TEXT_SECTION_NAME ".text"
|
||||
#define DATA_SECTION_NAME ".data"
|
||||
#define BSS_SECTION_NAME ".bss"
|
||||
#endif
|
||||
|
||||
#ifndef OCTETS_PER_BYTE_POWER
|
||||
#define OCTETS_PER_BYTE_POWER 0
|
||||
#endif
|
||||
#ifndef OCTETS_PER_BYTE
|
||||
#define OCTETS_PER_BYTE (1<<OCTETS_PER_BYTE_POWER)
|
||||
#endif
|
||||
#if OCTETS_PER_BYTE != (1<<OCTETS_PER_BYTE_POWER)
|
||||
#error "Octets per byte conflicts with its power-of-two definition!"
|
||||
#endif
|
||||
|
||||
#endif /* GAS */
|
52
contrib/toolchain/binutils/gas/asintl.h
Normal file
52
contrib/toolchain/binutils/gas/asintl.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* asintl.h - gas-specific header for gettext code.
|
||||
Copyright 1998, 1999, 2000, 2005, 2007 Free Software Foundation, Inc.
|
||||
|
||||
Written by Tom Tromey <tromey@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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifdef HAVE_LOCALE_H
|
||||
# ifndef ENABLE_NLS
|
||||
/* The Solaris version of locale.h always includes libintl.h. If we have
|
||||
been configured with --disable-nls then ENABLE_NLS will not be defined
|
||||
and the dummy definitions of bindtextdomain (et al) below will conflict
|
||||
with the defintions in libintl.h. So we define these values to prevent
|
||||
the bogus inclusion of libintl.h. */
|
||||
# define _LIBINTL_H
|
||||
# define _LIBGETTEXT_H
|
||||
# endif
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(String) gettext (String)
|
||||
# ifdef gettext_noop
|
||||
# define N_(String) gettext_noop (String)
|
||||
# else
|
||||
# define N_(String) (String)
|
||||
# endif
|
||||
#else
|
||||
# define gettext(Msgid) (Msgid)
|
||||
# define dgettext(Domainname, Msgid) (Msgid)
|
||||
# define dcgettext(Domainname, Msgid, Category) (Msgid)
|
||||
# define textdomain(Domainname) while (0) /* nothing */
|
||||
# define bindtextdomain(Domainname, Dirname) while (0) /* nothing */
|
||||
# define _(String) (String)
|
||||
# define N_(String) (String)
|
||||
#endif
|
614
contrib/toolchain/binutils/gas/atof-generic.c
Normal file
614
contrib/toolchain/binutils/gas/atof-generic.c
Normal file
@ -0,0 +1,614 @@
|
||||
/* atof_generic.c - turn a string of digits into a Flonum
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000,
|
||||
2001, 2003, 2005, 2006, 2007, 2009 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "safe-ctype.h"
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
||||
#ifdef TRACE
|
||||
static void flonum_print (const FLONUM_TYPE *);
|
||||
#endif
|
||||
|
||||
#define ASSUME_DECIMAL_MARK_IS_DOT
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Given a string of decimal digits , with optional decimal *
|
||||
* mark and optional decimal exponent (place value) of the *
|
||||
* lowest_order decimal digit: produce a floating point *
|
||||
* number. The number is 'generic' floating point: our *
|
||||
* caller will encode it for a specific machine architecture. *
|
||||
* *
|
||||
* Assumptions *
|
||||
* uses base (radix) 2 *
|
||||
* this machine uses 2's complement binary integers *
|
||||
* target flonums use " " " " *
|
||||
* target flonums exponents fit in a long *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
Syntax:
|
||||
|
||||
<flonum> ::= <optional-sign> <decimal-number> <optional-exponent>
|
||||
<optional-sign> ::= '+' | '-' | {empty}
|
||||
<decimal-number> ::= <integer>
|
||||
| <integer> <radix-character>
|
||||
| <integer> <radix-character> <integer>
|
||||
| <radix-character> <integer>
|
||||
|
||||
<optional-exponent> ::= {empty}
|
||||
| <exponent-character> <optional-sign> <integer>
|
||||
|
||||
<integer> ::= <digit> | <digit> <integer>
|
||||
<digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
|
||||
<exponent-character> ::= {one character from "string_of_decimal_exponent_marks"}
|
||||
<radix-character> ::= {one character from "string_of_decimal_marks"}
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
atof_generic (/* return pointer to just AFTER number we read. */
|
||||
char **address_of_string_pointer,
|
||||
/* At most one per number. */
|
||||
const char *string_of_decimal_marks,
|
||||
const char *string_of_decimal_exponent_marks,
|
||||
FLONUM_TYPE *address_of_generic_floating_point_number)
|
||||
{
|
||||
int return_value; /* 0 means OK. */
|
||||
char *first_digit;
|
||||
unsigned int number_of_digits_before_decimal;
|
||||
unsigned int number_of_digits_after_decimal;
|
||||
long decimal_exponent;
|
||||
unsigned int number_of_digits_available;
|
||||
char digits_sign_char;
|
||||
|
||||
/*
|
||||
* Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
|
||||
* It would be simpler to modify the string, but we don't; just to be nice
|
||||
* to caller.
|
||||
* We need to know how many digits we have, so we can allocate space for
|
||||
* the digits' value.
|
||||
*/
|
||||
|
||||
char *p;
|
||||
char c;
|
||||
int seen_significant_digit;
|
||||
|
||||
#ifdef ASSUME_DECIMAL_MARK_IS_DOT
|
||||
gas_assert (string_of_decimal_marks[0] == '.'
|
||||
&& string_of_decimal_marks[1] == 0);
|
||||
#define IS_DECIMAL_MARK(c) ((c) == '.')
|
||||
#else
|
||||
#define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c)))
|
||||
#endif
|
||||
|
||||
first_digit = *address_of_string_pointer;
|
||||
c = *first_digit;
|
||||
|
||||
if (c == '-' || c == '+')
|
||||
{
|
||||
digits_sign_char = c;
|
||||
first_digit++;
|
||||
}
|
||||
else
|
||||
digits_sign_char = '+';
|
||||
|
||||
switch (first_digit[0])
|
||||
{
|
||||
case 'n':
|
||||
case 'N':
|
||||
if (!strncasecmp ("nan", first_digit, 3))
|
||||
{
|
||||
address_of_generic_floating_point_number->sign = 0;
|
||||
address_of_generic_floating_point_number->exponent = 0;
|
||||
address_of_generic_floating_point_number->leader =
|
||||
address_of_generic_floating_point_number->low;
|
||||
*address_of_string_pointer = first_digit + 3;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
case 'I':
|
||||
if (!strncasecmp ("inf", first_digit, 3))
|
||||
{
|
||||
address_of_generic_floating_point_number->sign =
|
||||
digits_sign_char == '+' ? 'P' : 'N';
|
||||
address_of_generic_floating_point_number->exponent = 0;
|
||||
address_of_generic_floating_point_number->leader =
|
||||
address_of_generic_floating_point_number->low;
|
||||
|
||||
first_digit += 3;
|
||||
if (!strncasecmp ("inity", first_digit, 5))
|
||||
first_digit += 5;
|
||||
|
||||
*address_of_string_pointer = first_digit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
number_of_digits_before_decimal = 0;
|
||||
number_of_digits_after_decimal = 0;
|
||||
decimal_exponent = 0;
|
||||
seen_significant_digit = 0;
|
||||
for (p = first_digit;
|
||||
(((c = *p) != '\0')
|
||||
&& (!c || !IS_DECIMAL_MARK (c))
|
||||
&& (!c || !strchr (string_of_decimal_exponent_marks, c)));
|
||||
p++)
|
||||
{
|
||||
if (ISDIGIT (c))
|
||||
{
|
||||
if (seen_significant_digit || c > '0')
|
||||
{
|
||||
++number_of_digits_before_decimal;
|
||||
seen_significant_digit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_digit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break; /* p -> char after pre-decimal digits. */
|
||||
}
|
||||
} /* For each digit before decimal mark. */
|
||||
|
||||
#ifndef OLD_FLOAT_READS
|
||||
/* Ignore trailing 0's after the decimal point. The original code here
|
||||
* (ifdef'd out) does not do this, and numbers like
|
||||
* 4.29496729600000000000e+09 (2**31)
|
||||
* come out inexact for some reason related to length of the digit
|
||||
* string.
|
||||
*/
|
||||
if (c && IS_DECIMAL_MARK (c))
|
||||
{
|
||||
unsigned int zeros = 0; /* Length of current string of zeros */
|
||||
|
||||
for (p++; (c = *p) && ISDIGIT (c); p++)
|
||||
{
|
||||
if (c == '0')
|
||||
{
|
||||
zeros++;
|
||||
}
|
||||
else
|
||||
{
|
||||
number_of_digits_after_decimal += 1 + zeros;
|
||||
zeros = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (c && IS_DECIMAL_MARK (c))
|
||||
{
|
||||
for (p++;
|
||||
(((c = *p) != '\0')
|
||||
&& (!c || !strchr (string_of_decimal_exponent_marks, c)));
|
||||
p++)
|
||||
{
|
||||
if (ISDIGIT (c))
|
||||
{
|
||||
/* This may be retracted below. */
|
||||
number_of_digits_after_decimal++;
|
||||
|
||||
if ( /* seen_significant_digit || */ c > '0')
|
||||
{
|
||||
seen_significant_digit = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!seen_significant_digit)
|
||||
{
|
||||
number_of_digits_after_decimal = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} /* For each digit after decimal mark. */
|
||||
}
|
||||
|
||||
while (number_of_digits_after_decimal
|
||||
&& first_digit[number_of_digits_before_decimal
|
||||
+ number_of_digits_after_decimal] == '0')
|
||||
--number_of_digits_after_decimal;
|
||||
#endif
|
||||
|
||||
if (flag_m68k_mri)
|
||||
{
|
||||
while (c == '_')
|
||||
c = *++p;
|
||||
}
|
||||
if (c && strchr (string_of_decimal_exponent_marks, c))
|
||||
{
|
||||
char digits_exponent_sign_char;
|
||||
|
||||
c = *++p;
|
||||
if (flag_m68k_mri)
|
||||
{
|
||||
while (c == '_')
|
||||
c = *++p;
|
||||
}
|
||||
if (c && strchr ("+-", c))
|
||||
{
|
||||
digits_exponent_sign_char = c;
|
||||
c = *++p;
|
||||
}
|
||||
else
|
||||
{
|
||||
digits_exponent_sign_char = '+';
|
||||
}
|
||||
|
||||
for (; (c); c = *++p)
|
||||
{
|
||||
if (ISDIGIT (c))
|
||||
{
|
||||
decimal_exponent = decimal_exponent * 10 + c - '0';
|
||||
/*
|
||||
* BUG! If we overflow here, we lose!
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (digits_exponent_sign_char == '-')
|
||||
{
|
||||
decimal_exponent = -decimal_exponent;
|
||||
}
|
||||
}
|
||||
|
||||
*address_of_string_pointer = p;
|
||||
|
||||
number_of_digits_available =
|
||||
number_of_digits_before_decimal + number_of_digits_after_decimal;
|
||||
return_value = 0;
|
||||
if (number_of_digits_available == 0)
|
||||
{
|
||||
address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */
|
||||
address_of_generic_floating_point_number->leader
|
||||
= -1 + address_of_generic_floating_point_number->low;
|
||||
address_of_generic_floating_point_number->sign = digits_sign_char;
|
||||
/* We have just concocted (+/-)0.0E0 */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int count; /* Number of useful digits left to scan. */
|
||||
|
||||
LITTLENUM_TYPE *digits_binary_low;
|
||||
unsigned int precision;
|
||||
unsigned int maximum_useful_digits;
|
||||
unsigned int number_of_digits_to_use;
|
||||
unsigned int more_than_enough_bits_for_digits;
|
||||
unsigned int more_than_enough_littlenums_for_digits;
|
||||
unsigned int size_of_digits_in_littlenums;
|
||||
unsigned int size_of_digits_in_chars;
|
||||
FLONUM_TYPE power_of_10_flonum;
|
||||
FLONUM_TYPE digits_flonum;
|
||||
|
||||
precision = (address_of_generic_floating_point_number->high
|
||||
- address_of_generic_floating_point_number->low
|
||||
+ 1); /* Number of destination littlenums. */
|
||||
|
||||
/* Includes guard bits (two littlenums worth) */
|
||||
maximum_useful_digits = (((precision - 2))
|
||||
* ( (LITTLENUM_NUMBER_OF_BITS))
|
||||
* 1000000 / 3321928)
|
||||
+ 2; /* 2 :: guard digits. */
|
||||
|
||||
if (number_of_digits_available > maximum_useful_digits)
|
||||
{
|
||||
number_of_digits_to_use = maximum_useful_digits;
|
||||
}
|
||||
else
|
||||
{
|
||||
number_of_digits_to_use = number_of_digits_available;
|
||||
}
|
||||
|
||||
/* Cast these to SIGNED LONG first, otherwise, on systems with
|
||||
LONG wider than INT (such as Alpha OSF/1), unsignedness may
|
||||
cause unexpected results. */
|
||||
decimal_exponent += ((long) number_of_digits_before_decimal
|
||||
- (long) number_of_digits_to_use);
|
||||
|
||||
more_than_enough_bits_for_digits
|
||||
= (number_of_digits_to_use * 3321928 / 1000000 + 1);
|
||||
|
||||
more_than_enough_littlenums_for_digits
|
||||
= (more_than_enough_bits_for_digits
|
||||
/ LITTLENUM_NUMBER_OF_BITS)
|
||||
+ 2;
|
||||
|
||||
/* Compute (digits) part. In "12.34E56" this is the "1234" part.
|
||||
Arithmetic is exact here. If no digits are supplied then this
|
||||
part is a 0 valued binary integer. Allocate room to build up
|
||||
the binary number as littlenums. We want this memory to
|
||||
disappear when we leave this function. Assume no alignment
|
||||
problems => (room for n objects) == n * (room for 1
|
||||
object). */
|
||||
|
||||
size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
|
||||
size_of_digits_in_chars = size_of_digits_in_littlenums
|
||||
* sizeof (LITTLENUM_TYPE);
|
||||
|
||||
digits_binary_low = (LITTLENUM_TYPE *)
|
||||
alloca (size_of_digits_in_chars);
|
||||
|
||||
memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars);
|
||||
|
||||
/* Digits_binary_low[] is allocated and zeroed. */
|
||||
|
||||
/*
|
||||
* Parse the decimal digits as if * digits_low was in the units position.
|
||||
* Emit a binary number into digits_binary_low[].
|
||||
*
|
||||
* Use a large-precision version of:
|
||||
* (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
|
||||
*/
|
||||
|
||||
for (p = first_digit, count = number_of_digits_to_use; count; p++, --count)
|
||||
{
|
||||
c = *p;
|
||||
if (ISDIGIT (c))
|
||||
{
|
||||
/*
|
||||
* Multiply by 10. Assume can never overflow.
|
||||
* Add this digit to digits_binary_low[].
|
||||
*/
|
||||
|
||||
long carry;
|
||||
LITTLENUM_TYPE *littlenum_pointer;
|
||||
LITTLENUM_TYPE *littlenum_limit;
|
||||
|
||||
littlenum_limit = digits_binary_low
|
||||
+ more_than_enough_littlenums_for_digits
|
||||
- 1;
|
||||
|
||||
carry = c - '0'; /* char -> binary */
|
||||
|
||||
for (littlenum_pointer = digits_binary_low;
|
||||
littlenum_pointer <= littlenum_limit;
|
||||
littlenum_pointer++)
|
||||
{
|
||||
long work;
|
||||
|
||||
work = carry + 10 * (long) (*littlenum_pointer);
|
||||
*littlenum_pointer = work & LITTLENUM_MASK;
|
||||
carry = work >> LITTLENUM_NUMBER_OF_BITS;
|
||||
}
|
||||
|
||||
if (carry != 0)
|
||||
{
|
||||
/*
|
||||
* We have a GROSS internal error.
|
||||
* This should never happen.
|
||||
*/
|
||||
as_fatal (_("failed sanity check"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++count; /* '.' doesn't alter digits used count. */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Digits_binary_low[] properly encodes the value of the digits.
|
||||
* Forget about any high-order littlenums that are 0.
|
||||
*/
|
||||
while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0
|
||||
&& size_of_digits_in_littlenums >= 2)
|
||||
size_of_digits_in_littlenums--;
|
||||
|
||||
digits_flonum.low = digits_binary_low;
|
||||
digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1;
|
||||
digits_flonum.leader = digits_flonum.high;
|
||||
digits_flonum.exponent = 0;
|
||||
/*
|
||||
* The value of digits_flonum . sign should not be important.
|
||||
* We have already decided the output's sign.
|
||||
* We trust that the sign won't influence the other parts of the number!
|
||||
* So we give it a value for these reasons:
|
||||
* (1) courtesy to humans reading/debugging
|
||||
* these numbers so they don't get excited about strange values
|
||||
* (2) in future there may be more meaning attached to sign,
|
||||
* and what was
|
||||
* harmless noise may become disruptive, ill-conditioned (or worse)
|
||||
* input.
|
||||
*/
|
||||
digits_flonum.sign = '+';
|
||||
|
||||
{
|
||||
/*
|
||||
* Compute the mantssa (& exponent) of the power of 10.
|
||||
* If successful, then multiply the power of 10 by the digits
|
||||
* giving return_binary_mantissa and return_binary_exponent.
|
||||
*/
|
||||
|
||||
LITTLENUM_TYPE *power_binary_low;
|
||||
int decimal_exponent_is_negative;
|
||||
/* This refers to the "-56" in "12.34E-56". */
|
||||
/* FALSE: decimal_exponent is positive (or 0) */
|
||||
/* TRUE: decimal_exponent is negative */
|
||||
FLONUM_TYPE temporary_flonum;
|
||||
LITTLENUM_TYPE *temporary_binary_low;
|
||||
unsigned int size_of_power_in_littlenums;
|
||||
unsigned int size_of_power_in_chars;
|
||||
|
||||
size_of_power_in_littlenums = precision;
|
||||
/* Precision has a built-in fudge factor so we get a few guard bits. */
|
||||
|
||||
decimal_exponent_is_negative = decimal_exponent < 0;
|
||||
if (decimal_exponent_is_negative)
|
||||
{
|
||||
decimal_exponent = -decimal_exponent;
|
||||
}
|
||||
|
||||
/* From now on: the decimal exponent is > 0. Its sign is separate. */
|
||||
|
||||
size_of_power_in_chars = size_of_power_in_littlenums
|
||||
* sizeof (LITTLENUM_TYPE) + 2;
|
||||
|
||||
power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
|
||||
temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
|
||||
memset ((char *) power_binary_low, '\0', size_of_power_in_chars);
|
||||
*power_binary_low = 1;
|
||||
power_of_10_flonum.exponent = 0;
|
||||
power_of_10_flonum.low = power_binary_low;
|
||||
power_of_10_flonum.leader = power_binary_low;
|
||||
power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;
|
||||
power_of_10_flonum.sign = '+';
|
||||
temporary_flonum.low = temporary_binary_low;
|
||||
temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;
|
||||
/*
|
||||
* (power) == 1.
|
||||
* Space for temporary_flonum allocated.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ...
|
||||
*
|
||||
* WHILE more bits
|
||||
* DO find next bit (with place value)
|
||||
* multiply into power mantissa
|
||||
* OD
|
||||
*/
|
||||
{
|
||||
int place_number_limit;
|
||||
/* Any 10^(2^n) whose "n" exceeds this */
|
||||
/* value will fall off the end of */
|
||||
/* flonum_XXXX_powers_of_ten[]. */
|
||||
int place_number;
|
||||
const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */
|
||||
|
||||
place_number_limit = table_size_of_flonum_powers_of_ten;
|
||||
|
||||
multiplicand = (decimal_exponent_is_negative
|
||||
? flonum_negative_powers_of_ten
|
||||
: flonum_positive_powers_of_ten);
|
||||
|
||||
for (place_number = 1;/* Place value of this bit of exponent. */
|
||||
decimal_exponent;/* Quit when no more 1 bits in exponent. */
|
||||
decimal_exponent >>= 1, place_number++)
|
||||
{
|
||||
if (decimal_exponent & 1)
|
||||
{
|
||||
if (place_number > place_number_limit)
|
||||
{
|
||||
/* The decimal exponent has a magnitude so great
|
||||
that our tables can't help us fragment it.
|
||||
Although this routine is in error because it
|
||||
can't imagine a number that big, signal an
|
||||
error as if it is the user's fault for
|
||||
presenting such a big number. */
|
||||
return_value = ERROR_EXPONENT_OVERFLOW;
|
||||
/* quit out of loop gracefully */
|
||||
decimal_exponent = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TRACE
|
||||
printf ("before multiply, place_number = %d., power_of_10_flonum:\n",
|
||||
place_number);
|
||||
|
||||
flonum_print (&power_of_10_flonum);
|
||||
(void) putchar ('\n');
|
||||
#endif
|
||||
#ifdef TRACE
|
||||
printf ("multiplier:\n");
|
||||
flonum_print (multiplicand + place_number);
|
||||
(void) putchar ('\n');
|
||||
#endif
|
||||
flonum_multip (multiplicand + place_number,
|
||||
&power_of_10_flonum, &temporary_flonum);
|
||||
#ifdef TRACE
|
||||
printf ("after multiply:\n");
|
||||
flonum_print (&temporary_flonum);
|
||||
(void) putchar ('\n');
|
||||
#endif
|
||||
flonum_copy (&temporary_flonum, &power_of_10_flonum);
|
||||
#ifdef TRACE
|
||||
printf ("after copy:\n");
|
||||
flonum_print (&power_of_10_flonum);
|
||||
(void) putchar ('\n');
|
||||
#endif
|
||||
} /* If this bit of decimal_exponent was computable.*/
|
||||
} /* If this bit of decimal_exponent was set. */
|
||||
} /* For each bit of binary representation of exponent */
|
||||
#ifdef TRACE
|
||||
printf ("after computing power_of_10_flonum:\n");
|
||||
flonum_print (&power_of_10_flonum);
|
||||
(void) putchar ('\n');
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
|
||||
* It may be the number 1, in which case we don't NEED to multiply.
|
||||
*
|
||||
* Multiply (decimal digits) by power_of_10_flonum.
|
||||
*/
|
||||
|
||||
flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);
|
||||
/* Assert sign of the number we made is '+'. */
|
||||
address_of_generic_floating_point_number->sign = digits_sign_char;
|
||||
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
#ifdef TRACE
|
||||
static void
|
||||
flonum_print (f)
|
||||
const FLONUM_TYPE *f;
|
||||
{
|
||||
LITTLENUM_TYPE *lp;
|
||||
char littlenum_format[10];
|
||||
sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2);
|
||||
#define print_littlenum(LP) (printf (littlenum_format, LP))
|
||||
printf ("flonum @%p %c e%ld", f, f->sign, f->exponent);
|
||||
if (f->low < f->high)
|
||||
for (lp = f->high; lp >= f->low; lp--)
|
||||
print_littlenum (*lp);
|
||||
else
|
||||
for (lp = f->low; lp <= f->high; lp++)
|
||||
print_littlenum (*lp);
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* end of atof_generic.c */
|
42
contrib/toolchain/binutils/gas/bignum.h
Normal file
42
contrib/toolchain/binutils/gas/bignum.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* bignum.h-arbitrary precision integers
|
||||
Copyright 1987, 1992, 2003, 2005, 2007 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 3, 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, 51 Franklin Street - Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Arbitrary-precision integer arithmetic. *
|
||||
* For speed, we work in groups of bits, even though this *
|
||||
* complicates algorithms. *
|
||||
* Each group of bits is called a 'littlenum'. *
|
||||
* A bunch of littlenums representing a (possibly large) *
|
||||
* integer is called a 'bignum'. *
|
||||
* Bignums are >= 0. *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
#define LITTLENUM_NUMBER_OF_BITS (16)
|
||||
#define LITTLENUM_RADIX (1 << LITTLENUM_NUMBER_OF_BITS)
|
||||
#define LITTLENUM_MASK (0xFFFF)
|
||||
#define LITTLENUM_SHIFT (1)
|
||||
#define CHARS_PER_LITTLENUM (1 << LITTLENUM_SHIFT)
|
||||
#ifndef BITS_PER_CHAR
|
||||
#define BITS_PER_CHAR (8)
|
||||
#endif
|
||||
|
||||
typedef unsigned short LITTLENUM_TYPE;
|
48
contrib/toolchain/binutils/gas/bit_fix.h
Normal file
48
contrib/toolchain/binutils/gas/bit_fix.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* bit_fix.h
|
||||
Copyright 1987, 1992, 2000, 2001, 2003, 2005, 2007
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* The bit_fix was implemented to support machines that need variables
|
||||
to be inserted in bitfields other than 1, 2 and 4 bytes.
|
||||
Furthermore it gives us a possibility to mask in bits in the symbol
|
||||
when it's fixed in the objectcode and check the symbols limits.
|
||||
|
||||
The or-mask is used to set the huffman bits in displacements for the
|
||||
ns32k port.
|
||||
The acbi, addqi, movqi, cmpqi instruction requires an assembler that
|
||||
can handle bitfields. Ie. handle an expression, evaluate it and insert
|
||||
the result in some bitfield. (eg: 5 bits in a short field of an opcode). */
|
||||
|
||||
#ifndef __bit_fix_h__
|
||||
#define __bit_fix_h__
|
||||
|
||||
struct bit_fix {
|
||||
int fx_bit_size; /* Length of bitfield */
|
||||
int fx_bit_offset; /* Bit offset to bitfield */
|
||||
long fx_bit_base; /* Where do we apply the bitfix.
|
||||
If this is zero, default is assumed. */
|
||||
long fx_bit_base_adj; /* Adjustment of base */
|
||||
long fx_bit_max; /* Signextended max for bitfield */
|
||||
long fx_bit_min; /* Signextended min for bitfield */
|
||||
long fx_bit_add; /* Or mask, used for huffman prefix */
|
||||
};
|
||||
typedef struct bit_fix bit_fixS;
|
||||
|
||||
#endif /* __bit_fix_h__ */
|
117
contrib/toolchain/binutils/gas/compress-debug.c
Normal file
117
contrib/toolchain/binutils/gas/compress-debug.c
Normal file
@ -0,0 +1,117 @@
|
||||
/* compress-debug.c - compress debug sections
|
||||
Copyright 2010 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include "ansidecl.h"
|
||||
#include "compress-debug.h"
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
/* Initialize the compression engine. */
|
||||
|
||||
struct z_stream_s *
|
||||
compress_init (void)
|
||||
{
|
||||
#ifndef HAVE_ZLIB_H
|
||||
return NULL;
|
||||
#else
|
||||
static struct z_stream_s strm;
|
||||
|
||||
strm.zalloc = NULL;
|
||||
strm.zfree = NULL;
|
||||
strm.opaque = NULL;
|
||||
deflateInit (&strm, Z_DEFAULT_COMPRESSION);
|
||||
return &strm;
|
||||
#endif /* HAVE_ZLIB_H */
|
||||
}
|
||||
|
||||
/* Stream the contents of a frag to the compression engine. Output
|
||||
from the engine goes into the current frag on the obstack. */
|
||||
|
||||
int
|
||||
compress_data (struct z_stream_s *strm ATTRIBUTE_UNUSED,
|
||||
const char **next_in ATTRIBUTE_UNUSED,
|
||||
int *avail_in ATTRIBUTE_UNUSED,
|
||||
char **next_out ATTRIBUTE_UNUSED,
|
||||
int *avail_out ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifndef HAVE_ZLIB_H
|
||||
return -1;
|
||||
#else
|
||||
int out_size = 0;
|
||||
int x;
|
||||
|
||||
strm->next_in = (Bytef *) (*next_in);
|
||||
strm->avail_in = *avail_in;
|
||||
strm->next_out = (Bytef *) (*next_out);
|
||||
strm->avail_out = *avail_out;
|
||||
|
||||
x = deflate (strm, Z_NO_FLUSH);
|
||||
if (x != Z_OK)
|
||||
return -1;
|
||||
|
||||
out_size = *avail_out - strm->avail_out;
|
||||
*next_in = (char *) (strm->next_in);
|
||||
*avail_in = strm->avail_in;
|
||||
*next_out = (char *) (strm->next_out);
|
||||
*avail_out = strm->avail_out;
|
||||
|
||||
return out_size;
|
||||
#endif /* HAVE_ZLIB_H */
|
||||
}
|
||||
|
||||
/* Finish the compression and consume the remaining compressed output.
|
||||
Returns -1 for error, 0 when done, 1 when more output buffer is
|
||||
needed. */
|
||||
|
||||
int
|
||||
compress_finish (struct z_stream_s *strm ATTRIBUTE_UNUSED,
|
||||
char **next_out ATTRIBUTE_UNUSED,
|
||||
int *avail_out ATTRIBUTE_UNUSED,
|
||||
int *out_size ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifndef HAVE_ZLIB_H
|
||||
return -1;
|
||||
#else
|
||||
int x;
|
||||
|
||||
strm->avail_in = 0;
|
||||
strm->next_out = (Bytef *) (*next_out);
|
||||
strm->avail_out = *avail_out;
|
||||
|
||||
x = deflate (strm, Z_FINISH);
|
||||
|
||||
*out_size = *avail_out - strm->avail_out;
|
||||
*next_out = (char *) (strm->next_out);
|
||||
*avail_out = strm->avail_out;
|
||||
|
||||
if (x == Z_STREAM_END)
|
||||
{
|
||||
deflateEnd (strm);
|
||||
return 0;
|
||||
}
|
||||
if (strm->avail_out != 0)
|
||||
return -1;
|
||||
return 1;
|
||||
#endif /* HAVE_ZLIB_H */
|
||||
}
|
39
contrib/toolchain/binutils/gas/compress-debug.h
Normal file
39
contrib/toolchain/binutils/gas/compress-debug.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* compress-debug.h - Header file for compressed debug sections.
|
||||
Copyright 2010 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef COMPRESS_DEBUG_H
|
||||
#define COMPRESS_DEBUG_H
|
||||
|
||||
struct z_stream_s;
|
||||
|
||||
/* Initialize the compression engine. */
|
||||
extern struct z_stream_s *
|
||||
compress_init (void);
|
||||
|
||||
/* Stream the contents of a frag to the compression engine. Output
|
||||
from the engine goes into the current frag on the obstack. */
|
||||
extern int
|
||||
compress_data (struct z_stream_s *, const char **, int *, char **, int *);
|
||||
|
||||
/* Finish the compression and consume the remaining compressed output. */
|
||||
extern int
|
||||
compress_finish (struct z_stream_s *, char **, int *, int *);
|
||||
|
||||
#endif /* COMPRESS_DEBUG_H */
|
577
contrib/toolchain/binutils/gas/cond.c
Normal file
577
contrib/toolchain/binutils/gas/cond.c
Normal file
@ -0,0 +1,577 @@
|
||||
/* cond.c - conditional assembly pseudo-ops, and .include
|
||||
Copyright 1990, 1991, 1992, 1993, 1995, 1997, 1998, 2000, 2001, 2002,
|
||||
2003, 2005, 2006, 2007 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "sb.h"
|
||||
#include "macro.h"
|
||||
|
||||
#include "obstack.h"
|
||||
|
||||
/* This is allocated to grow and shrink as .ifdef/.endif pairs are
|
||||
scanned. */
|
||||
struct obstack cond_obstack;
|
||||
|
||||
struct file_line {
|
||||
char *file;
|
||||
unsigned int line;
|
||||
};
|
||||
|
||||
/* We push one of these structures for each .if, and pop it at the
|
||||
.endif. */
|
||||
|
||||
struct conditional_frame {
|
||||
/* The source file & line number of the "if". */
|
||||
struct file_line if_file_line;
|
||||
/* The source file & line of the "else". */
|
||||
struct file_line else_file_line;
|
||||
/* The previous conditional. */
|
||||
struct conditional_frame *previous_cframe;
|
||||
/* Have we seen an else yet? */
|
||||
int else_seen;
|
||||
/* Whether we are currently ignoring input. */
|
||||
int ignoring;
|
||||
/* Whether a conditional at a higher level is ignoring input.
|
||||
Set also when a branch of an "if .. elseif .." tree has matched
|
||||
to prevent further matches. */
|
||||
int dead_tree;
|
||||
/* Macro nesting level at which this conditional was created. */
|
||||
int macro_nest;
|
||||
};
|
||||
|
||||
static void initialize_cframe (struct conditional_frame *cframe);
|
||||
static char *get_mri_string (int, int *);
|
||||
|
||||
static struct conditional_frame *current_cframe = NULL;
|
||||
|
||||
/* Performs the .ifdef (test_defined == 1) and
|
||||
the .ifndef (test_defined == 0) pseudo op. */
|
||||
|
||||
void
|
||||
s_ifdef (int test_defined)
|
||||
{
|
||||
/* Points to name of symbol. */
|
||||
char *name;
|
||||
/* Points to symbol. */
|
||||
symbolS *symbolP;
|
||||
struct conditional_frame cframe;
|
||||
char c;
|
||||
|
||||
/* Leading whitespace is part of operand. */
|
||||
SKIP_WHITESPACE ();
|
||||
name = input_line_pointer;
|
||||
|
||||
if (!is_name_beginner (*name))
|
||||
{
|
||||
as_bad (_("invalid identifier for \".ifdef\""));
|
||||
obstack_1grow (&cond_obstack, 0);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
c = get_symbol_end ();
|
||||
symbolP = symbol_find (name);
|
||||
*input_line_pointer = c;
|
||||
|
||||
initialize_cframe (&cframe);
|
||||
|
||||
if (cframe.dead_tree)
|
||||
cframe.ignoring = 1;
|
||||
else
|
||||
{
|
||||
int is_defined;
|
||||
|
||||
/* Use the same definition of 'defined' as .equiv so that a symbol
|
||||
which has been referenced but not yet given a value/address is
|
||||
considered to be undefined. */
|
||||
is_defined =
|
||||
symbolP != NULL
|
||||
&& (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
|
||||
&& S_GET_SEGMENT (symbolP) != reg_section;
|
||||
|
||||
cframe.ignoring = ! (test_defined ^ is_defined);
|
||||
}
|
||||
|
||||
current_cframe = ((struct conditional_frame *)
|
||||
obstack_copy (&cond_obstack, &cframe,
|
||||
sizeof (cframe)));
|
||||
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& cframe.ignoring
|
||||
&& (cframe.previous_cframe == NULL
|
||||
|| ! cframe.previous_cframe->ignoring))
|
||||
listing_list (2);
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
void
|
||||
s_if (int arg)
|
||||
{
|
||||
expressionS operand;
|
||||
struct conditional_frame cframe;
|
||||
int t;
|
||||
char *stop = NULL;
|
||||
char stopc;
|
||||
|
||||
if (flag_mri)
|
||||
stop = mri_comment_field (&stopc);
|
||||
|
||||
/* Leading whitespace is part of operand. */
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
if (current_cframe != NULL && current_cframe->ignoring)
|
||||
{
|
||||
operand.X_add_number = 0;
|
||||
while (! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
++input_line_pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
expression_and_evaluate (&operand);
|
||||
if (operand.X_op != O_constant)
|
||||
as_bad (_("non-constant expression in \".if\" statement"));
|
||||
}
|
||||
|
||||
switch ((operatorT) arg)
|
||||
{
|
||||
case O_eq: t = operand.X_add_number == 0; break;
|
||||
case O_ne: t = operand.X_add_number != 0; break;
|
||||
case O_lt: t = operand.X_add_number < 0; break;
|
||||
case O_le: t = operand.X_add_number <= 0; break;
|
||||
case O_ge: t = operand.X_add_number >= 0; break;
|
||||
case O_gt: t = operand.X_add_number > 0; break;
|
||||
default:
|
||||
abort ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the above error is signaled, this will dispatch
|
||||
using an undefined result. No big deal. */
|
||||
initialize_cframe (&cframe);
|
||||
cframe.ignoring = cframe.dead_tree || ! t;
|
||||
current_cframe = ((struct conditional_frame *)
|
||||
obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
|
||||
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& cframe.ignoring
|
||||
&& (cframe.previous_cframe == NULL
|
||||
|| ! cframe.previous_cframe->ignoring))
|
||||
listing_list (2);
|
||||
|
||||
if (flag_mri)
|
||||
mri_comment_end (stop, stopc);
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* Performs the .ifb (test_blank == 1) and
|
||||
the .ifnb (test_blank == 0) pseudo op. */
|
||||
|
||||
void
|
||||
s_ifb (int test_blank)
|
||||
{
|
||||
struct conditional_frame cframe;
|
||||
|
||||
initialize_cframe (&cframe);
|
||||
|
||||
if (cframe.dead_tree)
|
||||
cframe.ignoring = 1;
|
||||
else
|
||||
{
|
||||
int is_eol;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
is_eol = is_end_of_line[(unsigned char) *input_line_pointer];
|
||||
cframe.ignoring = (test_blank == !is_eol);
|
||||
}
|
||||
|
||||
current_cframe = ((struct conditional_frame *)
|
||||
obstack_copy (&cond_obstack, &cframe,
|
||||
sizeof (cframe)));
|
||||
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& cframe.ignoring
|
||||
&& (cframe.previous_cframe == NULL
|
||||
|| ! cframe.previous_cframe->ignoring))
|
||||
listing_list (2);
|
||||
|
||||
ignore_rest_of_line ();
|
||||
}
|
||||
|
||||
/* Get a string for the MRI IFC or IFNC pseudo-ops. */
|
||||
|
||||
static char *
|
||||
get_mri_string (int terminator, int *len)
|
||||
{
|
||||
char *ret;
|
||||
char *s;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
s = ret = input_line_pointer;
|
||||
if (*input_line_pointer == '\'')
|
||||
{
|
||||
++s;
|
||||
++input_line_pointer;
|
||||
while (! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
{
|
||||
*s++ = *input_line_pointer++;
|
||||
if (s[-1] == '\'')
|
||||
{
|
||||
if (*input_line_pointer != '\'')
|
||||
break;
|
||||
++input_line_pointer;
|
||||
}
|
||||
}
|
||||
SKIP_WHITESPACE ();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*input_line_pointer != terminator
|
||||
&& ! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
++input_line_pointer;
|
||||
s = input_line_pointer;
|
||||
while (s > ret && (s[-1] == ' ' || s[-1] == '\t'))
|
||||
--s;
|
||||
}
|
||||
|
||||
*len = s - ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The MRI IFC and IFNC pseudo-ops. */
|
||||
|
||||
void
|
||||
s_ifc (int arg)
|
||||
{
|
||||
char *stop = NULL;
|
||||
char stopc;
|
||||
char *s1, *s2;
|
||||
int len1, len2;
|
||||
int res;
|
||||
struct conditional_frame cframe;
|
||||
|
||||
if (flag_mri)
|
||||
stop = mri_comment_field (&stopc);
|
||||
|
||||
s1 = get_mri_string (',', &len1);
|
||||
|
||||
if (*input_line_pointer != ',')
|
||||
as_bad (_("bad format for ifc or ifnc"));
|
||||
else
|
||||
++input_line_pointer;
|
||||
|
||||
s2 = get_mri_string (';', &len2);
|
||||
|
||||
res = len1 == len2 && strncmp (s1, s2, len1) == 0;
|
||||
|
||||
initialize_cframe (&cframe);
|
||||
cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
|
||||
current_cframe = ((struct conditional_frame *)
|
||||
obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
|
||||
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& cframe.ignoring
|
||||
&& (cframe.previous_cframe == NULL
|
||||
|| ! cframe.previous_cframe->ignoring))
|
||||
listing_list (2);
|
||||
|
||||
if (flag_mri)
|
||||
mri_comment_end (stop, stopc);
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
void
|
||||
s_elseif (int arg)
|
||||
{
|
||||
if (current_cframe == NULL)
|
||||
{
|
||||
as_bad (_("\".elseif\" without matching \".if\""));
|
||||
}
|
||||
else if (current_cframe->else_seen)
|
||||
{
|
||||
as_bad (_("\".elseif\" after \".else\""));
|
||||
as_bad_where (current_cframe->else_file_line.file,
|
||||
current_cframe->else_file_line.line,
|
||||
_("here is the previous \".else\""));
|
||||
as_bad_where (current_cframe->if_file_line.file,
|
||||
current_cframe->if_file_line.line,
|
||||
_("here is the previous \".if\""));
|
||||
}
|
||||
else
|
||||
{
|
||||
as_where (¤t_cframe->else_file_line.file,
|
||||
¤t_cframe->else_file_line.line);
|
||||
|
||||
current_cframe->dead_tree |= !current_cframe->ignoring;
|
||||
current_cframe->ignoring = current_cframe->dead_tree;
|
||||
}
|
||||
|
||||
if (current_cframe == NULL || current_cframe->ignoring)
|
||||
{
|
||||
while (! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
++input_line_pointer;
|
||||
|
||||
if (current_cframe == NULL)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
expressionS operand;
|
||||
int t;
|
||||
|
||||
/* Leading whitespace is part of operand. */
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
expression_and_evaluate (&operand);
|
||||
if (operand.X_op != O_constant)
|
||||
as_bad (_("non-constant expression in \".elseif\" statement"));
|
||||
|
||||
switch ((operatorT) arg)
|
||||
{
|
||||
case O_eq: t = operand.X_add_number == 0; break;
|
||||
case O_ne: t = operand.X_add_number != 0; break;
|
||||
case O_lt: t = operand.X_add_number < 0; break;
|
||||
case O_le: t = operand.X_add_number <= 0; break;
|
||||
case O_ge: t = operand.X_add_number >= 0; break;
|
||||
case O_gt: t = operand.X_add_number > 0; break;
|
||||
default:
|
||||
abort ();
|
||||
return;
|
||||
}
|
||||
|
||||
current_cframe->ignoring = current_cframe->dead_tree || ! t;
|
||||
}
|
||||
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& (current_cframe->previous_cframe == NULL
|
||||
|| ! current_cframe->previous_cframe->ignoring))
|
||||
{
|
||||
if (! current_cframe->ignoring)
|
||||
listing_list (1);
|
||||
else
|
||||
listing_list (2);
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
void
|
||||
s_endif (int arg ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct conditional_frame *hold;
|
||||
|
||||
if (current_cframe == NULL)
|
||||
{
|
||||
as_bad (_("\".endif\" without \".if\""));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& current_cframe->ignoring
|
||||
&& (current_cframe->previous_cframe == NULL
|
||||
|| ! current_cframe->previous_cframe->ignoring))
|
||||
listing_list (1);
|
||||
|
||||
hold = current_cframe;
|
||||
current_cframe = current_cframe->previous_cframe;
|
||||
obstack_free (&cond_obstack, hold);
|
||||
} /* if one pop too many */
|
||||
|
||||
if (flag_mri)
|
||||
{
|
||||
while (! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
++input_line_pointer;
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
void
|
||||
s_else (int arg ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (current_cframe == NULL)
|
||||
{
|
||||
as_bad (_("\".else\" without matching \".if\""));
|
||||
}
|
||||
else if (current_cframe->else_seen)
|
||||
{
|
||||
as_bad (_("duplicate \".else\""));
|
||||
as_bad_where (current_cframe->else_file_line.file,
|
||||
current_cframe->else_file_line.line,
|
||||
_("here is the previous \".else\""));
|
||||
as_bad_where (current_cframe->if_file_line.file,
|
||||
current_cframe->if_file_line.line,
|
||||
_("here is the previous \".if\""));
|
||||
}
|
||||
else
|
||||
{
|
||||
as_where (¤t_cframe->else_file_line.file,
|
||||
¤t_cframe->else_file_line.line);
|
||||
|
||||
current_cframe->ignoring =
|
||||
current_cframe->dead_tree | !current_cframe->ignoring;
|
||||
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& (current_cframe->previous_cframe == NULL
|
||||
|| ! current_cframe->previous_cframe->ignoring))
|
||||
{
|
||||
if (! current_cframe->ignoring)
|
||||
listing_list (1);
|
||||
else
|
||||
listing_list (2);
|
||||
}
|
||||
|
||||
current_cframe->else_seen = 1;
|
||||
}
|
||||
|
||||
if (flag_mri)
|
||||
{
|
||||
while (! is_end_of_line[(unsigned char) *input_line_pointer])
|
||||
++input_line_pointer;
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
void
|
||||
s_ifeqs (int arg)
|
||||
{
|
||||
char *s1, *s2;
|
||||
int len1, len2;
|
||||
int res;
|
||||
struct conditional_frame cframe;
|
||||
|
||||
s1 = demand_copy_C_string (&len1);
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
as_bad (_(".ifeqs syntax error"));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
++input_line_pointer;
|
||||
|
||||
s2 = demand_copy_C_string (&len2);
|
||||
|
||||
res = len1 == len2 && strncmp (s1, s2, len1) == 0;
|
||||
|
||||
initialize_cframe (&cframe);
|
||||
cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
|
||||
current_cframe = ((struct conditional_frame *)
|
||||
obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
|
||||
|
||||
if (LISTING_SKIP_COND ()
|
||||
&& cframe.ignoring
|
||||
&& (cframe.previous_cframe == NULL
|
||||
|| ! cframe.previous_cframe->ignoring))
|
||||
listing_list (2);
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
int
|
||||
ignore_input (void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = input_line_pointer;
|
||||
|
||||
if (NO_PSEUDO_DOT || flag_m68k_mri)
|
||||
{
|
||||
if (s[-1] != '.')
|
||||
--s;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s[-1] != '.')
|
||||
return (current_cframe != NULL) && (current_cframe->ignoring);
|
||||
}
|
||||
|
||||
/* We cannot ignore certain pseudo ops. */
|
||||
if (((s[0] == 'i'
|
||||
|| s[0] == 'I')
|
||||
&& (!strncasecmp (s, "if", 2)
|
||||
|| !strncasecmp (s, "ifdef", 5)
|
||||
|| !strncasecmp (s, "ifndef", 6)))
|
||||
|| ((s[0] == 'e'
|
||||
|| s[0] == 'E')
|
||||
&& (!strncasecmp (s, "else", 4)
|
||||
|| !strncasecmp (s, "endif", 5)
|
||||
|| !strncasecmp (s, "endc", 4))))
|
||||
return 0;
|
||||
|
||||
return (current_cframe != NULL) && (current_cframe->ignoring);
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_cframe (struct conditional_frame *cframe)
|
||||
{
|
||||
memset (cframe, 0, sizeof (*cframe));
|
||||
as_where (&cframe->if_file_line.file,
|
||||
&cframe->if_file_line.line);
|
||||
cframe->previous_cframe = current_cframe;
|
||||
cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring;
|
||||
cframe->macro_nest = macro_nest;
|
||||
}
|
||||
|
||||
/* Give an error if a conditional is unterminated inside a macro or
|
||||
the assembly as a whole. If NEST is non negative, we are being
|
||||
called because of the end of a macro expansion. If NEST is
|
||||
negative, we are being called at the of the input files. */
|
||||
|
||||
void
|
||||
cond_finish_check (int nest)
|
||||
{
|
||||
if (current_cframe != NULL && current_cframe->macro_nest >= nest)
|
||||
{
|
||||
if (nest >= 0)
|
||||
as_bad (_("end of macro inside conditional"));
|
||||
else
|
||||
as_bad (_("end of file inside conditional"));
|
||||
as_bad_where (current_cframe->if_file_line.file,
|
||||
current_cframe->if_file_line.line,
|
||||
_("here is the start of the unterminated conditional"));
|
||||
if (current_cframe->else_seen)
|
||||
as_bad_where (current_cframe->else_file_line.file,
|
||||
current_cframe->else_file_line.line,
|
||||
_("here is the \"else\" of the unterminated conditional"));
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called when we exit out of a macro. We assume
|
||||
that any conditionals which began within the macro are correctly
|
||||
nested, and just pop them off the stack. */
|
||||
|
||||
void
|
||||
cond_exit_macro (int nest)
|
||||
{
|
||||
while (current_cframe != NULL && current_cframe->macro_nest >= nest)
|
||||
{
|
||||
struct conditional_frame *hold;
|
||||
|
||||
hold = current_cframe;
|
||||
current_cframe = current_cframe->previous_cframe;
|
||||
obstack_free (&cond_obstack, hold);
|
||||
}
|
||||
}
|
363
contrib/toolchain/binutils/gas/config.h
Normal file
363
contrib/toolchain/binutils/gas/config.h
Normal file
@ -0,0 +1,363 @@
|
||||
/* config.h. Generated from config.in by configure. */
|
||||
/* config.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Check that config.h is #included before system headers
|
||||
(this works only for glibc, but that should be enough). */
|
||||
#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__CONFIG_H__)
|
||||
# error config.h must be #included before system headers
|
||||
#endif
|
||||
#define __CONFIG_H__ 1
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
/* #undef AC_APPLE_UNIVERSAL_BUILD */
|
||||
|
||||
/* Define if using AIX 5.2 value for C_WEAKEXT. */
|
||||
/* #undef AIX_WEAK_SUPPORT */
|
||||
|
||||
/* assert broken? */
|
||||
/* #undef BROKEN_ASSERT */
|
||||
|
||||
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
||||
systems. This function is required for `alloca.c' support on those systems.
|
||||
*/
|
||||
/* #undef CRAY_STACKSEG_END */
|
||||
|
||||
/* Compiling cross-assembler? */
|
||||
/* #undef CROSS_COMPILE */
|
||||
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
/* #undef C_ALLOCA */
|
||||
|
||||
/* Default architecture. */
|
||||
#define DEFAULT_ARCH "i386"
|
||||
|
||||
/* Default CRIS architecture. */
|
||||
/* #undef DEFAULT_CRIS_ARCH */
|
||||
|
||||
/* Default emulation. */
|
||||
#define DEFAULT_EMULATION ""
|
||||
|
||||
/* Supported emulations. */
|
||||
#define EMULATIONS
|
||||
|
||||
/* Define if you want run-time sanity checks. */
|
||||
/* #undef ENABLE_CHECKING */
|
||||
|
||||
/* Define to 1 if translation of program messages to the user's native
|
||||
language is requested. */
|
||||
/* #undef ENABLE_NLS */
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#define HAVE_ALLOCA 1
|
||||
|
||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
||||
*/
|
||||
/* #undef HAVE_ALLOCA_H */
|
||||
|
||||
/* Define to 1 if you have the declaration of `free', and to 0 if you don't.
|
||||
*/
|
||||
#define HAVE_DECL_FREE 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't.
|
||||
*/
|
||||
#define HAVE_DECL_GETENV 1
|
||||
|
||||
/* Is the prototype for getopt in <unistd.h> in the expected format? */
|
||||
#define HAVE_DECL_GETOPT 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `malloc', and to 0 if you don't.
|
||||
*/
|
||||
#define HAVE_DECL_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `mempcpy', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_MEMPCPY 0
|
||||
|
||||
/* Define to 1 if you have the declaration of `realloc', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_REALLOC 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `stpcpy', and to 0 if you don't.
|
||||
*/
|
||||
#define HAVE_DECL_STPCPY 0
|
||||
|
||||
/* Define to 1 if you have the declaration of `strstr', and to 0 if you don't.
|
||||
*/
|
||||
#define HAVE_DECL_STRSTR 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_VSNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef HAVE_DLFCN_H */
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define if your <locale.h> file defines LC_MESSAGES. */
|
||||
/* #undef HAVE_LC_MESSAGES */
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#define HAVE_LOCALE_H 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `remove' function. */
|
||||
#define HAVE_REMOVE
|
||||
|
||||
/* Define to 1 if you have the `sbrk' function. */
|
||||
/* #undef HAVE_SBRK */
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#define HAVE_SETLOCALE 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define if <sys/stat.h> has struct stat.st_mtim.tv_nsec */
|
||||
/* #undef HAVE_ST_MTIM_TV_NSEC */
|
||||
|
||||
/* Define if <sys/stat.h> has struct stat.st_mtim.tv_sec */
|
||||
/* #undef HAVE_ST_MTIM_TV_SEC */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#define HAVE_TIME_H 1
|
||||
|
||||
/* Define if <time.h> has struct tm.tm_gmtoff. */
|
||||
/* #undef HAVE_TM_GMTOFF */
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `unlink' function. */
|
||||
#define HAVE_UNLINK 1
|
||||
|
||||
/* Define to 1 if you have the <zlib.h> header file. */
|
||||
#define HAVE_ZLIB_H 1
|
||||
|
||||
/* Using i386 COFF? */
|
||||
#define I386COFF 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Using m68k COFF? */
|
||||
/* #undef M68KCOFF */
|
||||
|
||||
/* Using m88k COFF? */
|
||||
/* #undef M88KCOFF */
|
||||
|
||||
/* Default CPU for MIPS targets. */
|
||||
/* #undef MIPS_CPU_STRING_DEFAULT */
|
||||
|
||||
/* Generate 64-bit code by default on MIPS targets. */
|
||||
/* #undef MIPS_DEFAULT_64BIT */
|
||||
|
||||
/* Choose a default ABI for MIPS targets. */
|
||||
/* #undef MIPS_DEFAULT_ABI */
|
||||
|
||||
/* Define if environ is not declared in system header files. */
|
||||
/* #undef NEED_DECLARATION_ENVIRON */
|
||||
|
||||
/* Define if errno is not declared in system header files. */
|
||||
/* #undef NEED_DECLARATION_ERRNO */
|
||||
|
||||
/* Define if ffs is not declared in system header files. */
|
||||
#define NEED_DECLARATION_FFS 1
|
||||
|
||||
/* Define if free is not declared in system header files. */
|
||||
/* #undef NEED_DECLARATION_FREE */
|
||||
|
||||
/* Define if malloc is not declared in system header files. */
|
||||
/* #undef NEED_DECLARATION_MALLOC */
|
||||
|
||||
/* Define if sbrk is not declared in system header files. */
|
||||
#define NEED_DECLARATION_SBRK 1
|
||||
|
||||
/* Define if strstr is not declared in system header files. */
|
||||
/* #undef NEED_DECLARATION_STRSTR */
|
||||
|
||||
/* a.out support? */
|
||||
/* #undef OBJ_MAYBE_AOUT */
|
||||
|
||||
/* b.out support? */
|
||||
/* #undef OBJ_MAYBE_BOUT */
|
||||
|
||||
/* COFF support? */
|
||||
/* #undef OBJ_MAYBE_COFF */
|
||||
|
||||
/* ECOFF support? */
|
||||
/* #undef OBJ_MAYBE_ECOFF */
|
||||
|
||||
/* ELF support? */
|
||||
/* #undef OBJ_MAYBE_ELF */
|
||||
|
||||
/* generic support? */
|
||||
/* #undef OBJ_MAYBE_GENERIC */
|
||||
|
||||
/* SOM support? */
|
||||
/* #undef OBJ_MAYBE_SOM */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "gas"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define if defaulting to ELF on SCO 5. */
|
||||
/* #undef SCO_ELF */
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at runtime.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
/* #undef STACK_DIRECTION */
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Using strict COFF? */
|
||||
/* #undef STRICTCOFF */
|
||||
|
||||
/* Define if you can safely include both <string.h> and <strings.h>. */
|
||||
#define STRING_WITH_STRINGS 1
|
||||
|
||||
/* Target alias. */
|
||||
#define TARGET_ALIAS "mingw32"
|
||||
|
||||
/* Define as 1 if big endian. */
|
||||
/* #undef TARGET_BYTES_BIG_ENDIAN */
|
||||
|
||||
/* Canonical target. */
|
||||
#define TARGET_CANONICAL "i686-pc-mingw32"
|
||||
|
||||
/* Target CPU. */
|
||||
#define TARGET_CPU "i686"
|
||||
|
||||
/* Target OS. */
|
||||
#define TARGET_OS "mingw32"
|
||||
|
||||
/* Define if default target is PowerPC Solaris. */
|
||||
/* #undef TARGET_SOLARIS_COMMENT */
|
||||
|
||||
/* Define if target is Symbian OS. */
|
||||
/* #undef TARGET_SYMBIAN */
|
||||
|
||||
/* Target vendor. */
|
||||
#define TARGET_VENDOR "pc"
|
||||
|
||||
/* Use b modifier when opening binary files? */
|
||||
#define USE_BINARY_FOPEN 1
|
||||
|
||||
/* Use emulation support? */
|
||||
/* #undef USE_EMULATIONS */
|
||||
|
||||
/* Allow use of E_MIPS_ABI_O32 on MIPS targets. */
|
||||
/* #undef USE_E_MIPS_ABI_O32 */
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# define _ALL_SOURCE 1
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# define _TANDEM_SOURCE 1
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# define __EXTENSIONS__ 1
|
||||
#endif
|
||||
|
||||
|
||||
/* Using cgen code? */
|
||||
/* #undef USING_CGEN */
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.24"
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
/* # undef WORDS_BIGENDIAN */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
|
||||
`char[]'. */
|
||||
/* #undef YYTEXT_POINTER */
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
/* #undef _MINIX */
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
/* #undef _POSIX_1_SOURCE */
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
/* #undef _POSIX_SOURCE */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
813
contrib/toolchain/binutils/gas/config/atof-ieee.c
Normal file
813
contrib/toolchain/binutils/gas/config/atof-ieee.c
Normal file
@ -0,0 +1,813 @@
|
||||
/* atof_ieee.c - turn a Flonum into an IEEE floating point number
|
||||
Copyright 1987, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2005,
|
||||
2007, 2009 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
|
||||
/* Flonums returned here. */
|
||||
extern FLONUM_TYPE generic_floating_point_number;
|
||||
|
||||
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
|
||||
|
||||
#ifndef TC_LARGEST_EXPONENT_IS_NORMAL
|
||||
#define TC_LARGEST_EXPONENT_IS_NORMAL(PRECISION) 0
|
||||
#endif
|
||||
|
||||
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 (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 (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 (LITTLENUM_TYPE *words)
|
||||
{
|
||||
as_bad (_("cannot create floating-point number"));
|
||||
/* Zero the leftmost bit. */
|
||||
words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1;
|
||||
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 (char *str, /* Text to convert to binary. */
|
||||
int what_kind, /* 'd', 'f', 'x', 'p'. */
|
||||
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 (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 (TC_LARGEST_EXPONENT_IS_NORMAL (precision))
|
||||
as_warn (_("NaNs are not supported by this target\n"));
|
||||
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')
|
||||
{
|
||||
if (TC_LARGEST_EXPONENT_IS_NORMAL (precision))
|
||||
as_warn (_("Infinities are not supported by this target\n"));
|
||||
|
||||
/* +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')
|
||||
{
|
||||
if (TC_LARGEST_EXPONENT_IS_NORMAL (precision))
|
||||
as_warn (_("Infinities are not supported by this target\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]
|
||||
|| (prec_bits != (precision * LITTLENUM_NUMBER_OF_BITS
|
||||
- exponent_bits - 1)
|
||||
#ifdef TC_I386
|
||||
/* An extended precision float with only the integer
|
||||
bit set would be invalid. That must be converted
|
||||
to the smallest normalized number. */
|
||||
&& !(precision == X_PRECISION
|
||||
&& prec_bits == (precision * LITTLENUM_NUMBER_OF_BITS
|
||||
- exponent_bits - 2))
|
||||
#endif
|
||||
))
|
||||
{
|
||||
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;
|
||||
#ifdef TC_I386
|
||||
/* Set the integer bit in the extended precision format.
|
||||
This cannot happen on the m68k where the mantissa
|
||||
just overflows into the integer bit above. */
|
||||
if (precision == X_PRECISION)
|
||||
*lp++ = 1 << (LITTLENUM_NUMBER_OF_BITS - 1);
|
||||
#endif
|
||||
while (lp < words_end)
|
||||
*lp++ = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
*lp += 1;
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
else if ((unsigned long) exponent_4 > mask[exponent_bits]
|
||||
|| (! TC_LARGEST_EXPONENT_IS_NORMAL (precision)
|
||||
&& (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--)
|
||||
{
|
||||
carry = *lp + carry;
|
||||
*lp = carry;
|
||||
carry >>= LITTLENUM_NUMBER_OF_BITS;
|
||||
if (lp == words)
|
||||
break;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
return return_value;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
extern const char FLT_CHARS[];
|
||||
#define MAX_LITTLENUMS 6
|
||||
|
||||
/* This is a utility function called from various tc-*.c files. It
|
||||
is here in order to reduce code duplication.
|
||||
|
||||
Turn a string at input_line_pointer into a floating point constant
|
||||
of type TYPE (a character found in the FLT_CHARS macro), and store
|
||||
it as LITTLENUMS in the bytes buffer LITP. The number of chars
|
||||
emitted is stored in *SIZEP. BIG_WORDIAN is TRUE if the littlenums
|
||||
should be emitted most significant littlenum first.
|
||||
|
||||
An error message is returned, or a NULL pointer if everything went OK. */
|
||||
|
||||
char *
|
||||
ieee_md_atof (int type,
|
||||
char *litP,
|
||||
int *sizeP,
|
||||
bfd_boolean big_wordian)
|
||||
{
|
||||
LITTLENUM_TYPE words[MAX_LITTLENUMS];
|
||||
LITTLENUM_TYPE *wordP;
|
||||
char *t;
|
||||
int prec = 0;
|
||||
|
||||
if (strchr (FLT_CHARS, type) != NULL)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 's':
|
||||
case 'S':
|
||||
prec = F_PRECISION;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
case 'r':
|
||||
case 'R':
|
||||
prec = D_PRECISION;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
prec = X_PRECISION;
|
||||
type = 'x'; /* This is what atof_ieee() understands. */
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'p':
|
||||
case 'P':
|
||||
#ifdef TC_M68K
|
||||
/* Note: on the m68k there is a gap of 16 bits (one littlenum)
|
||||
between the exponent and mantissa. Hence the precision is
|
||||
6 and not 5. */
|
||||
prec = P_PRECISION + 1;
|
||||
#else
|
||||
prec = P_PRECISION;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* The 'f' and 'd' types are always recognised, even if the target has
|
||||
not put them into the FLT_CHARS macro. This is because the 'f' type
|
||||
can come from the .dc.s, .dcb.s, .float or .single pseudo-ops and the
|
||||
'd' type from the .dc.d, .dbc.d or .double pseudo-ops.
|
||||
|
||||
The 'x' type is not implicitly recongised however, even though it can
|
||||
be generated by the .dc.x and .dbc.x pseudo-ops because not all targets
|
||||
can support floating point values that big. ie the target has to
|
||||
explicitly allow them by putting them into FLT_CHARS. */
|
||||
else if (type == 'f')
|
||||
prec = F_PRECISION;
|
||||
else if (type == 'd')
|
||||
prec = D_PRECISION;
|
||||
|
||||
if (prec == 0)
|
||||
{
|
||||
*sizeP = 0;
|
||||
return _("Unrecognized or unsupported floating point constant");
|
||||
}
|
||||
|
||||
gas_assert (prec <= MAX_LITTLENUMS);
|
||||
|
||||
t = atof_ieee (input_line_pointer, type, words);
|
||||
if (t)
|
||||
input_line_pointer = t;
|
||||
|
||||
*sizeP = prec * sizeof (LITTLENUM_TYPE);
|
||||
|
||||
if (big_wordian)
|
||||
{
|
||||
for (wordP = words; prec --;)
|
||||
{
|
||||
md_number_to_chars (litP, (valueT) (* wordP ++), sizeof (LITTLENUM_TYPE));
|
||||
litP += sizeof (LITTLENUM_TYPE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (wordP = words + prec; prec --;)
|
||||
{
|
||||
md_number_to_chars (litP, (valueT) (* -- wordP), sizeof (LITTLENUM_TYPE));
|
||||
litP += sizeof (LITTLENUM_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
1018
contrib/toolchain/binutils/gas/config/obj-coff-seh.c
Normal file
1018
contrib/toolchain/binutils/gas/config/obj-coff-seh.c
Normal file
File diff suppressed because it is too large
Load Diff
205
contrib/toolchain/binutils/gas/config/obj-coff-seh.h
Normal file
205
contrib/toolchain/binutils/gas/config/obj-coff-seh.h
Normal file
@ -0,0 +1,205 @@
|
||||
/* seh pdata/xdata coff object file format
|
||||
Copyright 2009, 2010, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Short overview:
|
||||
There are at the moment three different function entry formats preset.
|
||||
The first is the MIPS one. The second version
|
||||
is for ARM, PPC, SH3, and SH4 mainly for Windows CE.
|
||||
The third is the IA64 and x64 version. Note, the IA64 isn't implemented yet,
|
||||
but to find information about it, please see specification about IA64 on
|
||||
http://download.intel.com/design/Itanium/Downloads/245358.pdf file.
|
||||
|
||||
The first version has just entries in the pdata section: BeginAddress,
|
||||
EndAddress, ExceptionHandler, HandlerData, and PrologueEndAddress. Each
|
||||
value is a pointer to the corresponding data and has size of 4 bytes.
|
||||
|
||||
The second variant has the following entries in the pdata section.
|
||||
BeginAddress, PrologueLength (8 bits), EndAddress (22 bits),
|
||||
Use-32-bit-instruction (1 bit), and Exception-Handler-Exists (1 bit).
|
||||
If the FunctionLength is zero, or the Exception-Handler-Exists bit
|
||||
is true, a PDATA_EH block is placed directly before function entry.
|
||||
|
||||
The third version has a function entry block of BeginAddress (RVA),
|
||||
EndAddress (RVA), and UnwindData (RVA). The description of the
|
||||
prologue, excepetion-handler, and additional SEH data is stored
|
||||
within the UNWIND_DATA field in the xdata section.
|
||||
|
||||
The pseudos:
|
||||
.seh_proc <fct_name>
|
||||
.seh_endprologue
|
||||
.seh_handler <handler>[,@unwind][,@except] (x64)
|
||||
.seh_handler <handler>[,<handler_data>] (others)
|
||||
.seh_handlerdata
|
||||
.seh_eh
|
||||
.seh_32/.seh_no32
|
||||
.seh_endproc
|
||||
.seh_setframe <reg>,<offset>
|
||||
.seh_stackalloc
|
||||
.seh_pushreg
|
||||
.seh_savereg
|
||||
.seh_savexmm
|
||||
.seh_pushframe
|
||||
*/
|
||||
|
||||
/* architecture specific pdata/xdata handling. */
|
||||
#define SEH_CMDS \
|
||||
{"seh_proc", obj_coff_seh_proc, 0}, \
|
||||
{"seh_endproc", obj_coff_seh_endproc, 0}, \
|
||||
{"seh_pushreg", obj_coff_seh_pushreg, 0}, \
|
||||
{"seh_savereg", obj_coff_seh_save, 1}, \
|
||||
{"seh_savexmm", obj_coff_seh_save, 2}, \
|
||||
{"seh_pushframe", obj_coff_seh_pushframe, 0}, \
|
||||
{"seh_endprologue", obj_coff_seh_endprologue, 0}, \
|
||||
{"seh_setframe", obj_coff_seh_setframe, 0}, \
|
||||
{"seh_stackalloc", obj_coff_seh_stackalloc, 0}, \
|
||||
{"seh_eh", obj_coff_seh_eh, 0}, \
|
||||
{"seh_32", obj_coff_seh_32, 1}, \
|
||||
{"seh_no32", obj_coff_seh_32, 0}, \
|
||||
{"seh_handler", obj_coff_seh_handler, 0}, \
|
||||
{"seh_handlerdata", obj_coff_seh_handlerdata, 0},
|
||||
|
||||
/* Type definitions. */
|
||||
|
||||
typedef struct seh_prologue_element
|
||||
{
|
||||
int code;
|
||||
int info;
|
||||
offsetT off;
|
||||
symbolS *pc_addr;
|
||||
} seh_prologue_element;
|
||||
|
||||
typedef struct seh_context
|
||||
{
|
||||
struct seh_context *next;
|
||||
|
||||
/* Initial code-segment. */
|
||||
segT code_seg;
|
||||
/* Function name. */
|
||||
char *func_name;
|
||||
/* BeginAddress. */
|
||||
symbolS *start_addr;
|
||||
/* EndAddress. */
|
||||
symbolS *end_addr;
|
||||
/* Unwind data. */
|
||||
symbolS *xdata_addr;
|
||||
/* PrologueEnd. */
|
||||
symbolS *endprologue_addr;
|
||||
/* ExceptionHandler. */
|
||||
expressionS handler;
|
||||
/* ExceptionHandlerData. (arm, mips) */
|
||||
expressionS handler_data;
|
||||
|
||||
/* ARM .seh_eh directive seen. */
|
||||
int handler_written;
|
||||
|
||||
/* WinCE specific data. */
|
||||
int use_instruction_32;
|
||||
/* Was record already processed. */
|
||||
int done;
|
||||
|
||||
/* x64 flags for the xdata header. */
|
||||
int handler_flags;
|
||||
int subsection;
|
||||
|
||||
/* x64 framereg and frame offset information. */
|
||||
int framereg;
|
||||
int frameoff;
|
||||
|
||||
/* Information about x64 specific unwind data fields. */
|
||||
int elems_count;
|
||||
int elems_max;
|
||||
seh_prologue_element *elems;
|
||||
} seh_context;
|
||||
|
||||
typedef enum seh_kind {
|
||||
seh_kind_unknown = 0,
|
||||
seh_kind_mips = 1, /* Used for MIPS and x86 pdata generation. */
|
||||
seh_kind_arm = 2, /* Used for ARM, PPC, SH3, and SH4 pdata (PDATA_EH) generation. */
|
||||
seh_kind_x64 = 3 /* Used for IA64 and x64 pdata/xdata generation. */
|
||||
} seh_kind;
|
||||
|
||||
/* Forward declarations. */
|
||||
static void obj_coff_seh_stackalloc (int);
|
||||
static void obj_coff_seh_setframe (int);
|
||||
static void obj_coff_seh_endprologue (int);
|
||||
static void obj_coff_seh_save (int);
|
||||
static void obj_coff_seh_pushreg (int);
|
||||
static void obj_coff_seh_pushframe (int);
|
||||
static void obj_coff_seh_endproc (int);
|
||||
static void obj_coff_seh_eh (int);
|
||||
static void obj_coff_seh_32 (int);
|
||||
static void obj_coff_seh_proc (int);
|
||||
static void obj_coff_seh_handler (int);
|
||||
static void obj_coff_seh_handlerdata (int);
|
||||
|
||||
#define UNDSEC bfd_und_section_ptr
|
||||
|
||||
/* Check if x64 UNW_... macros are already defined. */
|
||||
#ifndef PEX64_FLAG_NHANDLER
|
||||
/* We can't include here coff/pe.h header. So we have to copy macros
|
||||
from coff/pe.h here. */
|
||||
#define PEX64_UNWCODE_CODE(VAL) ((VAL) & 0xf)
|
||||
#define PEX64_UNWCODE_INFO(VAL) (((VAL) >> 4) & 0xf)
|
||||
|
||||
/* The unwind info. */
|
||||
#define UNW_FLAG_NHANDLER 0
|
||||
#define UNW_FLAG_EHANDLER 1
|
||||
#define UNW_FLAG_UHANDLER 2
|
||||
#define UNW_FLAG_FHANDLER 3
|
||||
#define UNW_FLAG_CHAININFO 4
|
||||
|
||||
#define UNW_FLAG_MASK 0x1f
|
||||
|
||||
/* The unwind codes. */
|
||||
#define UWOP_PUSH_NONVOL 0
|
||||
#define UWOP_ALLOC_LARGE 1
|
||||
#define UWOP_ALLOC_SMALL 2
|
||||
#define UWOP_SET_FPREG 3
|
||||
#define UWOP_SAVE_NONVOL 4
|
||||
#define UWOP_SAVE_NONVOL_FAR 5
|
||||
#define UWOP_SAVE_XMM 6
|
||||
#define UWOP_SAVE_XMM_FAR 7
|
||||
#define UWOP_SAVE_XMM128 8
|
||||
#define UWOP_SAVE_XMM128_FAR 9
|
||||
#define UWOP_PUSH_MACHFRAME 10
|
||||
|
||||
#define PEX64_UWI_VERSION(VAL) ((VAL) & 7)
|
||||
#define PEX64_UWI_FLAGS(VAL) (((VAL) >> 3) & 0x1f)
|
||||
#define PEX64_UWI_FRAMEREG(VAL) ((VAL) & 0xf)
|
||||
#define PEX64_UWI_FRAMEOFF(VAL) (((VAL) >> 4) & 0xf)
|
||||
#define PEX64_UWI_SIZEOF_UWCODE_ARRAY(VAL) \
|
||||
((((VAL) + 1) & ~1) * 2)
|
||||
|
||||
#define PEX64_OFFSET_TO_UNWIND_CODE 0x4
|
||||
|
||||
#define PEX64_OFFSET_TO_HANDLER_RVA (COUNTOFUNWINDCODES) \
|
||||
(PEX64_OFFSET_TO_UNWIND_CODE + \
|
||||
PEX64_UWI_SIZEOF_UWCODE_ARRAY(COUNTOFUNWINDCODES))
|
||||
|
||||
#define PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) \
|
||||
(PEX64_OFFSET_TO_HANDLER_RVA(COUNTOFUNWINDCODES) + 4)
|
||||
|
||||
#define PEX64_SCOPE_ENTRY(COUNTOFUNWINDCODES, IDX) \
|
||||
(PEX64_OFFSET_TO_SCOPE_COUNT(COUNTOFUNWINDCODES) + \
|
||||
PEX64_SCOPE_ENTRY_SIZE * (IDX))
|
||||
|
||||
#endif
|
||||
|
1957
contrib/toolchain/binutils/gas/config/obj-coff.c
Normal file
1957
contrib/toolchain/binutils/gas/config/obj-coff.c
Normal file
File diff suppressed because it is too large
Load Diff
415
contrib/toolchain/binutils/gas/config/obj-coff.h
Normal file
415
contrib/toolchain/binutils/gas/config/obj-coff.h
Normal file
@ -0,0 +1,415 @@
|
||||
/* coff object file format
|
||||
Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef OBJ_FORMAT_H
|
||||
#define OBJ_FORMAT_H
|
||||
|
||||
#define OBJ_COFF 1
|
||||
|
||||
#include "targ-cpu.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
|
||||
#ifdef TE_PEP
|
||||
#include "coff/x86_64.h"
|
||||
#else
|
||||
#include "coff/i386.h"
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_FORMAT
|
||||
#ifdef TE_PEP
|
||||
#define TARGET_FORMAT "coff-x86-64"
|
||||
#else
|
||||
#define TARGET_FORMAT "coff-i386"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TC_M68K
|
||||
#include "coff/m68k.h"
|
||||
#ifndef TARGET_FORMAT
|
||||
#define TARGET_FORMAT "coff-m68k"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TC_OR32
|
||||
#include "coff/or32.h"
|
||||
#define TARGET_FORMAT "coff-or32-big"
|
||||
#endif
|
||||
|
||||
#ifdef TC_I960
|
||||
#include "coff/i960.h"
|
||||
#define TARGET_FORMAT "coff-Intel-little"
|
||||
#endif
|
||||
|
||||
#ifdef TC_Z80
|
||||
#include "coff/z80.h"
|
||||
#define TARGET_FORMAT "coff-z80"
|
||||
#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
|
||||
|
||||
#ifdef TE_PE
|
||||
#define COFF_WITH_PE
|
||||
#endif
|
||||
|
||||
#include "coff/sh.h"
|
||||
|
||||
#ifdef TE_PE
|
||||
#define TARGET_FORMAT "pe-shl"
|
||||
#else
|
||||
|
||||
#define TARGET_FORMAT \
|
||||
(!target_big_endian \
|
||||
? (sh_small ? "coff-shl-small" : "coff-shl") \
|
||||
: (sh_small ? "coff-sh-small" : "coff-sh"))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TC_MIPS
|
||||
#define COFF_WITH_PE
|
||||
#include "coff/mipspe.h"
|
||||
#undef TARGET_FORMAT
|
||||
#define TARGET_FORMAT "pe-mips"
|
||||
#endif
|
||||
|
||||
#ifdef TC_TIC30
|
||||
#include "coff/tic30.h"
|
||||
#define TARGET_FORMAT "coff-tic30"
|
||||
#endif
|
||||
|
||||
#ifdef TC_TIC4X
|
||||
#include "coff/tic4x.h"
|
||||
#define TARGET_FORMAT "coff2-tic4x"
|
||||
#endif
|
||||
|
||||
#ifdef TC_TIC54X
|
||||
#include "coff/tic54x.h"
|
||||
#define TARGET_FORMAT "coff1-c54x"
|
||||
#endif
|
||||
|
||||
#ifdef TC_MCORE
|
||||
#include "coff/mcore.h"
|
||||
#ifndef TARGET_FORMAT
|
||||
#define TARGET_FORMAT "pe-mcore"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TE_PE
|
||||
#define obj_set_weak_hook pecoff_obj_set_weak_hook
|
||||
#define obj_clear_weak_hook pecoff_obj_clear_weak_hook
|
||||
#endif
|
||||
|
||||
#ifndef OBJ_COFF_MAX_AUXENTRIES
|
||||
#define OBJ_COFF_MAX_AUXENTRIES 1
|
||||
#endif
|
||||
|
||||
#define obj_symbol_new_hook coff_obj_symbol_new_hook
|
||||
#define obj_symbol_clone_hook coff_obj_symbol_clone_hook
|
||||
#define obj_read_begin_hook coff_obj_read_begin_hook
|
||||
|
||||
#include "bfd/libcoff.h"
|
||||
|
||||
#define OUTPUT_FLAVOR bfd_target_coff_flavour
|
||||
|
||||
/* 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 symbolS *
|
||||
#define sy_tc bal
|
||||
#endif
|
||||
|
||||
#define OBJ_SYMFIELD_TYPE unsigned long
|
||||
#define sy_obj sy_obj_flags
|
||||
|
||||
/* We can't use the predefined section symbols in bfd/section.c, as
|
||||
COFF symbols have extra fields. See bfd/libcoff.h:coff_symbol_type. */
|
||||
#ifndef obj_sec_sym_ok_for_reloc
|
||||
#define obj_sec_sym_ok_for_reloc(SEC) ((SEC)->owner != 0)
|
||||
#endif
|
||||
|
||||
#define SYM_AUXENT(S) \
|
||||
(&coffsymbol (symbol_get_bfdsym (S))->native[1].u.auxent)
|
||||
#define SYM_AUXINFO(S) \
|
||||
(&coffsymbol (symbol_get_bfdsym (S))->native[1])
|
||||
|
||||
/* The number of auxiliary entries. */
|
||||
#define S_GET_NUMBER_AUXILIARY(s) \
|
||||
(coffsymbol (symbol_get_bfdsym (s))->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)
|
||||
|
||||
/* 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) (* symbol_get_obj (s))
|
||||
#define SF_GET_DEBUG(s) (symbol_get_bfdsym (s)->flags & BSF_DEBUGGING)
|
||||
#define SF_SET_DEBUG(s) (symbol_get_bfdsym (s)->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;
|
||||
extern symbolS *coff_last_function;
|
||||
|
||||
#define obj_emit_lineno(WHERE, LINE, FILE_START) abort ()
|
||||
#define obj_app_file(name, app) c_dot_file_symbol (name, app)
|
||||
#define obj_frob_symbol(S,P) coff_frob_symbol (S, & P)
|
||||
#define obj_frob_section(S) coff_frob_section (S)
|
||||
#define obj_frob_file_after_relocs() coff_frob_file_after_relocs ()
|
||||
#ifndef obj_adjust_symtab
|
||||
#define obj_adjust_symtab() coff_adjust_symtab ()
|
||||
#endif
|
||||
|
||||
/* Forward the segment of a forwarded symbol, handle assignments that
|
||||
just copy symbol values, etc. */
|
||||
#ifndef OBJ_COPY_SYMBOL_ATTRIBUTES
|
||||
#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
|
||||
#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 const pseudo_typeS coff_pseudo_table[];
|
||||
|
||||
#ifndef obj_pop_insert
|
||||
#define obj_pop_insert() pop_insert (coff_pseudo_table)
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
#define INIT_STAB_SECTION(seg) obj_coff_init_stab_section (seg)
|
||||
|
||||
/* Store the number of relocations in the section aux entry. */
|
||||
#define SET_SECTION_RELOCS(sec, relocs, n) \
|
||||
SA_SET_SCN_NRELOC (section_symbol (sec), n)
|
||||
|
||||
#define obj_app_file(name, app) c_dot_file_symbol (name, app)
|
||||
|
||||
extern int S_SET_DATA_TYPE (symbolS *, int);
|
||||
extern int S_SET_STORAGE_CLASS (symbolS *, int);
|
||||
extern int S_GET_STORAGE_CLASS (symbolS *);
|
||||
extern void SA_SET_SYM_ENDNDX (symbolS *, symbolS *);
|
||||
extern void coff_add_linesym (symbolS *);
|
||||
extern void c_dot_file_symbol (const char *, int);
|
||||
extern void coff_frob_symbol (symbolS *, int *);
|
||||
extern void coff_adjust_symtab (void);
|
||||
extern void coff_frob_section (segT);
|
||||
extern void coff_adjust_section_syms (bfd *, asection *, void *);
|
||||
extern void coff_frob_file_after_relocs (void);
|
||||
extern void coff_obj_symbol_new_hook (symbolS *);
|
||||
extern void coff_obj_symbol_clone_hook (symbolS *, symbolS *);
|
||||
extern void coff_obj_read_begin_hook (void);
|
||||
#ifdef TE_PE
|
||||
extern void pecoff_obj_set_weak_hook (symbolS *);
|
||||
extern void pecoff_obj_clear_weak_hook (symbolS *);
|
||||
#endif
|
||||
extern void obj_coff_section (int);
|
||||
extern segT obj_coff_add_segment (const char *);
|
||||
extern void obj_coff_section (int);
|
||||
extern void c_dot_file_symbol (const char *, int);
|
||||
extern segT s_get_segment (symbolS *);
|
||||
#ifndef tc_coff_symbol_emit_hook
|
||||
extern void tc_coff_symbol_emit_hook (symbolS *);
|
||||
#endif
|
||||
extern void obj_coff_pe_handle_link_once (void);
|
||||
extern void obj_coff_init_stab_section (segT);
|
||||
extern void c_section_header (struct internal_scnhdr *,
|
||||
char *, long, long, long, long,
|
||||
long, long, long, long);
|
||||
extern void obj_coff_seh_do_final (void);
|
||||
|
||||
#ifndef obj_coff_generate_pdata
|
||||
#define obj_coff_generate_pdata obj_coff_seh_do_final
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* OBJ_FORMAT_H */
|
1005
contrib/toolchain/binutils/gas/config/tc-i386-intel.c
Normal file
1005
contrib/toolchain/binutils/gas/config/tc-i386-intel.c
Normal file
File diff suppressed because it is too large
Load Diff
10565
contrib/toolchain/binutils/gas/config/tc-i386.c
Normal file
10565
contrib/toolchain/binutils/gas/config/tc-i386.c
Normal file
File diff suppressed because it is too large
Load Diff
342
contrib/toolchain/binutils/gas/config/tc-i386.h
Normal file
342
contrib/toolchain/binutils/gas/config/tc-i386.h
Normal file
@ -0,0 +1,342 @@
|
||||
/* tc-i386.h -- Header file for tc-i386.c
|
||||
Copyright 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef TC_I386
|
||||
#define TC_I386 1
|
||||
|
||||
#include "opcodes/i386-opc.h"
|
||||
|
||||
struct fix;
|
||||
|
||||
#define TARGET_BYTES_BIG_ENDIAN 0
|
||||
|
||||
#define TARGET_ARCH (i386_arch ())
|
||||
#define TARGET_MACH (i386_mach ())
|
||||
extern enum bfd_architecture i386_arch (void);
|
||||
extern unsigned long i386_mach (void);
|
||||
|
||||
#ifdef TE_FreeBSD
|
||||
#define AOUT_TARGET_FORMAT "a.out-i386-freebsd"
|
||||
#endif
|
||||
#ifdef TE_NetBSD
|
||||
#define AOUT_TARGET_FORMAT "a.out-i386-netbsd"
|
||||
#endif
|
||||
#ifdef TE_386BSD
|
||||
#define AOUT_TARGET_FORMAT "a.out-i386-bsd"
|
||||
#endif
|
||||
#ifdef TE_LINUX
|
||||
#define AOUT_TARGET_FORMAT "a.out-i386-linux"
|
||||
#endif
|
||||
#ifdef TE_Mach
|
||||
#define AOUT_TARGET_FORMAT "a.out-mach3"
|
||||
#endif
|
||||
#ifdef TE_DYNIX
|
||||
#define AOUT_TARGET_FORMAT "a.out-i386-dynix"
|
||||
#endif
|
||||
#ifndef AOUT_TARGET_FORMAT
|
||||
#define AOUT_TARGET_FORMAT "a.out-i386"
|
||||
#endif
|
||||
|
||||
#ifdef TE_FreeBSD
|
||||
#define ELF_TARGET_FORMAT "elf32-i386-freebsd"
|
||||
#define ELF_TARGET_FORMAT64 "elf64-x86-64-freebsd"
|
||||
#elif defined (TE_VXWORKS)
|
||||
#define ELF_TARGET_FORMAT "elf32-i386-vxworks"
|
||||
#elif defined (TE_NACL)
|
||||
#define ELF_TARGET_FORMAT "elf32-i386-nacl"
|
||||
#define ELF_TARGET_FORMAT32 "elf32-x86-64-nacl"
|
||||
#define ELF_TARGET_FORMAT64 "elf64-x86-64-nacl"
|
||||
#endif
|
||||
|
||||
#ifdef TE_SOLARIS
|
||||
#define ELF_TARGET_FORMAT "elf32-i386-sol2"
|
||||
#define ELF_TARGET_FORMAT64 "elf64-x86-64-sol2"
|
||||
#endif
|
||||
|
||||
#ifndef ELF_TARGET_FORMAT
|
||||
#define ELF_TARGET_FORMAT "elf32-i386"
|
||||
#endif
|
||||
|
||||
#ifndef ELF_TARGET_FORMAT64
|
||||
#define ELF_TARGET_FORMAT64 "elf64-x86-64"
|
||||
#endif
|
||||
|
||||
#ifndef ELF_TARGET_FORMAT32
|
||||
#define ELF_TARGET_FORMAT32 "elf32-x86-64"
|
||||
#endif
|
||||
|
||||
#ifndef ELF_TARGET_L1OM_FORMAT
|
||||
#define ELF_TARGET_L1OM_FORMAT "elf64-l1om"
|
||||
#endif
|
||||
|
||||
#ifndef ELF_TARGET_K1OM_FORMAT
|
||||
#define ELF_TARGET_K1OM_FORMAT "elf64-k1om"
|
||||
#endif
|
||||
|
||||
#if ((defined (OBJ_MAYBE_COFF) && defined (OBJ_MAYBE_AOUT)) \
|
||||
|| defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \
|
||||
|| defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O))
|
||||
extern const char *i386_target_format (void);
|
||||
#define TARGET_FORMAT i386_target_format ()
|
||||
#else
|
||||
#ifdef TE_GO32
|
||||
#define TARGET_FORMAT "coff-go32"
|
||||
#endif
|
||||
#ifdef OBJ_AOUT
|
||||
#define TARGET_FORMAT AOUT_TARGET_FORMAT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined (OBJ_MAYBE_ELF) || defined (OBJ_ELF))
|
||||
#define md_end i386_elf_emit_arch_note
|
||||
extern void i386_elf_emit_arch_note (void);
|
||||
#endif
|
||||
|
||||
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
|
||||
|
||||
/* '$' may be used as immediate prefix. */
|
||||
#undef LOCAL_LABELS_DOLLAR
|
||||
#define LOCAL_LABELS_DOLLAR 0
|
||||
#undef LOCAL_LABELS_FB
|
||||
#define LOCAL_LABELS_FB 1
|
||||
|
||||
extern const char extra_symbol_chars[];
|
||||
#define tc_symbol_chars extra_symbol_chars
|
||||
|
||||
extern const char *i386_comment_chars;
|
||||
#define tc_comment_chars i386_comment_chars
|
||||
|
||||
/* 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
|
||||
|
||||
#if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && !defined (LEX_AT)
|
||||
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) x86_cons (EXP, NBYTES)
|
||||
#endif
|
||||
extern void x86_cons (expressionS *, int);
|
||||
|
||||
#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP) x86_cons_fix_new(FRAG, OFF, LEN, EXP)
|
||||
extern void x86_cons_fix_new
|
||||
(fragS *, unsigned int, unsigned int, expressionS *);
|
||||
|
||||
#define TC_ADDRESS_BYTES x86_address_bytes
|
||||
extern int x86_address_bytes (void);
|
||||
|
||||
#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
|
||||
|
||||
#define NO_RELOC BFD_RELOC_NONE
|
||||
|
||||
void i386_validate_fix (struct fix *);
|
||||
#define TC_VALIDATE_FIX(FIX,SEGTYPE,SKIP) i386_validate_fix(FIX)
|
||||
|
||||
#define tc_fix_adjustable(X) tc_i386_fix_adjustable(X)
|
||||
extern int tc_i386_fix_adjustable (struct fix *);
|
||||
|
||||
/* Values passed to md_apply_fix don't include the symbol value. */
|
||||
#define MD_APPLY_SYM_VALUE(FIX) 0
|
||||
|
||||
/* ELF wants external syms kept, as does PE COFF. */
|
||||
#if defined (TE_PE) && defined (STRICT_PE_FORMAT)
|
||||
#define EXTERN_FORCE_RELOC \
|
||||
(OUTPUT_FLAVOR == bfd_target_elf_flavour \
|
||||
|| OUTPUT_FLAVOR == bfd_target_coff_flavour)
|
||||
#else
|
||||
#define EXTERN_FORCE_RELOC \
|
||||
(OUTPUT_FLAVOR == bfd_target_elf_flavour)
|
||||
#endif
|
||||
|
||||
/* This expression evaluates to true if the relocation is for a local
|
||||
object for which we still want to do the relocation at runtime.
|
||||
False if we are willing to perform this relocation while building
|
||||
the .o file. GOTOFF and GOT32 do not need to be checked here because
|
||||
they are not pcrel. .*/
|
||||
|
||||
#define TC_FORCE_RELOCATION_LOCAL(FIX) \
|
||||
(!(FIX)->fx_pcrel \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_386_PLT32 \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_386_GOTPC \
|
||||
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \
|
||||
|| TC_FORCE_RELOCATION (FIX))
|
||||
|
||||
extern int i386_parse_name (char *, expressionS *, char *);
|
||||
#define md_parse_name(s, e, m, c) i386_parse_name (s, e, c)
|
||||
|
||||
extern operatorT i386_operator (const char *name, unsigned int operands, char *);
|
||||
#define md_operator i386_operator
|
||||
|
||||
extern int i386_need_index_operator (void);
|
||||
#define md_need_index_operator i386_need_index_operator
|
||||
|
||||
#define md_register_arithmetic 0
|
||||
|
||||
extern const struct relax_type md_relax_table[];
|
||||
#define TC_GENERIC_RELAX_TABLE md_relax_table
|
||||
|
||||
extern int optimize_align_code;
|
||||
|
||||
#define md_do_align(n, fill, len, max, around) \
|
||||
if ((n) \
|
||||
&& !need_pass_2 \
|
||||
&& optimize_align_code \
|
||||
&& (!(fill) \
|
||||
|| ((char)*(fill) == (char)0x90 && (len) == 1)) \
|
||||
&& subseg_text_p (now_seg)) \
|
||||
{ \
|
||||
frag_align_code ((n), (max)); \
|
||||
goto around; \
|
||||
}
|
||||
|
||||
#define MAX_MEM_FOR_RS_ALIGN_CODE 31
|
||||
|
||||
extern void i386_align_code (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));
|
||||
|
||||
void i386_print_statistics (FILE *);
|
||||
#define tc_print_statistics i386_print_statistics
|
||||
|
||||
extern unsigned int i386_frag_max_var (fragS *);
|
||||
#define md_frag_max_var i386_frag_max_var
|
||||
|
||||
#define md_number_to_chars number_to_chars_littleendian
|
||||
|
||||
enum processor_type
|
||||
{
|
||||
PROCESSOR_UNKNOWN,
|
||||
PROCESSOR_I386,
|
||||
PROCESSOR_I486,
|
||||
PROCESSOR_PENTIUM,
|
||||
PROCESSOR_PENTIUMPRO,
|
||||
PROCESSOR_PENTIUM4,
|
||||
PROCESSOR_NOCONA,
|
||||
PROCESSOR_CORE,
|
||||
PROCESSOR_CORE2,
|
||||
PROCESSOR_COREI7,
|
||||
PROCESSOR_L1OM,
|
||||
PROCESSOR_K1OM,
|
||||
PROCESSOR_K6,
|
||||
PROCESSOR_ATHLON,
|
||||
PROCESSOR_K8,
|
||||
PROCESSOR_GENERIC32,
|
||||
PROCESSOR_GENERIC64,
|
||||
PROCESSOR_AMDFAM10,
|
||||
PROCESSOR_BD,
|
||||
PROCESSOR_BT
|
||||
};
|
||||
|
||||
extern enum processor_type cpu_arch_tune;
|
||||
extern enum processor_type cpu_arch_isa;
|
||||
extern i386_cpu_flags cpu_arch_isa_flags;
|
||||
|
||||
struct i386_tc_frag_data
|
||||
{
|
||||
enum processor_type isa;
|
||||
i386_cpu_flags isa_flags;
|
||||
enum processor_type tune;
|
||||
};
|
||||
|
||||
/* We need to emit the right NOP pattern in .align frags. This is
|
||||
done after the text-to-bits assembly pass, so we need to mark it with
|
||||
the isa/tune settings at the time the .align was assembled. */
|
||||
#define TC_FRAG_TYPE struct i386_tc_frag_data
|
||||
|
||||
#define TC_FRAG_INIT(FRAGP) \
|
||||
do \
|
||||
{ \
|
||||
(FRAGP)->tc_frag_data.isa = cpu_arch_isa; \
|
||||
(FRAGP)->tc_frag_data.isa_flags = cpu_arch_isa_flags; \
|
||||
(FRAGP)->tc_frag_data.tune = cpu_arch_tune; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#ifdef SCO_ELF
|
||||
#define tc_init_after_args() sco_id ()
|
||||
extern void sco_id (void);
|
||||
#endif
|
||||
|
||||
#define WORKING_DOT_WORD 1
|
||||
|
||||
/* We want .cfi_* pseudo-ops for generating unwind info. */
|
||||
#define TARGET_USE_CFIPOP 1
|
||||
|
||||
extern unsigned int x86_dwarf2_return_column;
|
||||
#define DWARF2_DEFAULT_RETURN_COLUMN x86_dwarf2_return_column
|
||||
|
||||
extern int x86_cie_data_alignment;
|
||||
#define DWARF2_CIE_DATA_ALIGNMENT x86_cie_data_alignment
|
||||
|
||||
extern int x86_dwarf2_addr_size (void);
|
||||
#define DWARF2_ADDR_SIZE(bfd) x86_dwarf2_addr_size ()
|
||||
|
||||
#define tc_parse_to_dw2regnum tc_x86_parse_to_dw2regnum
|
||||
extern void tc_x86_parse_to_dw2regnum (expressionS *);
|
||||
|
||||
#define tc_cfi_frame_initial_instructions tc_x86_frame_initial_instructions
|
||||
extern void tc_x86_frame_initial_instructions (void);
|
||||
|
||||
#define md_elf_section_type(str,len) i386_elf_section_type (str, len)
|
||||
extern int i386_elf_section_type (const char *, size_t);
|
||||
|
||||
#ifdef TE_SOLARIS
|
||||
#define md_fix_up_eh_frame(sec) i386_solaris_fix_up_eh_frame (sec)
|
||||
extern void i386_solaris_fix_up_eh_frame (segT);
|
||||
#endif
|
||||
|
||||
/* Support for SHF_X86_64_LARGE */
|
||||
extern bfd_vma x86_64_section_word (char *, size_t);
|
||||
extern bfd_vma x86_64_section_letter (int, char **);
|
||||
#define md_elf_section_letter(LETTER, PTR_MSG) x86_64_section_letter (LETTER, PTR_MSG)
|
||||
#define md_elf_section_word(STR, LEN) x86_64_section_word (STR, LEN)
|
||||
|
||||
#ifdef TE_PE
|
||||
|
||||
#define O_secrel O_md1
|
||||
|
||||
#define TC_DWARF2_EMIT_OFFSET tc_pe_dwarf2_emit_offset
|
||||
void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int);
|
||||
|
||||
#endif /* TE_PE */
|
||||
|
||||
/* X_add_symbol:X_op_symbol (Intel mode only) */
|
||||
#define O_full_ptr O_md2
|
||||
|
||||
#ifdef OBJ_MACH_O
|
||||
|
||||
#define TC_FORCE_RELOCATION(FIX) (obj_mach_o_force_reloc (FIX))
|
||||
|
||||
#define TC_FORCE_RELOCATION_SUB_SAME(FIX,SEG) \
|
||||
(obj_mach_o_force_reloc_sub_same (FIX, SEG))
|
||||
|
||||
#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX,SEG) \
|
||||
(obj_mach_o_force_reloc_sub_local (FIX, SEG))
|
||||
|
||||
#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
|
||||
|
||||
#endif /* OBJ_MACH_O */
|
||||
|
||||
#endif /* TC_I386 */
|
26
contrib/toolchain/binutils/gas/config/te-pe.h
Normal file
26
contrib/toolchain/binutils/gas/config/te-pe.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* Copyright 2007 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 3,
|
||||
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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#define TE_PE
|
||||
#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME) /* Can have @'s inside labels. */
|
||||
|
||||
/* The PE format supports long section names. */
|
||||
#define COFF_LONG_SECTION_NAMES
|
||||
|
||||
#include "obj-format.h"
|
208
contrib/toolchain/binutils/gas/depend.c
Normal file
208
contrib/toolchain/binutils/gas/depend.c
Normal file
@ -0,0 +1,208 @@
|
||||
/* depend.c - Handle dependency tracking.
|
||||
Copyright 1997, 1998, 2000, 2001, 2003, 2004, 2005, 2007
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "filenames.h"
|
||||
|
||||
/* The file to write to, or NULL if no dependencies being kept. */
|
||||
static char * dep_file = NULL;
|
||||
|
||||
struct dependency
|
||||
{
|
||||
char * file;
|
||||
struct dependency * next;
|
||||
};
|
||||
|
||||
/* All the files we depend on. */
|
||||
static struct dependency * dep_chain = NULL;
|
||||
|
||||
/* Current column in output file. */
|
||||
static int column = 0;
|
||||
|
||||
static int quote_string_for_make (FILE *, char *);
|
||||
static void wrap_output (FILE *, char *, int);
|
||||
|
||||
/* Number of columns allowable. */
|
||||
#define MAX_COLUMNS 72
|
||||
|
||||
/* Start saving dependencies, to be written to FILENAME. If this is
|
||||
never called, then dependency tracking is simply skipped. */
|
||||
|
||||
void
|
||||
start_dependencies (char *filename)
|
||||
{
|
||||
dep_file = filename;
|
||||
}
|
||||
|
||||
/* Noticed a new filename, so try to register it. */
|
||||
|
||||
void
|
||||
register_dependency (char *filename)
|
||||
{
|
||||
struct dependency *dep;
|
||||
|
||||
if (dep_file == NULL)
|
||||
return;
|
||||
|
||||
for (dep = dep_chain; dep != NULL; dep = dep->next)
|
||||
{
|
||||
if (!filename_cmp (filename, dep->file))
|
||||
return;
|
||||
}
|
||||
|
||||
dep = (struct dependency *) xmalloc (sizeof (struct dependency));
|
||||
dep->file = xstrdup (filename);
|
||||
dep->next = dep_chain;
|
||||
dep_chain = dep;
|
||||
}
|
||||
|
||||
/* Quote a file name the way `make' wants it, and print it to FILE.
|
||||
If FILE is NULL, do no printing, but return the length of the
|
||||
quoted string.
|
||||
|
||||
This code is taken from gcc with only minor changes. */
|
||||
|
||||
static int
|
||||
quote_string_for_make (FILE *file, char *src)
|
||||
{
|
||||
char *p = src;
|
||||
int i = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char c = *p++;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\0':
|
||||
case ' ':
|
||||
case '\t':
|
||||
{
|
||||
/* GNU make uses a weird quoting scheme for white space.
|
||||
A space or tab preceded by 2N+1 backslashes represents
|
||||
N backslashes followed by space; a space or tab
|
||||
preceded by 2N backslashes represents N backslashes at
|
||||
the end of a file name; and backslashes in other
|
||||
contexts should not be doubled. */
|
||||
char *q;
|
||||
|
||||
for (q = p - 1; src < q && q[-1] == '\\'; q--)
|
||||
{
|
||||
if (file)
|
||||
putc ('\\', file);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!c)
|
||||
return i;
|
||||
if (file)
|
||||
putc ('\\', file);
|
||||
i++;
|
||||
goto ordinary_char;
|
||||
|
||||
case '$':
|
||||
if (file)
|
||||
putc (c, file);
|
||||
i++;
|
||||
/* Fall through. This can mishandle things like "$(" but
|
||||
there's no easy fix. */
|
||||
default:
|
||||
ordinary_char:
|
||||
/* This can mishandle characters in the string "\0\n%*?[\\~";
|
||||
exactly which chars are mishandled depends on the `make' version.
|
||||
We know of no portable solution for this;
|
||||
even GNU make 3.76.1 doesn't solve the problem entirely.
|
||||
(Also, '\0' is mishandled due to our calling conventions.) */
|
||||
if (file)
|
||||
putc (c, file);
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Append some output to the file, keeping track of columns and doing
|
||||
wrapping as necessary. */
|
||||
|
||||
static void
|
||||
wrap_output (FILE *f, char *string, int spacer)
|
||||
{
|
||||
int len = quote_string_for_make (NULL, string);
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (column
|
||||
&& (MAX_COLUMNS
|
||||
- 1 /* spacer */
|
||||
- 2 /* ` \' */
|
||||
< column + len))
|
||||
{
|
||||
fprintf (f, " \\\n ");
|
||||
column = 0;
|
||||
if (spacer == ' ')
|
||||
spacer = '\0';
|
||||
}
|
||||
|
||||
if (spacer == ' ')
|
||||
{
|
||||
putc (spacer, f);
|
||||
++column;
|
||||
}
|
||||
|
||||
quote_string_for_make (f, string);
|
||||
column += len;
|
||||
|
||||
if (spacer == ':')
|
||||
{
|
||||
putc (spacer, f);
|
||||
++column;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print dependency file. */
|
||||
|
||||
void
|
||||
print_dependencies (void)
|
||||
{
|
||||
FILE *f;
|
||||
struct dependency *dep;
|
||||
|
||||
if (dep_file == NULL)
|
||||
return;
|
||||
|
||||
f = fopen (dep_file, FOPEN_WT);
|
||||
if (f == NULL)
|
||||
{
|
||||
as_warn (_("can't open `%s' for writing"), dep_file);
|
||||
return;
|
||||
}
|
||||
|
||||
column = 0;
|
||||
wrap_output (f, out_file_name, ':');
|
||||
for (dep = dep_chain; dep != NULL; dep = dep->next)
|
||||
wrap_output (f, dep->file, ' ');
|
||||
|
||||
putc ('\n', f);
|
||||
|
||||
if (fclose (f))
|
||||
as_warn (_("can't close `%s'"), dep_file);
|
||||
}
|
2044
contrib/toolchain/binutils/gas/dw2gencfi.c
Normal file
2044
contrib/toolchain/binutils/gas/dw2gencfi.c
Normal file
File diff suppressed because it is too large
Load Diff
132
contrib/toolchain/binutils/gas/dw2gencfi.h
Normal file
132
contrib/toolchain/binutils/gas/dw2gencfi.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* dw2gencfi.h - Support for generating Dwarf2 CFI information.
|
||||
Copyright 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
|
||||
Contributed by Michal Ludvig <mludvig@suse.cz>
|
||||
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef DW2GENCFI_H
|
||||
#define DW2GENCFI_H
|
||||
|
||||
#include "dwarf2.h"
|
||||
|
||||
struct symbol;
|
||||
|
||||
extern const pseudo_typeS cfi_pseudo_table[];
|
||||
|
||||
/* cfi_finish() is called at the end of file. It will complain if
|
||||
the last CFI wasn't properly closed by .cfi_endproc. */
|
||||
extern void cfi_finish (void);
|
||||
|
||||
/* Entry points for backends to add unwind information. */
|
||||
extern void cfi_new_fde (struct symbol *);
|
||||
extern void cfi_end_fde (struct symbol *);
|
||||
extern void cfi_set_return_column (unsigned);
|
||||
extern void cfi_add_advance_loc (struct symbol *);
|
||||
|
||||
extern void cfi_add_CFA_offset (unsigned, offsetT);
|
||||
extern void cfi_add_CFA_def_cfa (unsigned, offsetT);
|
||||
extern void cfi_add_CFA_register (unsigned, unsigned);
|
||||
extern void cfi_add_CFA_def_cfa_register (unsigned);
|
||||
extern void cfi_add_CFA_def_cfa_offset (offsetT);
|
||||
extern void cfi_add_CFA_restore (unsigned);
|
||||
extern void cfi_add_CFA_undefined (unsigned);
|
||||
extern void cfi_add_CFA_same_value (unsigned);
|
||||
extern void cfi_add_CFA_remember_state (void);
|
||||
extern void cfi_add_CFA_restore_state (void);
|
||||
|
||||
/* Structures for md_cfi_end. */
|
||||
|
||||
#if defined (TE_PE) || defined (TE_PEP)
|
||||
#define SUPPORT_FRAME_LINKONCE 1
|
||||
#else
|
||||
#define SUPPORT_FRAME_LINKONCE 0
|
||||
#endif
|
||||
|
||||
struct cfi_insn_data
|
||||
{
|
||||
struct cfi_insn_data *next;
|
||||
#if SUPPORT_FRAME_LINKONCE
|
||||
segT cur_seg;
|
||||
#endif
|
||||
int insn;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned reg;
|
||||
offsetT offset;
|
||||
} ri;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned reg1;
|
||||
unsigned reg2;
|
||||
} rr;
|
||||
|
||||
unsigned r;
|
||||
offsetT i;
|
||||
|
||||
struct
|
||||
{
|
||||
symbolS *lab1;
|
||||
symbolS *lab2;
|
||||
} ll;
|
||||
|
||||
struct cfi_escape_data *esc;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned reg, encoding;
|
||||
expressionS exp;
|
||||
} ea;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct fde_entry
|
||||
{
|
||||
struct fde_entry *next;
|
||||
#if SUPPORT_FRAME_LINKONCE
|
||||
segT cur_seg;
|
||||
#endif
|
||||
symbolS *start_address;
|
||||
symbolS *end_address;
|
||||
struct cfi_insn_data *data;
|
||||
struct cfi_insn_data **last;
|
||||
unsigned char per_encoding;
|
||||
unsigned char lsda_encoding;
|
||||
expressionS personality;
|
||||
expressionS lsda;
|
||||
unsigned int return_column;
|
||||
unsigned int signal_frame;
|
||||
#if SUPPORT_FRAME_LINKONCE
|
||||
int handled;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The list of all FDEs that have been collected. */
|
||||
extern struct fde_entry *all_fde_data;
|
||||
|
||||
/* Fake CFI type; outside the byte range of any real CFI insn. */
|
||||
#define CFI_adjust_cfa_offset 0x100
|
||||
#define CFI_return_column 0x101
|
||||
#define CFI_rel_offset 0x102
|
||||
#define CFI_escape 0x103
|
||||
#define CFI_signal_frame 0x104
|
||||
#define CFI_val_encoded_addr 0x105
|
||||
|
||||
#endif /* DW2GENCFI_H */
|
1944
contrib/toolchain/binutils/gas/dwarf2dbg.c
Normal file
1944
contrib/toolchain/binutils/gas/dwarf2dbg.c
Normal file
File diff suppressed because it is too large
Load Diff
116
contrib/toolchain/binutils/gas/dwarf2dbg.h
Normal file
116
contrib/toolchain/binutils/gas/dwarf2dbg.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* dwarf2dbg.h - DWARF2 debug support
|
||||
Copyright 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2009
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef AS_DWARF2DBG_H
|
||||
#define AS_DWARF2DBG_H
|
||||
|
||||
#include "as.h"
|
||||
|
||||
#define DWARF2_FLAG_IS_STMT (1 << 0)
|
||||
#define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
|
||||
#define DWARF2_FLAG_PROLOGUE_END (1 << 2)
|
||||
#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
|
||||
|
||||
struct dwarf2_line_info {
|
||||
unsigned int filenum;
|
||||
unsigned int line;
|
||||
unsigned int column;
|
||||
unsigned int isa;
|
||||
unsigned int flags;
|
||||
unsigned int discriminator;
|
||||
};
|
||||
|
||||
/* Implements the .file FILENO "FILENAME" directive. FILENO can be 0
|
||||
to indicate that no file number has been assigned. All real file
|
||||
number must be >0. */
|
||||
extern char *dwarf2_directive_file (int dummy);
|
||||
|
||||
/* Implements the .loc FILENO LINENO [COLUMN] directive. FILENO is
|
||||
the file number, LINENO the line number and the (optional) COLUMN
|
||||
the column of the source code that the following instruction
|
||||
corresponds to. FILENO can be 0 to indicate that the filename
|
||||
specified by the textually most recent .file directive should be
|
||||
used. */
|
||||
extern void dwarf2_directive_loc (int dummy);
|
||||
|
||||
/* Implements the .loc_mark_labels {0,1} directive. */
|
||||
extern void dwarf2_directive_loc_mark_labels (int dummy);
|
||||
|
||||
/* Returns the current source information. If .file directives have
|
||||
been encountered, the info for the corresponding source file is
|
||||
returned. Otherwise, the info for the assembly source file is
|
||||
returned. */
|
||||
extern void dwarf2_where (struct dwarf2_line_info *l);
|
||||
|
||||
/* A hook to allow the target backend to inform the line number state
|
||||
machine of isa changes when assembler debug info is enabled. */
|
||||
extern void dwarf2_set_isa (unsigned int isa);
|
||||
|
||||
/* This function generates .debug_line info based on the address and
|
||||
source information passed in the arguments. ADDR should be the
|
||||
frag-relative offset of the instruction the information is for and
|
||||
L is the source information that should be associated with that
|
||||
address. */
|
||||
extern void dwarf2_gen_line_info (addressT addr, struct dwarf2_line_info *l);
|
||||
|
||||
/* Must be called for each generated instruction. */
|
||||
extern void dwarf2_emit_insn (int);
|
||||
|
||||
void dwarf2_move_insn (int);
|
||||
|
||||
/* Reset the state of the line number information to reflect that
|
||||
it has been used. */
|
||||
extern void dwarf2_consume_line_info (void);
|
||||
|
||||
/* Should be called for each code label. */
|
||||
extern void dwarf2_emit_label (symbolS *);
|
||||
|
||||
/* True when we've seen a .loc directive recently. Used to avoid
|
||||
doing work when there's nothing to do. */
|
||||
extern bfd_boolean dwarf2_loc_directive_seen;
|
||||
|
||||
/* True when we're supposed to set the basic block mark whenever a label
|
||||
is seen. Unless the target is doing Something Weird, just call
|
||||
dwarf2_emit_label. */
|
||||
extern bfd_boolean dwarf2_loc_mark_labels;
|
||||
|
||||
extern void dwarf2_init (void);
|
||||
|
||||
extern void dwarf2_finish (void);
|
||||
|
||||
extern int dwarf2dbg_estimate_size_before_relax (fragS *);
|
||||
extern int dwarf2dbg_relax_frag (fragS *);
|
||||
extern void dwarf2dbg_convert_frag (fragS *);
|
||||
|
||||
/* An enumeration which describes the sizes of offsets (to DWARF sections)
|
||||
and the mechanism by which the size is indicated. */
|
||||
enum dwarf2_format {
|
||||
/* 32-bit format: the initial length field is 4 bytes long. */
|
||||
dwarf2_format_32bit,
|
||||
/* DWARF3 64-bit format: the representation of the initial length
|
||||
(of a DWARF section) is 0xffffffff (4 bytes) followed by eight
|
||||
bytes indicating the actual length. */
|
||||
dwarf2_format_64bit,
|
||||
/* SGI extension to DWARF2: The initial length is eight bytes. */
|
||||
dwarf2_format_64bit_irix
|
||||
};
|
||||
|
||||
#endif /* AS_DWARF2DBG_H */
|
5244
contrib/toolchain/binutils/gas/ecoff.c
Normal file
5244
contrib/toolchain/binutils/gas/ecoff.c
Normal file
File diff suppressed because it is too large
Load Diff
113
contrib/toolchain/binutils/gas/ecoff.h
Normal file
113
contrib/toolchain/binutils/gas/ecoff.h
Normal file
@ -0,0 +1,113 @@
|
||||
/* ecoff.h -- header file for ECOFF debugging support
|
||||
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2004, 2005,
|
||||
2007, 2009 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
Put together by Ian Lance Taylor <ian@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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GAS_ECOFF_H
|
||||
#define GAS_ECOFF_H
|
||||
|
||||
#ifdef ECOFF_DEBUGGING
|
||||
|
||||
#include "coff/sym.h"
|
||||
#include "coff/ecoff.h"
|
||||
|
||||
/* Whether we have seen any ECOFF debugging information. */
|
||||
extern int ecoff_debugging_seen;
|
||||
|
||||
/* This function should be called at the start of assembly, by
|
||||
obj_read_begin_hook. */
|
||||
extern void ecoff_read_begin_hook (void);
|
||||
|
||||
/* This function should be called when the assembler switches to a new
|
||||
file. */
|
||||
extern void ecoff_new_file (const char *, int);
|
||||
|
||||
/* This function should be called when a new symbol is created, by
|
||||
obj_symbol_new_hook. */
|
||||
extern void ecoff_symbol_new_hook (symbolS *);
|
||||
|
||||
extern void ecoff_symbol_clone_hook (symbolS *, symbolS *);
|
||||
|
||||
/* This function should be called by the obj_frob_symbol hook. */
|
||||
extern void ecoff_frob_symbol (symbolS *);
|
||||
|
||||
/* Build the ECOFF debugging information. This should be called by
|
||||
obj_frob_file. This fills in the counts in *HDR; the offsets are
|
||||
filled in relative to the start of the *BUFP. It sets *BUFP to a
|
||||
block of memory holding the debugging information. It returns the
|
||||
length of *BUFP. */
|
||||
extern unsigned long ecoff_build_debug
|
||||
(HDRR *hdr, char **bufp, const struct ecoff_debug_swap *);
|
||||
|
||||
/* Functions to handle the ECOFF debugging directives. */
|
||||
extern void ecoff_directive_begin (int);
|
||||
extern void ecoff_directive_bend (int);
|
||||
extern void ecoff_directive_end (int);
|
||||
extern void ecoff_directive_ent (int);
|
||||
extern void ecoff_directive_fmask (int);
|
||||
extern void ecoff_directive_frame (int);
|
||||
extern void ecoff_directive_loc (int);
|
||||
extern void ecoff_directive_mask (int);
|
||||
|
||||
/* Other ECOFF directives. */
|
||||
extern void ecoff_directive_extern (int);
|
||||
extern void ecoff_directive_weakext (int);
|
||||
|
||||
/* Functions to handle the COFF debugging directives. */
|
||||
extern void ecoff_directive_def (int);
|
||||
extern void ecoff_directive_dim (int);
|
||||
extern void ecoff_directive_endef (int);
|
||||
extern void ecoff_directive_file (int);
|
||||
extern void ecoff_directive_scl (int);
|
||||
extern void ecoff_directive_size (int);
|
||||
extern void ecoff_directive_tag (int);
|
||||
extern void ecoff_directive_type (int);
|
||||
extern void ecoff_directive_val (int);
|
||||
|
||||
/* Handle stabs. */
|
||||
extern void ecoff_stab (segT sec, int what, const char *string,
|
||||
int type, int other, int desc);
|
||||
|
||||
/* Set the GP prologue size. */
|
||||
extern void ecoff_set_gp_prolog_size (int sz);
|
||||
|
||||
/* This routine is called from the ECOFF code to set the external
|
||||
information for a symbol. */
|
||||
#ifndef obj_ecoff_set_ext
|
||||
extern void obj_ecoff_set_ext (symbolS *, EXTR *);
|
||||
#endif
|
||||
|
||||
/* This routine is used to patch up a line number directive when
|
||||
instructions are moved around. */
|
||||
extern void ecoff_fix_loc (fragS *, unsigned long);
|
||||
|
||||
/* This function is called from read.c to peek at cur_file_ptr. */
|
||||
extern int ecoff_no_current_file (void);
|
||||
|
||||
/* This function returns the symbol associated with the current proc. */
|
||||
extern symbolS *ecoff_get_cur_proc_sym (void);
|
||||
|
||||
#endif /* ECOFF_DEBUGGING */
|
||||
|
||||
/* This routine is called from read.c to generate line number for .s file. */
|
||||
extern void ecoff_generate_asm_lineno (void);
|
||||
|
||||
#endif /* ! GAS_ECOFF_H */
|
557
contrib/toolchain/binutils/gas/ehopt.c
Normal file
557
contrib/toolchain/binutils/gas/ehopt.c
Normal file
@ -0,0 +1,557 @@
|
||||
/* ehopt.c--optimize gcc exception frame information.
|
||||
Copyright 1998, 2000, 2001, 2003, 2005, 2007, 2008, 2009
|
||||
Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor <ian@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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "subsegs.h"
|
||||
#include "struc-symbol.h"
|
||||
|
||||
/* We include this ELF file, even though we may not be assembling for
|
||||
ELF, since the exception frame information is always in a format
|
||||
derived from DWARF. */
|
||||
|
||||
#include "dwarf2.h"
|
||||
|
||||
/* Try to optimize gcc 2.8 exception frame information.
|
||||
|
||||
Exception frame information is emitted for every function in the
|
||||
.eh_frame or .debug_frame sections. Simple information for a function
|
||||
with no exceptions looks like this:
|
||||
|
||||
__FRAME_BEGIN__:
|
||||
.4byte .LLCIE1 / Length of Common Information Entry
|
||||
.LSCIE1:
|
||||
#if .eh_frame
|
||||
.4byte 0x0 / CIE Identifier Tag
|
||||
#elif .debug_frame
|
||||
.4byte 0xffffffff / CIE Identifier Tag
|
||||
#endif
|
||||
.byte 0x1 / CIE Version
|
||||
.byte 0x0 / CIE Augmentation (none)
|
||||
.byte 0x1 / ULEB128 0x1 (CIE Code Alignment Factor)
|
||||
.byte 0x7c / SLEB128 -4 (CIE Data Alignment Factor)
|
||||
.byte 0x8 / CIE RA Column
|
||||
.byte 0xc / DW_CFA_def_cfa
|
||||
.byte 0x4 / ULEB128 0x4
|
||||
.byte 0x4 / ULEB128 0x4
|
||||
.byte 0x88 / DW_CFA_offset, column 0x8
|
||||
.byte 0x1 / ULEB128 0x1
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.set .LLCIE1,.LECIE1-.LSCIE1 / CIE Length Symbol
|
||||
.4byte .LLFDE1 / FDE Length
|
||||
.LSFDE1:
|
||||
.4byte .LSFDE1-__FRAME_BEGIN__ / FDE CIE offset
|
||||
.4byte .LFB1 / FDE initial location
|
||||
.4byte .LFE1-.LFB1 / FDE address range
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI0-.LFB1
|
||||
.byte 0xe / DW_CFA_def_cfa_offset
|
||||
.byte 0x8 / ULEB128 0x8
|
||||
.byte 0x85 / DW_CFA_offset, column 0x5
|
||||
.byte 0x2 / ULEB128 0x2
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI1-.LCFI0
|
||||
.byte 0xd / DW_CFA_def_cfa_register
|
||||
.byte 0x5 / ULEB128 0x5
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI2-.LCFI1
|
||||
.byte 0x2e / DW_CFA_GNU_args_size
|
||||
.byte 0x4 / ULEB128 0x4
|
||||
.byte 0x4 / DW_CFA_advance_loc4
|
||||
.4byte .LCFI3-.LCFI2
|
||||
.byte 0x2e / DW_CFA_GNU_args_size
|
||||
.byte 0x0 / ULEB128 0x0
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
.set .LLFDE1,.LEFDE1-.LSFDE1 / FDE Length Symbol
|
||||
|
||||
The immediate issue we can address in the assembler is the
|
||||
DW_CFA_advance_loc4 followed by a four byte value. The value is
|
||||
the difference of two addresses in the function. Since gcc does
|
||||
not know this value, it always uses four bytes. We will know the
|
||||
value at the end of assembly, so we can do better. */
|
||||
|
||||
struct cie_info
|
||||
{
|
||||
unsigned code_alignment;
|
||||
int z_augmentation;
|
||||
};
|
||||
|
||||
static int get_cie_info (struct cie_info *);
|
||||
|
||||
/* Extract information from the CIE. */
|
||||
|
||||
static int
|
||||
get_cie_info (struct cie_info *info)
|
||||
{
|
||||
fragS *f;
|
||||
fixS *fix;
|
||||
int offset;
|
||||
char CIE_id;
|
||||
char augmentation[10];
|
||||
int iaug;
|
||||
int code_alignment = 0;
|
||||
|
||||
/* We should find the CIE at the start of the section. */
|
||||
|
||||
f = seg_info (now_seg)->frchainP->frch_root;
|
||||
fix = seg_info (now_seg)->frchainP->fix_root;
|
||||
|
||||
/* Look through the frags of the section to find the code alignment. */
|
||||
|
||||
/* First make sure that the CIE Identifier Tag is 0/-1. */
|
||||
|
||||
if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
|
||||
CIE_id = (char)0xff;
|
||||
else
|
||||
CIE_id = 0;
|
||||
|
||||
offset = 4;
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL
|
||||
|| f->fr_fix - offset < 4
|
||||
|| f->fr_literal[offset] != CIE_id
|
||||
|| f->fr_literal[offset + 1] != CIE_id
|
||||
|| f->fr_literal[offset + 2] != CIE_id
|
||||
|| f->fr_literal[offset + 3] != CIE_id)
|
||||
return 0;
|
||||
|
||||
/* Next make sure the CIE version number is 1. */
|
||||
|
||||
offset += 4;
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL
|
||||
|| f->fr_fix - offset < 1
|
||||
|| f->fr_literal[offset] != 1)
|
||||
return 0;
|
||||
|
||||
/* Skip the augmentation (a null terminated string). */
|
||||
|
||||
iaug = 0;
|
||||
++offset;
|
||||
while (1)
|
||||
{
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
|
||||
while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
|
||||
{
|
||||
if ((size_t) iaug < (sizeof augmentation) - 1)
|
||||
{
|
||||
augmentation[iaug] = f->fr_literal[offset];
|
||||
++iaug;
|
||||
}
|
||||
++offset;
|
||||
}
|
||||
if (offset < f->fr_fix)
|
||||
break;
|
||||
}
|
||||
++offset;
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
|
||||
augmentation[iaug] = '\0';
|
||||
if (augmentation[0] == '\0')
|
||||
{
|
||||
/* No augmentation. */
|
||||
}
|
||||
else if (strcmp (augmentation, "eh") == 0)
|
||||
{
|
||||
/* We have to skip a pointer. Unfortunately, we don't know how
|
||||
large it is. We find out by looking for a matching fixup. */
|
||||
while (fix != NULL
|
||||
&& (fix->fx_frag != f || fix->fx_where != offset))
|
||||
fix = fix->fx_next;
|
||||
if (fix == NULL)
|
||||
offset += 4;
|
||||
else
|
||||
offset += fix->fx_size;
|
||||
while (f != NULL && offset >= f->fr_fix)
|
||||
{
|
||||
offset -= f->fr_fix;
|
||||
f = f->fr_next;
|
||||
}
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
}
|
||||
else if (augmentation[0] != 'z')
|
||||
return 0;
|
||||
|
||||
/* We're now at the code alignment factor, which is a ULEB128. If
|
||||
it isn't a single byte, forget it. */
|
||||
|
||||
code_alignment = f->fr_literal[offset] & 0xff;
|
||||
if ((code_alignment & 0x80) != 0)
|
||||
code_alignment = 0;
|
||||
|
||||
info->code_alignment = code_alignment;
|
||||
info->z_augmentation = (augmentation[0] == 'z');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum frame_state
|
||||
{
|
||||
state_idle,
|
||||
state_saw_size,
|
||||
state_saw_cie_offset,
|
||||
state_saw_pc_begin,
|
||||
state_seeing_aug_size,
|
||||
state_skipping_aug,
|
||||
state_wait_loc4,
|
||||
state_saw_loc4,
|
||||
state_error,
|
||||
};
|
||||
|
||||
/* This function is called from emit_expr. It looks for cases which
|
||||
we can optimize.
|
||||
|
||||
Rather than try to parse all this information as we read it, we
|
||||
look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
|
||||
difference. We turn that into a rs_cfa_advance frag, and handle
|
||||
those frags at the end of the assembly. If the gcc output changes
|
||||
somewhat, this optimization may stop working.
|
||||
|
||||
This function returns non-zero if it handled the expression and
|
||||
emit_expr should not do anything, or zero otherwise. It can also
|
||||
change *EXP and *PNBYTES. */
|
||||
|
||||
int
|
||||
check_eh_frame (expressionS *exp, unsigned int *pnbytes)
|
||||
{
|
||||
struct frame_data
|
||||
{
|
||||
enum frame_state state;
|
||||
|
||||
int cie_info_ok;
|
||||
struct cie_info cie_info;
|
||||
|
||||
symbolS *size_end_sym;
|
||||
fragS *loc4_frag;
|
||||
int loc4_fix;
|
||||
|
||||
int aug_size;
|
||||
int aug_shift;
|
||||
};
|
||||
|
||||
static struct frame_data eh_frame_data;
|
||||
static struct frame_data debug_frame_data;
|
||||
struct frame_data *d;
|
||||
|
||||
/* Don't optimize. */
|
||||
if (flag_traditional_format)
|
||||
return 0;
|
||||
|
||||
#ifdef md_allow_eh_opt
|
||||
if (! md_allow_eh_opt)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* Select the proper section data. */
|
||||
if (strncmp (segment_name (now_seg), ".eh_frame", 9) == 0
|
||||
&& segment_name (now_seg)[9] != '_')
|
||||
d = &eh_frame_data;
|
||||
else if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
|
||||
d = &debug_frame_data;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (d->state >= state_saw_size && S_IS_DEFINED (d->size_end_sym))
|
||||
{
|
||||
/* We have come to the end of the CIE or FDE. See below where
|
||||
we set saw_size. We must check this first because we may now
|
||||
be looking at the next size. */
|
||||
d->state = state_idle;
|
||||
}
|
||||
|
||||
switch (d->state)
|
||||
{
|
||||
case state_idle:
|
||||
if (*pnbytes == 4)
|
||||
{
|
||||
/* This might be the size of the CIE or FDE. We want to know
|
||||
the size so that we don't accidentally optimize across an FDE
|
||||
boundary. We recognize the size in one of two forms: a
|
||||
symbol which will later be defined as a difference, or a
|
||||
subtraction of two symbols. Either way, we can tell when we
|
||||
are at the end of the FDE because the symbol becomes defined
|
||||
(in the case of a subtraction, the end symbol, from which the
|
||||
start symbol is being subtracted). Other ways of describing
|
||||
the size will not be optimized. */
|
||||
if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
|
||||
&& ! S_IS_DEFINED (exp->X_add_symbol))
|
||||
{
|
||||
d->state = state_saw_size;
|
||||
d->size_end_sym = exp->X_add_symbol;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case state_saw_size:
|
||||
case state_saw_cie_offset:
|
||||
/* Assume whatever form it appears in, it appears atomically. */
|
||||
d->state = (enum frame_state) (d->state + 1);
|
||||
break;
|
||||
|
||||
case state_saw_pc_begin:
|
||||
/* Decide whether we should see an augmentation. */
|
||||
if (! d->cie_info_ok
|
||||
&& ! (d->cie_info_ok = get_cie_info (&d->cie_info)))
|
||||
d->state = state_error;
|
||||
else if (d->cie_info.z_augmentation)
|
||||
{
|
||||
d->state = state_seeing_aug_size;
|
||||
d->aug_size = 0;
|
||||
d->aug_shift = 0;
|
||||
}
|
||||
else
|
||||
d->state = state_wait_loc4;
|
||||
break;
|
||||
|
||||
case state_seeing_aug_size:
|
||||
/* Bytes == -1 means this comes from an leb128 directive. */
|
||||
if ((int)*pnbytes == -1 && exp->X_op == O_constant)
|
||||
{
|
||||
d->aug_size = exp->X_add_number;
|
||||
d->state = state_skipping_aug;
|
||||
}
|
||||
else if (*pnbytes == 1 && exp->X_op == O_constant)
|
||||
{
|
||||
unsigned char byte = exp->X_add_number;
|
||||
d->aug_size |= (byte & 0x7f) << d->aug_shift;
|
||||
d->aug_shift += 7;
|
||||
if ((byte & 0x80) == 0)
|
||||
d->state = state_skipping_aug;
|
||||
}
|
||||
else
|
||||
d->state = state_error;
|
||||
if (d->state == state_skipping_aug && d->aug_size == 0)
|
||||
d->state = state_wait_loc4;
|
||||
break;
|
||||
|
||||
case state_skipping_aug:
|
||||
if ((int)*pnbytes < 0)
|
||||
d->state = state_error;
|
||||
else
|
||||
{
|
||||
int left = (d->aug_size -= *pnbytes);
|
||||
if (left == 0)
|
||||
d->state = state_wait_loc4;
|
||||
else if (left < 0)
|
||||
d->state = state_error;
|
||||
}
|
||||
break;
|
||||
|
||||
case state_wait_loc4:
|
||||
if (*pnbytes == 1
|
||||
&& exp->X_op == O_constant
|
||||
&& exp->X_add_number == DW_CFA_advance_loc4)
|
||||
{
|
||||
/* This might be a DW_CFA_advance_loc4. Record the frag and the
|
||||
position within the frag, so that we can change it later. */
|
||||
frag_grow (1);
|
||||
d->state = state_saw_loc4;
|
||||
d->loc4_frag = frag_now;
|
||||
d->loc4_fix = frag_now_fix ();
|
||||
}
|
||||
break;
|
||||
|
||||
case state_saw_loc4:
|
||||
d->state = state_wait_loc4;
|
||||
if (*pnbytes != 4)
|
||||
break;
|
||||
if (exp->X_op == O_constant)
|
||||
{
|
||||
/* This is a case which we can optimize. The two symbols being
|
||||
subtracted were in the same frag and the expression was
|
||||
reduced to a constant. We can do the optimization entirely
|
||||
in this function. */
|
||||
if (exp->X_add_number < 0x40)
|
||||
{
|
||||
d->loc4_frag->fr_literal[d->loc4_fix]
|
||||
= DW_CFA_advance_loc | exp->X_add_number;
|
||||
/* No more bytes needed. */
|
||||
return 1;
|
||||
}
|
||||
else if (exp->X_add_number < 0x100)
|
||||
{
|
||||
d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
|
||||
*pnbytes = 1;
|
||||
}
|
||||
else if (exp->X_add_number < 0x10000)
|
||||
{
|
||||
d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
|
||||
*pnbytes = 2;
|
||||
}
|
||||
}
|
||||
else if (exp->X_op == O_subtract && d->cie_info.code_alignment == 1)
|
||||
{
|
||||
/* This is a case we can optimize. The expression was not
|
||||
reduced, so we can not finish the optimization until the end
|
||||
of the assembly. We set up a variant frag which we handle
|
||||
later. */
|
||||
frag_var (rs_cfa, 4, 0, 1 << 3, make_expr_symbol (exp),
|
||||
d->loc4_fix, (char *) d->loc4_frag);
|
||||
return 1;
|
||||
}
|
||||
else if ((exp->X_op == O_divide
|
||||
|| exp->X_op == O_right_shift)
|
||||
&& d->cie_info.code_alignment > 1)
|
||||
{
|
||||
if (exp->X_add_symbol->bsym
|
||||
&& exp->X_op_symbol->bsym
|
||||
&& exp->X_add_symbol->sy_value.X_op == O_subtract
|
||||
&& exp->X_op_symbol->sy_value.X_op == O_constant
|
||||
&& ((exp->X_op == O_divide
|
||||
? exp->X_op_symbol->sy_value.X_add_number
|
||||
: (offsetT) 1 << exp->X_op_symbol->sy_value.X_add_number)
|
||||
== (offsetT) d->cie_info.code_alignment))
|
||||
{
|
||||
/* This is a case we can optimize as well. The expression was
|
||||
not reduced, so we can not finish the optimization until the
|
||||
end of the assembly. We set up a variant frag which we
|
||||
handle later. */
|
||||
frag_var (rs_cfa, 4, 0, d->cie_info.code_alignment << 3,
|
||||
make_expr_symbol (&exp->X_add_symbol->sy_value),
|
||||
d->loc4_fix, (char *) d->loc4_frag);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case state_error:
|
||||
/* Just skipping everything. */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The function estimates the size of a rs_cfa variant frag based on
|
||||
the current values of the symbols. It is called before the
|
||||
relaxation loop. We set fr_subtype{0:2} to the expected length. */
|
||||
|
||||
int
|
||||
eh_frame_estimate_size_before_relax (fragS *frag)
|
||||
{
|
||||
offsetT diff;
|
||||
int ca = frag->fr_subtype >> 3;
|
||||
int ret;
|
||||
|
||||
diff = resolve_symbol_value (frag->fr_symbol);
|
||||
|
||||
gas_assert (ca > 0);
|
||||
diff /= ca;
|
||||
if (diff < 0x40)
|
||||
ret = 0;
|
||||
else if (diff < 0x100)
|
||||
ret = 1;
|
||||
else if (diff < 0x10000)
|
||||
ret = 2;
|
||||
else
|
||||
ret = 4;
|
||||
|
||||
frag->fr_subtype = (frag->fr_subtype & ~7) | ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function relaxes a rs_cfa variant frag based on the current
|
||||
values of the symbols. fr_subtype{0:2} is the current length of
|
||||
the frag. This returns the change in frag length. */
|
||||
|
||||
int
|
||||
eh_frame_relax_frag (fragS *frag)
|
||||
{
|
||||
int oldsize, newsize;
|
||||
|
||||
oldsize = frag->fr_subtype & 7;
|
||||
newsize = eh_frame_estimate_size_before_relax (frag);
|
||||
return newsize - oldsize;
|
||||
}
|
||||
|
||||
/* This function converts a rs_cfa variant frag into a normal fill
|
||||
frag. This is called after all relaxation has been done.
|
||||
fr_subtype{0:2} will be the desired length of the frag. */
|
||||
|
||||
void
|
||||
eh_frame_convert_frag (fragS *frag)
|
||||
{
|
||||
offsetT diff;
|
||||
fragS *loc4_frag;
|
||||
int loc4_fix, ca;
|
||||
|
||||
loc4_frag = (fragS *) frag->fr_opcode;
|
||||
loc4_fix = (int) frag->fr_offset;
|
||||
|
||||
diff = resolve_symbol_value (frag->fr_symbol);
|
||||
|
||||
ca = frag->fr_subtype >> 3;
|
||||
gas_assert (ca > 0);
|
||||
diff /= ca;
|
||||
switch (frag->fr_subtype & 7)
|
||||
{
|
||||
case 0:
|
||||
gas_assert (diff < 0x40);
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | diff;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
gas_assert (diff < 0x100);
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
|
||||
frag->fr_literal[frag->fr_fix] = diff;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gas_assert (diff < 0x10000);
|
||||
loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
|
||||
md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
frag->fr_fix += frag->fr_subtype & 7;
|
||||
frag->fr_type = rs_fill;
|
||||
frag->fr_subtype = 0;
|
||||
frag->fr_offset = 0;
|
||||
}
|
2367
contrib/toolchain/binutils/gas/expr.c
Normal file
2367
contrib/toolchain/binutils/gas/expr.c
Normal file
File diff suppressed because it is too large
Load Diff
189
contrib/toolchain/binutils/gas/expr.h
Normal file
189
contrib/toolchain/binutils/gas/expr.h
Normal file
@ -0,0 +1,189 @@
|
||||
/* expr.h -> header file for expr.c
|
||||
Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2002, 2003, 2005, 2007, 2009 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/*
|
||||
* By popular demand, we define a struct to represent an expression.
|
||||
* This will no doubt mutate as expressions become baroque.
|
||||
*
|
||||
* Currently, we support expressions like "foo OP bar + 42". In other
|
||||
* words we permit a (possibly undefined) symbol, a (possibly
|
||||
* undefined) symbol and the operation used to combine the symbols,
|
||||
* and an (absolute) augend. RMS says this is so we can have 1-pass
|
||||
* assembly for any compiler emissions, and a 'case' statement might
|
||||
* emit 'undefined1 - undefined2'.
|
||||
*
|
||||
* The type of an expression used to be stored as a segment. That got
|
||||
* confusing because it overloaded the concept of a segment. I added
|
||||
* an operator field, instead.
|
||||
*/
|
||||
|
||||
/* This is the type of an expression. The operator types are also
|
||||
used while parsing an expression.
|
||||
|
||||
NOTE: This enumeration must match the op_rank array in expr.c. */
|
||||
|
||||
typedef enum {
|
||||
/* An illegal expression. */
|
||||
O_illegal,
|
||||
/* A nonexistent expression. */
|
||||
O_absent,
|
||||
/* X_add_number (a constant expression). */
|
||||
O_constant,
|
||||
/* X_add_symbol + X_add_number. */
|
||||
O_symbol,
|
||||
/* X_add_symbol + X_add_number - the base address of the image. */
|
||||
O_symbol_rva,
|
||||
/* A register (X_add_number is register number). */
|
||||
O_register,
|
||||
/* A big value. If X_add_number is negative or 0, the value is in
|
||||
generic_floating_point_number. Otherwise the value is in
|
||||
generic_bignum, and X_add_number is the number of LITTLENUMs in
|
||||
the value. */
|
||||
O_big,
|
||||
/* (- X_add_symbol) + X_add_number. */
|
||||
O_uminus,
|
||||
/* (~ X_add_symbol) + X_add_number. */
|
||||
O_bit_not,
|
||||
/* (! X_add_symbol) + X_add_number. */
|
||||
O_logical_not,
|
||||
/* (X_add_symbol * X_op_symbol) + X_add_number. */
|
||||
O_multiply,
|
||||
/* (X_add_symbol / X_op_symbol) + X_add_number. */
|
||||
O_divide,
|
||||
/* (X_add_symbol % X_op_symbol) + X_add_number. */
|
||||
O_modulus,
|
||||
/* (X_add_symbol << X_op_symbol) + X_add_number. */
|
||||
O_left_shift,
|
||||
/* (X_add_symbol >> X_op_symbol) + X_add_number. */
|
||||
O_right_shift,
|
||||
/* (X_add_symbol | X_op_symbol) + X_add_number. */
|
||||
O_bit_inclusive_or,
|
||||
/* (X_add_symbol |~ X_op_symbol) + X_add_number. */
|
||||
O_bit_or_not,
|
||||
/* (X_add_symbol ^ X_op_symbol) + X_add_number. */
|
||||
O_bit_exclusive_or,
|
||||
/* (X_add_symbol & X_op_symbol) + X_add_number. */
|
||||
O_bit_and,
|
||||
/* (X_add_symbol + X_op_symbol) + X_add_number. */
|
||||
O_add,
|
||||
/* (X_add_symbol - X_op_symbol) + X_add_number. */
|
||||
O_subtract,
|
||||
/* (X_add_symbol == X_op_symbol) + X_add_number. */
|
||||
O_eq,
|
||||
/* (X_add_symbol != X_op_symbol) + X_add_number. */
|
||||
O_ne,
|
||||
/* (X_add_symbol < X_op_symbol) + X_add_number. */
|
||||
O_lt,
|
||||
/* (X_add_symbol <= X_op_symbol) + X_add_number. */
|
||||
O_le,
|
||||
/* (X_add_symbol >= X_op_symbol) + X_add_number. */
|
||||
O_ge,
|
||||
/* (X_add_symbol > X_op_symbol) + X_add_number. */
|
||||
O_gt,
|
||||
/* (X_add_symbol && X_op_symbol) + X_add_number. */
|
||||
O_logical_and,
|
||||
/* (X_add_symbol || X_op_symbol) + X_add_number. */
|
||||
O_logical_or,
|
||||
/* X_op_symbol [ X_add_symbol ] */
|
||||
O_index,
|
||||
/* machine dependent operators */
|
||||
O_md1, O_md2, O_md3, O_md4, O_md5, O_md6, O_md7, O_md8,
|
||||
O_md9, O_md10, O_md11, O_md12, O_md13, O_md14, O_md15, O_md16,
|
||||
O_md17, O_md18, O_md19, O_md20, O_md21, O_md22, O_md23, O_md24,
|
||||
O_md25, O_md26, O_md27, O_md28, O_md29, O_md30, O_md31, O_md32,
|
||||
/* this must be the largest value */
|
||||
O_max
|
||||
} operatorT;
|
||||
|
||||
typedef struct expressionS {
|
||||
/* The main symbol. */
|
||||
symbolS *X_add_symbol;
|
||||
/* The second symbol, if needed. */
|
||||
symbolS *X_op_symbol;
|
||||
/* A number to add. */
|
||||
offsetT X_add_number;
|
||||
|
||||
/* The type of the expression. We can't assume that an arbitrary
|
||||
compiler can handle a bitfield of enum type. FIXME: We could
|
||||
check this using autoconf. */
|
||||
#ifdef __GNUC__
|
||||
operatorT X_op : 8;
|
||||
#else
|
||||
unsigned char X_op;
|
||||
#endif
|
||||
|
||||
/* Non-zero if X_add_number should be regarded as unsigned. This is
|
||||
only valid for O_constant expressions. It is only used when an
|
||||
O_constant must be extended into a bignum (i.e., it is not used
|
||||
when performing arithmetic on these values).
|
||||
FIXME: This field is not set very reliably. */
|
||||
unsigned int X_unsigned : 1;
|
||||
/* This is used to implement "word size + 1 bit" arithmetic, so that e.g.
|
||||
expressions used with .sleb128 directives can use the full range available
|
||||
for an unsigned word, but can also properly represent all values of a
|
||||
signed word. */
|
||||
unsigned int X_extrabit : 1;
|
||||
|
||||
/* 7 additional bits can be defined if needed. */
|
||||
|
||||
/* Machine dependent field */
|
||||
unsigned short X_md;
|
||||
} expressionS;
|
||||
|
||||
enum expr_mode
|
||||
{
|
||||
expr_evaluate,
|
||||
expr_normal,
|
||||
expr_defer
|
||||
};
|
||||
|
||||
/* "result" should be type (expressionS *). */
|
||||
#define expression(result) expr (0, result, expr_normal)
|
||||
#define expression_and_evaluate(result) expr (0, result, expr_evaluate)
|
||||
#define deferred_expression(result) expr (0, result, expr_defer)
|
||||
|
||||
/* If an expression is O_big, look here for its value. These common
|
||||
data may be clobbered whenever expr() is called. */
|
||||
/* Flonums returned here. Big enough to hold most precise flonum. */
|
||||
extern FLONUM_TYPE generic_floating_point_number;
|
||||
/* Bignums returned here. */
|
||||
extern LITTLENUM_TYPE generic_bignum[];
|
||||
/* Number of littlenums in above. */
|
||||
#define SIZE_OF_LARGE_NUMBER (20)
|
||||
|
||||
typedef char operator_rankT;
|
||||
|
||||
extern char get_symbol_end (void);
|
||||
extern void expr_begin (void);
|
||||
extern void expr_set_precedence (void);
|
||||
extern void expr_set_rank (operatorT, operator_rankT);
|
||||
extern void add_to_result (expressionS *, offsetT, int);
|
||||
extern void subtract_from_result (expressionS *, offsetT, int);
|
||||
extern segT expr (int, expressionS *, enum expr_mode);
|
||||
extern unsigned int get_single_number (void);
|
||||
extern symbolS *make_expr_symbol (expressionS * expressionP);
|
||||
extern int expr_symbol_where (symbolS *, char **, unsigned int *);
|
||||
extern void current_location (expressionS *);
|
||||
|
||||
extern symbolS *expr_build_uconstant (offsetT);
|
||||
extern symbolS *expr_build_dot (void);
|
||||
|
||||
int resolve_expression (expressionS *);
|
71
contrib/toolchain/binutils/gas/flonum-copy.c
Normal file
71
contrib/toolchain/binutils/gas/flonum-copy.c
Normal file
@ -0,0 +1,71 @@
|
||||
/* flonum_copy.c - copy a flonum
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 2000, 2003, 2005, 2007
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
|
||||
void
|
||||
flonum_copy (FLONUM_TYPE *in, FLONUM_TYPE *out)
|
||||
{
|
||||
unsigned int in_length; /* 0 origin */
|
||||
unsigned int out_length; /* 0 origin */
|
||||
|
||||
out->sign = in->sign;
|
||||
in_length = in->leader - in->low;
|
||||
|
||||
if (in->leader < in->low)
|
||||
{
|
||||
out->leader = out->low - 1; /* 0.0 case */
|
||||
}
|
||||
else
|
||||
{
|
||||
out_length = out->high - out->low;
|
||||
/* Assume no GAPS in packing of littlenums.
|
||||
I.e. sizeof(array) == sizeof(element) * number_of_elements. */
|
||||
if (in_length <= out_length)
|
||||
{
|
||||
{
|
||||
/* For defensive programming, zero any high-order
|
||||
littlenums we don't need. This is destroying evidence
|
||||
and wasting time, so why bother??? */
|
||||
if (in_length < out_length)
|
||||
{
|
||||
memset ((char *) (out->low + in_length + 1), '\0',
|
||||
out_length - in_length);
|
||||
}
|
||||
}
|
||||
memcpy ((void *) (out->low), (void *) (in->low),
|
||||
((in_length + 1) * sizeof (LITTLENUM_TYPE)));
|
||||
out->exponent = in->exponent;
|
||||
out->leader = in->leader - in->low + out->low;
|
||||
}
|
||||
else
|
||||
{
|
||||
int shorten; /* 1-origin. Number of littlenums we drop. */
|
||||
|
||||
shorten = in_length - out_length;
|
||||
/* Assume out_length >= 0 ! */
|
||||
memcpy ((void *) (out->low), (void *) (in->low + shorten),
|
||||
((out_length + 1) * sizeof (LITTLENUM_TYPE)));
|
||||
out->leader = out->high;
|
||||
out->exponent = in->exponent + shorten;
|
||||
}
|
||||
} /* if any significant bits */
|
||||
}
|
228
contrib/toolchain/binutils/gas/flonum-konst.c
Normal file
228
contrib/toolchain/binutils/gas/flonum-konst.c
Normal file
@ -0,0 +1,228 @@
|
||||
/* flonum_const.c - Useful Flonum constants
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2000, 2002,
|
||||
2005, 2007 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include "flonum.h"
|
||||
/* JF: I added the last entry to this table, and I'm not
|
||||
sure if its right or not. Could go either way. I wish
|
||||
I really understood this stuff. */
|
||||
|
||||
const int table_size_of_flonum_powers_of_ten = 13;
|
||||
|
||||
static const LITTLENUM_TYPE zero[] = {
|
||||
1
|
||||
};
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Warning: the low order bits may be WRONG here. *
|
||||
* I took this from a suspect bc(1) script. *
|
||||
* "minus_X"[] is supposed to be 10^(2^-X) expressed in base 2^16. *
|
||||
* The radix point is just AFTER the highest element of the [] *
|
||||
* *
|
||||
* Because bc rounds DOWN for printing (I think), the lowest *
|
||||
* significance littlenums should probably have 1 added to them. *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
/* JF: If this equals 6553/(2^16)+39321/(2^32)+... it approaches .1 */
|
||||
static const LITTLENUM_TYPE minus_1[] = {
|
||||
39322, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321,
|
||||
39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 6553
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_1[] = {
|
||||
10
|
||||
};
|
||||
|
||||
/* JF: If this equals 655/(2^16) + 23592/(2^32) + ... it approaches .01 */
|
||||
static const LITTLENUM_TYPE minus_2[] = {
|
||||
10486, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 49807,
|
||||
10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 655
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_2[] = {
|
||||
100
|
||||
};
|
||||
|
||||
/* This approaches .0001 */
|
||||
static const LITTLENUM_TYPE minus_3[] = {
|
||||
52534, 20027, 37329, 65116, 64067, 60397, 14784, 18979, 33659, 19503,
|
||||
2726, 9542, 629, 2202, 40475, 10590, 4299, 47815, 36280, 6
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_3[] = {
|
||||
10000
|
||||
};
|
||||
|
||||
/* JF: this approaches 1e-8 */
|
||||
static const LITTLENUM_TYPE minus_4[] = {
|
||||
22517, 49501, 54293, 19424, 60699, 6716, 24348, 22618, 23904, 21327,
|
||||
3919, 44703, 19149, 28803, 48959, 6259, 50273, 62237, 42
|
||||
};
|
||||
|
||||
/* This equals 1525 * 2^16 + 57600 */
|
||||
static const LITTLENUM_TYPE plus_4[] = {
|
||||
57600, 1525
|
||||
};
|
||||
|
||||
/* This approaches 1e-16 */
|
||||
static const LITTLENUM_TYPE minus_5[] = {
|
||||
22199, 45957, 17005, 26266, 10526, 16260, 55017, 35680, 40443, 19789,
|
||||
17356, 30195, 55905, 28426, 63010, 44197, 1844
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_5[] = {
|
||||
28609, 34546, 35
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_6[] = {
|
||||
30926, 26518, 13110, 43018, 54982, 48258, 24658, 15209, 63366, 11929,
|
||||
20069, 43857, 60487, 51
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_6[] = {
|
||||
61313, 34220, 16731, 11629, 1262
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_7[] = {
|
||||
29819, 14733, 21490, 40602, 31315, 65186, 2695
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_7[] = {
|
||||
7937, 49002, 60772, 28216, 38893, 55975, 63988, 59711, 20227, 24
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_8[] = {
|
||||
27579, 64807, 12543, 794, 13907, 61297, 12013, 64360, 15961, 20566,
|
||||
24178, 15922, 59427, 110
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_8[] = {
|
||||
15873, 11925, 39177, 991, 14589, 3861, 58415, 9076, 62956, 54223,
|
||||
56328, 50180, 45274, 48333, 32537, 42547, 9731, 59679, 590
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_9[] = {
|
||||
11042, 8464, 58971, 63429, 6022, 63485, 5500, 53464, 47545, 50068,
|
||||
56988, 22819, 49708, 54493, 9920, 47667, 40409, 35764, 10383, 54466,
|
||||
32702, 17493, 32420, 34382, 22750, 20681, 12300
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_9[] = {
|
||||
20678, 27614, 28272, 53066, 55311, 54677, 29038, 9906, 26288, 44486,
|
||||
13860, 7445, 54106, 15426, 21518, 25599, 29632, 52309, 61207, 26105,
|
||||
10482, 21948, 51191, 32988, 60892, 62574, 61390, 24540, 21495, 5
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_10[] = {
|
||||
6214, 48771, 23471, 30163, 31763, 38013, 57001, 11770, 18263, 36366,
|
||||
20742, 45086, 56969, 53231, 37856, 55814, 38057, 15692, 46761, 8713,
|
||||
6102, 20083, 8269, 11839, 11571, 50963, 15649, 11698, 40675, 2308
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_10[] = {
|
||||
63839, 36576, 45712, 44516, 37803, 29482, 4966, 30556, 37961, 23310,
|
||||
27070, 44972, 29507, 48257, 45209, 7494, 17831, 38728, 41577, 29443,
|
||||
36016, 7955, 35339, 35479, 36011, 14553, 49618, 5588, 25396, 28
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_11[] = {
|
||||
16663, 56882, 61983, 7804, 36555, 32060, 34502, 1000, 14356, 21681,
|
||||
6605, 34767, 51411, 59048, 53614, 39850, 30079, 6496, 6846, 26841,
|
||||
40778, 19578, 59899, 44085, 54016, 24259, 11232, 21229, 21313, 81
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_11[] = {
|
||||
92, 9054, 62707, 17993, 7821, 56838, 13992, 21321, 29637, 48426,
|
||||
42982, 38668, 49574, 28820, 18200, 18927, 53979, 16219, 37484, 2516,
|
||||
44642, 14665, 11587, 41926, 13556, 23956, 54320, 6661, 55766, 805
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_12[] = {
|
||||
33202, 45969, 58804, 56734, 16482, 26007, 44984, 49334, 31007, 32944,
|
||||
44517, 63329, 47131, 15291, 59465, 2264, 23218, 11829, 59771, 38798,
|
||||
31051, 28748, 23129, 40541, 41562, 35108, 50620, 59014, 51817, 6613
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_12[] = {
|
||||
10098, 37922, 58070, 7432, 10470, 63465, 23718, 62190, 47420, 7009,
|
||||
38443, 4587, 45596, 38472, 52129, 52779, 29012, 13559, 48688, 31678,
|
||||
41753, 58662, 10668, 36067, 29906, 56906, 21461, 46556, 59571, 9
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE minus_13[] = {
|
||||
45309, 27592, 37144, 34637, 34328, 41671, 34620, 24135, 53401, 22112,
|
||||
21576, 45147, 39310, 44051, 48572, 3676, 46544, 59768, 33350, 2323,
|
||||
49524, 61568, 3903, 36487, 36356, 30903, 14975, 9035, 29715, 667
|
||||
};
|
||||
|
||||
static const LITTLENUM_TYPE plus_13[] = {
|
||||
18788, 16960, 6318, 45685, 55400, 46230, 35794, 25588, 7253, 55541,
|
||||
49716, 59760, 63592, 8191, 63765, 58530, 44667, 13294, 10001, 55586,
|
||||
47887, 18738, 9509, 40896, 42506, 52580, 4171, 325, 12329, 98
|
||||
};
|
||||
|
||||
/* Shut up complaints about differing pointer types. They only differ
|
||||
in the const attribute, but there isn't any easy way to do this
|
||||
*/
|
||||
#define X (LITTLENUM_TYPE *)
|
||||
|
||||
const FLONUM_TYPE flonum_negative_powers_of_ten[] = {
|
||||
{X zero, X zero, X zero, 0, '+'},
|
||||
{X minus_1, X minus_1 + 19, X minus_1 + 19, -20, '+'},
|
||||
{X minus_2, X minus_2 + 19, X minus_2 + 19, -20, '+'},
|
||||
{X minus_3, X minus_3 + 19, X minus_3 + 19, -20, '+'},
|
||||
{X minus_4, X minus_4 + 18, X minus_4 + 18, -20, '+'},
|
||||
{X minus_5, X minus_5 + 16, X minus_5 + 16, -20, '+'},
|
||||
{X minus_6, X minus_6 + 13, X minus_6 + 13, -20, '+'},
|
||||
{X minus_7, X minus_7 + 6, X minus_7 + 6, -20, '+'},
|
||||
{X minus_8, X minus_8 + 13, X minus_8 + 13, -40, '+'},
|
||||
{X minus_9, X minus_9 + 26, X minus_9 + 26, -80, '+'},
|
||||
{X minus_10, X minus_10 + 29, X minus_10 + 29, -136, '+'},
|
||||
{X minus_11, X minus_11 + 29, X minus_11 + 29, -242, '+'},
|
||||
{X minus_12, X minus_12 + 29, X minus_12 + 29, -455, '+'},
|
||||
{X minus_13, X minus_13 + 29, X minus_13 + 29, -880, '+'},
|
||||
};
|
||||
|
||||
const FLONUM_TYPE flonum_positive_powers_of_ten[] = {
|
||||
{X zero, X zero, X zero, 0, '+'},
|
||||
{X plus_1, X plus_1 + 0, X plus_1 + 0, 0, '+'},
|
||||
{X plus_2, X plus_2 + 0, X plus_2 + 0, 0, '+'},
|
||||
{X plus_3, X plus_3 + 0, X plus_3 + 0, 0, '+'},
|
||||
{X plus_4, X plus_4 + 1, X plus_4 + 1, 0, '+'},
|
||||
{X plus_5, X plus_5 + 2, X plus_5 + 2, 1, '+'},
|
||||
{X plus_6, X plus_6 + 4, X plus_6 + 4, 2, '+'},
|
||||
{X plus_7, X plus_7 + 9, X plus_7 + 9, 4, '+'},
|
||||
{X plus_8, X plus_8 + 18, X plus_8 + 18, 8, '+'},
|
||||
{X plus_9, X plus_9 + 29, X plus_9 + 29, 24, '+'},
|
||||
{X plus_10, X plus_10 + 29, X plus_10 + 29, 77, '+'},
|
||||
{X plus_11, X plus_11 + 29, X plus_11 + 29, 183, '+'},
|
||||
{X plus_12, X plus_12 + 29, X plus_12 + 29, 396, '+'},
|
||||
{X plus_13, X plus_13 + 29, X plus_13 + 29, 821, '+'},
|
||||
};
|
||||
|
||||
#ifdef VMS
|
||||
void
|
||||
dummy1 ()
|
||||
{
|
||||
}
|
||||
#endif
|
188
contrib/toolchain/binutils/gas/flonum-mult.c
Normal file
188
contrib/toolchain/binutils/gas/flonum-mult.c
Normal file
@ -0,0 +1,188 @@
|
||||
/* flonum_mult.c - multiply two flonums
|
||||
Copyright 1987, 1990, 1991, 1992, 1995, 2000, 2002, 2003, 2007
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include "flonum.h"
|
||||
|
||||
/* plan for a . b => p(roduct)
|
||||
|
||||
+-------+-------+-/ /-+-------+-------+
|
||||
| a | a | ... | a | a |
|
||||
| A | A-1 | | 1 | 0 |
|
||||
+-------+-------+-/ /-+-------+-------+
|
||||
|
||||
+-------+-------+-/ /-+-------+-------+
|
||||
| b | b | ... | b | b |
|
||||
| B | B-1 | | 1 | 0 |
|
||||
+-------+-------+-/ /-+-------+-------+
|
||||
|
||||
+-------+-------+-/ /-+-------+-/ /-+-------+-------+
|
||||
| p | p | ... | p | ... | p | p |
|
||||
| A+B+1| A+B | | N | | 1 | 0 |
|
||||
+-------+-------+-/ /-+-------+-/ /-+-------+-------+
|
||||
|
||||
/^\
|
||||
(carry) a .b ... | ... a .b a .b
|
||||
A B | 0 1 0 0
|
||||
|
|
||||
... | ... a .b
|
||||
| 1 0
|
||||
|
|
||||
| ...
|
||||
|
|
||||
|
|
||||
|
|
||||
| ___
|
||||
| \
|
||||
+----- P = > a .b
|
||||
N /__ i j
|
||||
|
||||
N = 0 ... A+B
|
||||
|
||||
for all i,j where i+j=N
|
||||
[i,j integers > 0]
|
||||
|
||||
a[], b[], p[] may not intersect.
|
||||
Zero length factors signify 0 significant bits: treat as 0.0.
|
||||
0.0 factors do the right thing.
|
||||
Zero length product OK.
|
||||
|
||||
I chose the ForTran accent "foo[bar]" instead of the C accent "*garply"
|
||||
because I felt the ForTran way was more intuitive. The C way would
|
||||
probably yield better code on most C compilers. Dean Elsner.
|
||||
(C style also gives deeper insight [to me] ... oh well ...) */
|
||||
|
||||
void
|
||||
flonum_multip (const FLONUM_TYPE *a, const FLONUM_TYPE *b,
|
||||
FLONUM_TYPE *product)
|
||||
{
|
||||
int size_of_a; /* 0 origin */
|
||||
int size_of_b; /* 0 origin */
|
||||
int size_of_product; /* 0 origin */
|
||||
int size_of_sum; /* 0 origin */
|
||||
int extra_product_positions; /* 1 origin */
|
||||
unsigned long work;
|
||||
unsigned long carry;
|
||||
long exponent;
|
||||
LITTLENUM_TYPE *q;
|
||||
long significant; /* TRUE when we emit a non-0 littlenum */
|
||||
/* ForTran accent follows. */
|
||||
int P; /* Scan product low-order -> high. */
|
||||
int N; /* As in sum above. */
|
||||
int A; /* Which [] of a? */
|
||||
int B; /* Which [] of b? */
|
||||
|
||||
if ((a->sign != '-' && a->sign != '+')
|
||||
|| (b->sign != '-' && b->sign != '+'))
|
||||
{
|
||||
/* Got to fail somehow. Any suggestions? */
|
||||
product->sign = 0;
|
||||
return;
|
||||
}
|
||||
product->sign = (a->sign == b->sign) ? '+' : '-';
|
||||
size_of_a = a->leader - a->low;
|
||||
size_of_b = b->leader - b->low;
|
||||
exponent = a->exponent + b->exponent;
|
||||
size_of_product = product->high - product->low;
|
||||
size_of_sum = size_of_a + size_of_b;
|
||||
extra_product_positions = size_of_product - size_of_sum;
|
||||
if (extra_product_positions < 0)
|
||||
{
|
||||
P = extra_product_positions; /* P < 0 */
|
||||
exponent -= extra_product_positions; /* Increases exponent. */
|
||||
}
|
||||
else
|
||||
{
|
||||
P = 0;
|
||||
}
|
||||
carry = 0;
|
||||
significant = 0;
|
||||
for (N = 0; N <= size_of_sum; N++)
|
||||
{
|
||||
work = carry;
|
||||
carry = 0;
|
||||
for (A = 0; A <= N; A++)
|
||||
{
|
||||
B = N - A;
|
||||
if (A <= size_of_a && B <= size_of_b && B >= 0)
|
||||
{
|
||||
#ifdef TRACE
|
||||
printf ("a:low[%d.]=%04x b:low[%d.]=%04x work_before=%08x\n",
|
||||
A, a->low[A], B, b->low[B], work);
|
||||
#endif
|
||||
/* Watch out for sign extension! Without the casts, on
|
||||
the DEC Alpha, the multiplication result is *signed*
|
||||
int, which gets sign-extended to convert to the
|
||||
unsigned long! */
|
||||
work += (unsigned long) a->low[A] * (unsigned long) b->low[B];
|
||||
carry += work >> LITTLENUM_NUMBER_OF_BITS;
|
||||
work &= LITTLENUM_MASK;
|
||||
#ifdef TRACE
|
||||
printf ("work=%08x carry=%04x\n", work, carry);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
significant |= work;
|
||||
if (significant || P < 0)
|
||||
{
|
||||
if (P >= 0)
|
||||
{
|
||||
product->low[P] = work;
|
||||
#ifdef TRACE
|
||||
printf ("P=%d. work[p]:=%04x\n", P, work);
|
||||
#endif
|
||||
}
|
||||
P++;
|
||||
}
|
||||
else
|
||||
{
|
||||
extra_product_positions++;
|
||||
exponent++;
|
||||
}
|
||||
}
|
||||
/* [P]-> position # size_of_sum + 1.
|
||||
This is where 'carry' should go. */
|
||||
#ifdef TRACE
|
||||
printf ("final carry =%04x\n", carry);
|
||||
#endif
|
||||
if (carry)
|
||||
{
|
||||
if (extra_product_positions > 0)
|
||||
product->low[P] = carry;
|
||||
else
|
||||
{
|
||||
/* No room at high order for carry littlenum. */
|
||||
/* Shift right 1 to make room for most significant littlenum. */
|
||||
exponent++;
|
||||
P--;
|
||||
for (q = product->low + P; q >= product->low; q--)
|
||||
{
|
||||
work = *q;
|
||||
*q = carry;
|
||||
carry = work;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
P--;
|
||||
product->leader = product->low + P;
|
||||
product->exponent = exponent;
|
||||
}
|
102
contrib/toolchain/binutils/gas/flonum.h
Normal file
102
contrib/toolchain/binutils/gas/flonum.h
Normal file
@ -0,0 +1,102 @@
|
||||
/* flonum.h - Floating point package
|
||||
Copyright 1987, 1990, 1991, 1992, 1994, 1996, 2000, 2003, 2005, 2007
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Arbitrary-precision floating point arithmetic. *
|
||||
* *
|
||||
* *
|
||||
* Notation: a floating point number is expressed as *
|
||||
* MANTISSA * (2 ** EXPONENT). *
|
||||
* *
|
||||
* If this offends more traditional mathematicians, then *
|
||||
* please tell me your nomenclature for flonums! *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
#include "bignum.h"
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Variable precision floating point numbers. *
|
||||
* *
|
||||
* Exponent is the place value of the low littlenum. E.g.: *
|
||||
* If 0: low points to the units littlenum. *
|
||||
* If 1: low points to the LITTLENUM_RADIX littlenum. *
|
||||
* If -1: low points to the 1/LITTLENUM_RADIX littlenum. *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
/* JF: A sign value of 0 means we have been asked to assemble NaN
|
||||
A sign value of 'P' means we've been asked to assemble +Inf
|
||||
A sign value of 'N' means we've been asked to assemble -Inf
|
||||
*/
|
||||
struct FLONUM_STRUCT {
|
||||
LITTLENUM_TYPE *low; /* low order littlenum of a bignum */
|
||||
LITTLENUM_TYPE *high; /* high order littlenum of a bignum */
|
||||
LITTLENUM_TYPE *leader; /* -> 1st non-zero littlenum */
|
||||
/* If flonum is 0.0, leader==low-1 */
|
||||
long exponent; /* base LITTLENUM_RADIX */
|
||||
char sign; /* '+' or '-' */
|
||||
};
|
||||
|
||||
typedef struct FLONUM_STRUCT FLONUM_TYPE;
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Since we can (& do) meet with exponents like 10^5000, it *
|
||||
* is silly to make a table of ~ 10,000 entries, one for each *
|
||||
* power of 10. We keep a table where item [n] is a struct *
|
||||
* FLONUM_FLOATING_POINT representing 10^(2^n). We then *
|
||||
* multiply appropriate entries from this table to get any *
|
||||
* particular power of 10. For the example of 10^5000, a table *
|
||||
* of just 25 entries suffices: 10^(2^-12)...10^(2^+12). *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
extern const FLONUM_TYPE flonum_positive_powers_of_ten[];
|
||||
extern const FLONUM_TYPE flonum_negative_powers_of_ten[];
|
||||
extern const int table_size_of_flonum_powers_of_ten;
|
||||
/* Flonum_XXX_powers_of_ten[] table has legal indices from 0 to
|
||||
+ this number inclusive. */
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Declare worker functions. *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
int atof_generic (char **address_of_string_pointer,
|
||||
const char *string_of_decimal_marks,
|
||||
const char *string_of_decimal_exponent_marks,
|
||||
FLONUM_TYPE * address_of_generic_floating_point_number);
|
||||
|
||||
void flonum_copy (FLONUM_TYPE * in, FLONUM_TYPE * out);
|
||||
void flonum_multip (const FLONUM_TYPE * a, const FLONUM_TYPE * b,
|
||||
FLONUM_TYPE * product);
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* Declare error codes. *
|
||||
* *
|
||||
\***********************************************************************/
|
||||
|
||||
#define ERROR_EXPONENT_OVERFLOW (2)
|
445
contrib/toolchain/binutils/gas/frags.c
Normal file
445
contrib/toolchain/binutils/gas/frags.c
Normal file
@ -0,0 +1,445 @@
|
||||
/* frags.c - manage frags -
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "subsegs.h"
|
||||
#include "obstack.h"
|
||||
|
||||
extern fragS zero_address_frag;
|
||||
extern fragS predefined_address_frag;
|
||||
|
||||
/* Initialization for frag routines. */
|
||||
|
||||
void
|
||||
frag_init (void)
|
||||
{
|
||||
zero_address_frag.fr_type = rs_fill;
|
||||
predefined_address_frag.fr_type = rs_fill;
|
||||
}
|
||||
|
||||
/* Check that we're not trying to assemble into a section that can't
|
||||
allocate frags (currently, this is only possible in the absolute
|
||||
section), or into an mri common. */
|
||||
|
||||
static void
|
||||
frag_alloc_check (const struct obstack *ob)
|
||||
{
|
||||
if (ob->chunk_size == 0)
|
||||
{
|
||||
as_bad (_("attempt to allocate data in absolute section"));
|
||||
subseg_set (text_section, 0);
|
||||
}
|
||||
|
||||
if (mri_common_symbol != NULL)
|
||||
{
|
||||
as_bad (_("attempt to allocate data in common section"));
|
||||
mri_common_symbol = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a frag on the specified obstack.
|
||||
Call this routine from everywhere else, so that all the weird alignment
|
||||
hackery can be done in just one place. */
|
||||
|
||||
fragS *
|
||||
frag_alloc (struct obstack *ob)
|
||||
{
|
||||
fragS *ptr;
|
||||
int oalign;
|
||||
|
||||
(void) obstack_alloc (ob, 0);
|
||||
oalign = obstack_alignment_mask (ob);
|
||||
obstack_alignment_mask (ob) = 0;
|
||||
ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG);
|
||||
obstack_alignment_mask (ob) = oalign;
|
||||
memset (ptr, 0, SIZEOF_STRUCT_FRAG);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Try to augment current frag by nchars chars.
|
||||
If there is no room, close of the current frag with a ".fill 0"
|
||||
and begin a new frag. Unless the new frag has nchars chars available
|
||||
do not return. Do not set up any fields of *now_frag. */
|
||||
|
||||
void
|
||||
frag_grow (unsigned int nchars)
|
||||
{
|
||||
if (obstack_room (&frchain_now->frch_obstack) < nchars)
|
||||
{
|
||||
long oldc;
|
||||
long newc;
|
||||
|
||||
/* Try to allocate a bit more than needed right now. But don't do
|
||||
this if we would waste too much memory. Especially necessary
|
||||
for extremely big (like 2GB initialized) frags. */
|
||||
if (nchars < 0x10000)
|
||||
newc = 2 * nchars;
|
||||
else
|
||||
newc = nchars + 0x10000;
|
||||
newc += SIZEOF_STRUCT_FRAG;
|
||||
|
||||
/* Check for possible overflow. */
|
||||
if (newc < 0)
|
||||
as_fatal (_("can't extend frag %u chars"), nchars);
|
||||
|
||||
/* Force to allocate at least NEWC bytes, but not less than the
|
||||
default. */
|
||||
oldc = obstack_chunk_size (&frchain_now->frch_obstack);
|
||||
if (newc > oldc)
|
||||
obstack_chunk_size (&frchain_now->frch_obstack) = newc;
|
||||
|
||||
while (obstack_room (&frchain_now->frch_obstack) < nchars)
|
||||
{
|
||||
/* Not enough room in this frag. Close it and start a new one.
|
||||
This must be done in a loop because the created frag may not
|
||||
be big enough if the current obstack chunk is used. */
|
||||
frag_wane (frag_now);
|
||||
frag_new (0);
|
||||
}
|
||||
|
||||
/* Restore the old chunk size. */
|
||||
obstack_chunk_size (&frchain_now->frch_obstack) = oldc;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call this to close off a completed frag, and start up a new (empty)
|
||||
frag, in the same subsegment as the old frag.
|
||||
[frchain_now remains the same but frag_now is updated.]
|
||||
Because this calculates the correct value of fr_fix by
|
||||
looking at the obstack 'frags', it needs to know how many
|
||||
characters at the end of the old frag belong to the maximal
|
||||
variable part; The rest must belong to fr_fix.
|
||||
It doesn't actually set up the old frag's fr_var. You may have
|
||||
set fr_var == 1, but allocated 10 chars to the end of the frag;
|
||||
In this case you pass old_frags_var_max_size == 10.
|
||||
In fact, you may use fr_var for something totally unrelated to the
|
||||
size of the variable part of the frag; None of the generic frag
|
||||
handling code makes use of fr_var.
|
||||
|
||||
Make a new frag, initialising some components. Link new frag at end
|
||||
of frchain_now. */
|
||||
|
||||
void
|
||||
frag_new (int old_frags_var_max_size
|
||||
/* Number of chars (already allocated on obstack frags) in
|
||||
variable_length part of frag. */)
|
||||
{
|
||||
fragS *former_last_fragP;
|
||||
frchainS *frchP;
|
||||
|
||||
gas_assert (frchain_now->frch_last == frag_now);
|
||||
|
||||
/* Fix up old frag's fr_fix. */
|
||||
frag_now->fr_fix = frag_now_fix_octets () - old_frags_var_max_size;
|
||||
/* Make sure its type is valid. */
|
||||
gas_assert (frag_now->fr_type != 0);
|
||||
|
||||
/* This will align the obstack so the next struct we allocate on it
|
||||
will begin at a correct boundary. */
|
||||
obstack_finish (&frchain_now->frch_obstack);
|
||||
frchP = frchain_now;
|
||||
know (frchP);
|
||||
former_last_fragP = frchP->frch_last;
|
||||
gas_assert (former_last_fragP != 0);
|
||||
gas_assert (former_last_fragP == frag_now);
|
||||
frag_now = frag_alloc (&frchP->frch_obstack);
|
||||
|
||||
as_where (&frag_now->fr_file, &frag_now->fr_line);
|
||||
|
||||
/* Generally, frag_now->points to an address rounded up to next
|
||||
alignment. However, characters will add to obstack frags
|
||||
IMMEDIATELY after the struct frag, even if they are not starting
|
||||
at an alignment address. */
|
||||
former_last_fragP->fr_next = frag_now;
|
||||
frchP->frch_last = frag_now;
|
||||
|
||||
#ifndef NO_LISTING
|
||||
{
|
||||
extern struct list_info_struct *listing_tail;
|
||||
frag_now->line = listing_tail;
|
||||
}
|
||||
#endif
|
||||
|
||||
gas_assert (frchain_now->frch_last == frag_now);
|
||||
|
||||
frag_now->fr_next = NULL;
|
||||
}
|
||||
|
||||
/* Start a new frag unless we have n more chars of room in the current frag.
|
||||
Close off the old frag with a .fill 0.
|
||||
|
||||
Return the address of the 1st char to write into. Advance
|
||||
frag_now_growth past the new chars. */
|
||||
|
||||
char *
|
||||
frag_more (int nchars)
|
||||
{
|
||||
register char *retval;
|
||||
|
||||
frag_alloc_check (&frchain_now->frch_obstack);
|
||||
frag_grow (nchars);
|
||||
retval = obstack_next_free (&frchain_now->frch_obstack);
|
||||
obstack_blank_fast (&frchain_now->frch_obstack, nchars);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Close the current frag, setting its fields for a relaxable frag. Start a
|
||||
new frag. */
|
||||
|
||||
static void
|
||||
frag_var_init (relax_stateT type, int max_chars, int var,
|
||||
relax_substateT subtype, symbolS *symbol, offsetT offset,
|
||||
char *opcode)
|
||||
{
|
||||
frag_now->fr_var = var;
|
||||
frag_now->fr_type = type;
|
||||
frag_now->fr_subtype = subtype;
|
||||
frag_now->fr_symbol = symbol;
|
||||
frag_now->fr_offset = offset;
|
||||
frag_now->fr_opcode = opcode;
|
||||
#ifdef USING_CGEN
|
||||
frag_now->fr_cgen.insn = 0;
|
||||
frag_now->fr_cgen.opindex = 0;
|
||||
frag_now->fr_cgen.opinfo = 0;
|
||||
#endif
|
||||
#ifdef TC_FRAG_INIT
|
||||
TC_FRAG_INIT (frag_now);
|
||||
#endif
|
||||
as_where (&frag_now->fr_file, &frag_now->fr_line);
|
||||
|
||||
frag_new (max_chars);
|
||||
}
|
||||
|
||||
/* Start a new frag unless we have max_chars more chars of room in the
|
||||
current frag. Close off the old frag with a .fill 0.
|
||||
|
||||
Set up a machine_dependent relaxable frag, then start a new frag.
|
||||
Return the address of the 1st char of the var part of the old frag
|
||||
to write into. */
|
||||
|
||||
char *
|
||||
frag_var (relax_stateT type, int max_chars, int var, relax_substateT subtype,
|
||||
symbolS *symbol, offsetT offset, char *opcode)
|
||||
{
|
||||
register char *retval;
|
||||
|
||||
frag_grow (max_chars);
|
||||
retval = obstack_next_free (&frchain_now->frch_obstack);
|
||||
obstack_blank_fast (&frchain_now->frch_obstack, max_chars);
|
||||
frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* OVE: This variant of frag_var assumes that space for the tail has been
|
||||
allocated by caller.
|
||||
No call to frag_grow is done. */
|
||||
|
||||
char *
|
||||
frag_variant (relax_stateT type, int max_chars, int var,
|
||||
relax_substateT subtype, symbolS *symbol, offsetT offset,
|
||||
char *opcode)
|
||||
{
|
||||
register char *retval;
|
||||
|
||||
retval = obstack_next_free (&frchain_now->frch_obstack);
|
||||
frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Reduce the variable end of a frag to a harmless state. */
|
||||
|
||||
void
|
||||
frag_wane (register fragS *fragP)
|
||||
{
|
||||
fragP->fr_type = rs_fill;
|
||||
fragP->fr_offset = 0;
|
||||
fragP->fr_var = 0;
|
||||
}
|
||||
|
||||
/* Return the number of bytes by which the current frag can be grown. */
|
||||
|
||||
int
|
||||
frag_room (void)
|
||||
{
|
||||
return obstack_room (&frchain_now->frch_obstack);
|
||||
}
|
||||
|
||||
/* Make an alignment frag. The size of this frag will be adjusted to
|
||||
force the next frag to have the appropriate alignment. ALIGNMENT
|
||||
is the power of two to which to align. FILL_CHARACTER is the
|
||||
character to use to fill in any bytes which are skipped. MAX is
|
||||
the maximum number of characters to skip when doing the alignment,
|
||||
or 0 if there is no maximum. */
|
||||
|
||||
void
|
||||
frag_align (int alignment, int fill_character, int max)
|
||||
{
|
||||
if (now_seg == absolute_section)
|
||||
{
|
||||
addressT new_off;
|
||||
addressT mask;
|
||||
|
||||
mask = (~(addressT) 0) << alignment;
|
||||
new_off = (abs_section_offset + ~mask) & mask;
|
||||
if (max == 0 || new_off - abs_section_offset <= (addressT) max)
|
||||
abs_section_offset = new_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = frag_var (rs_align, 1, 1, (relax_substateT) max,
|
||||
(symbolS *) 0, (offsetT) alignment, (char *) 0);
|
||||
*p = fill_character;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make an alignment frag like frag_align, but fill with a repeating
|
||||
pattern rather than a single byte. ALIGNMENT is the power of two
|
||||
to which to align. FILL_PATTERN is the fill pattern to repeat in
|
||||
the bytes which are skipped. N_FILL is the number of bytes in
|
||||
FILL_PATTERN. MAX is the maximum number of characters to skip when
|
||||
doing the alignment, or 0 if there is no maximum. */
|
||||
|
||||
void
|
||||
frag_align_pattern (int alignment, const char *fill_pattern,
|
||||
int n_fill, int max)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) max,
|
||||
(symbolS *) 0, (offsetT) alignment, (char *) 0);
|
||||
memcpy (p, fill_pattern, n_fill);
|
||||
}
|
||||
|
||||
/* The NOP_OPCODE is for the alignment fill value. Fill it with a nop
|
||||
instruction so that the disassembler does not choke on it. */
|
||||
#ifndef NOP_OPCODE
|
||||
#define NOP_OPCODE 0x00
|
||||
#endif
|
||||
|
||||
/* Use this to restrict the amount of memory allocated for representing
|
||||
the alignment code. Needs to be large enough to hold any fixed sized
|
||||
prologue plus the replicating portion. */
|
||||
#ifndef MAX_MEM_FOR_RS_ALIGN_CODE
|
||||
/* Assume that if HANDLE_ALIGN is not defined then no special action
|
||||
is required to code fill, which means that we get just repeat the
|
||||
one NOP_OPCODE byte. */
|
||||
# ifndef HANDLE_ALIGN
|
||||
# define MAX_MEM_FOR_RS_ALIGN_CODE 1
|
||||
# else
|
||||
# define MAX_MEM_FOR_RS_ALIGN_CODE ((1 << alignment) - 1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void
|
||||
frag_align_code (int alignment, int max)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, 1,
|
||||
(relax_substateT) max, (symbolS *) 0,
|
||||
(offsetT) alignment, (char *) 0);
|
||||
*p = NOP_OPCODE;
|
||||
}
|
||||
|
||||
addressT
|
||||
frag_now_fix_octets (void)
|
||||
{
|
||||
if (now_seg == absolute_section)
|
||||
return abs_section_offset;
|
||||
|
||||
return ((char *) obstack_next_free (&frchain_now->frch_obstack)
|
||||
- frag_now->fr_literal);
|
||||
}
|
||||
|
||||
addressT
|
||||
frag_now_fix (void)
|
||||
{
|
||||
return frag_now_fix_octets () / OCTETS_PER_BYTE;
|
||||
}
|
||||
|
||||
void
|
||||
frag_append_1_char (int datum)
|
||||
{
|
||||
frag_alloc_check (&frchain_now->frch_obstack);
|
||||
if (obstack_room (&frchain_now->frch_obstack) <= 1)
|
||||
{
|
||||
frag_wane (frag_now);
|
||||
frag_new (0);
|
||||
}
|
||||
obstack_1grow (&frchain_now->frch_obstack, datum);
|
||||
}
|
||||
|
||||
/* Return TRUE if FRAG1 and FRAG2 have a fixed relationship between
|
||||
their start addresses. Set OFFSET to the difference in address
|
||||
not already accounted for in the frag FR_ADDRESS. */
|
||||
|
||||
bfd_boolean
|
||||
frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset)
|
||||
{
|
||||
const fragS *frag;
|
||||
offsetT off;
|
||||
|
||||
/* Start with offset initialised to difference between the two frags.
|
||||
Prior to assigning frag addresses this will be zero. */
|
||||
off = frag1->fr_address - frag2->fr_address;
|
||||
if (frag1 == frag2)
|
||||
{
|
||||
*offset = off;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Maybe frag2 is after frag1. */
|
||||
frag = frag1;
|
||||
while (frag->fr_type == rs_fill)
|
||||
{
|
||||
off += frag->fr_fix + frag->fr_offset * frag->fr_var;
|
||||
frag = frag->fr_next;
|
||||
if (frag == NULL)
|
||||
break;
|
||||
if (frag == frag2)
|
||||
{
|
||||
*offset = off;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe frag1 is after frag2. */
|
||||
off = frag1->fr_address - frag2->fr_address;
|
||||
frag = frag2;
|
||||
while (frag->fr_type == rs_fill)
|
||||
{
|
||||
off -= frag->fr_fix + frag->fr_offset * frag->fr_var;
|
||||
frag = frag->fr_next;
|
||||
if (frag == NULL)
|
||||
break;
|
||||
if (frag == frag1)
|
||||
{
|
||||
*offset = off;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
160
contrib/toolchain/binutils/gas/frags.h
Normal file
160
contrib/toolchain/binutils/gas/frags.h
Normal file
@ -0,0 +1,160 @@
|
||||
/* frags.h - Header file for the frag concept.
|
||||
Copyright 1987, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef FRAGS_H
|
||||
#define FRAGS_H
|
||||
|
||||
struct obstack;
|
||||
|
||||
/* A code fragment (frag) is some known number of chars, followed by some
|
||||
unknown number of chars. Typically the unknown number of chars is an
|
||||
instruction address whose size is yet unknown. We always know the greatest
|
||||
possible size the unknown number of chars may become, and reserve that
|
||||
much room at the end of the frag.
|
||||
Once created, frags do not change address during assembly.
|
||||
We chain the frags in (a) forward-linked list(s). The object-file address
|
||||
of the 1st char of a frag is generally not known until after relax().
|
||||
Many things at assembly time describe an address by {object-file-address
|
||||
of a particular frag}+offset.
|
||||
|
||||
BUG: it may be smarter to have a single pointer off to various different
|
||||
notes for different frag kinds. See how code pans. */
|
||||
|
||||
struct frag {
|
||||
/* Object file address (as an octet offset). */
|
||||
addressT fr_address;
|
||||
/* When relaxing multiple times, remember the address the frag had
|
||||
in the last relax pass. */
|
||||
addressT last_fr_address;
|
||||
|
||||
/* (Fixed) number of octets we know we have. May be 0. */
|
||||
offsetT fr_fix;
|
||||
/* May be used for (Variable) number of octets after above.
|
||||
The generic frag handling code no longer makes any use of fr_var. */
|
||||
offsetT fr_var;
|
||||
/* For variable-length tail. */
|
||||
offsetT fr_offset;
|
||||
/* For variable-length tail. */
|
||||
symbolS *fr_symbol;
|
||||
/* Points to opcode low addr byte, for relaxation. */
|
||||
char *fr_opcode;
|
||||
|
||||
/* Chain forward; ascending address order. Rooted in frch_root. */
|
||||
struct frag *fr_next;
|
||||
|
||||
/* Where the frag was created, or where it became a variant frag. */
|
||||
char *fr_file;
|
||||
unsigned int fr_line;
|
||||
|
||||
#ifndef NO_LISTING
|
||||
struct list_info_struct *line;
|
||||
#endif
|
||||
|
||||
/* A serial number for a sequence of frags having at most one alignment
|
||||
or org frag, and that at the tail of the sequence. */
|
||||
unsigned int region:16;
|
||||
|
||||
/* Flipped each relax pass so we can easily determine whether
|
||||
fr_address has been adjusted. */
|
||||
unsigned int relax_marker:1;
|
||||
|
||||
/* Used to ensure that all insns are emitted on proper address
|
||||
boundaries. */
|
||||
unsigned int has_code:1;
|
||||
unsigned int insn_addr:6;
|
||||
|
||||
/* What state is my tail in? */
|
||||
relax_stateT fr_type;
|
||||
relax_substateT fr_subtype;
|
||||
|
||||
#ifdef USING_CGEN
|
||||
/* Don't include this unless using CGEN to keep frag size down. */
|
||||
struct {
|
||||
/* CGEN_INSN entry for this instruction. */
|
||||
const struct cgen_insn *insn;
|
||||
/* Index into operand table. */
|
||||
int opindex;
|
||||
/* Target specific data, usually reloc number. */
|
||||
int opinfo;
|
||||
} fr_cgen;
|
||||
#endif
|
||||
|
||||
#ifdef TC_FRAG_TYPE
|
||||
TC_FRAG_TYPE tc_frag_data;
|
||||
#endif
|
||||
#ifdef OBJ_FRAG_TYPE
|
||||
OBJ_FRAG_TYPE obj_frag_data;
|
||||
#endif
|
||||
|
||||
/* Data begins here. */
|
||||
char fr_literal[1];
|
||||
};
|
||||
|
||||
#define SIZEOF_STRUCT_FRAG \
|
||||
((char *) zero_address_frag.fr_literal - (char *) &zero_address_frag)
|
||||
/* We want to say fr_literal[0] above. */
|
||||
|
||||
/* Current frag we are building. This frag is incomplete. It is,
|
||||
however, included in frchain_now. The fr_fix field is bogus;
|
||||
instead, use frag_now_fix (). */
|
||||
COMMON fragS *frag_now;
|
||||
extern addressT frag_now_fix (void);
|
||||
extern addressT frag_now_fix_octets (void);
|
||||
|
||||
/* For foreign-segment symbol fixups. */
|
||||
COMMON fragS zero_address_frag;
|
||||
COMMON fragS predefined_address_frag;
|
||||
|
||||
extern void frag_append_1_char (int);
|
||||
#define FRAG_APPEND_1_CHAR(X) frag_append_1_char (X)
|
||||
|
||||
void frag_init (void);
|
||||
fragS *frag_alloc (struct obstack *);
|
||||
void frag_grow (unsigned int nchars);
|
||||
char *frag_more (int nchars);
|
||||
void frag_align (int alignment, int fill_character, int max);
|
||||
void frag_align_pattern (int alignment, const char *fill_pattern,
|
||||
int n_fill, int max);
|
||||
void frag_align_code (int alignment, int max);
|
||||
void frag_new (int old_frags_var_max_size);
|
||||
void frag_wane (fragS * fragP);
|
||||
int frag_room (void);
|
||||
|
||||
char *frag_variant (relax_stateT type,
|
||||
int max_chars,
|
||||
int var,
|
||||
relax_substateT subtype,
|
||||
symbolS * symbol,
|
||||
offsetT offset,
|
||||
char *opcode);
|
||||
|
||||
char *frag_var (relax_stateT type,
|
||||
int max_chars,
|
||||
int var,
|
||||
relax_substateT subtype,
|
||||
symbolS * symbol,
|
||||
offsetT offset,
|
||||
char *opcode);
|
||||
|
||||
bfd_boolean frag_offset_fixed_p (const fragS *, const fragS *, offsetT *);
|
||||
|
||||
#endif /* FRAGS_H */
|
597
contrib/toolchain/binutils/gas/hash.c
Normal file
597
contrib/toolchain/binutils/gas/hash.c
Normal file
@ -0,0 +1,597 @@
|
||||
/* hash.c -- gas hash table code
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999,
|
||||
2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2011, 2013
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* This version of the hash table code is a wholescale replacement of
|
||||
the old hash table code, which was fairly bad. This is based on
|
||||
the hash table code in BFD, but optimized slightly for the
|
||||
assembler. The assembler does not need to derive structures that
|
||||
are stored in the hash table. Instead, it always stores a pointer.
|
||||
The assembler uses the hash table mostly to store symbols, and we
|
||||
don't need to confuse the symbol structure with a hash table
|
||||
structure. */
|
||||
|
||||
#include "as.h"
|
||||
#include "safe-ctype.h"
|
||||
#include "obstack.h"
|
||||
|
||||
/* An entry in a hash table. */
|
||||
|
||||
struct hash_entry {
|
||||
/* Next entry for this hash code. */
|
||||
struct hash_entry *next;
|
||||
/* String being hashed. */
|
||||
const char *string;
|
||||
/* Hash code. This is the full hash code, not the index into the
|
||||
table. */
|
||||
unsigned long hash;
|
||||
/* Pointer being stored in the hash table. */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* A hash table. */
|
||||
|
||||
struct hash_control {
|
||||
/* The hash array. */
|
||||
struct hash_entry **table;
|
||||
/* The number of slots in the hash table. */
|
||||
unsigned int size;
|
||||
/* An obstack for this hash table. */
|
||||
struct obstack memory;
|
||||
|
||||
#ifdef HASH_STATISTICS
|
||||
/* Statistics. */
|
||||
unsigned long lookups;
|
||||
unsigned long hash_compares;
|
||||
unsigned long string_compares;
|
||||
unsigned long insertions;
|
||||
unsigned long replacements;
|
||||
unsigned long deletions;
|
||||
#endif /* HASH_STATISTICS */
|
||||
};
|
||||
|
||||
/* The default number of entries to use when creating a hash table.
|
||||
Note this value can be reduced to 4051 by using the command line
|
||||
switch --reduce-memory-overheads, or set to other values by using
|
||||
the --hash-size=<NUMBER> switch. */
|
||||
|
||||
static unsigned long gas_hash_table_size = 65537;
|
||||
|
||||
void
|
||||
set_gas_hash_table_size (unsigned long size)
|
||||
{
|
||||
gas_hash_table_size = bfd_hash_set_default_size (size);
|
||||
}
|
||||
|
||||
/* Create a hash table. This return a control block. */
|
||||
|
||||
struct hash_control *
|
||||
hash_new_sized (unsigned long size)
|
||||
{
|
||||
unsigned long alloc;
|
||||
struct hash_control *ret;
|
||||
|
||||
ret = (struct hash_control *) xmalloc (sizeof *ret);
|
||||
obstack_begin (&ret->memory, chunksize);
|
||||
alloc = size * sizeof (struct hash_entry *);
|
||||
ret->table = (struct hash_entry **) obstack_alloc (&ret->memory, alloc);
|
||||
memset (ret->table, 0, alloc);
|
||||
ret->size = size;
|
||||
|
||||
#ifdef HASH_STATISTICS
|
||||
ret->lookups = 0;
|
||||
ret->hash_compares = 0;
|
||||
ret->string_compares = 0;
|
||||
ret->insertions = 0;
|
||||
ret->replacements = 0;
|
||||
ret->deletions = 0;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct hash_control *
|
||||
hash_new (void)
|
||||
{
|
||||
return hash_new_sized (gas_hash_table_size);
|
||||
}
|
||||
|
||||
/* Delete a hash table, freeing all allocated memory. */
|
||||
|
||||
void
|
||||
hash_die (struct hash_control *table)
|
||||
{
|
||||
obstack_free (&table->memory, 0);
|
||||
free (table);
|
||||
}
|
||||
|
||||
/* Look up a string in a hash table. This returns a pointer to the
|
||||
hash_entry, or NULL if the string is not in the table. If PLIST is
|
||||
not NULL, this sets *PLIST to point to the start of the list which
|
||||
would hold this hash entry. If PHASH is not NULL, this sets *PHASH
|
||||
to the hash code for KEY.
|
||||
|
||||
Each time we look up a string, we move it to the start of the list
|
||||
for its hash code, to take advantage of referential locality. */
|
||||
|
||||
static struct hash_entry *
|
||||
hash_lookup (struct hash_control *table, const char *key, size_t len,
|
||||
struct hash_entry ***plist, unsigned long *phash)
|
||||
{
|
||||
unsigned long hash;
|
||||
size_t n;
|
||||
unsigned int c;
|
||||
unsigned int hindex;
|
||||
struct hash_entry **list;
|
||||
struct hash_entry *p;
|
||||
struct hash_entry *prev;
|
||||
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->lookups;
|
||||
#endif
|
||||
|
||||
hash = 0;
|
||||
for (n = 0; n < len; n++)
|
||||
{
|
||||
c = key[n];
|
||||
hash += c + (c << 17);
|
||||
hash ^= hash >> 2;
|
||||
}
|
||||
hash += len + (len << 17);
|
||||
hash ^= hash >> 2;
|
||||
|
||||
if (phash != NULL)
|
||||
*phash = hash;
|
||||
|
||||
hindex = hash % table->size;
|
||||
list = table->table + hindex;
|
||||
|
||||
if (plist != NULL)
|
||||
*plist = list;
|
||||
|
||||
prev = NULL;
|
||||
for (p = *list; p != NULL; p = p->next)
|
||||
{
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->hash_compares;
|
||||
#endif
|
||||
|
||||
if (p->hash == hash)
|
||||
{
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->string_compares;
|
||||
#endif
|
||||
|
||||
if (strncmp (p->string, key, len) == 0 && p->string[len] == '\0')
|
||||
{
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = p->next;
|
||||
p->next = *list;
|
||||
*list = p;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
prev = p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Insert an entry into a hash table. This returns NULL on success.
|
||||
On error, it returns a printable string indicating the error. It
|
||||
is considered to be an error if the entry already exists in the
|
||||
hash table. */
|
||||
|
||||
const char *
|
||||
hash_insert (struct hash_control *table, const char *key, void *val)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
struct hash_entry **list;
|
||||
unsigned long hash;
|
||||
|
||||
p = hash_lookup (table, key, strlen (key), &list, &hash);
|
||||
if (p != NULL)
|
||||
return "exists";
|
||||
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->insertions;
|
||||
#endif
|
||||
|
||||
p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p));
|
||||
p->string = key;
|
||||
p->hash = hash;
|
||||
p->data = val;
|
||||
|
||||
p->next = *list;
|
||||
*list = p;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Insert or replace an entry in a hash table. This returns NULL on
|
||||
success. On error, it returns a printable string indicating the
|
||||
error. If an entry already exists, its value is replaced. */
|
||||
|
||||
const char *
|
||||
hash_jam (struct hash_control *table, const char *key, void *val)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
struct hash_entry **list;
|
||||
unsigned long hash;
|
||||
|
||||
p = hash_lookup (table, key, strlen (key), &list, &hash);
|
||||
if (p != NULL)
|
||||
{
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->replacements;
|
||||
#endif
|
||||
|
||||
p->data = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->insertions;
|
||||
#endif
|
||||
|
||||
p = (struct hash_entry *) obstack_alloc (&table->memory, sizeof (*p));
|
||||
p->string = key;
|
||||
p->hash = hash;
|
||||
p->data = val;
|
||||
|
||||
p->next = *list;
|
||||
*list = p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Replace an existing entry in a hash table. This returns the old
|
||||
value stored for the entry. If the entry is not found in the hash
|
||||
table, this does nothing and returns NULL. */
|
||||
|
||||
void *
|
||||
hash_replace (struct hash_control *table, const char *key, void *value)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
void *ret;
|
||||
|
||||
p = hash_lookup (table, key, strlen (key), NULL, NULL);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->replacements;
|
||||
#endif
|
||||
|
||||
ret = p->data;
|
||||
|
||||
p->data = value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Find an entry in a hash table, returning its value. Returns NULL
|
||||
if the entry is not found. */
|
||||
|
||||
void *
|
||||
hash_find (struct hash_control *table, const char *key)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
|
||||
p = hash_lookup (table, key, strlen (key), NULL, NULL);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
/* As hash_find, but KEY is of length LEN and is not guaranteed to be
|
||||
NUL-terminated. */
|
||||
|
||||
void *
|
||||
hash_find_n (struct hash_control *table, const char *key, size_t len)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
|
||||
p = hash_lookup (table, key, len, NULL, NULL);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
/* Delete an entry from a hash table. This returns the value stored
|
||||
for that entry, or NULL if there is no such entry. */
|
||||
|
||||
void *
|
||||
hash_delete (struct hash_control *table, const char *key, int freeme)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
struct hash_entry **list;
|
||||
|
||||
p = hash_lookup (table, key, strlen (key), &list, NULL);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
if (p != *list)
|
||||
abort ();
|
||||
|
||||
#ifdef HASH_STATISTICS
|
||||
++table->deletions;
|
||||
#endif
|
||||
|
||||
*list = p->next;
|
||||
|
||||
if (freeme)
|
||||
obstack_free (&table->memory, p);
|
||||
|
||||
return p->data;
|
||||
}
|
||||
|
||||
/* Traverse a hash table. Call the function on every entry in the
|
||||
hash table. */
|
||||
|
||||
void
|
||||
hash_traverse (struct hash_control *table,
|
||||
void (*pfn) (const char *key, void *value))
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < table->size; ++i)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
|
||||
for (p = table->table[i]; p != NULL; p = p->next)
|
||||
(*pfn) (p->string, p->data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print hash table statistics on the specified file. NAME is the
|
||||
name of the hash table, used for printing a header. */
|
||||
|
||||
void
|
||||
hash_print_statistics (FILE *f ATTRIBUTE_UNUSED,
|
||||
const char *name ATTRIBUTE_UNUSED,
|
||||
struct hash_control *table ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifdef HASH_STATISTICS
|
||||
unsigned int i;
|
||||
unsigned long total;
|
||||
unsigned long empty;
|
||||
|
||||
fprintf (f, "%s hash statistics:\n", name);
|
||||
fprintf (f, "\t%lu lookups\n", table->lookups);
|
||||
fprintf (f, "\t%lu hash comparisons\n", table->hash_compares);
|
||||
fprintf (f, "\t%lu string comparisons\n", table->string_compares);
|
||||
fprintf (f, "\t%lu insertions\n", table->insertions);
|
||||
fprintf (f, "\t%lu replacements\n", table->replacements);
|
||||
fprintf (f, "\t%lu deletions\n", table->deletions);
|
||||
|
||||
total = 0;
|
||||
empty = 0;
|
||||
for (i = 0; i < table->size; ++i)
|
||||
{
|
||||
struct hash_entry *p;
|
||||
|
||||
if (table->table[i] == NULL)
|
||||
++empty;
|
||||
else
|
||||
{
|
||||
for (p = table->table[i]; p != NULL; p = p->next)
|
||||
++total;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (f, "\t%g average chain length\n", (double) total / table->size);
|
||||
fprintf (f, "\t%lu empty slots\n", empty);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/* This test program is left over from the old hash table code. */
|
||||
|
||||
/* Number of hash tables to maintain (at once) in any testing. */
|
||||
#define TABLES (6)
|
||||
|
||||
/* We can have 12 statistics. */
|
||||
#define STATBUFSIZE (12)
|
||||
|
||||
/* Display statistics here. */
|
||||
int statbuf[STATBUFSIZE];
|
||||
|
||||
/* Human farts here. */
|
||||
char answer[100];
|
||||
|
||||
/* We test many hash tables at once. */
|
||||
char *hashtable[TABLES];
|
||||
|
||||
/* Points to current hash_control. */
|
||||
char *h;
|
||||
char **pp;
|
||||
char *p;
|
||||
char *name;
|
||||
char *value;
|
||||
int size;
|
||||
int used;
|
||||
char command;
|
||||
|
||||
/* Number 0:TABLES-1 of current hashed symbol table. */
|
||||
int number;
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
void applicatee ();
|
||||
void destroy ();
|
||||
char *what ();
|
||||
int *ip;
|
||||
|
||||
number = 0;
|
||||
h = 0;
|
||||
printf ("type h <RETURN> for help\n");
|
||||
for (;;)
|
||||
{
|
||||
printf ("hash_test command: ");
|
||||
gets (answer);
|
||||
command = answer[0];
|
||||
command = TOLOWER (command); /* Ecch! */
|
||||
switch (command)
|
||||
{
|
||||
case '#':
|
||||
printf ("old hash table #=%d.\n", number);
|
||||
whattable ();
|
||||
break;
|
||||
case '?':
|
||||
for (pp = hashtable; pp < hashtable + TABLES; pp++)
|
||||
{
|
||||
printf ("address of hash table #%d control block is %xx\n",
|
||||
pp - hashtable, *pp);
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
hash_traverse (h, applicatee);
|
||||
break;
|
||||
case 'd':
|
||||
hash_traverse (h, destroy);
|
||||
hash_die (h);
|
||||
break;
|
||||
case 'f':
|
||||
p = hash_find (h, name = what ("symbol"));
|
||||
printf ("value of \"%s\" is \"%s\"\n", name, p ? p : "NOT-PRESENT");
|
||||
break;
|
||||
case 'h':
|
||||
printf ("# show old, select new default hash table number\n");
|
||||
printf ("? display all hashtable control block addresses\n");
|
||||
printf ("a apply a simple display-er to each symbol in table\n");
|
||||
printf ("d die: destroy hashtable\n");
|
||||
printf ("f find value of nominated symbol\n");
|
||||
printf ("h this help\n");
|
||||
printf ("i insert value into symbol\n");
|
||||
printf ("j jam value into symbol\n");
|
||||
printf ("n new hashtable\n");
|
||||
printf ("r replace a value with another\n");
|
||||
printf ("s say what %% of table is used\n");
|
||||
printf ("q exit this program\n");
|
||||
printf ("x delete a symbol from table, report its value\n");
|
||||
break;
|
||||
case 'i':
|
||||
p = hash_insert (h, name = what ("symbol"), value = what ("value"));
|
||||
if (p)
|
||||
{
|
||||
printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value,
|
||||
p);
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
p = hash_jam (h, name = what ("symbol"), value = what ("value"));
|
||||
if (p)
|
||||
{
|
||||
printf ("symbol=\"%s\" value=\"%s\" error=%s\n", name, value, p);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
h = hashtable[number] = (char *) hash_new ();
|
||||
break;
|
||||
case 'q':
|
||||
exit (EXIT_SUCCESS);
|
||||
case 'r':
|
||||
p = hash_replace (h, name = what ("symbol"), value = what ("value"));
|
||||
printf ("old value was \"%s\"\n", p ? p : "{}");
|
||||
break;
|
||||
case 's':
|
||||
hash_say (h, statbuf, STATBUFSIZE);
|
||||
for (ip = statbuf; ip < statbuf + STATBUFSIZE; ip++)
|
||||
{
|
||||
printf ("%d ", *ip);
|
||||
}
|
||||
printf ("\n");
|
||||
break;
|
||||
case 'x':
|
||||
p = hash_delete (h, name = what ("symbol"));
|
||||
printf ("old value was \"%s\"\n", p ? p : "{}");
|
||||
break;
|
||||
default:
|
||||
printf ("I can't understand command \"%c\"\n", command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
what (description)
|
||||
char *description;
|
||||
{
|
||||
printf (" %s : ", description);
|
||||
gets (answer);
|
||||
return xstrdup (answer);
|
||||
}
|
||||
|
||||
void
|
||||
destroy (string, value)
|
||||
char *string;
|
||||
char *value;
|
||||
{
|
||||
free (string);
|
||||
free (value);
|
||||
}
|
||||
|
||||
void
|
||||
applicatee (string, value)
|
||||
char *string;
|
||||
char *value;
|
||||
{
|
||||
printf ("%.20s-%.20s\n", string, value);
|
||||
}
|
||||
|
||||
/* Determine number: what hash table to use.
|
||||
Also determine h: points to hash_control. */
|
||||
|
||||
void
|
||||
whattable ()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
printf (" what hash table (%d:%d) ? ", 0, TABLES - 1);
|
||||
gets (answer);
|
||||
sscanf (answer, "%d", &number);
|
||||
if (number >= 0 && number < TABLES)
|
||||
{
|
||||
h = hashtable[number];
|
||||
if (!h)
|
||||
{
|
||||
printf ("warning: current hash-table-#%d. has no hash-control\n", number);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("invalid hash table number: %d\n", number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
89
contrib/toolchain/binutils/gas/hash.h
Normal file
89
contrib/toolchain/binutils/gas/hash.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* hash.h -- header file for gas hash table routines
|
||||
Copyright 1987, 1992, 1993, 1995, 1999, 2003, 2005, 2007, 2008, 2013
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef HASH_H
|
||||
#define HASH_H
|
||||
|
||||
struct hash_control;
|
||||
|
||||
/* Set the size of the hash table used. */
|
||||
|
||||
void set_gas_hash_table_size (unsigned long);
|
||||
|
||||
/* Create a hash table. This return a control block. */
|
||||
|
||||
extern struct hash_control *hash_new (void);
|
||||
extern struct hash_control *hash_new_sized (unsigned long);
|
||||
|
||||
/* Delete a hash table, freeing all allocated memory. */
|
||||
|
||||
extern void hash_die (struct hash_control *);
|
||||
|
||||
/* Insert an entry into a hash table. This returns NULL on success.
|
||||
On error, it returns a printable string indicating the error. It
|
||||
is considered to be an error if the entry already exists in the
|
||||
hash table. */
|
||||
|
||||
extern const char *hash_insert (struct hash_control *,
|
||||
const char *key, void *value);
|
||||
|
||||
/* Insert or replace an entry in a hash table. This returns NULL on
|
||||
success. On error, it returns a printable string indicating the
|
||||
error. If an entry already exists, its value is replaced. */
|
||||
|
||||
extern const char *hash_jam (struct hash_control *,
|
||||
const char *key, void *value);
|
||||
|
||||
/* Replace an existing entry in a hash table. This returns the old
|
||||
value stored for the entry. If the entry is not found in the hash
|
||||
table, this does nothing and returns NULL. */
|
||||
|
||||
extern void *hash_replace (struct hash_control *, const char *key,
|
||||
void *value);
|
||||
|
||||
/* Find an entry in a hash table, returning its value. Returns NULL
|
||||
if the entry is not found. */
|
||||
|
||||
extern void *hash_find (struct hash_control *, const char *key);
|
||||
|
||||
/* As hash_find, but KEY is of length LEN and is not guaranteed to be
|
||||
NUL-terminated. */
|
||||
|
||||
extern void *hash_find_n (struct hash_control *, const char *key, size_t len);
|
||||
|
||||
/* Delete an entry from a hash table. This returns the value stored
|
||||
for that entry, or NULL if there is no such entry. */
|
||||
|
||||
extern void *hash_delete (struct hash_control *, const char *key, int);
|
||||
|
||||
/* Traverse a hash table. Call the function on every entry in the
|
||||
hash table. */
|
||||
|
||||
extern void hash_traverse (struct hash_control *,
|
||||
void (*pfn) (const char *key, void *value));
|
||||
|
||||
/* Print hash table statistics on the specified file. NAME is the
|
||||
name of the hash table, used for printing a header. */
|
||||
|
||||
extern void hash_print_statistics (FILE *, const char *name,
|
||||
struct hash_control *);
|
||||
|
||||
#endif /* HASH_H */
|
259
contrib/toolchain/binutils/gas/input-file.c
Normal file
259
contrib/toolchain/binutils/gas/input-file.c
Normal file
@ -0,0 +1,259 @@
|
||||
/* input_file.c - Deal with Input Files -
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001,
|
||||
2002, 2003, 2005, 2006, 2007, 2009, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Confines all details of reading source bytes to this module.
|
||||
All O/S specific crocks should live here.
|
||||
What we lose in "efficiency" we gain in modularity.
|
||||
Note we don't need to #include the "as.h" file. No common coupling! */
|
||||
|
||||
#include "as.h"
|
||||
#include "input-file.h"
|
||||
#include "safe-ctype.h"
|
||||
|
||||
/* This variable is non-zero if the file currently being read should be
|
||||
preprocessed by app. It is zero if the file can be read straight in. */
|
||||
int preprocess = 0;
|
||||
|
||||
/* This code opens a file, then delivers BUFFER_SIZE character
|
||||
chunks of the file on demand.
|
||||
BUFFER_SIZE is supposed to be a number chosen for speed.
|
||||
The caller only asks once what BUFFER_SIZE is, and asks before
|
||||
the nature of the input files (if any) is known. */
|
||||
|
||||
#define BUFFER_SIZE (32 * 1024)
|
||||
|
||||
/* We use static data: the data area is not sharable. */
|
||||
|
||||
static FILE *f_in;
|
||||
static char *file_name;
|
||||
|
||||
/* Struct for saving the state of this module for file includes. */
|
||||
struct saved_file
|
||||
{
|
||||
FILE * f_in;
|
||||
char * file_name;
|
||||
int preprocess;
|
||||
char * app_save;
|
||||
};
|
||||
|
||||
/* These hooks accommodate most operating systems. */
|
||||
|
||||
void
|
||||
input_file_begin (void)
|
||||
{
|
||||
f_in = (FILE *) 0;
|
||||
}
|
||||
|
||||
void
|
||||
input_file_end (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Return BUFFER_SIZE. */
|
||||
size_t
|
||||
input_file_buffer_size (void)
|
||||
{
|
||||
return (BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/* Push the state of our input, returning a pointer to saved info that
|
||||
can be restored with input_file_pop (). */
|
||||
|
||||
char *
|
||||
input_file_push (void)
|
||||
{
|
||||
register struct saved_file *saved;
|
||||
|
||||
saved = (struct saved_file *) xmalloc (sizeof *saved);
|
||||
|
||||
saved->f_in = f_in;
|
||||
saved->file_name = file_name;
|
||||
saved->preprocess = preprocess;
|
||||
if (preprocess)
|
||||
saved->app_save = app_push ();
|
||||
|
||||
/* Initialize for new file. */
|
||||
input_file_begin ();
|
||||
|
||||
return (char *) saved;
|
||||
}
|
||||
|
||||
void
|
||||
input_file_pop (char *arg)
|
||||
{
|
||||
register struct saved_file *saved = (struct saved_file *) arg;
|
||||
|
||||
input_file_end (); /* Close out old file. */
|
||||
|
||||
f_in = saved->f_in;
|
||||
file_name = saved->file_name;
|
||||
preprocess = saved->preprocess;
|
||||
if (preprocess)
|
||||
app_pop (saved->app_save);
|
||||
|
||||
free (arg);
|
||||
}
|
||||
|
||||
void
|
||||
input_file_open (char *filename, /* "" means use stdin. Must not be 0. */
|
||||
int pre)
|
||||
{
|
||||
int c;
|
||||
char buf[80];
|
||||
|
||||
preprocess = pre;
|
||||
|
||||
gas_assert (filename != 0); /* Filename may not be NULL. */
|
||||
if (filename[0])
|
||||
{
|
||||
f_in = fopen (filename, FOPEN_RT);
|
||||
file_name = filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use stdin for the input file. */
|
||||
f_in = stdin;
|
||||
/* For error messages. */
|
||||
file_name = _("{standard input}");
|
||||
}
|
||||
|
||||
if (f_in == NULL)
|
||||
{
|
||||
as_bad (_("can't open %s for reading: %s"),
|
||||
file_name, xstrerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
c = getc (f_in);
|
||||
|
||||
if (ferror (f_in))
|
||||
{
|
||||
as_bad (_("can't read from %s: %s"),
|
||||
file_name, xstrerror (errno));
|
||||
|
||||
fclose (f_in);
|
||||
f_in = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for an empty input file. */
|
||||
if (feof (f_in))
|
||||
{
|
||||
fclose (f_in);
|
||||
f_in = NULL;
|
||||
return;
|
||||
}
|
||||
gas_assert (c != EOF);
|
||||
|
||||
if (c == '#')
|
||||
{
|
||||
/* Begins with comment, may not want to preprocess. */
|
||||
c = getc (f_in);
|
||||
if (c == 'N')
|
||||
{
|
||||
if (fgets (buf, sizeof (buf), f_in)
|
||||
&& !strncmp (buf, "O_APP", 5) && ISSPACE (buf[5]))
|
||||
preprocess = 0;
|
||||
if (!strchr (buf, '\n'))
|
||||
ungetc ('#', f_in); /* It was longer. */
|
||||
else
|
||||
ungetc ('\n', f_in);
|
||||
}
|
||||
else if (c == 'A')
|
||||
{
|
||||
if (fgets (buf, sizeof (buf), f_in)
|
||||
&& !strncmp (buf, "PP", 2) && ISSPACE (buf[2]))
|
||||
preprocess = 1;
|
||||
if (!strchr (buf, '\n'))
|
||||
ungetc ('#', f_in);
|
||||
else
|
||||
ungetc ('\n', f_in);
|
||||
}
|
||||
else if (c == '\n')
|
||||
ungetc ('\n', f_in);
|
||||
else
|
||||
ungetc ('#', f_in);
|
||||
}
|
||||
else
|
||||
ungetc (c, f_in);
|
||||
}
|
||||
|
||||
/* Close input file. */
|
||||
|
||||
void
|
||||
input_file_close (void)
|
||||
{
|
||||
/* Don't close a null file pointer. */
|
||||
if (f_in != NULL)
|
||||
fclose (f_in);
|
||||
|
||||
f_in = 0;
|
||||
}
|
||||
|
||||
/* This function is passed to do_scrub_chars. */
|
||||
|
||||
static size_t
|
||||
input_file_get (char *buf, size_t buflen)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (feof (f_in))
|
||||
return 0;
|
||||
|
||||
size = fread (buf, sizeof (char), buflen, f_in);
|
||||
if (ferror (f_in))
|
||||
as_bad (_("can't read from %s: %s"), file_name, xstrerror (errno));
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Read a buffer from the input file. */
|
||||
|
||||
char *
|
||||
input_file_give_next_buffer (char *where /* Where to place 1st character of new buffer. */)
|
||||
{
|
||||
char *return_value; /* -> Last char of what we read, + 1. */
|
||||
size_t size;
|
||||
|
||||
if (f_in == (FILE *) 0)
|
||||
return 0;
|
||||
/* fflush (stdin); could be done here if you want to synchronise
|
||||
stdin and stdout, for the case where our input file is stdin.
|
||||
Since the assembler shouldn't do any output to stdout, we
|
||||
don't bother to synch output and input. */
|
||||
if (preprocess)
|
||||
size = do_scrub_chars (input_file_get, where, BUFFER_SIZE);
|
||||
else
|
||||
size = input_file_get (where, BUFFER_SIZE);
|
||||
|
||||
if (size)
|
||||
return_value = where + size;
|
||||
else
|
||||
{
|
||||
if (fclose (f_in))
|
||||
as_warn (_("can't close %s: %s"), file_name, xstrerror (errno));
|
||||
|
||||
f_in = (FILE *) 0;
|
||||
return_value = 0;
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
66
contrib/toolchain/binutils/gas/input-file.h
Normal file
66
contrib/toolchain/binutils/gas/input-file.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* input_file.h header for input-file.c
|
||||
Copyright 1987, 1992, 1993, 2000, 2003, 2005, 2006, 2007, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/*"input_file.c":Operating-system dependant functions to read source files.*/
|
||||
|
||||
/*
|
||||
* No matter what the operating system, this module must provide the
|
||||
* following services to its callers.
|
||||
*
|
||||
* input_file_begin() Call once before anything else.
|
||||
*
|
||||
* input_file_end() Call once after everything else.
|
||||
*
|
||||
* input_file_buffer_size() Call anytime. Returns largest possible
|
||||
* delivery from
|
||||
* input_file_give_next_buffer().
|
||||
*
|
||||
* input_file_open(name) Call once for each input file.
|
||||
*
|
||||
* input_file_give_next_buffer(where) Call once to get each new buffer.
|
||||
* Return 0: no more chars left in file,
|
||||
* the file has already been closed.
|
||||
* Otherwise: return a pointer to just
|
||||
* after the last character we read
|
||||
* into the buffer.
|
||||
* If we can only read 0 characters, then
|
||||
* end-of-file is faked.
|
||||
*
|
||||
* input_file_push() Push state, which can be restored
|
||||
* later. Does implicit input_file_begin.
|
||||
* Returns char * to saved state.
|
||||
*
|
||||
* input_file_pop (arg) Pops previously saved state.
|
||||
*
|
||||
* input_file_close () Closes opened file.
|
||||
*
|
||||
* All errors are reported so caller doesn't have to think
|
||||
* about I/O errors.
|
||||
*/
|
||||
|
||||
char *input_file_give_next_buffer (char *where);
|
||||
char *input_file_push (void);
|
||||
size_t input_file_buffer_size (void);
|
||||
void input_file_begin (void);
|
||||
void input_file_close (void);
|
||||
void input_file_end (void);
|
||||
void input_file_open (char *filename, int pre);
|
||||
void input_file_pop (char *arg);
|
523
contrib/toolchain/binutils/gas/input-scrub.c
Normal file
523
contrib/toolchain/binutils/gas/input-scrub.c
Normal file
@ -0,0 +1,523 @@
|
||||
/* input_scrub.c - Break up input buffers into whole numbers of lines.
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "filenames.h"
|
||||
#include "input-file.h"
|
||||
#include "sb.h"
|
||||
#include "listing.h"
|
||||
|
||||
/*
|
||||
* O/S independent module to supply buffers of sanitised source code
|
||||
* to rest of assembler. We get sanitised input data of arbitrary length.
|
||||
* We break these buffers on line boundaries, recombine pieces that
|
||||
* were broken across buffers, and return a buffer of full lines to
|
||||
* the caller.
|
||||
* The last partial line begins the next buffer we build and return to caller.
|
||||
* The buffer returned to caller is preceded by BEFORE_STRING and followed
|
||||
* by AFTER_STRING, as sentinels. The last character before AFTER_STRING
|
||||
* is a newline.
|
||||
* Also looks after line numbers, for e.g. error messages.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We don't care how filthy our buffers are, but our callers assume
|
||||
* that the following sanitation has already been done.
|
||||
*
|
||||
* No comments, reduce a comment to a space.
|
||||
* Reduce a tab to a space unless it is 1st char of line.
|
||||
* All multiple tabs and spaces collapsed into 1 char. Tab only
|
||||
* legal if 1st char of line.
|
||||
* # line file statements converted to .line x;.file y; statements.
|
||||
* Escaped newlines at end of line: remove them but add as many newlines
|
||||
* to end of statement as you removed in the middle, to synch line numbers.
|
||||
*/
|
||||
|
||||
#define BEFORE_STRING ("\n")
|
||||
#define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */
|
||||
#define BEFORE_SIZE (1)
|
||||
#define AFTER_SIZE (1)
|
||||
|
||||
#ifndef TC_EOL_IN_INSN
|
||||
#define TC_EOL_IN_INSN(P) 0
|
||||
#endif
|
||||
|
||||
static char *buffer_start; /*->1st char of full buffer area. */
|
||||
static char *partial_where; /*->after last full line in buffer. */
|
||||
static int partial_size; /* >=0. Number of chars in partial line in buffer. */
|
||||
|
||||
/* Because we need AFTER_STRING just after last full line, it clobbers
|
||||
1st part of partial line. So we preserve 1st part of partial line
|
||||
here. */
|
||||
static char save_source[AFTER_SIZE];
|
||||
|
||||
/* What is the largest size buffer that input_file_give_next_buffer()
|
||||
could return to us? */
|
||||
static unsigned int buffer_length;
|
||||
|
||||
/* The index into an sb structure we are reading from. -1 if none. */
|
||||
static size_t sb_index = -1;
|
||||
|
||||
/* If we are reading from an sb structure, this is it. */
|
||||
static sb from_sb;
|
||||
|
||||
/* Should we do a conditional check on from_sb? */
|
||||
static int from_sb_is_expansion = 1;
|
||||
|
||||
/* The number of nested sb structures we have included. */
|
||||
int macro_nest;
|
||||
|
||||
/* We can have more than one source file open at once, though the info for all
|
||||
but the latest one are saved off in a struct input_save. These files remain
|
||||
open, so we are limited by the number of open files allowed by the
|
||||
underlying OS. We may also sequentially read more than one source file in an
|
||||
assembly. */
|
||||
|
||||
/* We must track the physical file and line number for error messages. We also
|
||||
track a "logical" file and line number corresponding to (C?) compiler
|
||||
source line numbers. Whenever we open a file we must fill in
|
||||
physical_input_file. So if it is NULL we have not opened any files yet. */
|
||||
|
||||
static char *physical_input_file;
|
||||
static char *logical_input_file;
|
||||
|
||||
/* 1-origin line number in a source file. */
|
||||
/* A line ends in '\n' or eof. */
|
||||
static unsigned int physical_input_line;
|
||||
static int logical_input_line;
|
||||
|
||||
/* Struct used to save the state of the input handler during include files */
|
||||
struct input_save {
|
||||
char * buffer_start;
|
||||
char * partial_where;
|
||||
int partial_size;
|
||||
char save_source[AFTER_SIZE];
|
||||
size_t buffer_length;
|
||||
char * physical_input_file;
|
||||
char * logical_input_file;
|
||||
unsigned int physical_input_line;
|
||||
int logical_input_line;
|
||||
size_t sb_index;
|
||||
sb from_sb;
|
||||
int from_sb_is_expansion; /* Should we do a conditional check? */
|
||||
struct input_save * next_saved_file; /* Chain of input_saves. */
|
||||
char * input_file_save; /* Saved state of input routines. */
|
||||
char * saved_position; /* Caller's saved position in buf. */
|
||||
};
|
||||
|
||||
static struct input_save *input_scrub_push (char *saved_position);
|
||||
static char *input_scrub_pop (struct input_save *arg);
|
||||
|
||||
/* Saved information about the file that .include'd this one. When we hit EOF,
|
||||
we automatically pop to that file. */
|
||||
|
||||
static struct input_save *next_saved_file;
|
||||
|
||||
/* Push the state of input reading and scrubbing so that we can #include.
|
||||
The return value is a 'void *' (fudged for old compilers) to a save
|
||||
area, which can be restored by passing it to input_scrub_pop(). */
|
||||
|
||||
static struct input_save *
|
||||
input_scrub_push (char *saved_position)
|
||||
{
|
||||
register struct input_save *saved;
|
||||
|
||||
saved = (struct input_save *) xmalloc (sizeof *saved);
|
||||
|
||||
saved->saved_position = saved_position;
|
||||
saved->buffer_start = buffer_start;
|
||||
saved->partial_where = partial_where;
|
||||
saved->partial_size = partial_size;
|
||||
saved->buffer_length = buffer_length;
|
||||
saved->physical_input_file = physical_input_file;
|
||||
saved->logical_input_file = logical_input_file;
|
||||
saved->physical_input_line = physical_input_line;
|
||||
saved->logical_input_line = logical_input_line;
|
||||
saved->sb_index = sb_index;
|
||||
saved->from_sb = from_sb;
|
||||
saved->from_sb_is_expansion = from_sb_is_expansion;
|
||||
memcpy (saved->save_source, save_source, sizeof (save_source));
|
||||
saved->next_saved_file = next_saved_file;
|
||||
saved->input_file_save = input_file_push ();
|
||||
|
||||
input_file_begin (); /* Reinitialize! */
|
||||
logical_input_line = -1;
|
||||
logical_input_file = (char *) NULL;
|
||||
buffer_length = input_file_buffer_size ();
|
||||
sb_index = -1;
|
||||
|
||||
buffer_start = (char *) xmalloc ((BEFORE_SIZE + buffer_length
|
||||
+ buffer_length + AFTER_SIZE));
|
||||
memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static char *
|
||||
input_scrub_pop (struct input_save *saved)
|
||||
{
|
||||
char *saved_position;
|
||||
|
||||
input_scrub_end (); /* Finish off old buffer */
|
||||
|
||||
input_file_pop (saved->input_file_save);
|
||||
saved_position = saved->saved_position;
|
||||
buffer_start = saved->buffer_start;
|
||||
buffer_length = saved->buffer_length;
|
||||
physical_input_file = saved->physical_input_file;
|
||||
logical_input_file = saved->logical_input_file;
|
||||
physical_input_line = saved->physical_input_line;
|
||||
logical_input_line = saved->logical_input_line;
|
||||
sb_index = saved->sb_index;
|
||||
from_sb = saved->from_sb;
|
||||
from_sb_is_expansion = saved->from_sb_is_expansion;
|
||||
partial_where = saved->partial_where;
|
||||
partial_size = saved->partial_size;
|
||||
next_saved_file = saved->next_saved_file;
|
||||
memcpy (save_source, saved->save_source, sizeof (save_source));
|
||||
|
||||
free (saved);
|
||||
return saved_position;
|
||||
}
|
||||
|
||||
void
|
||||
input_scrub_begin (void)
|
||||
{
|
||||
know (strlen (BEFORE_STRING) == BEFORE_SIZE);
|
||||
know (strlen (AFTER_STRING) == AFTER_SIZE
|
||||
|| (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1));
|
||||
|
||||
input_file_begin ();
|
||||
|
||||
buffer_length = input_file_buffer_size ();
|
||||
|
||||
buffer_start = (char *) xmalloc ((BEFORE_SIZE + buffer_length
|
||||
+ buffer_length + AFTER_SIZE));
|
||||
memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
|
||||
|
||||
/* Line number things. */
|
||||
logical_input_line = -1;
|
||||
logical_input_file = (char *) NULL;
|
||||
physical_input_file = NULL; /* No file read yet. */
|
||||
next_saved_file = NULL; /* At EOF, don't pop to any other file */
|
||||
do_scrub_begin (flag_m68k_mri);
|
||||
}
|
||||
|
||||
void
|
||||
input_scrub_end (void)
|
||||
{
|
||||
if (buffer_start)
|
||||
{
|
||||
free (buffer_start);
|
||||
buffer_start = 0;
|
||||
input_file_end ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Start reading input from a new file.
|
||||
Return start of caller's part of buffer. */
|
||||
|
||||
char *
|
||||
input_scrub_new_file (char *filename)
|
||||
{
|
||||
input_file_open (filename, !flag_no_comments);
|
||||
physical_input_file = filename[0] ? filename : _("{standard input}");
|
||||
physical_input_line = 0;
|
||||
|
||||
partial_size = 0;
|
||||
return (buffer_start + BEFORE_SIZE);
|
||||
}
|
||||
|
||||
/* Include a file from the current file. Save our state, cause it to
|
||||
be restored on EOF, and begin handling a new file. Same result as
|
||||
input_scrub_new_file. */
|
||||
|
||||
char *
|
||||
input_scrub_include_file (char *filename, char *position)
|
||||
{
|
||||
next_saved_file = input_scrub_push (position);
|
||||
return input_scrub_new_file (filename);
|
||||
}
|
||||
|
||||
/* Start getting input from an sb structure. This is used when
|
||||
expanding a macro. */
|
||||
|
||||
void
|
||||
input_scrub_include_sb (sb *from, char *position, int is_expansion)
|
||||
{
|
||||
int newline;
|
||||
|
||||
if (macro_nest > max_macro_nest)
|
||||
as_fatal (_("macros nested too deeply"));
|
||||
++macro_nest;
|
||||
|
||||
#ifdef md_macro_start
|
||||
if (is_expansion)
|
||||
{
|
||||
md_macro_start ();
|
||||
}
|
||||
#endif
|
||||
|
||||
next_saved_file = input_scrub_push (position);
|
||||
|
||||
/* Allocate sufficient space: from->len + optional newline. */
|
||||
newline = from->len >= 1 && from->ptr[0] != '\n';
|
||||
sb_build (&from_sb, from->len + newline);
|
||||
from_sb_is_expansion = is_expansion;
|
||||
if (newline)
|
||||
{
|
||||
/* Add the sentinel required by read.c. */
|
||||
sb_add_char (&from_sb, '\n');
|
||||
}
|
||||
sb_scrub_and_add_sb (&from_sb, from);
|
||||
|
||||
/* Make sure the parser looks at defined contents when it scans for
|
||||
e.g. end-of-line at the end of a macro. */
|
||||
sb_terminate (&from_sb);
|
||||
|
||||
sb_index = 1;
|
||||
|
||||
/* These variables are reset by input_scrub_push. Restore them
|
||||
since we are, after all, still at the same point in the file. */
|
||||
logical_input_line = next_saved_file->logical_input_line;
|
||||
logical_input_file = next_saved_file->logical_input_file;
|
||||
}
|
||||
|
||||
void
|
||||
input_scrub_close (void)
|
||||
{
|
||||
input_file_close ();
|
||||
physical_input_line = 0;
|
||||
logical_input_line = -1;
|
||||
}
|
||||
|
||||
char *
|
||||
input_scrub_next_buffer (char **bufp)
|
||||
{
|
||||
register char *limit; /*->just after last char of buffer. */
|
||||
|
||||
if (sb_index != (size_t) -1)
|
||||
{
|
||||
if (sb_index >= from_sb.len)
|
||||
{
|
||||
sb_kill (&from_sb);
|
||||
if (from_sb_is_expansion)
|
||||
{
|
||||
cond_finish_check (macro_nest);
|
||||
#ifdef md_macro_end
|
||||
/* Allow the target to clean up per-macro expansion
|
||||
data. */
|
||||
md_macro_end ();
|
||||
#endif
|
||||
}
|
||||
--macro_nest;
|
||||
partial_where = NULL;
|
||||
if (next_saved_file != NULL)
|
||||
*bufp = input_scrub_pop (next_saved_file);
|
||||
return partial_where;
|
||||
}
|
||||
|
||||
partial_where = from_sb.ptr + from_sb.len;
|
||||
partial_size = 0;
|
||||
*bufp = from_sb.ptr + sb_index;
|
||||
sb_index = from_sb.len;
|
||||
return partial_where;
|
||||
}
|
||||
|
||||
*bufp = buffer_start + BEFORE_SIZE;
|
||||
|
||||
if (partial_size)
|
||||
{
|
||||
memmove (buffer_start + BEFORE_SIZE, partial_where,
|
||||
(unsigned int) partial_size);
|
||||
memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE);
|
||||
}
|
||||
limit = input_file_give_next_buffer (buffer_start
|
||||
+ BEFORE_SIZE
|
||||
+ partial_size);
|
||||
if (limit)
|
||||
{
|
||||
register char *p; /* Find last newline. */
|
||||
/* Terminate the buffer to avoid confusing TC_EOL_IN_INSN. */
|
||||
*limit = '\0';
|
||||
for (p = limit - 1; *p != '\n' || TC_EOL_IN_INSN (p); --p)
|
||||
;
|
||||
++p;
|
||||
|
||||
while (p <= buffer_start + BEFORE_SIZE)
|
||||
{
|
||||
int limoff;
|
||||
|
||||
limoff = limit - buffer_start;
|
||||
buffer_length += input_file_buffer_size ();
|
||||
buffer_start = (char *) xrealloc (buffer_start,
|
||||
(BEFORE_SIZE
|
||||
+ 2 * buffer_length
|
||||
+ AFTER_SIZE));
|
||||
*bufp = buffer_start + BEFORE_SIZE;
|
||||
limit = input_file_give_next_buffer (buffer_start + limoff);
|
||||
|
||||
if (limit == NULL)
|
||||
{
|
||||
as_warn (_("partial line at end of file ignored"));
|
||||
partial_where = NULL;
|
||||
if (next_saved_file)
|
||||
*bufp = input_scrub_pop (next_saved_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Terminate the buffer to avoid confusing TC_EOL_IN_INSN. */
|
||||
*limit = '\0';
|
||||
for (p = limit - 1; *p != '\n' || TC_EOL_IN_INSN (p); --p)
|
||||
;
|
||||
++p;
|
||||
}
|
||||
|
||||
partial_where = p;
|
||||
partial_size = limit - p;
|
||||
memcpy (save_source, partial_where, (int) AFTER_SIZE);
|
||||
memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
partial_where = 0;
|
||||
if (partial_size > 0)
|
||||
{
|
||||
as_warn (_("partial line at end of file ignored"));
|
||||
}
|
||||
|
||||
/* Tell the listing we've finished the file. */
|
||||
LISTING_EOF ();
|
||||
|
||||
/* If we should pop to another file at EOF, do it. */
|
||||
if (next_saved_file)
|
||||
{
|
||||
*bufp = input_scrub_pop (next_saved_file); /* Pop state */
|
||||
/* partial_where is now correct to return, since we popped it. */
|
||||
}
|
||||
}
|
||||
return (partial_where);
|
||||
}
|
||||
|
||||
/* The remaining part of this file deals with line numbers, error
|
||||
messages and so on. Return TRUE if we opened any file. */
|
||||
|
||||
int
|
||||
seen_at_least_1_file (void)
|
||||
{
|
||||
return (physical_input_file != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bump_line_counters (void)
|
||||
{
|
||||
if (sb_index == (size_t) -1)
|
||||
{
|
||||
++physical_input_line;
|
||||
if (logical_input_line >= 0)
|
||||
++logical_input_line;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tells us what the new logical line number and file are.
|
||||
If the line_number is -1, we don't change the current logical line
|
||||
number. If it is -2, we decrement the logical line number (this is
|
||||
to support the .appfile pseudo-op inserted into the stream by
|
||||
do_scrub_chars).
|
||||
If the fname is NULL, we don't change the current logical file name.
|
||||
Returns nonzero if the filename actually changes. */
|
||||
|
||||
int
|
||||
new_logical_line_flags (char *fname, /* DON'T destroy it! We point to it! */
|
||||
int line_number,
|
||||
int flags)
|
||||
{
|
||||
switch (flags)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (line_number != -1)
|
||||
abort ();
|
||||
break;
|
||||
case 1 << 1:
|
||||
case 1 << 2:
|
||||
/* FIXME: we could check that include nesting is correct. */
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (line_number >= 0)
|
||||
logical_input_line = line_number;
|
||||
else if (line_number == -1 && fname && !*fname && (flags & (1 << 2)))
|
||||
{
|
||||
logical_input_file = physical_input_file;
|
||||
logical_input_line = physical_input_line;
|
||||
fname = NULL;
|
||||
}
|
||||
|
||||
if (fname
|
||||
&& (logical_input_file == NULL
|
||||
|| filename_cmp (logical_input_file, fname)))
|
||||
{
|
||||
logical_input_file = fname;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
new_logical_line (char *fname, int line_number)
|
||||
{
|
||||
return new_logical_line_flags (fname, line_number, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Return the current file name and line number.
|
||||
namep should be char * const *, but there are compilers which screw
|
||||
up declarations like that, and it's easier to avoid it. */
|
||||
|
||||
void
|
||||
as_where (char **namep, unsigned int *linep)
|
||||
{
|
||||
if (logical_input_file != NULL
|
||||
&& (linep == NULL || logical_input_line >= 0))
|
||||
{
|
||||
*namep = logical_input_file;
|
||||
if (linep != NULL)
|
||||
*linep = logical_input_line;
|
||||
}
|
||||
else if (physical_input_file != NULL)
|
||||
{
|
||||
*namep = physical_input_file;
|
||||
if (linep != NULL)
|
||||
*linep = physical_input_line;
|
||||
}
|
||||
else
|
||||
{
|
||||
*namep = 0;
|
||||
if (linep != NULL)
|
||||
*linep = 0;
|
||||
}
|
||||
}
|
1
contrib/toolchain/binutils/gas/itbl-cpu.h
Normal file
1
contrib/toolchain/binutils/gas/itbl-cpu.h
Normal file
@ -0,0 +1 @@
|
||||
#include "itbl-i386.h"
|
1660
contrib/toolchain/binutils/gas/listing.c
Normal file
1660
contrib/toolchain/binutils/gas/listing.c
Normal file
File diff suppressed because it is too large
Load Diff
67
contrib/toolchain/binutils/gas/listing.h
Normal file
67
contrib/toolchain/binutils/gas/listing.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* This file is listing.h
|
||||
Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1997, 1998,
|
||||
2003, 2005, 2007, 2008, 2009 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef __listing_h__
|
||||
#define __listing_h__
|
||||
|
||||
#define LISTING_LISTING 1
|
||||
#define LISTING_SYMBOLS 2
|
||||
#define LISTING_NOFORM 4
|
||||
#define LISTING_HLL 8
|
||||
#define LISTING_NODEBUG 16
|
||||
#define LISTING_NOCOND 32
|
||||
#define LISTING_MACEXP 64
|
||||
#define LISTING_GENERAL 128
|
||||
|
||||
#define LISTING_DEFAULT (LISTING_LISTING | LISTING_HLL | LISTING_SYMBOLS)
|
||||
|
||||
#ifndef NO_LISTING
|
||||
#define LISTING_NEWLINE() { if (listing) listing_newline (NULL); }
|
||||
#else
|
||||
#define LISTING_NEWLINE() {;}
|
||||
#endif
|
||||
#define LISTING_EOF() LISTING_NEWLINE()
|
||||
|
||||
#define LISTING_SKIP_COND() ((listing & LISTING_NOCOND) != 0)
|
||||
|
||||
void listing_eject (int);
|
||||
void listing_error (const char *message);
|
||||
void listing_file (const char *name);
|
||||
void listing_list (int on);
|
||||
void listing_newline (char *ps);
|
||||
void listing_prev_line (void);
|
||||
void listing_print (char *, char **);
|
||||
void listing_psize (int);
|
||||
void listing_nopage (int);
|
||||
void listing_source_file (const char *);
|
||||
void listing_source_line (unsigned int);
|
||||
void listing_title (int depth);
|
||||
void listing_warning (const char *message);
|
||||
void listing_width (unsigned int x);
|
||||
|
||||
extern int listing_lhs_width;
|
||||
extern int listing_lhs_width_second;
|
||||
extern int listing_lhs_cont_lines;
|
||||
extern int listing_rhs_width;
|
||||
|
||||
#endif /* __listing_h__ */
|
||||
|
||||
/* end of listing.h */
|
96
contrib/toolchain/binutils/gas/literal.c
Normal file
96
contrib/toolchain/binutils/gas/literal.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* literal.c - GAS literal pool management.
|
||||
Copyright 1994, 2000, 2005, 2007 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 3, 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, 51 Franklin Street - Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* This isn't quite a "constant" pool. Some of the values may get
|
||||
adjusted at run time, e.g., for symbolic relocations when shared
|
||||
libraries are in use. It's more of a "literal" pool.
|
||||
|
||||
On the Alpha, this should be used for .lita and .lit8. (Is there
|
||||
ever a .lit4?) On the MIPS, it could be used for .lit4 as well.
|
||||
|
||||
The expressions passed here should contain either constants or symbols,
|
||||
not a combination of both. Typically, the constant pool is accessed
|
||||
with some sort of GP register, so the size of the pool must be kept down
|
||||
if possible. The exception is section offsets -- if you're storing a
|
||||
pointer to the start of .data, for example, and your machine provides
|
||||
for 16-bit signed addends, you might want to store .data+32K, so that
|
||||
you can access all of the first 64K of .data with the one pointer.
|
||||
|
||||
This isn't a requirement, just a guideline that can help keep .o file
|
||||
size down. */
|
||||
|
||||
#include "as.h"
|
||||
#include "subsegs.h"
|
||||
|
||||
#ifdef NEED_LITERAL_POOL
|
||||
|
||||
valueT
|
||||
add_to_literal_pool (sym, addend, sec, size)
|
||||
symbolS *sym;
|
||||
valueT addend;
|
||||
segT sec;
|
||||
int size;
|
||||
{
|
||||
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 (sec);
|
||||
fixS *fixp;
|
||||
|
||||
offset = 0;
|
||||
/* @@ 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 += size)
|
||||
{
|
||||
if (fixp->fx_addsy == sym && fixp->fx_offset == addend)
|
||||
return offset;
|
||||
}
|
||||
|
||||
subseg_set (sec, 0);
|
||||
p = frag_more (size);
|
||||
memset (p, 0, size);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 4:
|
||||
reloc_type = BFD_RELOC_32;
|
||||
break;
|
||||
case 8:
|
||||
reloc_type = BFD_RELOC_64;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
fix_new (frag_now, p - frag_now->fr_literal, size, sym, addend, 0,
|
||||
reloc_type);
|
||||
|
||||
subseg_set (current_section, current_subsec);
|
||||
offset = seginfo->literal_pool_size;
|
||||
seginfo->literal_pool_size += size;
|
||||
return offset;
|
||||
}
|
||||
#endif
|
1382
contrib/toolchain/binutils/gas/macro.c
Normal file
1382
contrib/toolchain/binutils/gas/macro.c
Normal file
File diff suppressed because it is too large
Load Diff
97
contrib/toolchain/binutils/gas/macro.h
Normal file
97
contrib/toolchain/binutils/gas/macro.h
Normal file
@ -0,0 +1,97 @@
|
||||
/* macro.h - header file for macro support for gas
|
||||
Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006,
|
||||
2007, 2012 Free Software Foundation, Inc.
|
||||
|
||||
Written by Steve and Judy Chamberlain of Cygnus Support,
|
||||
sac@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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef MACRO_H
|
||||
|
||||
#define MACRO_H
|
||||
|
||||
/* Structures used to store macros.
|
||||
|
||||
Each macro knows its name and included text. It gets built with a
|
||||
list of formal arguments, and also keeps a hash table which points
|
||||
into the list to speed up formal search. Each formal knows its
|
||||
name and its default value. Each time the macro is expanded, the
|
||||
formals get the actual values attached to them. */
|
||||
|
||||
enum formal_type
|
||||
{
|
||||
FORMAL_OPTIONAL,
|
||||
FORMAL_REQUIRED,
|
||||
FORMAL_VARARG
|
||||
};
|
||||
|
||||
/* Describe the formal arguments to a macro. */
|
||||
|
||||
typedef struct formal_struct {
|
||||
struct formal_struct *next; /* Next formal in list. */
|
||||
sb name; /* Name of the formal. */
|
||||
sb def; /* The default value. */
|
||||
sb actual; /* The actual argument (changed on each expansion). */
|
||||
int index; /* The index of the formal 0..formal_count - 1. */
|
||||
enum formal_type type; /* The kind of the formal. */
|
||||
} formal_entry;
|
||||
|
||||
/* Other values found in the index field of a formal_entry. */
|
||||
#define QUAL_INDEX (-1)
|
||||
#define NARG_INDEX (-2)
|
||||
#define LOCAL_INDEX (-3)
|
||||
|
||||
/* Describe the macro. */
|
||||
|
||||
typedef struct macro_struct
|
||||
{
|
||||
sb sub; /* Substitution text. */
|
||||
int formal_count; /* Number of formal args. */
|
||||
formal_entry *formals; /* Pointer to list of formal_structs. */
|
||||
struct hash_control *formal_hash; /* Hash table of formals. */
|
||||
const char *name; /* Macro name. */
|
||||
char *file; /* File the macro was defined in. */
|
||||
unsigned int line; /* Line number of definition. */
|
||||
} macro_entry;
|
||||
|
||||
/* Whether any macros have been defined. */
|
||||
|
||||
extern int macro_defined;
|
||||
|
||||
/* The macro nesting level. */
|
||||
|
||||
extern int macro_nest;
|
||||
|
||||
/* The macro hash table. */
|
||||
|
||||
extern struct hash_control *macro_hash;
|
||||
|
||||
extern int buffer_and_nest (const char *, const char *, sb *,
|
||||
size_t (*) (sb *));
|
||||
extern void macro_init (int, int, int,
|
||||
size_t (*) (const char *, size_t, sb *, offsetT *));
|
||||
extern void macro_set_alternate (int);
|
||||
extern void macro_mri_mode (int);
|
||||
extern const char *define_macro (size_t, sb *, sb *, size_t (*) (sb *),
|
||||
char *, unsigned int, const char **);
|
||||
extern int check_macro (const char *, sb *, const char **, macro_entry **);
|
||||
extern void delete_macro (const char *);
|
||||
extern const char *expand_irp (int, size_t, sb *, sb *, size_t (*) (sb *));
|
||||
|
||||
#endif
|
440
contrib/toolchain/binutils/gas/messages.c
Normal file
440
contrib/toolchain/binutils/gas/messages.c
Normal file
@ -0,0 +1,440 @@
|
||||
/* messages.c - error reporter -
|
||||
Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
|
||||
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
|
||||
static void identify (char *);
|
||||
static void as_show_where (void);
|
||||
static void as_warn_internal (char *, unsigned int, char *);
|
||||
static void as_bad_internal (char *, unsigned int, char *);
|
||||
|
||||
/* Despite the rest of the comments in this file, (FIXME-SOON),
|
||||
here is the current scheme for error messages etc:
|
||||
|
||||
as_fatal() is used when gas is quite confused and
|
||||
continuing the assembly is pointless. In this case we
|
||||
exit immediately with error status.
|
||||
|
||||
as_bad() is used to mark errors that result in what we
|
||||
presume to be a useless object file. Say, we ignored
|
||||
something that might have been vital. If we see any of
|
||||
these, assembly will continue to the end of the source,
|
||||
no object file will be produced, and we will terminate
|
||||
with error status. The new option, -Z, tells us to
|
||||
produce an object file anyway but we still exit with
|
||||
error status. The assumption here is that you don't want
|
||||
this object file but we could be wrong.
|
||||
|
||||
as_warn() is used when we have an error from which we
|
||||
have a plausible error recovery. eg, masking the top
|
||||
bits of a constant that is longer than will fit in the
|
||||
destination. In this case we will continue to assemble
|
||||
the source, although we may have made a bad assumption,
|
||||
and we will produce an object file and return normal exit
|
||||
status (ie, no error). The new option -X tells us to
|
||||
treat all as_warn() errors as as_bad() errors. That is,
|
||||
no object file will be produced and we will exit with
|
||||
error status. The idea here is that we don't kill an
|
||||
entire make because of an error that we knew how to
|
||||
correct. On the other hand, sometimes you might want to
|
||||
stop the make at these points.
|
||||
|
||||
as_tsktsk() is used when we see a minor error for which
|
||||
our error recovery action is almost certainly correct.
|
||||
In this case, we print a message and then assembly
|
||||
continues as though no error occurred. */
|
||||
|
||||
static void
|
||||
identify (char *file)
|
||||
{
|
||||
static int identified;
|
||||
|
||||
if (identified)
|
||||
return;
|
||||
identified++;
|
||||
|
||||
if (!file)
|
||||
{
|
||||
unsigned int x;
|
||||
as_where (&file, &x);
|
||||
}
|
||||
|
||||
if (file)
|
||||
fprintf (stderr, "%s: ", file);
|
||||
fprintf (stderr, _("Assembler messages:\n"));
|
||||
}
|
||||
|
||||
/* The number of warnings issued. */
|
||||
static int warning_count;
|
||||
|
||||
int
|
||||
had_warnings (void)
|
||||
{
|
||||
return warning_count;
|
||||
}
|
||||
|
||||
/* Nonzero if we've hit a 'bad error', and should not write an obj file,
|
||||
and exit with a nonzero error code. */
|
||||
|
||||
static int error_count;
|
||||
|
||||
int
|
||||
had_errors (void)
|
||||
{
|
||||
return error_count;
|
||||
}
|
||||
|
||||
/* Print the current location to stderr. */
|
||||
|
||||
static void
|
||||
as_show_where (void)
|
||||
{
|
||||
char *file;
|
||||
unsigned int line;
|
||||
|
||||
as_where (&file, &line);
|
||||
identify (file);
|
||||
if (file)
|
||||
{
|
||||
if (line != 0)
|
||||
fprintf (stderr, "%s:%u: ", file, line);
|
||||
else
|
||||
fprintf (stderr, "%s: ", file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send to stderr a string as a warning, and locate warning
|
||||
in input file(s).
|
||||
Please only use this for when we have some recovery action.
|
||||
Please explain in string (which may have '\n's) what recovery was
|
||||
done. */
|
||||
|
||||
void
|
||||
as_tsktsk (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
as_show_where ();
|
||||
va_start (args, format);
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
(void) putc ('\n', stderr);
|
||||
}
|
||||
|
||||
/* The common portion of as_warn and as_warn_where. */
|
||||
|
||||
static void
|
||||
as_warn_internal (char *file, unsigned int line, char *buffer)
|
||||
{
|
||||
++warning_count;
|
||||
|
||||
if (file == NULL)
|
||||
as_where (&file, &line);
|
||||
|
||||
identify (file);
|
||||
if (file)
|
||||
{
|
||||
if (line != 0)
|
||||
fprintf (stderr, "%s:%u: ", file, line);
|
||||
else
|
||||
fprintf (stderr, "%s: ", file);
|
||||
}
|
||||
fprintf (stderr, _("Warning: "));
|
||||
fputs (buffer, stderr);
|
||||
(void) putc ('\n', stderr);
|
||||
#ifndef NO_LISTING
|
||||
listing_warning (buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Send to stderr a string as a warning, and locate warning
|
||||
in input file(s).
|
||||
Please only use this for when we have some recovery action.
|
||||
Please explain in string (which may have '\n's) what recovery was
|
||||
done. */
|
||||
|
||||
void
|
||||
as_warn (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[2000];
|
||||
|
||||
if (!flag_no_warnings)
|
||||
{
|
||||
va_start (args, format);
|
||||
vsnprintf (buffer, sizeof (buffer), format, args);
|
||||
va_end (args);
|
||||
as_warn_internal ((char *) NULL, 0, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Like as_bad but the file name and line number are passed in.
|
||||
Unfortunately, we have to repeat the function in order to handle
|
||||
the varargs correctly and portably. */
|
||||
|
||||
void
|
||||
as_warn_where (char *file, unsigned int line, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[2000];
|
||||
|
||||
if (!flag_no_warnings)
|
||||
{
|
||||
va_start (args, format);
|
||||
vsnprintf (buffer, sizeof (buffer), format, args);
|
||||
va_end (args);
|
||||
as_warn_internal (file, line, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* The common portion of as_bad and as_bad_where. */
|
||||
|
||||
static void
|
||||
as_bad_internal (char *file, unsigned int line, char *buffer)
|
||||
{
|
||||
++error_count;
|
||||
|
||||
if (file == NULL)
|
||||
as_where (&file, &line);
|
||||
|
||||
identify (file);
|
||||
if (file)
|
||||
{
|
||||
if (line != 0)
|
||||
fprintf (stderr, "%s:%u: ", file, line);
|
||||
else
|
||||
fprintf (stderr, "%s: ", file);
|
||||
}
|
||||
fprintf (stderr, _("Error: "));
|
||||
fputs (buffer, stderr);
|
||||
(void) putc ('\n', stderr);
|
||||
#ifndef NO_LISTING
|
||||
listing_error (buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Send to stderr a string as a warning, and locate warning in input
|
||||
file(s). Please us when there is no recovery, but we want to
|
||||
continue processing but not produce an object file.
|
||||
Please explain in string (which may have '\n's) what recovery was
|
||||
done. */
|
||||
|
||||
void
|
||||
as_bad (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[2000];
|
||||
|
||||
va_start (args, format);
|
||||
vsnprintf (buffer, sizeof (buffer), format, args);
|
||||
va_end (args);
|
||||
|
||||
as_bad_internal ((char *) NULL, 0, buffer);
|
||||
}
|
||||
|
||||
/* Like as_bad but the file name and line number are passed in.
|
||||
Unfortunately, we have to repeat the function in order to handle
|
||||
the varargs correctly and portably. */
|
||||
|
||||
void
|
||||
as_bad_where (char *file, unsigned int line, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[2000];
|
||||
|
||||
va_start (args, format);
|
||||
vsnprintf (buffer, sizeof (buffer), format, args);
|
||||
va_end (args);
|
||||
|
||||
as_bad_internal (file, line, buffer);
|
||||
}
|
||||
|
||||
/* Send to stderr a string as a fatal message, and print location of
|
||||
error in input file(s).
|
||||
Please only use this for when we DON'T have some recovery action.
|
||||
It xexit()s with a warning status. */
|
||||
|
||||
void
|
||||
as_fatal (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
as_show_where ();
|
||||
va_start (args, format);
|
||||
fprintf (stderr, _("Fatal error: "));
|
||||
vfprintf (stderr, format, args);
|
||||
(void) putc ('\n', stderr);
|
||||
va_end (args);
|
||||
/* Delete the output file, if it exists. This will prevent make from
|
||||
thinking that a file was created and hence does not need rebuilding. */
|
||||
if (out_file_name != NULL)
|
||||
unlink_if_ordinary (out_file_name);
|
||||
xexit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Indicate assertion failure.
|
||||
Arguments: Filename, line number, optional function name. */
|
||||
|
||||
void
|
||||
as_assert (const char *file, int line, const char *fn)
|
||||
{
|
||||
as_show_where ();
|
||||
fprintf (stderr, _("Internal error!\n"));
|
||||
if (fn)
|
||||
fprintf (stderr, _("Assertion failure in %s at %s line %d.\n"),
|
||||
fn, file, line);
|
||||
else
|
||||
fprintf (stderr, _("Assertion failure at %s line %d.\n"), file, line);
|
||||
fprintf (stderr, _("Please report this bug.\n"));
|
||||
xexit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* as_abort: Print a friendly message saying how totally hosed we are,
|
||||
and exit without producing a core file. */
|
||||
|
||||
void
|
||||
as_abort (const char *file, int line, const char *fn)
|
||||
{
|
||||
as_show_where ();
|
||||
if (fn)
|
||||
fprintf (stderr, _("Internal error, aborting at %s line %d in %s\n"),
|
||||
file, line, fn);
|
||||
else
|
||||
fprintf (stderr, _("Internal error, aborting at %s line %d\n"),
|
||||
file, line);
|
||||
fprintf (stderr, _("Please report this bug.\n"));
|
||||
xexit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Support routines. */
|
||||
|
||||
void
|
||||
sprint_value (char *buf, valueT val)
|
||||
{
|
||||
if (sizeof (val) <= sizeof (long))
|
||||
{
|
||||
sprintf (buf, "%ld", (long) val);
|
||||
return;
|
||||
}
|
||||
if (sizeof (val) <= sizeof (bfd_vma))
|
||||
{
|
||||
sprintf_vma (buf, val);
|
||||
return;
|
||||
}
|
||||
abort ();
|
||||
}
|
||||
|
||||
#define HEX_MAX_THRESHOLD 1024
|
||||
#define HEX_MIN_THRESHOLD -(HEX_MAX_THRESHOLD)
|
||||
|
||||
static void
|
||||
as_internal_value_out_of_range (char * prefix,
|
||||
offsetT val,
|
||||
offsetT min,
|
||||
offsetT max,
|
||||
char * file,
|
||||
unsigned line,
|
||||
int bad)
|
||||
{
|
||||
const char * err;
|
||||
|
||||
if (prefix == NULL)
|
||||
prefix = "";
|
||||
|
||||
if (val >= min && val <= max)
|
||||
{
|
||||
addressT right = max & -max;
|
||||
|
||||
if (max <= 1)
|
||||
abort ();
|
||||
|
||||
/* xgettext:c-format */
|
||||
err = _("%s out of domain (%d is not a multiple of %d)");
|
||||
if (bad)
|
||||
as_bad_where (file, line, err,
|
||||
prefix, (int) val, (int) right);
|
||||
else
|
||||
as_warn_where (file, line, err,
|
||||
prefix, (int) val, (int) right);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( val < HEX_MAX_THRESHOLD
|
||||
&& min < HEX_MAX_THRESHOLD
|
||||
&& max < HEX_MAX_THRESHOLD
|
||||
&& val > HEX_MIN_THRESHOLD
|
||||
&& min > HEX_MIN_THRESHOLD
|
||||
&& max > HEX_MIN_THRESHOLD)
|
||||
{
|
||||
/* xgettext:c-format */
|
||||
err = _("%s out of range (%d is not between %d and %d)");
|
||||
|
||||
if (bad)
|
||||
as_bad_where (file, line, err,
|
||||
prefix, (int) val, (int) min, (int) max);
|
||||
else
|
||||
as_warn_where (file, line, err,
|
||||
prefix, (int) val, (int) min, (int) max);
|
||||
}
|
||||
else
|
||||
{
|
||||
char val_buf [sizeof (val) * 3 + 2];
|
||||
char min_buf [sizeof (val) * 3 + 2];
|
||||
char max_buf [sizeof (val) * 3 + 2];
|
||||
|
||||
if (sizeof (val) > sizeof (bfd_vma))
|
||||
abort ();
|
||||
|
||||
sprintf_vma (val_buf, (bfd_vma) val);
|
||||
sprintf_vma (min_buf, (bfd_vma) min);
|
||||
sprintf_vma (max_buf, (bfd_vma) max);
|
||||
|
||||
/* xgettext:c-format. */
|
||||
err = _("%s out of range (0x%s is not between 0x%s and 0x%s)");
|
||||
|
||||
if (bad)
|
||||
as_bad_where (file, line, err, prefix, val_buf, min_buf, max_buf);
|
||||
else
|
||||
as_warn_where (file, line, err, prefix, val_buf, min_buf, max_buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
as_warn_value_out_of_range (char * prefix,
|
||||
offsetT value,
|
||||
offsetT min,
|
||||
offsetT max,
|
||||
char * file,
|
||||
unsigned line)
|
||||
{
|
||||
as_internal_value_out_of_range (prefix, value, min, max, file, line, 0);
|
||||
}
|
||||
|
||||
void
|
||||
as_bad_value_out_of_range (char * prefix,
|
||||
offsetT value,
|
||||
offsetT min,
|
||||
offsetT max,
|
||||
char * file,
|
||||
unsigned line)
|
||||
{
|
||||
as_internal_value_out_of_range (prefix, value, min, max, file, line, 1);
|
||||
}
|
1
contrib/toolchain/binutils/gas/obj-format.h
Normal file
1
contrib/toolchain/binutils/gas/obj-format.h
Normal file
@ -0,0 +1 @@
|
||||
#include "obj-coff.h"
|
87
contrib/toolchain/binutils/gas/obj.h
Normal file
87
contrib/toolchain/binutils/gas/obj.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* obj.h - defines the object dependent hooks for all object
|
||||
format backends.
|
||||
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1995, 1996, 1997, 1999, 2000,
|
||||
2002, 2003, 2004, 2005, 2007, 2009, 2010 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
char *obj_default_output_file_name (void);
|
||||
void obj_emit_relocations (char **where, fixS * fixP,
|
||||
relax_addressT segment_address_in_file);
|
||||
void obj_emit_strings (char **where);
|
||||
void obj_emit_symbols (char **where, symbolS * symbols);
|
||||
#ifndef obj_read_begin_hook
|
||||
void obj_read_begin_hook (void);
|
||||
#endif
|
||||
|
||||
#ifndef obj_symbol_new_hook
|
||||
void obj_symbol_new_hook (symbolS * symbolP);
|
||||
#endif
|
||||
|
||||
void obj_symbol_to_chars (char **where, symbolS * symbolP);
|
||||
|
||||
extern const pseudo_typeS obj_pseudo_table[];
|
||||
|
||||
struct format_ops {
|
||||
int flavor;
|
||||
unsigned dfl_leading_underscore : 1;
|
||||
unsigned emit_section_symbols : 1;
|
||||
void (*begin) (void);
|
||||
void (*app_file) (const char *, int);
|
||||
void (*frob_symbol) (symbolS *, int *);
|
||||
void (*frob_file) (void);
|
||||
void (*frob_file_before_adjust) (void);
|
||||
void (*frob_file_before_fix) (void);
|
||||
void (*frob_file_after_relocs) (void);
|
||||
bfd_vma (*s_get_size) (symbolS *);
|
||||
void (*s_set_size) (symbolS *, bfd_vma);
|
||||
bfd_vma (*s_get_align) (symbolS *);
|
||||
void (*s_set_align) (symbolS *, bfd_vma);
|
||||
int (*s_get_other) (symbolS *);
|
||||
void (*s_set_other) (symbolS *, int);
|
||||
int (*s_get_desc) (symbolS *);
|
||||
void (*s_set_desc) (symbolS *, int);
|
||||
int (*s_get_type) (symbolS *);
|
||||
void (*s_set_type) (symbolS *, int);
|
||||
void (*copy_symbol_attributes) (symbolS *, symbolS *);
|
||||
void (*generate_asm_lineno) (void);
|
||||
void (*process_stab) (segT, int, const char *, int, int, int);
|
||||
int (*separate_stab_sections) (void);
|
||||
void (*init_stab_section) (segT);
|
||||
int (*sec_sym_ok_for_reloc) (asection *);
|
||||
void (*pop_insert) (void);
|
||||
/* For configurations using ECOFF_DEBUGGING, this callback is used. */
|
||||
void (*ecoff_set_ext) (symbolS *, struct ecoff_extr *);
|
||||
|
||||
void (*read_begin_hook) (void);
|
||||
void (*symbol_new_hook) (symbolS *);
|
||||
void (*symbol_clone_hook) (symbolS *, symbolS *);
|
||||
void (*adjust_symtab) (void);
|
||||
};
|
||||
|
||||
extern const struct format_ops elf_format_ops;
|
||||
extern const struct format_ops ecoff_format_ops;
|
||||
extern const struct format_ops coff_format_ops;
|
||||
extern const struct format_ops aout_format_ops;
|
||||
|
||||
#ifndef this_format
|
||||
COMMON const struct format_ops *this_format;
|
||||
#endif
|
||||
|
||||
/* end of obj.h */
|
74
contrib/toolchain/binutils/gas/output-file.c
Normal file
74
contrib/toolchain/binutils/gas/output-file.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* output-file.c - Deal with the output file
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1996, 1998, 1999, 2001,
|
||||
2003, 2004, 2005, 2006, 2007 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "output-file.h"
|
||||
|
||||
#ifndef TARGET_MACH
|
||||
#define TARGET_MACH 0
|
||||
#endif
|
||||
|
||||
bfd *stdoutput;
|
||||
|
||||
void
|
||||
output_file_create (char *name)
|
||||
{
|
||||
if (name[0] == '-' && name[1] == '\0')
|
||||
as_fatal (_("can't open a bfd on stdout %s"), name);
|
||||
|
||||
else if (!(stdoutput = bfd_openw (name, TARGET_FORMAT)))
|
||||
{
|
||||
bfd_error_type err = bfd_get_error ();
|
||||
|
||||
if (err == bfd_error_invalid_target)
|
||||
as_fatal (_("selected target format '%s' unknown"), TARGET_FORMAT);
|
||||
else
|
||||
as_fatal (_("can't create %s: %s"), name, bfd_errmsg (err));
|
||||
}
|
||||
|
||||
bfd_set_format (stdoutput, bfd_object);
|
||||
bfd_set_arch_mach (stdoutput, TARGET_ARCH, TARGET_MACH);
|
||||
if (flag_traditional_format)
|
||||
stdoutput->flags |= BFD_TRADITIONAL_FORMAT;
|
||||
}
|
||||
|
||||
void
|
||||
output_file_close (char *filename)
|
||||
{
|
||||
bfd_boolean res;
|
||||
|
||||
if (stdoutput == NULL)
|
||||
return;
|
||||
|
||||
/* Close the bfd. */
|
||||
if (had_errors ())
|
||||
res = bfd_cache_close_all ();
|
||||
else
|
||||
res = bfd_close (stdoutput);
|
||||
|
||||
/* Prevent an infinite loop - if the close failed we will call as_fatal
|
||||
which will call xexit() which may call this function again... */
|
||||
stdoutput = NULL;
|
||||
|
||||
if (! res)
|
||||
as_fatal (_("can't close %s: %s"), filename,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
}
|
26
contrib/toolchain/binutils/gas/output-file.h
Normal file
26
contrib/toolchain/binutils/gas/output-file.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* This file is output-file.h
|
||||
|
||||
Copyright 1987, 1988, 1989, 1990, 1991, 1992, 2003, 2005, 2007
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
void output_file_append (char *where, long length, char *filename);
|
||||
void output_file_close (char *filename);
|
||||
void output_file_create (char *name);
|
||||
|
||||
/* end of output-file.h */
|
6107
contrib/toolchain/binutils/gas/read.c
Normal file
6107
contrib/toolchain/binutils/gas/read.c
Normal file
File diff suppressed because it is too large
Load Diff
193
contrib/toolchain/binutils/gas/read.h
Normal file
193
contrib/toolchain/binutils/gas/read.h
Normal file
@ -0,0 +1,193 @@
|
||||
/* read.h - of read.c
|
||||
Copyright 1986, 1990, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2012
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
extern char *input_line_pointer; /* -> char we are parsing now. */
|
||||
|
||||
/* Define to make whitespace be allowed in many syntactically
|
||||
unnecessary places. Normally undefined. For compatibility with
|
||||
ancient GNU cc. */
|
||||
/* #undef PERMIT_WHITESPACE */
|
||||
#define PERMIT_WHITESPACE
|
||||
|
||||
#ifdef PERMIT_WHITESPACE
|
||||
#define SKIP_WHITESPACE() \
|
||||
((*input_line_pointer == ' ') ? ++input_line_pointer : 0)
|
||||
#else
|
||||
#define SKIP_WHITESPACE() know(*input_line_pointer != ' ' )
|
||||
#endif
|
||||
|
||||
#define LEX_NAME (1) /* may continue a name */
|
||||
#define LEX_BEGIN_NAME (2) /* may begin a name */
|
||||
#define LEX_END_NAME (4) /* ends a name */
|
||||
|
||||
#define is_name_beginner(c) \
|
||||
( lex_type[(unsigned char) (c)] & LEX_BEGIN_NAME )
|
||||
#define is_part_of_name(c) \
|
||||
( lex_type[(unsigned char) (c)] & LEX_NAME )
|
||||
#define is_name_ender(c) \
|
||||
( lex_type[(unsigned char) (c)] & LEX_END_NAME )
|
||||
|
||||
#ifndef is_a_char
|
||||
#define CHAR_MASK (0xff)
|
||||
#define NOT_A_CHAR (CHAR_MASK+1)
|
||||
#define is_a_char(c) (((unsigned) (c)) <= CHAR_MASK)
|
||||
#endif /* is_a_char() */
|
||||
|
||||
extern char lex_type[];
|
||||
extern char is_end_of_line[];
|
||||
|
||||
extern int is_it_end_of_statement (void);
|
||||
extern char *find_end_of_line (char *, int);
|
||||
|
||||
extern int target_big_endian;
|
||||
|
||||
/* These are initialized by the CPU specific target files (tc-*.c). */
|
||||
extern const char comment_chars[];
|
||||
extern const char line_comment_chars[];
|
||||
extern const char line_separator_chars[];
|
||||
|
||||
/* Table of -I directories. */
|
||||
extern char **include_dirs;
|
||||
extern int include_dir_count;
|
||||
extern int include_dir_maxlen;
|
||||
|
||||
/* The offset in the absolute section. */
|
||||
extern addressT abs_section_offset;
|
||||
|
||||
/* The label on a line, used by some of the pseudo-ops. */
|
||||
extern symbolS *line_label;
|
||||
|
||||
/* This is used to support MRI common sections. */
|
||||
extern symbolS *mri_common_symbol;
|
||||
|
||||
/* True if a stabs line debug statement is currently being emitted. */
|
||||
extern int outputting_stabs_line_debug;
|
||||
|
||||
/* Possible arguments to .linkonce. */
|
||||
enum linkonce_type {
|
||||
LINKONCE_UNSET = 0,
|
||||
LINKONCE_DISCARD,
|
||||
LINKONCE_ONE_ONLY,
|
||||
LINKONCE_SAME_SIZE,
|
||||
LINKONCE_SAME_CONTENTS
|
||||
};
|
||||
|
||||
#ifndef TC_CASE_SENSITIVE
|
||||
extern char original_case_string[];
|
||||
#endif
|
||||
|
||||
extern void pop_insert (const pseudo_typeS *);
|
||||
extern unsigned int get_stab_string_offset
|
||||
(const char *string, const char *stabstr_secname);
|
||||
extern void aout_process_stab (int, const char *, int, int, int);
|
||||
extern char *demand_copy_string (int *lenP);
|
||||
extern char *demand_copy_C_string (int *len_pointer);
|
||||
extern char get_absolute_expression_and_terminator (long *val_pointer);
|
||||
extern offsetT get_absolute_expression (void);
|
||||
extern unsigned int next_char_of_string (void);
|
||||
extern void s_mri_sect (char *);
|
||||
extern char *mri_comment_field (char *);
|
||||
extern void mri_comment_end (char *, int);
|
||||
extern void add_include_dir (char *path);
|
||||
extern void cons (int nbytes);
|
||||
extern void demand_empty_rest_of_line (void);
|
||||
extern void emit_expr (expressionS *exp, unsigned int nbytes);
|
||||
extern void emit_expr_fix (expressionS *, unsigned int, fragS *, char *);
|
||||
extern void equals (char *sym_name, int reassign);
|
||||
extern void float_cons (int float_type);
|
||||
extern void ignore_rest_of_line (void);
|
||||
#define discard_rest_of_line ignore_rest_of_line
|
||||
extern int output_leb128 (char *, valueT, int sign);
|
||||
extern void pseudo_set (symbolS * symbolP);
|
||||
extern void read_a_source_file (char *name);
|
||||
extern void read_begin (void);
|
||||
extern void read_print_statistics (FILE *);
|
||||
extern int sizeof_leb128 (valueT, int sign);
|
||||
extern void stabs_generate_asm_file (void);
|
||||
extern void stabs_generate_asm_lineno (void);
|
||||
extern void stabs_generate_asm_func (const char *, const char *);
|
||||
extern void stabs_generate_asm_endfunc (const char *, const char *);
|
||||
extern void do_repeat (int,const char *,const char *);
|
||||
extern void do_repeat_with_expander (int, const char *, const char *, const char *);
|
||||
extern void end_repeat (int);
|
||||
extern void do_parse_cons_expression (expressionS *, int);
|
||||
|
||||
extern void generate_lineno_debug (void);
|
||||
|
||||
extern void s_abort (int) ATTRIBUTE_NORETURN;
|
||||
extern void s_align_bytes (int arg);
|
||||
extern void s_align_ptwo (int);
|
||||
extern void bss_alloc (symbolS *, addressT, int);
|
||||
extern offsetT parse_align (int);
|
||||
extern symbolS *s_comm_internal (int, symbolS *(*) (int, symbolS *, addressT));
|
||||
extern symbolS *s_lcomm_internal (int, symbolS *, addressT);
|
||||
extern void s_app_file_string (char *, int);
|
||||
extern void s_app_file (int);
|
||||
extern void s_app_line (int);
|
||||
extern void s_bundle_align_mode (int);
|
||||
extern void s_bundle_lock (int);
|
||||
extern void s_bundle_unlock (int);
|
||||
extern void s_comm (int);
|
||||
extern void s_data (int);
|
||||
extern void s_desc (int);
|
||||
extern void s_else (int arg);
|
||||
extern void s_elseif (int arg);
|
||||
extern void s_end (int arg);
|
||||
extern void s_endif (int arg);
|
||||
extern void s_err (int);
|
||||
extern void s_errwarn (int);
|
||||
extern void s_fail (int);
|
||||
extern void s_fill (int);
|
||||
extern void s_float_space (int mult);
|
||||
extern void s_func (int);
|
||||
extern void s_globl (int arg);
|
||||
extern void s_if (int arg);
|
||||
extern void s_ifb (int arg);
|
||||
extern void s_ifc (int arg);
|
||||
extern void s_ifdef (int arg);
|
||||
extern void s_ifeqs (int arg);
|
||||
extern void s_ignore (int arg);
|
||||
extern void s_include (int arg);
|
||||
extern void s_irp (int arg);
|
||||
extern void s_lcomm (int needs_align);
|
||||
extern void s_lcomm_bytes (int needs_align);
|
||||
extern void s_leb128 (int sign);
|
||||
extern void s_linkonce (int);
|
||||
extern void s_lsym (int);
|
||||
extern void s_macro (int);
|
||||
extern void s_mexit (int);
|
||||
extern void s_mri (int);
|
||||
extern void s_mri_common (int);
|
||||
extern void s_org (int);
|
||||
extern void s_print (int);
|
||||
extern void s_purgem (int);
|
||||
extern void s_rept (int);
|
||||
extern void s_set (int);
|
||||
extern void s_space (int mult);
|
||||
extern void s_stab (int what);
|
||||
extern void s_struct (int);
|
||||
extern void s_text (int);
|
||||
extern void stringer (int append_zero);
|
||||
extern void s_xstab (int what);
|
||||
extern void s_rva (int);
|
||||
extern void s_incbin (int);
|
||||
extern void s_weakref (int);
|
91
contrib/toolchain/binutils/gas/remap.c
Normal file
91
contrib/toolchain/binutils/gas/remap.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* Remap file names for debug info for GNU assembler.
|
||||
Copyright 2007 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "filenames.h"
|
||||
|
||||
/* Structure recording the mapping from source file and directory
|
||||
names at compile time to those to be embedded in debug
|
||||
information. */
|
||||
typedef struct debug_prefix_map
|
||||
{
|
||||
const char *old_prefix;
|
||||
const char *new_prefix;
|
||||
size_t old_len;
|
||||
size_t new_len;
|
||||
struct debug_prefix_map *next;
|
||||
} debug_prefix_map;
|
||||
|
||||
/* Linked list of such structures. */
|
||||
debug_prefix_map *debug_prefix_maps;
|
||||
|
||||
|
||||
/* Record a debug file prefix mapping. ARG is the argument to
|
||||
-fdebug-prefix-map and must be of the form OLD=NEW. */
|
||||
|
||||
void
|
||||
add_debug_prefix_map (const char *arg)
|
||||
{
|
||||
debug_prefix_map *map;
|
||||
const char *p;
|
||||
char *o;
|
||||
|
||||
p = strchr (arg, '=');
|
||||
if (!p)
|
||||
{
|
||||
as_fatal (_("invalid argument '%s' to -fdebug-prefix-map"), arg);
|
||||
return;
|
||||
}
|
||||
map = (struct debug_prefix_map *) xmalloc (sizeof (debug_prefix_map));
|
||||
o = xstrdup (arg);
|
||||
map->old_prefix = o;
|
||||
map->old_len = p - arg;
|
||||
o[map->old_len] = 0;
|
||||
p++;
|
||||
map->new_prefix = xstrdup (p);
|
||||
map->new_len = strlen (p);
|
||||
map->next = debug_prefix_maps;
|
||||
debug_prefix_maps = map;
|
||||
}
|
||||
|
||||
/* Perform user-specified mapping of debug filename prefixes. Returns
|
||||
a newly allocated buffer containing the name corresponding to FILENAME.
|
||||
It is the caller's responsibility to free the buffer. */
|
||||
|
||||
const char *
|
||||
remap_debug_filename (const char *filename)
|
||||
{
|
||||
debug_prefix_map *map;
|
||||
char *s;
|
||||
const char *name;
|
||||
size_t name_len;
|
||||
|
||||
for (map = debug_prefix_maps; map; map = map->next)
|
||||
if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
|
||||
break;
|
||||
if (!map)
|
||||
return xstrdup (filename);
|
||||
name = filename + map->old_len;
|
||||
name_len = strlen (name) + 1;
|
||||
s = (char *) alloca (name_len + map->new_len);
|
||||
memcpy (s, map->new_prefix, map->new_len);
|
||||
memcpy (s + map->new_len, name, name_len);
|
||||
return xstrdup (s);
|
||||
}
|
237
contrib/toolchain/binutils/gas/sb.c
Normal file
237
contrib/toolchain/binutils/gas/sb.c
Normal file
@ -0,0 +1,237 @@
|
||||
/* sb.c - string buffer manipulation routines
|
||||
Copyright 1994, 1995, 2000, 2003, 2005, 2006, 2007, 2009, 2012
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Written by Steve and Judy Chamberlain of Cygnus Support,
|
||||
sac@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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "sb.h"
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
/* These routines are about manipulating strings.
|
||||
|
||||
They are managed in things called `sb's which is an abbreviation
|
||||
for string buffers. An sb has to be created, things can be glued
|
||||
on to it, and at the end of it's life it should be freed. The
|
||||
contents should never be pointed at whilst it is still growing,
|
||||
since it could be moved at any time
|
||||
|
||||
eg:
|
||||
sb_new (&foo);
|
||||
sb_grow... (&foo,...);
|
||||
use foo->ptr[*];
|
||||
sb_kill (&foo); */
|
||||
|
||||
/* Buffers start at INIT_ALLOC size, and roughly double each time we
|
||||
go over the current allocation. MALLOC_OVERHEAD is a guess at the
|
||||
system malloc overhead. We aim to not waste any memory in the
|
||||
underlying page/chunk allocated by the system malloc. */
|
||||
#define MALLOC_OVERHEAD (2 * sizeof (size_t))
|
||||
#define INIT_ALLOC (64 - MALLOC_OVERHEAD - 1)
|
||||
|
||||
static void sb_check (sb *, size_t);
|
||||
|
||||
/* Initializes an sb. */
|
||||
|
||||
void
|
||||
sb_build (sb *ptr, size_t size)
|
||||
{
|
||||
ptr->ptr = xmalloc (size + 1);
|
||||
ptr->max = size;
|
||||
ptr->len = 0;
|
||||
}
|
||||
|
||||
void
|
||||
sb_new (sb *ptr)
|
||||
{
|
||||
sb_build (ptr, INIT_ALLOC);
|
||||
}
|
||||
|
||||
/* Deallocate the sb at ptr. */
|
||||
|
||||
void
|
||||
sb_kill (sb *ptr)
|
||||
{
|
||||
free (ptr->ptr);
|
||||
}
|
||||
|
||||
/* Add the sb at s to the end of the sb at ptr. */
|
||||
|
||||
void
|
||||
sb_add_sb (sb *ptr, sb *s)
|
||||
{
|
||||
sb_check (ptr, s->len);
|
||||
memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
|
||||
ptr->len += s->len;
|
||||
}
|
||||
|
||||
/* Helper for sb_scrub_and_add_sb. */
|
||||
|
||||
static sb *sb_to_scrub;
|
||||
static char *scrub_position;
|
||||
static size_t
|
||||
scrub_from_sb (char *buf, size_t buflen)
|
||||
{
|
||||
size_t copy;
|
||||
copy = sb_to_scrub->len - (scrub_position - sb_to_scrub->ptr);
|
||||
if (copy > buflen)
|
||||
copy = buflen;
|
||||
memcpy (buf, scrub_position, copy);
|
||||
scrub_position += copy;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* Run the sb at s through do_scrub_chars and add the result to the sb
|
||||
at ptr. */
|
||||
|
||||
void
|
||||
sb_scrub_and_add_sb (sb *ptr, sb *s)
|
||||
{
|
||||
sb_to_scrub = s;
|
||||
scrub_position = s->ptr;
|
||||
|
||||
sb_check (ptr, s->len);
|
||||
ptr->len += do_scrub_chars (scrub_from_sb, ptr->ptr + ptr->len, s->len);
|
||||
|
||||
sb_to_scrub = 0;
|
||||
scrub_position = 0;
|
||||
}
|
||||
|
||||
/* Make sure that the sb at ptr has room for another len characters,
|
||||
and grow it if it doesn't. */
|
||||
|
||||
static void
|
||||
sb_check (sb *ptr, size_t len)
|
||||
{
|
||||
size_t want = ptr->len + len;
|
||||
|
||||
if (want > ptr->max)
|
||||
{
|
||||
size_t max;
|
||||
|
||||
want += MALLOC_OVERHEAD + 1;
|
||||
if ((ssize_t) want < 0)
|
||||
as_fatal ("string buffer overflow");
|
||||
#if GCC_VERSION >= 3004
|
||||
max = (size_t) 1 << (CHAR_BIT * sizeof (want)
|
||||
- (sizeof (want) <= sizeof (long)
|
||||
? __builtin_clzl ((long) want)
|
||||
: __builtin_clzll ((long long) want)));
|
||||
#else
|
||||
max = 128;
|
||||
while (want > max)
|
||||
max <<= 1;
|
||||
#endif
|
||||
max -= MALLOC_OVERHEAD + 1;
|
||||
ptr->max = max;
|
||||
ptr->ptr = xrealloc (ptr->ptr, max + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the sb at ptr point back to the beginning. */
|
||||
|
||||
void
|
||||
sb_reset (sb *ptr)
|
||||
{
|
||||
ptr->len = 0;
|
||||
}
|
||||
|
||||
/* Add character c to the end of the sb at ptr. */
|
||||
|
||||
void
|
||||
sb_add_char (sb *ptr, size_t c)
|
||||
{
|
||||
sb_check (ptr, 1);
|
||||
ptr->ptr[ptr->len++] = c;
|
||||
}
|
||||
|
||||
/* Add null terminated string s to the end of sb at ptr. */
|
||||
|
||||
void
|
||||
sb_add_string (sb *ptr, const char *s)
|
||||
{
|
||||
size_t len = strlen (s);
|
||||
sb_check (ptr, len);
|
||||
memcpy (ptr->ptr + ptr->len, s, len);
|
||||
ptr->len += len;
|
||||
}
|
||||
|
||||
/* Add string at s of length len to sb at ptr */
|
||||
|
||||
void
|
||||
sb_add_buffer (sb *ptr, const char *s, size_t len)
|
||||
{
|
||||
sb_check (ptr, len);
|
||||
memcpy (ptr->ptr + ptr->len, s, len);
|
||||
ptr->len += len;
|
||||
}
|
||||
|
||||
/* Write terminating NUL and return string. */
|
||||
|
||||
char *
|
||||
sb_terminate (sb *in)
|
||||
{
|
||||
in->ptr[in->len] = 0;
|
||||
return in->ptr;
|
||||
}
|
||||
|
||||
/* Start at the index idx into the string in sb at ptr and skip
|
||||
whitespace. return the index of the first non whitespace character. */
|
||||
|
||||
size_t
|
||||
sb_skip_white (size_t idx, sb *ptr)
|
||||
{
|
||||
while (idx < ptr->len
|
||||
&& (ptr->ptr[idx] == ' '
|
||||
|| ptr->ptr[idx] == '\t'))
|
||||
idx++;
|
||||
return idx;
|
||||
}
|
||||
|
||||
/* Start at the index idx into the sb at ptr. skips whitespace,
|
||||
a comma and any following whitespace. returns the index of the
|
||||
next character. */
|
||||
|
||||
size_t
|
||||
sb_skip_comma (size_t idx, sb *ptr)
|
||||
{
|
||||
while (idx < ptr->len
|
||||
&& (ptr->ptr[idx] == ' '
|
||||
|| ptr->ptr[idx] == '\t'))
|
||||
idx++;
|
||||
|
||||
if (idx < ptr->len
|
||||
&& ptr->ptr[idx] == ',')
|
||||
idx++;
|
||||
|
||||
while (idx < ptr->len
|
||||
&& (ptr->ptr[idx] == ' '
|
||||
|| ptr->ptr[idx] == '\t'))
|
||||
idx++;
|
||||
|
||||
return idx;
|
||||
}
|
71
contrib/toolchain/binutils/gas/sb.h
Normal file
71
contrib/toolchain/binutils/gas/sb.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* sb.h - header file for string buffer manipulation routines
|
||||
Copyright 1994, 1995, 2000, 2003, 2005, 2006, 2007, 2012
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Written by Steve and Judy Chamberlain of Cygnus Support,
|
||||
sac@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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef SB_H
|
||||
|
||||
#define SB_H
|
||||
|
||||
/* String blocks
|
||||
|
||||
I had a couple of choices when deciding upon this data structure.
|
||||
gas uses null terminated strings for all its internal work. This
|
||||
often means that parts of the program that want to examine
|
||||
substrings have to manipulate the data in the string to do the
|
||||
right thing (a common operation is to single out a bit of text by
|
||||
saving away the character after it, nulling it out, operating on
|
||||
the substring and then replacing the character which was under the
|
||||
null). This is a pain and I remember a load of problems that I had with
|
||||
code in gas which almost got this right. Also, it's harder to grow and
|
||||
allocate null terminated strings efficiently.
|
||||
|
||||
Obstacks provide all the functionality needed, but are too
|
||||
complicated, hence the sb.
|
||||
|
||||
An sb is allocated by the caller. */
|
||||
|
||||
typedef struct sb
|
||||
{
|
||||
char *ptr; /* Points to the current block. */
|
||||
size_t len; /* How much is used. */
|
||||
size_t max; /* The maximum length. */
|
||||
}
|
||||
sb;
|
||||
|
||||
extern void sb_new (sb *);
|
||||
extern void sb_build (sb *, size_t);
|
||||
extern void sb_kill (sb *);
|
||||
extern void sb_add_sb (sb *, sb *);
|
||||
extern void sb_scrub_and_add_sb (sb *, sb *);
|
||||
extern void sb_reset (sb *);
|
||||
extern void sb_add_char (sb *, size_t);
|
||||
extern void sb_add_string (sb *, const char *);
|
||||
extern void sb_add_buffer (sb *, const char *, size_t);
|
||||
extern char *sb_terminate (sb *);
|
||||
extern size_t sb_skip_white (size_t, sb *);
|
||||
extern size_t sb_skip_comma (size_t, sb *);
|
||||
|
||||
/* Actually in input-scrub.c. */
|
||||
extern void input_scrub_include_sb (sb *, char *, int);
|
||||
|
||||
#endif /* SB_H */
|
710
contrib/toolchain/binutils/gas/stabs.c
Normal file
710
contrib/toolchain/binutils/gas/stabs.c
Normal file
@ -0,0 +1,710 @@
|
||||
/* Generic stabs parsing for gas.
|
||||
Copyright 1989, 1990, 1991, 1993, 1995, 1996, 1997, 1998, 2000, 2001
|
||||
2002, 2003, 2004, 2005, 2007, 2009 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 3,
|
||||
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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "as.h"
|
||||
#include "filenames.h"
|
||||
#include "obstack.h"
|
||||
#include "subsegs.h"
|
||||
#include "ecoff.h"
|
||||
|
||||
/* We need this, despite the apparent object format dependency, since
|
||||
it defines stab types, which all object formats can use now. */
|
||||
|
||||
#include "aout/stab_gnu.h"
|
||||
|
||||
/* Holds whether the assembler is generating stabs line debugging
|
||||
information or not. Potentially used by md_cleanup function. */
|
||||
|
||||
int outputting_stabs_line_debug = 0;
|
||||
|
||||
static void s_stab_generic (int, char *, char *);
|
||||
static void generate_asm_file (int, char *);
|
||||
|
||||
/* Allow backends to override the names used for the stab sections. */
|
||||
#ifndef STAB_SECTION_NAME
|
||||
#define STAB_SECTION_NAME ".stab"
|
||||
#endif
|
||||
|
||||
#ifndef STAB_STRING_SECTION_NAME
|
||||
#define STAB_STRING_SECTION_NAME ".stabstr"
|
||||
#endif
|
||||
|
||||
/* Non-zero if we're in the middle of a .func function, in which case
|
||||
stabs_generate_asm_lineno emits function relative line number stabs.
|
||||
Otherwise it emits line number stabs with absolute addresses. Note that
|
||||
both cases only apply to assembler code assembled with -gstabs. */
|
||||
static int in_dot_func_p;
|
||||
|
||||
/* Label at start of current function if in_dot_func_p != 0. */
|
||||
static const char *current_function_label;
|
||||
|
||||
/*
|
||||
* Handle .stabX directives, which used to be open-coded.
|
||||
* So much creeping featurism overloaded the semantics that we decided
|
||||
* to put all .stabX thinking in one place. Here.
|
||||
*
|
||||
* We try to make any .stabX directive legal. Other people's AS will often
|
||||
* do assembly-time consistency checks: eg assigning meaning to n_type bits
|
||||
* and "protecting" you from setting them to certain values. (They also zero
|
||||
* certain bits before emitting symbols. Tut tut.)
|
||||
*
|
||||
* If an expression is not absolute we either gripe or use the relocation
|
||||
* information. Other people's assemblers silently forget information they
|
||||
* don't need and invent information they need that you didn't supply.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Build a string dictionary entry for a .stabX symbol.
|
||||
* The symbol is added to the .<secname>str section.
|
||||
*/
|
||||
|
||||
#ifndef SEPARATE_STAB_SECTIONS
|
||||
#define SEPARATE_STAB_SECTIONS 0
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
get_stab_string_offset (const char *string, const char *stabstr_secname)
|
||||
{
|
||||
unsigned int length;
|
||||
unsigned int retval;
|
||||
segT save_seg;
|
||||
subsegT save_subseg;
|
||||
segT seg;
|
||||
char *p;
|
||||
|
||||
if (! SEPARATE_STAB_SECTIONS)
|
||||
abort ();
|
||||
|
||||
length = strlen (string);
|
||||
|
||||
save_seg = now_seg;
|
||||
save_subseg = now_subseg;
|
||||
|
||||
/* Create the stab string section. */
|
||||
seg = subseg_new (stabstr_secname, 0);
|
||||
|
||||
retval = seg_info (seg)->stabu.stab_string_size;
|
||||
if (retval <= 0)
|
||||
{
|
||||
/* Make sure the first string is empty. */
|
||||
p = frag_more (1);
|
||||
*p = 0;
|
||||
retval = seg_info (seg)->stabu.stab_string_size = 1;
|
||||
bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_DEBUGGING);
|
||||
if (seg->name == stabstr_secname)
|
||||
seg->name = xstrdup (stabstr_secname);
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{ /* Ordinary case. */
|
||||
p = frag_more (length + 1);
|
||||
strcpy (p, string);
|
||||
|
||||
seg_info (seg)->stabu.stab_string_size += length + 1;
|
||||
}
|
||||
else
|
||||
retval = 0;
|
||||
|
||||
subseg_set (save_seg, save_subseg);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef AOUT_STABS
|
||||
#ifndef OBJ_PROCESS_STAB
|
||||
#define OBJ_PROCESS_STAB(SEG,W,S,T,O,D) aout_process_stab(W,S,T,O,D)
|
||||
#endif
|
||||
|
||||
/* Here instead of obj-aout.c because other formats use it too. */
|
||||
void
|
||||
aout_process_stab (what, string, type, other, desc)
|
||||
int what;
|
||||
const char *string;
|
||||
int type, other, desc;
|
||||
{
|
||||
/* Put the stab information in the symbol table. */
|
||||
symbolS *symbol;
|
||||
|
||||
/* Create the symbol now, but only insert it into the symbol chain
|
||||
after any symbols mentioned in the value expression get into the
|
||||
symbol chain. This is to avoid "continuation symbols" (where one
|
||||
ends in "\" and the debug info is continued in the next .stabs
|
||||
directive) from being separated by other random symbols. */
|
||||
symbol = symbol_create (string, undefined_section, 0,
|
||||
&zero_address_frag);
|
||||
if (what == 's' || what == 'n')
|
||||
{
|
||||
/* Pick up the value from the input line. */
|
||||
pseudo_set (symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* .stabd sets the name to NULL. Why? */
|
||||
S_SET_NAME (symbol, NULL);
|
||||
symbol_set_frag (symbol, frag_now);
|
||||
S_SET_VALUE (symbol, (valueT) frag_now_fix ());
|
||||
}
|
||||
|
||||
symbol_append (symbol, symbol_lastP, &symbol_rootP, &symbol_lastP);
|
||||
|
||||
symbol_get_bfdsym (symbol)->flags |= BSF_DEBUGGING;
|
||||
|
||||
S_SET_TYPE (symbol, type);
|
||||
S_SET_OTHER (symbol, other);
|
||||
S_SET_DESC (symbol, desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This can handle different kinds of stabs (s,n,d) and different
|
||||
kinds of stab sections. */
|
||||
|
||||
static void
|
||||
s_stab_generic (int what, char *stab_secname, char *stabstr_secname)
|
||||
{
|
||||
long longint;
|
||||
char *string, *saved_string_obstack_end;
|
||||
int type;
|
||||
int other;
|
||||
int desc;
|
||||
|
||||
/* The general format is:
|
||||
.stabs "STRING",TYPE,OTHER,DESC,VALUE
|
||||
.stabn TYPE,OTHER,DESC,VALUE
|
||||
.stabd TYPE,OTHER,DESC
|
||||
At this point input_line_pointer points after the pseudo-op and
|
||||
any trailing whitespace. The argument what is one of 's', 'n' or
|
||||
'd' indicating which type of .stab this is. */
|
||||
|
||||
if (what != 's')
|
||||
{
|
||||
string = "";
|
||||
saved_string_obstack_end = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int length;
|
||||
|
||||
string = demand_copy_C_string (&length);
|
||||
/* FIXME: We should probably find some other temporary storage
|
||||
for string, rather than leaking memory if someone else
|
||||
happens to use the notes obstack. */
|
||||
saved_string_obstack_end = notes.next_free;
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer == ',')
|
||||
input_line_pointer++;
|
||||
else
|
||||
{
|
||||
as_warn (_(".stab%c: missing comma"), what);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (get_absolute_expression_and_terminator (&longint) != ',')
|
||||
{
|
||||
as_warn (_(".stab%c: missing comma"), what);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
type = longint;
|
||||
|
||||
if (get_absolute_expression_and_terminator (&longint) != ',')
|
||||
{
|
||||
as_warn (_(".stab%c: missing comma"), what);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
other = longint;
|
||||
|
||||
desc = get_absolute_expression ();
|
||||
|
||||
if ((desc > 0xffff) || (desc < -0x8000))
|
||||
/* This could happen for example with a source file with a huge
|
||||
number of lines. The only cure is to use a different debug
|
||||
format, probably DWARF. */
|
||||
as_warn (_(".stab%c: description field '%x' too big, try a different debug format"),
|
||||
what, desc);
|
||||
|
||||
if (what == 's' || what == 'n')
|
||||
{
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
as_warn (_(".stab%c: missing comma"), what);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
input_line_pointer++;
|
||||
SKIP_WHITESPACE ();
|
||||
}
|
||||
|
||||
#ifdef TC_PPC
|
||||
#ifdef OBJ_ELF
|
||||
/* Solaris on PowerPC has decided that .stabd can take 4 arguments, so if we were
|
||||
given 4 arguments, make it a .stabn */
|
||||
else if (what == 'd')
|
||||
{
|
||||
char *save_location = input_line_pointer;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer == ',')
|
||||
{
|
||||
input_line_pointer++;
|
||||
what = 'n';
|
||||
}
|
||||
else
|
||||
input_line_pointer = save_location;
|
||||
}
|
||||
#endif /* OBJ_ELF */
|
||||
#endif /* TC_PPC */
|
||||
|
||||
#ifndef NO_LISTING
|
||||
if (listing)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case N_SLINE:
|
||||
listing_source_line ((unsigned int) desc);
|
||||
break;
|
||||
case N_SO:
|
||||
case N_SOL:
|
||||
listing_source_file (string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* ! NO_LISTING */
|
||||
|
||||
/* We have now gathered the type, other, and desc information. For
|
||||
.stabs or .stabn, input_line_pointer is now pointing at the
|
||||
value. */
|
||||
|
||||
if (SEPARATE_STAB_SECTIONS)
|
||||
/* Output the stab information in a separate section. This is used
|
||||
at least for COFF and ELF. */
|
||||
{
|
||||
segT saved_seg = now_seg;
|
||||
subsegT saved_subseg = now_subseg;
|
||||
fragS *saved_frag = frag_now;
|
||||
valueT dot;
|
||||
segT seg;
|
||||
unsigned int stroff;
|
||||
char *p;
|
||||
|
||||
static segT cached_sec;
|
||||
static char *cached_secname;
|
||||
|
||||
dot = frag_now_fix ();
|
||||
|
||||
#ifdef md_flush_pending_output
|
||||
md_flush_pending_output ();
|
||||
#endif
|
||||
|
||||
if (cached_secname && !strcmp (cached_secname, stab_secname))
|
||||
{
|
||||
seg = cached_sec;
|
||||
subseg_set (seg, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
seg = subseg_new (stab_secname, 0);
|
||||
if (cached_secname)
|
||||
free (cached_secname);
|
||||
cached_secname = xstrdup (stab_secname);
|
||||
cached_sec = seg;
|
||||
}
|
||||
|
||||
if (! seg_info (seg)->hadone)
|
||||
{
|
||||
bfd_set_section_flags (stdoutput, seg,
|
||||
SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
|
||||
#ifdef INIT_STAB_SECTION
|
||||
INIT_STAB_SECTION (seg);
|
||||
#endif
|
||||
seg_info (seg)->hadone = 1;
|
||||
}
|
||||
|
||||
stroff = get_stab_string_offset (string, stabstr_secname);
|
||||
if (what == 's')
|
||||
{
|
||||
/* Release the string, if nobody else has used the obstack. */
|
||||
if (saved_string_obstack_end == notes.next_free)
|
||||
obstack_free (¬es, string);
|
||||
}
|
||||
|
||||
/* At least for now, stabs in a special stab section are always
|
||||
output as 12 byte blocks of information. */
|
||||
p = frag_more (8);
|
||||
md_number_to_chars (p, (valueT) stroff, 4);
|
||||
md_number_to_chars (p + 4, (valueT) type, 1);
|
||||
md_number_to_chars (p + 5, (valueT) other, 1);
|
||||
md_number_to_chars (p + 6, (valueT) desc, 2);
|
||||
|
||||
if (what == 's' || what == 'n')
|
||||
{
|
||||
/* Pick up the value from the input line. */
|
||||
cons (4);
|
||||
input_line_pointer--;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolS *symbol;
|
||||
expressionS exp;
|
||||
|
||||
/* Arrange for a value representing the current location. */
|
||||
symbol = symbol_temp_new (saved_seg, dot, saved_frag);
|
||||
|
||||
exp.X_op = O_symbol;
|
||||
exp.X_add_symbol = symbol;
|
||||
exp.X_add_number = 0;
|
||||
|
||||
emit_expr (&exp, 4);
|
||||
}
|
||||
|
||||
#ifdef OBJ_PROCESS_STAB
|
||||
OBJ_PROCESS_STAB (seg, what, string, type, other, desc);
|
||||
#endif
|
||||
|
||||
subseg_set (saved_seg, saved_subseg);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef OBJ_PROCESS_STAB
|
||||
OBJ_PROCESS_STAB (0, what, string, type, other, desc);
|
||||
#else
|
||||
abort ();
|
||||
#endif
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
/* Regular stab directive. */
|
||||
|
||||
void
|
||||
s_stab (int what)
|
||||
{
|
||||
s_stab_generic (what, STAB_SECTION_NAME, STAB_STRING_SECTION_NAME);
|
||||
}
|
||||
|
||||
/* "Extended stabs", used in Solaris only now. */
|
||||
|
||||
void
|
||||
s_xstab (int what)
|
||||
{
|
||||
int length;
|
||||
char *stab_secname, *stabstr_secname;
|
||||
static char *saved_secname, *saved_strsecname;
|
||||
|
||||
/* @@ MEMORY LEAK: This allocates a copy of the string, but in most
|
||||
cases it will be the same string, so we could release the storage
|
||||
back to the obstack it came from. */
|
||||
stab_secname = demand_copy_C_string (&length);
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer == ',')
|
||||
input_line_pointer++;
|
||||
else
|
||||
{
|
||||
as_bad (_("comma missing in .xstabs"));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* To get the name of the stab string section, simply add "str" to
|
||||
the stab section name. */
|
||||
if (saved_secname == 0 || strcmp (saved_secname, stab_secname))
|
||||
{
|
||||
stabstr_secname = (char *) xmalloc (strlen (stab_secname) + 4);
|
||||
strcpy (stabstr_secname, stab_secname);
|
||||
strcat (stabstr_secname, "str");
|
||||
if (saved_secname)
|
||||
{
|
||||
free (saved_secname);
|
||||
free (saved_strsecname);
|
||||
}
|
||||
saved_secname = stab_secname;
|
||||
saved_strsecname = stabstr_secname;
|
||||
}
|
||||
s_stab_generic (what, saved_secname, saved_strsecname);
|
||||
}
|
||||
|
||||
#ifdef S_SET_DESC
|
||||
|
||||
/* Frob invented at RMS' request. Set the n_desc of a symbol. */
|
||||
|
||||
void
|
||||
s_desc (ignore)
|
||||
int ignore ATTRIBUTE_UNUSED;
|
||||
{
|
||||
char *name;
|
||||
char c;
|
||||
char *p;
|
||||
symbolS *symbolP;
|
||||
int temp;
|
||||
|
||||
name = input_line_pointer;
|
||||
c = get_symbol_end ();
|
||||
p = input_line_pointer;
|
||||
*p = c;
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
*p = 0;
|
||||
as_bad (_("expected comma after \"%s\""), name);
|
||||
*p = c;
|
||||
ignore_rest_of_line ();
|
||||
}
|
||||
else
|
||||
{
|
||||
input_line_pointer++;
|
||||
temp = get_absolute_expression ();
|
||||
*p = 0;
|
||||
symbolP = symbol_find_or_make (name);
|
||||
*p = c;
|
||||
S_SET_DESC (symbolP, temp);
|
||||
}
|
||||
demand_empty_rest_of_line ();
|
||||
} /* s_desc() */
|
||||
|
||||
#endif /* defined (S_SET_DESC) */
|
||||
|
||||
/* Generate stabs debugging information to denote the main source file. */
|
||||
|
||||
void
|
||||
stabs_generate_asm_file (void)
|
||||
{
|
||||
char *file;
|
||||
unsigned int lineno;
|
||||
|
||||
as_where (&file, &lineno);
|
||||
if (use_gnu_debug_info_extensions)
|
||||
{
|
||||
const char *dir;
|
||||
char *dir2;
|
||||
|
||||
dir = remap_debug_filename (getpwd ());
|
||||
dir2 = (char *) alloca (strlen (dir) + 2);
|
||||
sprintf (dir2, "%s%s", dir, "/");
|
||||
generate_asm_file (N_SO, dir2);
|
||||
xfree ((char *) dir);
|
||||
}
|
||||
generate_asm_file (N_SO, file);
|
||||
}
|
||||
|
||||
/* Generate stabs debugging information to denote the source file.
|
||||
TYPE is one of N_SO, N_SOL. */
|
||||
|
||||
static void
|
||||
generate_asm_file (int type, char *file)
|
||||
{
|
||||
static char *last_file;
|
||||
static int label_count;
|
||||
char *hold;
|
||||
char sym[30];
|
||||
char *buf;
|
||||
char *tmp = file;
|
||||
char *file_endp = file + strlen (file);
|
||||
char *bufp;
|
||||
|
||||
if (last_file != NULL
|
||||
&& filename_cmp (last_file, file) == 0)
|
||||
return;
|
||||
|
||||
/* Rather than try to do this in some efficient fashion, we just
|
||||
generate a string and then parse it again. That lets us use the
|
||||
existing stabs hook, which expect to see a string, rather than
|
||||
inventing new ones. */
|
||||
hold = input_line_pointer;
|
||||
|
||||
sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
|
||||
++label_count;
|
||||
|
||||
/* Allocate enough space for the file name (possibly extended with
|
||||
doubled up backslashes), the symbol name, and the other characters
|
||||
that make up a stabs file directive. */
|
||||
bufp = buf = (char *) xmalloc (2 * strlen (file) + strlen (sym) + 12);
|
||||
|
||||
*bufp++ = '"';
|
||||
|
||||
while (tmp < file_endp)
|
||||
{
|
||||
char *bslash = strchr (tmp, '\\');
|
||||
size_t len = (bslash) ? (size_t) (bslash - tmp + 1) : strlen (tmp);
|
||||
|
||||
/* Double all backslashes, since demand_copy_C_string (used by
|
||||
s_stab to extract the part in quotes) will try to replace them as
|
||||
escape sequences. backslash may appear in a filespec. */
|
||||
strncpy (bufp, tmp, len);
|
||||
|
||||
tmp += len;
|
||||
bufp += len;
|
||||
|
||||
if (bslash != NULL)
|
||||
*bufp++ = '\\';
|
||||
}
|
||||
|
||||
sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
|
||||
|
||||
input_line_pointer = buf;
|
||||
s_stab ('s');
|
||||
colon (sym);
|
||||
|
||||
if (last_file != NULL)
|
||||
free (last_file);
|
||||
last_file = xstrdup (file);
|
||||
|
||||
free (buf);
|
||||
|
||||
input_line_pointer = hold;
|
||||
}
|
||||
|
||||
/* Generate stabs debugging information for the current line. This is
|
||||
used to produce debugging information for an assembler file. */
|
||||
|
||||
void
|
||||
stabs_generate_asm_lineno (void)
|
||||
{
|
||||
static int label_count;
|
||||
char *hold;
|
||||
char *file;
|
||||
unsigned int lineno;
|
||||
char *buf;
|
||||
char sym[30];
|
||||
/* Remember the last file/line and avoid duplicates. */
|
||||
static unsigned int prev_lineno = -1;
|
||||
static char *prev_file = NULL;
|
||||
|
||||
/* Rather than try to do this in some efficient fashion, we just
|
||||
generate a string and then parse it again. That lets us use the
|
||||
existing stabs hook, which expect to see a string, rather than
|
||||
inventing new ones. */
|
||||
|
||||
hold = input_line_pointer;
|
||||
|
||||
as_where (&file, &lineno);
|
||||
|
||||
/* Don't emit sequences of stabs for the same line. */
|
||||
if (prev_file == NULL)
|
||||
{
|
||||
/* First time thru. */
|
||||
prev_file = xstrdup (file);
|
||||
prev_lineno = lineno;
|
||||
}
|
||||
else if (lineno == prev_lineno
|
||||
&& filename_cmp (file, prev_file) == 0)
|
||||
{
|
||||
/* Same file/line as last time. */
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remember file/line for next time. */
|
||||
prev_lineno = lineno;
|
||||
if (filename_cmp (file, prev_file) != 0)
|
||||
{
|
||||
free (prev_file);
|
||||
prev_file = xstrdup (file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Let the world know that we are in the middle of generating a
|
||||
piece of stabs line debugging information. */
|
||||
outputting_stabs_line_debug = 1;
|
||||
|
||||
generate_asm_file (N_SOL, file);
|
||||
|
||||
sprintf (sym, "%sL%d", FAKE_LABEL_NAME, label_count);
|
||||
++label_count;
|
||||
|
||||
if (in_dot_func_p)
|
||||
{
|
||||
buf = (char *) alloca (100 + strlen (current_function_label));
|
||||
sprintf (buf, "%d,0,%d,%s-%s\n", N_SLINE, lineno,
|
||||
sym, current_function_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = (char *) alloca (100);
|
||||
sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
|
||||
}
|
||||
input_line_pointer = buf;
|
||||
s_stab ('n');
|
||||
colon (sym);
|
||||
|
||||
input_line_pointer = hold;
|
||||
outputting_stabs_line_debug = 0;
|
||||
}
|
||||
|
||||
/* Emit a function stab.
|
||||
All assembler functions are assumed to have return type `void'. */
|
||||
|
||||
void
|
||||
stabs_generate_asm_func (const char *funcname, const char *startlabname)
|
||||
{
|
||||
static int void_emitted_p;
|
||||
char *hold = input_line_pointer;
|
||||
char *buf;
|
||||
char *file;
|
||||
unsigned int lineno;
|
||||
|
||||
if (! void_emitted_p)
|
||||
{
|
||||
input_line_pointer = "\"void:t1=1\",128,0,0,0";
|
||||
s_stab ('s');
|
||||
void_emitted_p = 1;
|
||||
}
|
||||
|
||||
as_where (&file, &lineno);
|
||||
if (asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
|
||||
funcname, N_FUN, lineno + 1, startlabname) == -1)
|
||||
as_fatal ("%s", xstrerror (errno));
|
||||
input_line_pointer = buf;
|
||||
s_stab ('s');
|
||||
free (buf);
|
||||
|
||||
input_line_pointer = hold;
|
||||
current_function_label = xstrdup (startlabname);
|
||||
in_dot_func_p = 1;
|
||||
}
|
||||
|
||||
/* Emit a stab to record the end of a function. */
|
||||
|
||||
void
|
||||
stabs_generate_asm_endfunc (const char *funcname ATTRIBUTE_UNUSED,
|
||||
const char *startlabname)
|
||||
{
|
||||
static int label_count;
|
||||
char *hold = input_line_pointer;
|
||||
char *buf;
|
||||
char sym[30];
|
||||
|
||||
sprintf (sym, "%sendfunc%d", FAKE_LABEL_NAME, label_count);
|
||||
++label_count;
|
||||
colon (sym);
|
||||
|
||||
if (asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname) == -1)
|
||||
as_fatal ("%s", xstrerror (errno));
|
||||
input_line_pointer = buf;
|
||||
s_stab ('s');
|
||||
free (buf);
|
||||
|
||||
input_line_pointer = hold;
|
||||
in_dot_func_p = 0;
|
||||
current_function_label = NULL;
|
||||
}
|
159
contrib/toolchain/binutils/gas/struc-symbol.h
Normal file
159
contrib/toolchain/binutils/gas/struc-symbol.h
Normal file
@ -0,0 +1,159 @@
|
||||
/* struct_symbol.h - Internal symbol structure
|
||||
Copyright 1987, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2005,
|
||||
2007, 2008, 2009 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef __struc_symbol_h__
|
||||
#define __struc_symbol_h__
|
||||
|
||||
struct symbol_flags
|
||||
{
|
||||
/* Wether the symbol is a local_symbol. */
|
||||
unsigned int sy_local_symbol : 1;
|
||||
|
||||
/* Wether symbol has been written. */
|
||||
unsigned int sy_written : 1;
|
||||
|
||||
/* Whether symbol value has been completely resolved (used during
|
||||
final pass over symbol table). */
|
||||
unsigned int sy_resolved : 1;
|
||||
|
||||
/* Whether the symbol value is currently being resolved (used to
|
||||
detect loops in symbol dependencies). */
|
||||
unsigned int sy_resolving : 1;
|
||||
|
||||
/* Whether the symbol value is used in a reloc. This is used to
|
||||
ensure that symbols used in relocs are written out, even if they
|
||||
are local and would otherwise not be. */
|
||||
unsigned int sy_used_in_reloc : 1;
|
||||
|
||||
/* Whether the symbol is used as an operand or in an expression.
|
||||
NOTE: Not all the backends keep this information accurate;
|
||||
backends which use this bit are responsible for setting it when
|
||||
a symbol is used in backend routines. */
|
||||
unsigned int sy_used : 1;
|
||||
|
||||
/* Whether the symbol can be re-defined. */
|
||||
unsigned int sy_volatile : 1;
|
||||
|
||||
/* Whether the symbol is a forward reference. */
|
||||
unsigned int sy_forward_ref : 1;
|
||||
|
||||
/* This is set if the symbol is defined in an MRI common section.
|
||||
We handle such sections as single common symbols, so symbols
|
||||
defined within them must be treated specially by the relocation
|
||||
routines. */
|
||||
unsigned int sy_mri_common : 1;
|
||||
|
||||
/* This is set if the symbol is set with a .weakref directive. */
|
||||
unsigned int sy_weakrefr : 1;
|
||||
|
||||
/* This is set when the symbol is referenced as part of a .weakref
|
||||
directive, but only if the symbol was not in the symbol table
|
||||
before. It is cleared as soon as any direct reference to the
|
||||
symbol is present. */
|
||||
unsigned int sy_weakrefd : 1;
|
||||
};
|
||||
|
||||
/* The information we keep for a symbol. Note that the symbol table
|
||||
holds pointers both to this and to local_symbol structures. See
|
||||
below. */
|
||||
|
||||
struct symbol
|
||||
{
|
||||
/* Symbol flags. */
|
||||
struct symbol_flags sy_flags;
|
||||
|
||||
/* BFD symbol */
|
||||
asymbol *bsym;
|
||||
|
||||
/* The value of the symbol. */
|
||||
expressionS sy_value;
|
||||
|
||||
/* Forwards and (optionally) backwards chain pointers. */
|
||||
struct symbol *sy_next;
|
||||
struct symbol *sy_previous;
|
||||
|
||||
/* Pointer to the frag this symbol is attached to, if any.
|
||||
Otherwise, NULL. */
|
||||
struct frag *sy_frag;
|
||||
|
||||
#ifdef OBJ_SYMFIELD_TYPE
|
||||
OBJ_SYMFIELD_TYPE sy_obj;
|
||||
#endif
|
||||
|
||||
#ifdef TC_SYMFIELD_TYPE
|
||||
TC_SYMFIELD_TYPE sy_tc;
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_SYMBOL_FIELDS
|
||||
TARGET_SYMBOL_FIELDS
|
||||
#endif
|
||||
};
|
||||
|
||||
/* A pointer in the symbol may point to either a complete symbol
|
||||
(struct symbol above) or to a local symbol (struct local_symbol
|
||||
defined here). The symbol code can detect the case by examining
|
||||
the first field. It is always NULL for a local symbol.
|
||||
|
||||
We do this because we ordinarily only need a small amount of
|
||||
information for a local symbol. The symbol table takes up a lot of
|
||||
space, and storing less information for a local symbol can make a
|
||||
big difference in assembler memory usage when assembling a large
|
||||
file. */
|
||||
|
||||
struct local_symbol
|
||||
{
|
||||
/* Symbol flags. Only sy_local_symbol and sy_resolved are relevant. */
|
||||
struct symbol_flags lsy_flags;
|
||||
|
||||
/* The symbol section. This also serves as a flag. If this is
|
||||
reg_section, then this symbol has been converted into a regular
|
||||
symbol, and lsy_sym points to it. */
|
||||
segT lsy_section;
|
||||
|
||||
/* The symbol name. */
|
||||
const char *lsy_name;
|
||||
|
||||
/* The symbol frag or the real symbol, depending upon the value in
|
||||
lsy_section. */
|
||||
union
|
||||
{
|
||||
fragS *lsy_frag;
|
||||
symbolS *lsy_sym;
|
||||
} u;
|
||||
|
||||
/* The value of the symbol. */
|
||||
valueT lsy_value;
|
||||
|
||||
#ifdef TC_LOCAL_SYMFIELD_TYPE
|
||||
TC_LOCAL_SYMFIELD_TYPE lsy_tc;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define local_symbol_converted_p(l) ((l)->lsy_section == reg_section)
|
||||
#define local_symbol_mark_converted(l) ((l)->lsy_section = reg_section)
|
||||
#define local_symbol_resolved_p(l) ((l)->lsy_flags.sy_resolved)
|
||||
#define local_symbol_mark_resolved(l) ((l)->lsy_flags.sy_resolved = 1)
|
||||
#define local_symbol_get_frag(l) ((l)->u.lsy_frag)
|
||||
#define local_symbol_set_frag(l, f) ((l)->u.lsy_frag = (f))
|
||||
#define local_symbol_get_real_symbol(l) ((l)->u.lsy_sym)
|
||||
#define local_symbol_set_real_symbol(l, s) ((l)->u.lsy_sym = (s))
|
||||
|
||||
#endif /* __struc_symbol_h__ */
|
330
contrib/toolchain/binutils/gas/subsegs.c
Normal file
330
contrib/toolchain/binutils/gas/subsegs.c
Normal file
@ -0,0 +1,330 @@
|
||||
/* subsegs.c - subsegments -
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Segments & sub-segments. */
|
||||
|
||||
#include "as.h"
|
||||
|
||||
#include "subsegs.h"
|
||||
#include "obstack.h"
|
||||
|
||||
frchainS *frchain_now;
|
||||
|
||||
static struct obstack frchains;
|
||||
|
||||
static fragS dummy_frag;
|
||||
|
||||
|
||||
void
|
||||
subsegs_begin (void)
|
||||
{
|
||||
obstack_begin (&frchains, chunksize);
|
||||
#if __GNUC__ >= 2
|
||||
obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
|
||||
#endif
|
||||
|
||||
frchain_now = NULL; /* Warn new_subseg() that we are booting. */
|
||||
frag_now = &dummy_frag;
|
||||
}
|
||||
|
||||
/*
|
||||
* subseg_change()
|
||||
*
|
||||
* Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
|
||||
* subsegment. If we are already in the correct subsegment, change nothing.
|
||||
* This is used eg as a worker for subseg_set [which does make a new frag_now]
|
||||
* and for changing segments after we have read the source. We construct eg
|
||||
* fixSs even after the source file is read, so we do have to keep the
|
||||
* segment context correct.
|
||||
*/
|
||||
void
|
||||
subseg_change (register segT seg, register int subseg)
|
||||
{
|
||||
segment_info_type *seginfo = seg_info (seg);
|
||||
now_seg = seg;
|
||||
now_subseg = subseg;
|
||||
|
||||
if (! seginfo)
|
||||
{
|
||||
seginfo = (segment_info_type *) xcalloc (1, sizeof (*seginfo));
|
||||
seginfo->bfd_section = seg;
|
||||
bfd_set_section_userdata (stdoutput, seg, seginfo);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
subseg_set_rest (segT seg, subsegT subseg)
|
||||
{
|
||||
frchainS *frcP; /* crawl frchain chain */
|
||||
frchainS **lastPP; /* address of last pointer */
|
||||
frchainS *newP; /* address of new frchain */
|
||||
segment_info_type *seginfo;
|
||||
|
||||
mri_common_symbol = NULL;
|
||||
|
||||
if (frag_now && frchain_now)
|
||||
frchain_now->frch_frag_now = frag_now;
|
||||
|
||||
gas_assert (frchain_now == 0
|
||||
|| frchain_now->frch_last == frag_now);
|
||||
|
||||
subseg_change (seg, (int) subseg);
|
||||
|
||||
seginfo = seg_info (seg);
|
||||
|
||||
/* Attempt to find or make a frchain for that subsection.
|
||||
We keep the list sorted by subsection number. */
|
||||
for (frcP = *(lastPP = &seginfo->frchainP);
|
||||
frcP != NULL;
|
||||
frcP = *(lastPP = &frcP->frch_next))
|
||||
if (frcP->frch_subseg >= subseg)
|
||||
break;
|
||||
|
||||
if (frcP == NULL || frcP->frch_subseg != subseg)
|
||||
{
|
||||
/* This should be the only code that creates a frchainS. */
|
||||
|
||||
newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
|
||||
newP->frch_subseg = subseg;
|
||||
newP->fix_root = NULL;
|
||||
newP->fix_tail = NULL;
|
||||
obstack_begin (&newP->frch_obstack, chunksize);
|
||||
#if __GNUC__ >= 2
|
||||
obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
|
||||
#endif
|
||||
newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
|
||||
newP->frch_frag_now->fr_type = rs_fill;
|
||||
newP->frch_cfi_data = NULL;
|
||||
|
||||
newP->frch_root = newP->frch_last = newP->frch_frag_now;
|
||||
|
||||
*lastPP = newP;
|
||||
newP->frch_next = frcP;
|
||||
frcP = newP;
|
||||
}
|
||||
|
||||
frchain_now = frcP;
|
||||
frag_now = frcP->frch_frag_now;
|
||||
|
||||
gas_assert (frchain_now->frch_last == frag_now);
|
||||
}
|
||||
|
||||
/*
|
||||
* subseg_set(segT, subsegT)
|
||||
*
|
||||
* If you attempt to change to the current subsegment, nothing happens.
|
||||
*
|
||||
* In: segT, subsegT code for new subsegment.
|
||||
* frag_now -> incomplete frag for current subsegment.
|
||||
* If frag_now==NULL, then there is no old, incomplete frag, so
|
||||
* the old frag is not closed off.
|
||||
*
|
||||
* Out: now_subseg, now_seg updated.
|
||||
* Frchain_now points to the (possibly new) struct frchain for this
|
||||
* sub-segment.
|
||||
*/
|
||||
|
||||
segT
|
||||
subseg_get (const char *segname, int force_new)
|
||||
{
|
||||
segT secptr;
|
||||
segment_info_type *seginfo;
|
||||
const char *now_seg_name = (now_seg
|
||||
? bfd_get_section_name (stdoutput, now_seg)
|
||||
: 0);
|
||||
|
||||
if (!force_new
|
||||
&& now_seg_name
|
||||
&& (now_seg_name == segname
|
||||
|| !strcmp (now_seg_name, segname)))
|
||||
return now_seg;
|
||||
|
||||
if (!force_new)
|
||||
secptr = bfd_make_section_old_way (stdoutput, segname);
|
||||
else
|
||||
secptr = bfd_make_section_anyway (stdoutput, segname);
|
||||
|
||||
seginfo = seg_info (secptr);
|
||||
if (! seginfo)
|
||||
{
|
||||
secptr->output_section = secptr;
|
||||
seginfo = (segment_info_type *) xcalloc (1, sizeof (*seginfo));
|
||||
seginfo->bfd_section = secptr;
|
||||
bfd_set_section_userdata (stdoutput, secptr, seginfo);
|
||||
}
|
||||
return secptr;
|
||||
}
|
||||
|
||||
segT
|
||||
subseg_new (const char *segname, subsegT subseg)
|
||||
{
|
||||
segT secptr;
|
||||
|
||||
secptr = subseg_get (segname, 0);
|
||||
subseg_set_rest (secptr, subseg);
|
||||
return secptr;
|
||||
}
|
||||
|
||||
/* Like subseg_new, except a new section is always created, even if
|
||||
a section with that name already exists. */
|
||||
segT
|
||||
subseg_force_new (const char *segname, subsegT subseg)
|
||||
{
|
||||
segT secptr;
|
||||
|
||||
secptr = subseg_get (segname, 1);
|
||||
subseg_set_rest (secptr, subseg);
|
||||
return secptr;
|
||||
}
|
||||
|
||||
void
|
||||
subseg_set (segT secptr, subsegT subseg)
|
||||
{
|
||||
if (! (secptr == now_seg && subseg == now_subseg))
|
||||
subseg_set_rest (secptr, subseg);
|
||||
mri_common_symbol = NULL;
|
||||
}
|
||||
|
||||
#ifndef obj_sec_sym_ok_for_reloc
|
||||
#define obj_sec_sym_ok_for_reloc(SEC) 0
|
||||
#endif
|
||||
|
||||
symbolS *
|
||||
section_symbol (segT sec)
|
||||
{
|
||||
segment_info_type *seginfo = seg_info (sec);
|
||||
symbolS *s;
|
||||
|
||||
if (seginfo == 0)
|
||||
abort ();
|
||||
if (seginfo->sym)
|
||||
return seginfo->sym;
|
||||
|
||||
#ifndef EMIT_SECTION_SYMBOLS
|
||||
#define EMIT_SECTION_SYMBOLS 1
|
||||
#endif
|
||||
|
||||
if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen)
|
||||
{
|
||||
/* Here we know it won't be going into the symbol table. */
|
||||
s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag);
|
||||
}
|
||||
else
|
||||
{
|
||||
segT seg;
|
||||
s = symbol_find (sec->symbol->name);
|
||||
/* We have to make sure it is the right symbol when we
|
||||
have multiple sections with the same section name. */
|
||||
if (s == NULL
|
||||
|| ((seg = S_GET_SEGMENT (s)) != sec
|
||||
&& seg != undefined_section))
|
||||
s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag);
|
||||
else if (seg == undefined_section)
|
||||
{
|
||||
S_SET_SEGMENT (s, sec);
|
||||
symbol_set_frag (s, &zero_address_frag);
|
||||
}
|
||||
}
|
||||
|
||||
S_CLEAR_EXTERNAL (s);
|
||||
|
||||
/* Use the BFD section symbol, if possible. */
|
||||
if (obj_sec_sym_ok_for_reloc (sec))
|
||||
symbol_set_bfdsym (s, sec->symbol);
|
||||
else
|
||||
symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM;
|
||||
|
||||
seginfo->sym = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Return whether the specified segment is thought to hold text. */
|
||||
|
||||
int
|
||||
subseg_text_p (segT sec)
|
||||
{
|
||||
return (bfd_get_section_flags (stdoutput, sec) & SEC_CODE) != 0;
|
||||
}
|
||||
|
||||
/* Return non zero if SEC has at least one byte of data. It is
|
||||
possible that we'll return zero even on a non-empty section because
|
||||
we don't know all the fragment types, and it is possible that an
|
||||
fr_fix == 0 one still contributes data. Think of this as
|
||||
seg_definitely_not_empty_p. */
|
||||
|
||||
int
|
||||
seg_not_empty_p (segT sec ATTRIBUTE_UNUSED)
|
||||
{
|
||||
segment_info_type *seginfo = seg_info (sec);
|
||||
frchainS *chain;
|
||||
fragS *frag;
|
||||
|
||||
if (!seginfo)
|
||||
return 0;
|
||||
|
||||
for (chain = seginfo->frchainP; chain; chain = chain->frch_next)
|
||||
{
|
||||
for (frag = chain->frch_root; frag; frag = frag->fr_next)
|
||||
if (frag->fr_fix)
|
||||
return 1;
|
||||
if (obstack_next_free (&chain->frch_obstack)
|
||||
!= chain->frch_last->fr_literal)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
subsegs_print_statistics (FILE *file)
|
||||
{
|
||||
frchainS *frchp;
|
||||
asection *s;
|
||||
|
||||
fprintf (file, "frag chains:\n");
|
||||
for (s = stdoutput->sections; s; s = s->next)
|
||||
{
|
||||
segment_info_type *seginfo;
|
||||
|
||||
/* Skip gas-internal sections. */
|
||||
if (segment_name (s)[0] == '*')
|
||||
continue;
|
||||
|
||||
seginfo = seg_info (s);
|
||||
if (!seginfo)
|
||||
continue;
|
||||
|
||||
for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next)
|
||||
{
|
||||
int count = 0;
|
||||
fragS *fragp;
|
||||
|
||||
for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
|
||||
count++;
|
||||
|
||||
fprintf (file, "\n");
|
||||
fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
|
||||
segment_name (s), count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end of subsegs.c */
|
117
contrib/toolchain/binutils/gas/subsegs.h
Normal file
117
contrib/toolchain/binutils/gas/subsegs.h
Normal file
@ -0,0 +1,117 @@
|
||||
/* subsegs.h -> subsegs.c
|
||||
Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2003, 2005,
|
||||
2006, 2007, 2009 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/*
|
||||
* For every sub-segment the user mentions in the ASsembler program,
|
||||
* we make one struct frchain. Each sub-segment has exactly one struct frchain
|
||||
* and vice versa.
|
||||
*
|
||||
* Struct frchain's are forward chained (in ascending order of sub-segment
|
||||
* code number). The chain runs through frch_next of each subsegment.
|
||||
* This makes it hard to find a subsegment's frags
|
||||
* if programmer uses a lot of them. Most programs only use text0 and
|
||||
* data0, so they don't suffer. At least this way:
|
||||
* (1) There are no "arbitrary" restrictions on how many subsegments
|
||||
* can be programmed;
|
||||
* (2) Subsegments' frchain-s are (later) chained together in the order in
|
||||
* which they are emitted for object file viz text then data.
|
||||
*
|
||||
* From each struct frchain dangles a chain of struct frags. The frags
|
||||
* represent code fragments, for that sub-segment, forward chained.
|
||||
*/
|
||||
|
||||
#include "obstack.h"
|
||||
|
||||
struct frch_cfi_data;
|
||||
|
||||
struct frchain /* control building of a frag chain */
|
||||
{ /* FRCH = FRagment CHain control */
|
||||
struct frag *frch_root; /* 1st struct frag in chain, or NULL */
|
||||
struct frag *frch_last; /* last struct frag in chain, or NULL */
|
||||
struct frchain *frch_next; /* next in chain of struct frchain-s */
|
||||
subsegT frch_subseg; /* subsegment number of this chain */
|
||||
fixS *fix_root; /* Root of fixups for this subsegment. */
|
||||
fixS *fix_tail; /* Last fixup for this subsegment. */
|
||||
struct obstack frch_obstack; /* for objects in this frag chain */
|
||||
fragS *frch_frag_now; /* frag_now for this subsegment */
|
||||
struct frch_cfi_data *frch_cfi_data;
|
||||
};
|
||||
|
||||
typedef struct frchain frchainS;
|
||||
|
||||
/* Frchain we are assembling into now. That is, the current segment's
|
||||
frag chain, even if it contains no (complete) frags. */
|
||||
extern frchainS *frchain_now;
|
||||
|
||||
typedef struct segment_info_struct {
|
||||
frchainS *frchainP;
|
||||
unsigned int hadone : 1;
|
||||
|
||||
/* This field is set if this is a .bss section which does not really
|
||||
have any contents. Once upon a time a .bss section did not have
|
||||
any frags, but that is no longer true. This field prevent the
|
||||
SEC_HAS_CONTENTS flag from being set for the section even if
|
||||
there are frags. */
|
||||
unsigned int bss : 1;
|
||||
|
||||
int user_stuff;
|
||||
|
||||
/* Fixups for this segment. This is only valid after the frchains
|
||||
are run together. */
|
||||
fixS *fix_root;
|
||||
fixS *fix_tail;
|
||||
|
||||
symbolS *dot;
|
||||
|
||||
struct lineno_list *lineno_list_head;
|
||||
struct lineno_list *lineno_list_tail;
|
||||
|
||||
/* Which BFD section does this gas segment correspond to? */
|
||||
asection *bfd_section;
|
||||
|
||||
/* NULL, or pointer to the gas symbol that is the section symbol for
|
||||
this section. sym->bsym and bfd_section->symbol should be the same. */
|
||||
symbolS *sym;
|
||||
|
||||
union {
|
||||
/* Current size of section holding stabs strings. */
|
||||
unsigned long stab_string_size;
|
||||
/* Initial frag for ELF. */
|
||||
char *p;
|
||||
}
|
||||
stabu;
|
||||
|
||||
#ifdef NEED_LITERAL_POOL
|
||||
unsigned long literal_pool_size;
|
||||
#endif
|
||||
|
||||
#ifdef TC_SEGMENT_INFO_TYPE
|
||||
TC_SEGMENT_INFO_TYPE tc_segment_info_data;
|
||||
#endif
|
||||
} segment_info_type;
|
||||
|
||||
|
||||
#define seg_info(sec) \
|
||||
((segment_info_type *) bfd_get_section_userdata (stdoutput, sec))
|
||||
|
||||
extern symbolS *section_symbol (segT);
|
||||
|
||||
extern void subsegs_print_statistics (FILE *);
|
3252
contrib/toolchain/binutils/gas/symbols.c
Normal file
3252
contrib/toolchain/binutils/gas/symbols.c
Normal file
File diff suppressed because it is too large
Load Diff
216
contrib/toolchain/binutils/gas/symbols.h
Normal file
216
contrib/toolchain/binutils/gas/symbols.h
Normal file
@ -0,0 +1,216 @@
|
||||
/* symbols.h -
|
||||
Copyright 1987, 1990, 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
extern struct obstack notes; /* eg FixS live here. */
|
||||
|
||||
extern struct obstack cond_obstack; /* this is where we track .ifdef/.endif
|
||||
(if we do that at all). */
|
||||
|
||||
extern symbolS *symbol_rootP; /* all the symbol nodes */
|
||||
extern symbolS *symbol_lastP; /* last struct symbol we made, or NULL */
|
||||
|
||||
extern symbolS abs_symbol;
|
||||
extern symbolS dot_symbol;
|
||||
|
||||
extern int symbol_table_frozen;
|
||||
|
||||
/* This is non-zero if symbols are case sensitive, which is the
|
||||
default. */
|
||||
extern int symbols_case_sensitive;
|
||||
|
||||
char * symbol_relc_make_expr (expressionS *);
|
||||
char * symbol_relc_make_sym (symbolS *);
|
||||
char * symbol_relc_make_value (offsetT);
|
||||
char *decode_local_label_name (char *s);
|
||||
symbolS *symbol_find (const char *name);
|
||||
symbolS *symbol_find_noref (const char *name, int noref);
|
||||
symbolS *symbol_find_exact (const char *name);
|
||||
symbolS *symbol_find_exact_noref (const char *name, int noref);
|
||||
symbolS *symbol_find_or_make (const char *name);
|
||||
symbolS *symbol_make (const char *name);
|
||||
symbolS *symbol_new (const char *name, segT segment, valueT value,
|
||||
fragS * frag);
|
||||
symbolS *symbol_create (const char *name, segT segment, valueT value,
|
||||
fragS * frag);
|
||||
struct local_symbol *local_symbol_make (const char *name, segT section,
|
||||
valueT val, fragS *frag);
|
||||
symbolS *symbol_clone (symbolS *, int);
|
||||
#undef symbol_clone_if_forward_ref
|
||||
symbolS *symbol_clone_if_forward_ref (symbolS *, int);
|
||||
#define symbol_clone_if_forward_ref(s) symbol_clone_if_forward_ref (s, 0)
|
||||
symbolS *symbol_temp_new (segT, valueT, fragS *);
|
||||
symbolS *symbol_temp_new_now (void);
|
||||
symbolS *symbol_temp_make (void);
|
||||
|
||||
symbolS *colon (const char *sym_name);
|
||||
void local_colon (int n);
|
||||
void symbol_begin (void);
|
||||
void dot_symbol_init (void);
|
||||
void symbol_print_statistics (FILE *);
|
||||
void symbol_table_insert (symbolS * symbolP);
|
||||
valueT resolve_symbol_value (symbolS *);
|
||||
void resolve_local_symbol_values (void);
|
||||
int snapshot_symbol (symbolS **, valueT *, segT *, fragS **);
|
||||
|
||||
void print_symbol_value (symbolS *);
|
||||
void print_expr (expressionS *);
|
||||
void print_expr_1 (FILE *, expressionS *);
|
||||
void print_symbol_value_1 (FILE *, symbolS *);
|
||||
|
||||
int dollar_label_defined (long l);
|
||||
void dollar_label_clear (void);
|
||||
void define_dollar_label (long l);
|
||||
char *dollar_label_name (long l, int augend);
|
||||
|
||||
void fb_label_instance_inc (long label);
|
||||
char *fb_label_name (long n, long augend);
|
||||
|
||||
extern void copy_symbol_attributes (symbolS *, symbolS *);
|
||||
|
||||
/* Get and set the values of symbols. These used to be macros. */
|
||||
extern valueT S_GET_VALUE (symbolS *);
|
||||
extern void S_SET_VALUE (symbolS *, valueT);
|
||||
|
||||
extern int S_IS_FUNCTION (symbolS *);
|
||||
extern int S_IS_EXTERNAL (symbolS *);
|
||||
extern int S_IS_WEAK (symbolS *);
|
||||
extern int S_IS_WEAKREFR (symbolS *);
|
||||
extern int S_IS_WEAKREFD (symbolS *);
|
||||
extern int S_IS_COMMON (symbolS *);
|
||||
extern int S_IS_DEFINED (symbolS *);
|
||||
extern int S_FORCE_RELOC (symbolS *, int);
|
||||
extern int S_IS_DEBUG (symbolS *);
|
||||
extern int S_IS_LOCAL (symbolS *);
|
||||
extern int S_IS_STABD (symbolS *);
|
||||
extern int S_CAN_BE_REDEFINED (const symbolS *);
|
||||
extern int S_IS_VOLATILE (const symbolS *);
|
||||
extern int S_IS_FORWARD_REF (const symbolS *);
|
||||
extern const char *S_GET_NAME (symbolS *);
|
||||
extern segT S_GET_SEGMENT (symbolS *);
|
||||
extern void S_SET_SEGMENT (symbolS *, segT);
|
||||
extern void S_SET_EXTERNAL (symbolS *);
|
||||
extern void S_SET_NAME (symbolS *, const char *);
|
||||
extern void S_CLEAR_EXTERNAL (symbolS *);
|
||||
extern void S_SET_WEAK (symbolS *);
|
||||
extern void S_SET_WEAKREFR (symbolS *);
|
||||
extern void S_CLEAR_WEAKREFR (symbolS *);
|
||||
extern void S_SET_WEAKREFD (symbolS *);
|
||||
extern void S_CLEAR_WEAKREFD (symbolS *);
|
||||
extern void S_SET_THREAD_LOCAL (symbolS *);
|
||||
extern void S_SET_VOLATILE (symbolS *);
|
||||
extern void S_CLEAR_VOLATILE (symbolS *);
|
||||
extern void S_SET_FORWARD_REF (symbolS *);
|
||||
|
||||
#ifndef WORKING_DOT_WORD
|
||||
struct broken_word
|
||||
{
|
||||
/* Linked list -- one of these structures per ".word x-y+C"
|
||||
expression. */
|
||||
struct broken_word *next_broken_word;
|
||||
/* Segment and subsegment for broken word. */
|
||||
segT seg;
|
||||
subsegT subseg;
|
||||
/* Which frag is this broken word in? */
|
||||
fragS *frag;
|
||||
/* Where in the frag is it? */
|
||||
char *word_goes_here;
|
||||
/* Where to add the break. */
|
||||
fragS *dispfrag; /* where to add the break */
|
||||
/* Operands of expression. */
|
||||
symbolS *add;
|
||||
symbolS *sub;
|
||||
offsetT addnum;
|
||||
|
||||
int added; /* nasty thing happened yet? */
|
||||
/* 1: added and has a long-jump */
|
||||
/* 2: added but uses someone elses long-jump */
|
||||
|
||||
/* Pointer to broken_word with a similar long-jump. */
|
||||
struct broken_word *use_jump;
|
||||
};
|
||||
extern struct broken_word *broken_words;
|
||||
#endif /* ndef WORKING_DOT_WORD */
|
||||
|
||||
/*
|
||||
* Current means for getting from symbols to segments and vice verse.
|
||||
* This will change for infinite-segments support (e.g. COFF).
|
||||
*/
|
||||
extern const segT N_TYPE_seg[]; /* subseg.c */
|
||||
|
||||
#define SEGMENT_TO_SYMBOL_TYPE(seg) ( seg_N_TYPE [(int) (seg)] )
|
||||
extern const short seg_N_TYPE[];/* subseg.c */
|
||||
|
||||
#define N_REGISTER 30 /* Fake N_TYPE value for SEG_REGISTER */
|
||||
|
||||
void symbol_clear_list_pointers (symbolS * symbolP);
|
||||
|
||||
void symbol_insert (symbolS * addme, symbolS * target,
|
||||
symbolS ** rootP, symbolS ** lastP);
|
||||
void symbol_remove (symbolS * symbolP, symbolS ** rootP,
|
||||
symbolS ** lastP);
|
||||
|
||||
extern symbolS *symbol_previous (symbolS *);
|
||||
|
||||
void verify_symbol_chain (symbolS * rootP, symbolS * lastP);
|
||||
|
||||
void symbol_append (symbolS * addme, symbolS * target,
|
||||
symbolS ** rootP, symbolS ** lastP);
|
||||
|
||||
extern symbolS *symbol_next (symbolS *);
|
||||
|
||||
extern expressionS *symbol_get_value_expression (symbolS *);
|
||||
extern void symbol_set_value_expression (symbolS *, const expressionS *);
|
||||
extern offsetT *symbol_X_add_number (symbolS *);
|
||||
extern void symbol_set_value_now (symbolS *);
|
||||
extern void symbol_set_frag (symbolS *, fragS *);
|
||||
extern fragS *symbol_get_frag (symbolS *);
|
||||
extern void symbol_mark_used (symbolS *);
|
||||
extern void symbol_clear_used (symbolS *);
|
||||
extern int symbol_used_p (symbolS *);
|
||||
extern void symbol_mark_used_in_reloc (symbolS *);
|
||||
extern void symbol_clear_used_in_reloc (symbolS *);
|
||||
extern int symbol_used_in_reloc_p (symbolS *);
|
||||
extern void symbol_mark_mri_common (symbolS *);
|
||||
extern void symbol_clear_mri_common (symbolS *);
|
||||
extern int symbol_mri_common_p (symbolS *);
|
||||
extern void symbol_mark_written (symbolS *);
|
||||
extern void symbol_clear_written (symbolS *);
|
||||
extern int symbol_written_p (symbolS *);
|
||||
extern void symbol_mark_resolved (symbolS *);
|
||||
extern int symbol_resolved_p (symbolS *);
|
||||
extern int symbol_section_p (symbolS *);
|
||||
extern int symbol_equated_p (symbolS *);
|
||||
extern int symbol_equated_reloc_p (symbolS *);
|
||||
extern int symbol_constant_p (symbolS *);
|
||||
extern int symbol_shadow_p (symbolS *);
|
||||
extern asymbol *symbol_get_bfdsym (symbolS *);
|
||||
extern void symbol_set_bfdsym (symbolS *, asymbol *);
|
||||
extern int symbol_same_p (symbolS *, symbolS *);
|
||||
|
||||
#ifdef OBJ_SYMFIELD_TYPE
|
||||
OBJ_SYMFIELD_TYPE *symbol_get_obj (symbolS *);
|
||||
void symbol_set_obj (symbolS *, OBJ_SYMFIELD_TYPE *);
|
||||
#endif
|
||||
|
||||
#ifdef TC_SYMFIELD_TYPE
|
||||
TC_SYMFIELD_TYPE *symbol_get_tc (symbolS *);
|
||||
void symbol_set_tc (symbolS *, TC_SYMFIELD_TYPE *);
|
||||
#endif
|
1
contrib/toolchain/binutils/gas/targ-cpu.h
Normal file
1
contrib/toolchain/binutils/gas/targ-cpu.h
Normal file
@ -0,0 +1 @@
|
||||
#include "tc-i386.h"
|
1
contrib/toolchain/binutils/gas/targ-env.h
Normal file
1
contrib/toolchain/binutils/gas/targ-env.h
Normal file
@ -0,0 +1 @@
|
||||
#include "te-pe.h"
|
79
contrib/toolchain/binutils/gas/tc.h
Normal file
79
contrib/toolchain/binutils/gas/tc.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* tc.h - target cpu dependent
|
||||
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 2000, 2001, 2003,
|
||||
2004, 2005, 2006, 2007, 2008, 2009
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* In theory (mine, at least!) the machine dependent part of the assembler
|
||||
should only have to include one file. This one. -- JF */
|
||||
|
||||
extern const pseudo_typeS md_pseudo_table[];
|
||||
|
||||
char * md_atof (int, char *, int *);
|
||||
int md_parse_option (int, char *);
|
||||
void md_show_usage (FILE *);
|
||||
void md_assemble (char *);
|
||||
void md_begin (void);
|
||||
#ifndef md_number_to_chars
|
||||
void md_number_to_chars (char *, valueT, int);
|
||||
#endif
|
||||
void md_apply_fix (fixS *, valueT *, segT);
|
||||
|
||||
#ifndef WORKING_DOT_WORD
|
||||
extern int md_short_jump_size;
|
||||
extern int md_long_jump_size;
|
||||
#endif
|
||||
|
||||
#ifdef TE_PE
|
||||
/* The name of an external symbol which is
|
||||
used to make weak PE symbol names unique. */
|
||||
extern const char * an_external_name;
|
||||
#endif
|
||||
|
||||
#ifndef md_create_long_jump
|
||||
void md_create_long_jump (char *, addressT, addressT, fragS *, symbolS *);
|
||||
#endif
|
||||
#ifndef md_create_short_jump
|
||||
void md_create_short_jump (char *, addressT, addressT, fragS *, symbolS *);
|
||||
#endif
|
||||
#ifndef md_pcrel_from
|
||||
long md_pcrel_from (fixS *);
|
||||
#endif
|
||||
#ifndef md_operand
|
||||
void md_operand (expressionS *);
|
||||
#endif
|
||||
#ifndef md_estimate_size_before_relax
|
||||
int md_estimate_size_before_relax (fragS * fragP, segT);
|
||||
#endif
|
||||
#ifndef md_section_align
|
||||
valueT md_section_align (segT, valueT);
|
||||
#endif
|
||||
#ifndef md_undefined_symbol
|
||||
symbolS *md_undefined_symbol (char *);
|
||||
#endif
|
||||
|
||||
#ifndef md_convert_frag
|
||||
void md_convert_frag (bfd *, segT, fragS *);
|
||||
#endif
|
||||
#ifndef RELOC_EXPANSION_POSSIBLE
|
||||
extern arelent *tc_gen_reloc (asection *, fixS *);
|
||||
#else
|
||||
extern arelent **tc_gen_reloc (asection *, fixS *);
|
||||
#endif
|
2868
contrib/toolchain/binutils/gas/write.c
Normal file
2868
contrib/toolchain/binutils/gas/write.c
Normal file
File diff suppressed because it is too large
Load Diff
191
contrib/toolchain/binutils/gas/write.h
Normal file
191
contrib/toolchain/binutils/gas/write.h
Normal file
@ -0,0 +1,191 @@
|
||||
/* write.h
|
||||
Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
|
||||
2002, 2003, 2005, 2006, 2007
|
||||
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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef __write_h__
|
||||
#define __write_h__
|
||||
|
||||
/* This is the name of a fake symbol which will never appear in the
|
||||
assembler output. S_IS_LOCAL detects it because of the \001. */
|
||||
#ifndef FAKE_LABEL_NAME
|
||||
#define FAKE_LABEL_NAME "L0\001"
|
||||
#endif
|
||||
|
||||
#include "bit_fix.h"
|
||||
|
||||
/*
|
||||
* FixSs may be built up in any order.
|
||||
*/
|
||||
|
||||
struct fix
|
||||
{
|
||||
/* These small fields are grouped together for compactness of
|
||||
this structure, and efficiency of access on some architectures. */
|
||||
|
||||
/* Is this a pc-relative relocation? */
|
||||
unsigned fx_pcrel : 1;
|
||||
|
||||
/* Is this value an immediate displacement? */
|
||||
/* Only used on ns32k; merge it into TC_FIX_TYPE sometime. */
|
||||
unsigned fx_im_disp : 2;
|
||||
|
||||
/* Some bits for the CPU specific code. */
|
||||
unsigned fx_tcbit : 1;
|
||||
unsigned fx_tcbit2 : 1;
|
||||
|
||||
/* Has this relocation already been applied? */
|
||||
unsigned fx_done : 1;
|
||||
|
||||
/* Suppress overflow complaints on large addends. This is used
|
||||
in the PowerPC ELF config to allow large addends on the
|
||||
BFD_RELOC_{LO16,HI16,HI16_S} relocations.
|
||||
|
||||
@@ Can this be determined from BFD? */
|
||||
unsigned fx_no_overflow : 1;
|
||||
|
||||
/* The value is signed when checking for overflow. */
|
||||
unsigned fx_signed : 1;
|
||||
|
||||
/* pc-relative offset adjust (only used by some CPU specific code) */
|
||||
signed char fx_pcrel_adjust;
|
||||
|
||||
/* How many bytes are involved? */
|
||||
unsigned char fx_size;
|
||||
|
||||
/* Which frag does this fix apply to? */
|
||||
fragS *fx_frag;
|
||||
|
||||
/* Where is the first byte to fix up? */
|
||||
long fx_where;
|
||||
|
||||
/* NULL or Symbol whose value we add in. */
|
||||
symbolS *fx_addsy;
|
||||
|
||||
/* NULL or Symbol whose value we subtract. */
|
||||
symbolS *fx_subsy;
|
||||
|
||||
/* Absolute number we add in. */
|
||||
valueT fx_offset;
|
||||
|
||||
/* The value of dot when the fixup expression was parsed. */
|
||||
addressT fx_dot_value;
|
||||
|
||||
/* The frag fx_dot_value is based on. */
|
||||
fragS *fx_dot_frag;
|
||||
|
||||
/* Next fixS in linked list, or NULL. */
|
||||
struct fix *fx_next;
|
||||
|
||||
/* If NULL, no bitfix's to do. */
|
||||
/* Only i960-coff and ns32k use this, and i960-coff stores an
|
||||
integer. This can probably be folded into tc_fix_data, below.
|
||||
@@ Alpha also uses it, but only to disable certain relocation
|
||||
processing. */
|
||||
bit_fixS *fx_bit_fixP;
|
||||
|
||||
bfd_reloc_code_real_type fx_r_type;
|
||||
|
||||
/* This field is sort of misnamed. It appears to be a sort of random
|
||||
scratch field, for use by the back ends. The main gas code doesn't
|
||||
do anything but initialize it to zero. The use of it does need to
|
||||
be coordinated between the cpu and format files, though. E.g., some
|
||||
coff targets pass the `addend' field from the cpu file via this
|
||||
field. I don't know why the `fx_offset' field above can't be used
|
||||
for that; investigate later and document. KR */
|
||||
valueT fx_addnumber;
|
||||
|
||||
/* The location of the instruction which created the reloc, used
|
||||
in error messages. */
|
||||
char *fx_file;
|
||||
unsigned fx_line;
|
||||
|
||||
#ifdef USING_CGEN
|
||||
struct {
|
||||
/* CGEN_INSN entry for this instruction. */
|
||||
const struct cgen_insn *insn;
|
||||
/* Target specific data, usually reloc number. */
|
||||
int opinfo;
|
||||
/* Which ifield this fixup applies to. */
|
||||
struct cgen_maybe_multi_ifield * field;
|
||||
/* is this field is the MSB field in a set? */
|
||||
int msb_field_p;
|
||||
} fx_cgen;
|
||||
#endif
|
||||
|
||||
#ifdef TC_FIX_TYPE
|
||||
/* Location where a backend can attach additional data
|
||||
needed to perform fixups. */
|
||||
TC_FIX_TYPE tc_fix_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct fix fixS;
|
||||
|
||||
struct reloc_list
|
||||
{
|
||||
struct reloc_list *next;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
symbolS *offset_sym;
|
||||
reloc_howto_type *howto;
|
||||
symbolS *sym;
|
||||
bfd_vma addend;
|
||||
} a;
|
||||
struct
|
||||
{
|
||||
asection *sec;
|
||||
asymbol *s;
|
||||
arelent r;
|
||||
} b;
|
||||
} u;
|
||||
char *file;
|
||||
unsigned int line;
|
||||
};
|
||||
|
||||
extern int finalize_syms;
|
||||
extern symbolS *abs_section_sym;
|
||||
extern addressT dot_value;
|
||||
extern fragS *dot_frag;
|
||||
extern struct reloc_list* reloc_list;
|
||||
|
||||
extern void append (char **charPP, char *fromP, unsigned long length);
|
||||
extern void record_alignment (segT seg, int align);
|
||||
extern int get_recorded_alignment (segT seg);
|
||||
extern void subsegs_finish (void);
|
||||
extern void write_object_file (void);
|
||||
extern long relax_frag (segT, fragS *, long);
|
||||
extern int relax_segment (struct frag *, segT, int);
|
||||
extern void number_to_chars_littleendian (char *, valueT, int);
|
||||
extern void number_to_chars_bigendian (char *, valueT, int);
|
||||
extern fixS *fix_new
|
||||
(fragS * frag, int where, int size, symbolS * add_symbol,
|
||||
offsetT offset, int pcrel, bfd_reloc_code_real_type r_type);
|
||||
extern fixS *fix_at_start
|
||||
(fragS * frag, int size, symbolS * add_symbol,
|
||||
offsetT offset, int pcrel, bfd_reloc_code_real_type r_type);
|
||||
extern fixS *fix_new_exp
|
||||
(fragS * frag, int where, int size, expressionS *exp, int pcrel,
|
||||
bfd_reloc_code_real_type r_type);
|
||||
extern void write_print_statistics (FILE *);
|
||||
|
||||
#endif /* __write_h__ */
|
Loading…
Reference in New Issue
Block a user