aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@cygnus>1996-01-30 18:12:41 +0000
committerKen Raeburn <raeburn@cygnus>1996-01-30 18:12:41 +0000
commit0e6f2f82d2ff41c6cd97b811c586842ac3945a28 (patch)
treed4230949c93a2ec1e2eb07bc6456723f1dd0833e /gas
parenta8763553e45e8340a9067f77e32c620ca0c4baca (diff)
downloadgdb-0e6f2f82d2ff41c6cd97b811c586842ac3945a28.zip
gdb-0e6f2f82d2ff41c6cd97b811c586842ac3945a28.tar.gz
gdb-0e6f2f82d2ff41c6cd97b811c586842ac3945a28.tar.bz2
* config/tc-i960.c (parse_memop): In MRI mode, don't use implicit scaling of
index. * expr.c (operand): Accept 0x hex constants in MRI mode if not on m68k. (PR 8836)
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog8
-rw-r--r--gas/config/tc-i960.c1621
2 files changed, 818 insertions, 811 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 3a28f27..a06347b 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,11 @@
+Tue Jan 30 12:35:24 1996 Ken Raeburn <raeburn@cygnus.com>
+
+ * config/tc-i960.c (parse_memop): In MRI mode, don't use implicit
+ scaling of index.
+
+ * expr.c (operand): Accept 0x hex constants in MRI mode if not on
+ m68k.
+
Mon Jan 29 12:21:30 1996 Ian Lance Taylor <ian@cygnus.com>
* config/obj-elf.c (obj_elf_type): Set BSF_OBJECT flag for a type
diff --git a/gas/config/tc-i960.c b/gas/config/tc-i960.c
index 1cdfa97..45154cb 100644
--- a/gas/config/tc-i960.c
+++ b/gas/config/tc-i960.c
@@ -1,3 +1,4 @@
+/* to sanitize : grep -v XL */
/* tc-i960.c - All the i80960-specific stuff
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
@@ -15,67 +16,50 @@
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* See comment on md_parse_option for 80960-specific invocation options. */
-/******************************************************************************
- * i80690 NOTE!!!:
- * Header, symbol, and relocation info will be used on the host machine
- * only -- only executable code is actually downloaded to the i80960.
- * Therefore, leave all such information in host byte order.
- *
- * (That's a slight lie -- we DO download some header information, but
- * the downloader converts the file format and corrects the byte-ordering
- * of the relevant fields while doing so.)
- *
- * ==> THIS IS NO LONGER TRUE USING BFD. WE CAN GENERATE ANY BYTE ORDER
- * FOR THE HEADER, AND READ ANY BYTE ORDER. PREFERENCE WOULD BE TO
- * USE LITTLE-ENDIAN BYTE ORDER THROUGHOUT, REGARDLESS OF HOST. <==
- *
- ***************************************************************************** */
-
/* There are 4 different lengths of (potentially) symbol-based displacements
- * in the 80960 instruction set, each of which could require address fix-ups
- * and (in the case of external symbols) emission of relocation directives:
- *
- * 32-bit (MEMB)
- * This is a standard length for the base assembler and requires no
- * special action.
- *
- * 13-bit (COBR)
- * This is a non-standard length, but the base assembler has a hook for
- * bit field address fixups: the fixS structure can point to a descriptor
- * of the field, in which case our md_number_to_field() routine gets called
- * to process it.
- *
- * I made the hook a little cleaner by having fix_new() (in the base
- * assembler) return a pointer to the fixS in question. And I made it a
- * little simpler by storing the field size (in this case 13) instead of
- * of a pointer to another structure: 80960 displacements are ALWAYS
- * stored in the low-order bits of a 4-byte word.
- *
- * Since the target of a COBR cannot be external, no relocation directives
- * for this size displacement have to be generated. But the base assembler
- * had to be modified to issue error messages if the symbol did turn out
- * to be external.
- *
- * 24-bit (CTRL)
- * Fixups are handled as for the 13-bit case (except that 24 is stored
- * in the fixS).
- *
- * The relocation directive generated is the same as that for the 32-bit
- * displacement, except that it's PC-relative (the 32-bit displacement
- * never is). The i80960 version of the linker needs a mod to
- * distinguish and handle the 24-bit case.
- *
- * 12-bit (MEMA)
- * MEMA formats are always promoted to MEMB (32-bit) if the displacement
- * is based on a symbol, because it could be relocated at link time.
- * The only time we use the 12-bit format is if an absolute value of
- * less than 4096 is specified, in which case we need neither a fixup nor
- * a relocation directive.
- */
+ in the 80960 instruction set, each of which could require address fix-ups
+ and (in the case of external symbols) emission of relocation directives:
+
+ 32-bit (MEMB)
+ This is a standard length for the base assembler and requires no
+ special action.
+
+ 13-bit (COBR)
+ This is a non-standard length, but the base assembler has a
+ hook for bit field address fixups: the fixS structure can
+ point to a descriptor of the field, in which case our
+ md_number_to_field() routine gets called to process it.
+
+ I made the hook a little cleaner by having fix_new() (in the base
+ assembler) return a pointer to the fixS in question. And I made it a
+ little simpler by storing the field size (in this case 13) instead of
+ of a pointer to another structure: 80960 displacements are ALWAYS
+ stored in the low-order bits of a 4-byte word.
+
+ Since the target of a COBR cannot be external, no relocation
+ directives for this size displacement have to be generated.
+ But the base assembler had to be modified to issue error
+ messages if the symbol did turn out to be external.
+
+ 24-bit (CTRL)
+ Fixups are handled as for the 13-bit case (except that 24 is stored
+ in the fixS).
+
+ The relocation directive generated is the same as that for the 32-bit
+ displacement, except that it's PC-relative (the 32-bit displacement
+ never is). The i80960 version of the linker needs a mod to
+ distinguish and handle the 24-bit case.
+
+ 12-bit (MEMA)
+ MEMA formats are always promoted to MEMB (32-bit) if the displacement
+ is based on a symbol, because it could be relocated at link time.
+ The only time we use the 12-bit format is if an absolute value of
+ less than 4096 is specified, in which case we need neither a fixup nor
+ a relocation directive. */
#include <stdio.h>
#include <ctype.h>
@@ -86,11 +70,41 @@
#include "opcode/i960.h"
-extern char *strchr ();
+#if defined (OBJ_AOUT) || defined (OBJ_BOUT)
+
+#define TC_S_IS_SYSPROC(s) ((1<=S_GET_OTHER(s)) && (S_GET_OTHER(s)<=32))
+#define TC_S_IS_BALNAME(s) (S_GET_OTHER(s) == N_BALNAME)
+#define TC_S_IS_CALLNAME(s) (S_GET_OTHER(s) == N_CALLNAME)
+#define TC_S_IS_BADPROC(s) ((S_GET_OTHER(s) != 0) && !TC_S_IS_CALLNAME(s) && !TC_S_IS_BALNAME(s) && !TC_S_IS_SYSPROC(s))
+
+#define TC_S_SET_SYSPROC(s, p) (S_SET_OTHER((s), (p)+1))
+#define TC_S_GET_SYSPROC(s) (S_GET_OTHER(s)-1)
+
+#define TC_S_FORCE_TO_BALNAME(s) (S_SET_OTHER((s), N_BALNAME))
+#define TC_S_FORCE_TO_CALLNAME(s) (S_SET_OTHER((s), N_CALLNAME))
+#define TC_S_FORCE_TO_SYSPROC(s) {;}
+
+#else /* ! OBJ_A/BOUT */
+#ifdef OBJ_COFF
+
+#define TC_S_IS_SYSPROC(s) (S_GET_STORAGE_CLASS(s) == C_SCALL)
+#define TC_S_IS_BALNAME(s) (SF_GET_BALNAME(s))
+#define TC_S_IS_CALLNAME(s) (SF_GET_CALLNAME(s))
+#define TC_S_IS_BADPROC(s) (TC_S_IS_SYSPROC(s) && TC_S_GET_SYSPROC(s) < 0 && 31 < TC_S_GET_SYSPROC(s))
+
+#define TC_S_SET_SYSPROC(s, p) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx = (p))
+#define TC_S_GET_SYSPROC(s) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx)
+
+#define TC_S_FORCE_TO_BALNAME(s) (SF_SET_BALNAME(s))
+#define TC_S_FORCE_TO_CALLNAME(s) (SF_SET_CALLNAME(s))
+#define TC_S_FORCE_TO_SYSPROC(s) (S_SET_STORAGE_CLASS((s), C_SCALL))
+
+#else /* ! OBJ_COFF */
+you lose;
+#endif /* ! OBJ_COFF */
+#endif /* ! OBJ_A/BOUT */
extern char *input_line_pointer;
-extern struct hash_control *po_hash;
-extern char *next_object_file_charP;
#if !defined (BFD_ASSEMBLER) && !defined (BFD)
#ifdef OBJ_COFF
@@ -100,9 +114,7 @@ const int md_reloc_size = sizeof (struct relocation_info);
#endif /* OBJ_COFF */
#endif
-/***************************
- * Local i80960 routines *
- ************************** */
+/* Local i80960 routines. */
static void brcnt_emit (); /* Emit branch-prediction instrumentation code */
static char *brlab_next (); /* Return next branch local label */
@@ -131,24 +143,23 @@ static int shift_ok (); /* Will a 'shlo' substiture for a 'ldconst'? */
static void syntax (); /* Give syntax error */
static int targ_has_sfr (); /* Target chip supports spec-func register? */
static int targ_has_iclass (); /* Target chip supports instruction set? */
-/* static void unlink_sym(); *//* Remove a symbol from the symbol list */
/* See md_parse_option() for meanings of these options */
static char norelax; /* True if -norelax switch seen */
-static char instrument_branches;/* True if -b switch seen */
+static char instrument_branches; /* True if -b switch seen */
/* Characters that always start a comment.
- * If the pre-processor is disabled, these aren't very useful.
+ If the pre-processor is disabled, these aren't very useful.
*/
const char comment_chars[] = "#";
/* Characters that only start a comment at the beginning of
- * a line. If the line seems to have the form '# 123 filename'
- * .line and .file directives will appear in the pre-processed output.
- *
- * Note that input_file.c hand checks for '#' at the beginning of the
- * first line of the input file. This is because the compiler outputs
- * #NO_APP at the beginning of its output.
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output.
+
+ Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output.
*/
/* Also note that comments started like this one will always work. */
@@ -161,38 +172,38 @@ const char line_separator_chars[1];
const char EXP_CHARS[] = "eE";
/* Chars that mean this number is a floating point constant,
- * as in 0f12.456 or 0d1.2345e12
+ as in 0f12.456 or 0d1.2345e12
*/
const char FLT_CHARS[] = "fFdDtT";
/* Table used by base assembler to relax addresses based on varying length
- * instructions. The fields are:
- * 1) most positive reach of this state,
- * 2) most negative reach of this state,
- * 3) how many bytes this mode will add to the size of the current frag
- * 4) which index into the table to try if we can't fit into this one.
- *
- * For i80960, the only application is the (de-)optimization of cobr
- * instructions into separate compare and branch instructions when a 13-bit
- * displacement won't hack it.
+ instructions. The fields are:
+ 1) most positive reach of this state,
+ 2) most negative reach of this state,
+ 3) how many bytes this mode will add to the size of the current frag
+ 4) which index into the table to try if we can't fit into this one.
+
+ For i80960, the only application is the (de-)optimization of cobr
+ instructions into separate compare and branch instructions when a 13-bit
+ displacement won't hack it.
*/
-const relax_typeS
- md_relax_table[] =
+const relax_typeS md_relax_table[] =
{
{0, 0, 0, 0}, /* State 0 => no more relaxation possible */
{4088, -4096, 0, 2}, /* State 1: conditional branch (cobr) */
{0x800000 - 8, -0x800000, 4, 0}, /* State 2: compare (reg) & branch (ctrl) */
};
+static void s_endian PARAMS ((int));
/* These are the machine dependent pseudo-ops.
- *
- * This table describes all the machine specific pseudo-ops the assembler
- * has to support. The fields are:
- * pseudo-op name without dot
- * function to call to execute this pseudo-op
- * integer arg to pass to the function
+
+ This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ integer arg to pass to the function
*/
#define S_LEAFPROC 1
#define S_SYSPROC 2
@@ -200,6 +211,7 @@ const relax_typeS
const pseudo_typeS md_pseudo_table[] =
{
{"bss", s_lcomm, 1},
+ {"endian", s_endian, 0},
{"extended", float_cons, 't'},
{"leafproc", parse_po, S_LEAFPROC},
{"sysproc", parse_po, S_SYSPROC},
@@ -276,13 +288,13 @@ struct regop
};
-/* Number and assembler mnemonic for all registers that can appear in operands */
-static struct
+/* Number and assembler mnemonic for all registers that can appear in
+ operands. */
+static const struct
{
char *reg_name;
int reg_num;
}
-
regnames[] =
{
{ "pfp", 0 },
@@ -355,9 +367,8 @@ regnames[] =
{ "sf30", 62 },
{ "sf31", 63 },
- /* Numbers for floating point registers are for assembler internal use
- * only: they are scaled back to [0-3] for binary output.
- */
+ /* Numbers for floating point registers are for assembler internal
+ use only: they are scaled back to [0-3] for binary output. */
#define FP0 64
{ "fp0", 64 },
@@ -372,15 +383,13 @@ regnames[] =
#define IS_SF_REG(n) ((SF0 <= (n)) && ((n) < FP0))
#define IS_FP_REG(n) ((n) >= FP0)
-/* Number and assembler mnemonic for all registers that can appear as 'abase'
- * (indirect addressing) registers.
- */
-static struct
+/* Number and assembler mnemonic for all registers that can appear as
+ 'abase' (indirect addressing) registers. */
+static const struct
{
char *areg_name;
int areg_num;
}
-
aregs[] =
{
{ "(pfp)", 0 },
@@ -437,76 +446,72 @@ static struct hash_control *areg_hash; /* Abase register hash table */
#define ARCH_KB 2
#define ARCH_MC 3
#define ARCH_CA 4
+#define ARCH_XL 5
int architecture = ARCH_ANY; /* Architecture requested on invocation line */
int iclasses_seen; /* OR of instruction classes (I_* constants)
- * for which we've actually assembled
- * instructions.
+ * for which we've actually assembled
+ * instructions.
*/
/* BRANCH-PREDICTION INSTRUMENTATION
- *
- * The following supports generation of branch-prediction instrumentation
- * (turned on by -b switch). The instrumentation collects counts
- * of branches taken/not-taken for later input to a utility that will
- * set the branch prediction bits of the instructions in accordance with
- * the behavior observed. (Note that the KX series does not have
- * brach-prediction.)
- *
- * The instrumentation consists of:
- *
- * (1) before and after each conditional branch, a call to an external
- * routine that increments and steps over an inline counter. The
- * counter itself, initialized to 0, immediately follows the call
- * instruction. For each branch, the counter following the branch
- * is the number of times the branch was not taken, and the difference
- * between the counters is the number of times it was taken. An
- * example of an instrumented conditional branch:
- *
- * call BR_CNT_FUNC
- * .word 0
- * LBRANCH23: be label
- * call BR_CNT_FUNC
- * .word 0
- *
- * (2) a table of pointers to the instrumented branches, so that an
- * external postprocessing routine can locate all of the counters.
- * the table begins with a 2-word header: a pointer to the next in
- * a linked list of such tables (initialized to 0); and a count
- * of the number of entries in the table (exclusive of the header.
- *
- * Note that input source code is expected to already contain calls
- * an external routine that will link the branch local table into a
- * list of such tables.
+
+ The following supports generation of branch-prediction instrumentation
+ (turned on by -b switch). The instrumentation collects counts
+ of branches taken/not-taken for later input to a utility that will
+ set the branch prediction bits of the instructions in accordance with
+ the behavior observed. (Note that the KX series does not have
+ brach-prediction.)
+
+ The instrumentation consists of:
+
+ (1) before and after each conditional branch, a call to an external
+ routine that increments and steps over an inline counter. The
+ counter itself, initialized to 0, immediately follows the call
+ instruction. For each branch, the counter following the branch
+ is the number of times the branch was not taken, and the difference
+ between the counters is the number of times it was taken. An
+ example of an instrumented conditional branch:
+
+ call BR_CNT_FUNC
+ .word 0
+ LBRANCH23: be label
+ call BR_CNT_FUNC
+ .word 0
+
+ (2) a table of pointers to the instrumented branches, so that an
+ external postprocessing routine can locate all of the counters.
+ the table begins with a 2-word header: a pointer to the next in
+ a linked list of such tables (initialized to 0); and a count
+ of the number of entries in the table (exclusive of the header.
+
+ Note that input source code is expected to already contain calls
+ an external routine that will link the branch local table into a
+ list of such tables.
*/
-static int br_cnt; /* Number of branches instrumented so far.
- * Also used to generate unique local labels
- * for each instrumented branch
- */
+/* Number of branches instrumented so far. Also used to generate
+ unique local labels for each instrumented branch. */
+static int br_cnt;
#define BR_LABEL_BASE "LBRANCH"
-/* Basename of local labels on instrumented
- * branches, to avoid conflict with compiler-
- * generated local labels.
- */
+/* Basename of local labels on instrumented branches, to avoid
+ conflict with compiler- generated local labels. */
#define BR_CNT_FUNC "__inc_branch"
-/* Name of the external routine that will
- * increment (and step over) an inline counter.
- */
+/* Name of the external routine that will increment (and step over) an
+ inline counter. */
#define BR_TAB_NAME "__BRANCH_TABLE__"
-/* Name of the table of pointers to branches.
- * A local (i.e., non-external) symbol.
- */
+/* Name of the table of pointers to branches. A local (i.e.,
+ non-external) symbol. */
/*****************************************************************************
- * md_begin: One-time initialization.
- *
- * Set up hash tables.
- *
- **************************************************************************** */
+ md_begin: One-time initialization.
+
+ Set up hash tables.
+
+ *************************************************************************** */
void
md_begin ()
{
@@ -527,48 +532,43 @@ md_begin ()
for (i = 0; regnames[i].reg_name && !retval; i++)
retval = hash_insert (reg_hash, regnames[i].reg_name,
- &regnames[i].reg_num);
+ (char *) &regnames[i].reg_num);
for (i = 0; aregs[i].areg_name && !retval; i++)
retval = hash_insert (areg_hash, aregs[i].areg_name,
- &aregs[i].areg_num);
+ (char *) &aregs[i].areg_num);
if (retval)
as_fatal ("Hashing returned \"%s\".", retval);
}
/*****************************************************************************
- * md_assemble: Assemble an instruction
- *
- * Assumptions about the passed-in text:
- * - all comments, labels removed
- * - text is an instruction
- * - all white space compressed to single blanks
- * - all character constants have been replaced with decimal
- *
- **************************************************************************** */
+ md_assemble: Assemble an instruction
+
+ Assumptions about the passed-in text:
+ - all comments, labels removed
+ - text is an instruction
+ - all white space compressed to single blanks
+ - all character constants have been replaced with decimal
+
+ *************************************************************************** */
void
md_assemble (textP)
char *textP; /* Source text of instruction */
{
- /* Parsed instruction text, containing NO whitespace:
- * arg[0]->opcode mnemonic
- * arg[1-3]->operands, with char constants
- * replaced by decimal numbers
- */
+ /* Parsed instruction text, containing NO whitespace: arg[0]->opcode
+ mnemonic arg[1-3]->operands, with char constants replaced by
+ decimal numbers. */
char *args[4];
int n_ops; /* Number of instruction operands */
/* Pointer to instruction description */
struct i960_opcode *oP;
- /* TRUE iff opcode mnemonic included branch-prediction
- * suffix (".f" or ".t")
- */
+ /* TRUE iff opcode mnemonic included branch-prediction suffix (".f"
+ or ".t"). */
int branch_predict;
- /* Setting of branch-prediction bit(s) to be OR'd
- * into instruction opcode of CTRL/COBR format
- * instructions.
- */
+ /* Setting of branch-prediction bit(s) to be OR'd into instruction
+ opcode of CTRL/COBR format instructions. */
long bp_bits;
int n; /* Offset of last character in opcode mnemonic */
@@ -603,18 +603,16 @@ md_assemble (textP)
if (args[0][n - 1] == '.' && (args[0][n] == 't' || args[0][n] == 'f'))
{
/* We could check here to see if the target architecture
- * supports branch prediction, but why bother? The bit
- * will just be ignored by processors that don't use it.
- */
+ supports branch prediction, but why bother? The bit will
+ just be ignored by processors that don't use it. */
branch_predict = 1;
bp_bits = (args[0][n] == 't') ? BP_TAKEN : BP_NOT_TAKEN;
args[0][n - 1] = '\0'; /* Strip suffix from opcode mnemonic */
}
/* Look up opcode mnemonic in table and check number of operands.
- * Check that opcode is legal for the target architecture.
- * If all looks good, assemble instruction.
- */
+ Check that opcode is legal for the target architecture. If all
+ looks good, assemble instruction. */
oP = (struct i960_opcode *) hash_find (op_hash, args[0]);
if (!oP || !targ_has_iclass (oP->iclass))
{
@@ -689,9 +687,9 @@ md_assemble (textP)
} /* md_assemble() */
/*****************************************************************************
- * md_number_to_chars: convert a number to target byte order
- *
- **************************************************************************** */
+ md_number_to_chars: convert a number to target byte order
+
+ *************************************************************************** */
void
md_number_to_chars (buf, value, n)
char *buf;
@@ -702,9 +700,9 @@ md_number_to_chars (buf, value, n)
}
/*****************************************************************************
- * md_chars_to_number: convert from target byte order to host byte order.
- *
- **************************************************************************** */
+ md_chars_to_number: convert from target byte order to host byte order.
+
+ *************************************************************************** */
int
md_chars_to_number (val, n)
unsigned char *val; /* Value in target byte order */
@@ -725,17 +723,17 @@ md_chars_to_number (val, n)
#define LNUM_SIZE sizeof(LITTLENUM_TYPE)
/*****************************************************************************
- * md_atof: convert ascii to floating point
- *
- * Turn a string at input_line_pointer into a floating point constant of type
- * 'type', and store the appropriate bytes at *litP. The number of LITTLENUMS
- * emitted is returned at 'sizeP'. An error message is returned, or a pointer
- * to an empty message if OK.
- *
- * Note we call the i386 floating point routine, rather than complicating
- * things with more files or symbolic links.
- *
- **************************************************************************** */
+ md_atof: convert ascii to floating point
+
+ Turn a string at input_line_pointer into a floating point constant of type
+ 'type', and store the appropriate bytes at *litP. The number of LITTLENUMS
+ emitted is returned at 'sizeP'. An error message is returned, or a pointer
+ to an empty message if OK.
+
+ Note we call the i386 floating point routine, rather than complicating
+ things with more files or symbolic links.
+
+ *************************************************************************** */
char *
md_atof (type, litP, sizeP)
int type;
@@ -795,9 +793,9 @@ md_atof (type, litP, sizeP)
/*****************************************************************************
- * md_number_to_imm
- *
- **************************************************************************** */
+ md_number_to_imm
+
+ *************************************************************************** */
void
md_number_to_imm (buf, val, n)
char *buf;
@@ -809,9 +807,9 @@ md_number_to_imm (buf, val, n)
/*****************************************************************************
- * md_number_to_disp
- *
- **************************************************************************** */
+ md_number_to_disp
+
+ *************************************************************************** */
void
md_number_to_disp (buf, val, n)
char *buf;
@@ -822,12 +820,12 @@ md_number_to_disp (buf, val, n)
}
/*****************************************************************************
- * md_number_to_field:
- *
- * Stick a value (an address fixup) into a bit field of
- * previously-generated instruction.
- *
- **************************************************************************** */
+ md_number_to_field:
+
+ Stick a value (an address fixup) into a bit field of
+ previously-generated instruction.
+
+ *************************************************************************** */
void
md_number_to_field (instrP, val, bfixP)
char *instrP; /* Pointer to instruction to be fixed */
@@ -838,13 +836,11 @@ md_number_to_field (instrP, val, bfixP)
long instr; /* 32-bit instruction to be fixed-up */
long sign; /* 0 or -1, according to sign bit of 'val' */
- /* Convert instruction back to host byte order
- */
+ /* Convert instruction back to host byte order. */
instr = md_chars_to_number (instrP, 4);
- /* Surprise! -- we stored the number of bits
- * to be modified rather than a pointer to a structure.
- */
+ /* Surprise! -- we stored the number of bits to be modified rather
+ than a pointer to a structure. */
numbits = (int) bfixP;
if (numbits == 1)
{
@@ -854,9 +850,8 @@ md_number_to_field (instrP, val, bfixP)
know ((numbits == 13) || (numbits == 24));
- /* Propagate sign bit of 'val' for the given number of bits.
- * Result should be all 0 or all 1
- */
+ /* Propagate sign bit of 'val' for the given number of bits. Result
+ should be all 0 or all 1. */
sign = val >> ((int) numbits - 1);
if (((val < 0) && (sign != -1))
|| ((val > 0) && (sign != 0)))
@@ -867,92 +862,96 @@ md_number_to_field (instrP, val, bfixP)
else
{
/* Put bit field into instruction and write back in target
- * byte order.
- */
+ * byte order.
+ */
val &= ~(-1 << (int) numbits); /* Clear unused sign bits */
instr |= val;
md_number_to_chars (instrP, instr, 4);
}
} /* md_number_to_field() */
-
+
/*****************************************************************************
- * md_parse_option
- * Invocation line includes a switch not recognized by the base assembler.
- * See if it's a processor-specific option. For the 960, these are:
- *
- * -norelax:
- * Conditional branch instructions that require displacements
- * greater than 13 bits (or that have external targets) should
- * generate errors. The default is to replace each such
- * instruction with the corresponding compare (or chkbit) and
- * branch instructions. Note that the Intel "j" cobr directives
- * are ALWAYS "de-optimized" in this way when necessary,
- * regardless of the setting of this option.
- *
- * -b:
- * Add code to collect information about branches taken, for
- * later optimization of branch prediction bits by a separate
- * tool. COBR and CNTL format instructions have branch
- * prediction bits (in the CX architecture); if "BR" represents
- * an instruction in one of these classes, the following rep-
- * resents the code generated by the assembler:
- *
- * call <increment routine>
- * .word 0 # pre-counter
- * Label: BR
- * call <increment routine>
- * .word 0 # post-counter
- *
- * A table of all such "Labels" is also generated.
- *
- *
- * -AKA, -AKB, -AKC, -ASA, -ASB, -AMC, -ACA:
- * Select the 80960 architecture. Instructions or features not
- * supported by the selected architecture cause fatal errors.
- * The default is to generate code for any instruction or feature
- * that is supported by SOME version of the 960 (even if this
- * means mixing architectures!).
- *
- *****************************************************************************/
+ md_parse_option
+ Invocation line includes a switch not recognized by the base assembler.
+ See if it's a processor-specific option. For the 960, these are:
+
+ -norelax:
+ Conditional branch instructions that require displacements
+ greater than 13 bits (or that have external targets) should
+ generate errors. The default is to replace each such
+ instruction with the corresponding compare (or chkbit) and
+ branch instructions. Note that the Intel "j" cobr directives
+ are ALWAYS "de-optimized" in this way when necessary,
+ regardless of the setting of this option.
+
+ -b:
+ Add code to collect information about branches taken, for
+ later optimization of branch prediction bits by a separate
+ tool. COBR and CNTL format instructions have branch
+ prediction bits (in the CX architecture); if "BR" represents
+ an instruction in one of these classes, the following rep-
+ resents the code generated by the assembler:
+
+ call <increment routine>
+ .word 0 # pre-counter
+ Label: BR
+ call <increment routine>
+ .word 0 # post-counter
+
+ A table of all such "Labels" is also generated.
+
+
+ -AKA, -AKB, -AKC, -ASA, -ASB, -AMC, -ACA:
+ Select the 80960 architecture. Instructions or features not
+ supported by the selected architecture cause fatal errors.
+ The default is to generate code for any instruction or feature
+ that is supported by SOME version of the 960 (even if this
+ means mixing architectures!).
+
+ ****************************************************************************/
CONST char *md_shortopts = "A:b";
-struct option md_longopts[] = {
+struct option md_longopts[] =
+{
#define OPTION_LINKRELAX (OPTION_MD_BASE)
{"linkrelax", no_argument, NULL, OPTION_LINKRELAX},
+ {"link-relax", no_argument, NULL, OPTION_LINKRELAX},
#define OPTION_NORELAX (OPTION_MD_BASE + 1)
{"norelax", no_argument, NULL, OPTION_NORELAX},
+ {"no-relax", no_argument, NULL, OPTION_NORELAX},
{NULL, no_argument, NULL, 0}
};
-size_t md_longopts_size = sizeof(md_longopts);
+size_t md_longopts_size = sizeof (md_longopts);
+
+struct tabentry
+ {
+ char *flag;
+ int arch;
+ };
+static const struct tabentry arch_tab[] =
+{
+ {"KA", ARCH_KA},
+ {"KB", ARCH_KB},
+ {"SA", ARCH_KA}, /* Synonym for KA */
+ {"SB", ARCH_KB}, /* Synonym for KB */
+ {"KC", ARCH_MC}, /* Synonym for MC */
+ {"MC", ARCH_MC},
+ {"CA", ARCH_CA},
+ {"XL", ARCH_XL},
+ {NULL, 0}
+};
int
md_parse_option (c, arg)
int c;
char *arg;
{
- struct tabentry
- {
- char *flag;
- int arch;
- };
- static struct tabentry arch_tab[] =
- {
- { "KA", ARCH_KA },
- { "KB", ARCH_KB },
- { "SA", ARCH_KA }, /* Synonym for KA */
- { "SB", ARCH_KB }, /* Synonym for KB */
- { "KC", ARCH_MC }, /* Synonym for MC */
- { "MC", ARCH_MC },
- { "CA", ARCH_CA },
- { NULL, 0 }
- };
-
switch (c)
{
case OPTION_LINKRELAX:
linkrelax = 1;
- flagseen['L'] = 1;
+ flag_keep_locals = 1;
break;
case OPTION_NORELAX:
@@ -965,16 +964,12 @@ md_parse_option (c, arg)
case 'A':
{
- struct tabentry *tp;
+ const struct tabentry *tp;
char *p = arg;
for (tp = arch_tab; tp->flag != NULL; tp++)
- {
- if (!strcmp (p, tp->flag))
- {
- break;
- }
- }
+ if (!strcmp (p, tp->flag))
+ break;
if (tp->flag == NULL)
{
@@ -982,9 +977,7 @@ md_parse_option (c, arg)
return 0;
}
else
- {
- architecture = tp->arch;
- }
+ architecture = tp->arch;
}
break;
@@ -999,33 +992,38 @@ void
md_show_usage (stream)
FILE *stream;
{
- fprintf(stream, "\
-I960 options:\n\
--ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC\n\
+ int i;
+ fprintf (stream, "I960 options:\n");
+ for (i = 0; arch_tab[i].flag; i++)
+ fprintf (stream, "%s-A%s", i ? " | " : "", arch_tab[i].flag);
+ fprintf (stream, "\n\
specify variant of 960 architecture\n\
-b add code to collect statistics about branches taken\n\
--linkrelax make relocatable instructions undefined (?)\n\
--norelax don't alter compare-and-branch instructions for\n\
+-link-relax preserve individual alignment directives so linker\n\
+ can do relaxing (b.out format only)\n\
+-no-relax don't alter compare-and-branch instructions for\n\
long displacements\n");
}
+#ifndef BFD_ASSEMBLER
/*****************************************************************************
- * md_convert_frag:
- * Called by base assembler after address relaxation is finished: modify
- * variable fragments according to how much relaxation was done.
- *
- * If the fragment substate is still 1, a 13-bit displacement was enough
- * to reach the symbol in question. Set up an address fixup, but otherwise
- * leave the cobr instruction alone.
- *
- * If the fragment substate is 2, a 13-bit displacement was not enough.
- * Replace the cobr with a two instructions (a compare and a branch).
- *
- **************************************************************************** */
+ md_convert_frag:
+ Called by base assembler after address relaxation is finished: modify
+ variable fragments according to how much relaxation was done.
+
+ If the fragment substate is still 1, a 13-bit displacement was enough
+ to reach the symbol in question. Set up an address fixup, but otherwise
+ leave the cobr instruction alone.
+
+ If the fragment substate is 2, a 13-bit displacement was not enough.
+ Replace the cobr with a two instructions (a compare and a branch).
+
+ *************************************************************************** */
void
-md_convert_frag (headers, fragP)
+md_convert_frag (headers, seg, fragP)
object_headers *headers;
+ segT seg;
fragS *fragP;
{
fixS *fixP; /* Structure describing needed address fix */
@@ -1055,25 +1053,24 @@ md_convert_frag (headers, fragP)
}
/*****************************************************************************
- * md_estimate_size_before_relax: How much does it look like *fragP will grow?
- *
- * Called by base assembler just before address relaxation.
- * Return the amount by which the fragment will grow.
- *
- * Any symbol that is now undefined will not become defined; cobr's
- * based on undefined symbols will have to be replaced with a compare
- * instruction and a branch instruction, and the code fragment will grow
- * by 4 bytes.
- *
- **************************************************************************** */
+ md_estimate_size_before_relax: How much does it look like *fragP will grow?
+
+ Called by base assembler just before address relaxation.
+ Return the amount by which the fragment will grow.
+
+ Any symbol that is now undefined will not become defined; cobr's
+ based on undefined symbols will have to be replaced with a compare
+ instruction and a branch instruction, and the code fragment will grow
+ by 4 bytes.
+
+ *************************************************************************** */
int
md_estimate_size_before_relax (fragP, segment_type)
register fragS *fragP;
register segT segment_type;
{
/* If symbol is undefined in this segment, go to "relaxed" state
- * (compare and branch instructions instead of cobr) right now.
- */
+ (compare and branch instructions instead of cobr) right now. */
if (S_GET_SEGMENT (fragP->fr_symbol) != segment_type)
{
relax_cobr (fragP);
@@ -1084,18 +1081,18 @@ md_estimate_size_before_relax (fragP, segment_type)
/*****************************************************************************
- * md_ri_to_chars:
- * This routine exists in order to overcome machine byte-order problems
- * when dealing with bit-field entries in the relocation_info struct.
- *
- * But relocation info will be used on the host machine only (only
- * executable code is actually downloaded to the i80960). Therefore,
- * we leave it in host byte order.
- *
- * The above comment is no longer true. This routine now really
- * does do the reordering (Ian Taylor 28 Aug 92).
- *
- **************************************************************************** */
+ md_ri_to_chars:
+ This routine exists in order to overcome machine byte-order problems
+ when dealing with bit-field entries in the relocation_info struct.
+
+ But relocation info will be used on the host machine only (only
+ executable code is actually downloaded to the i80960). Therefore,
+ we leave it in host byte order.
+
+ The above comment is no longer true. This routine now really
+ does do the reordering (Ian Taylor 28 Aug 92).
+
+ *************************************************************************** */
void
md_ri_to_chars (where, ri)
char *where;
@@ -1141,21 +1138,16 @@ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
}
#endif
+#endif /* BFD_ASSEMBLER */
-/*************************************************************
- * *
- * FOLLOWING ARE THE LOCAL ROUTINES, IN ALPHABETICAL ORDER *
- * *
- ************************************************************ */
-
-
+/* FOLLOWING ARE THE LOCAL ROUTINES, IN ALPHABETICAL ORDER */
/*****************************************************************************
- * brcnt_emit: Emit code to increment inline branch counter.
- *
- * See the comments above the declaration of 'br_cnt' for details on
- * branch-prediction instrumentation.
- **************************************************************************** */
+ brcnt_emit: Emit code to increment inline branch counter.
+
+ See the comments above the declaration of 'br_cnt' for details on
+ branch-prediction instrumentation.
+ *************************************************************************** */
static void
brcnt_emit ()
{
@@ -1164,11 +1156,11 @@ brcnt_emit ()
}
/*****************************************************************************
- * brlab_next: generate the next branch local label
- *
- * See the comments above the declaration of 'br_cnt' for details on
- * branch-prediction instrumentation.
- **************************************************************************** */
+ brlab_next: generate the next branch local label
+
+ See the comments above the declaration of 'br_cnt' for details on
+ branch-prediction instrumentation.
+ *************************************************************************** */
static char *
brlab_next ()
{
@@ -1179,42 +1171,43 @@ brlab_next ()
}
/*****************************************************************************
- * brtab_emit: generate the fetch-prediction branch table.
- *
- * See the comments above the declaration of 'br_cnt' for details on
- * branch-prediction instrumentation.
- *
- * The code emitted here would be functionally equivalent to the following
- * example assembler source.
- *
- * .data
- * .align 2
- * BR_TAB_NAME:
- * .word 0 # link to next table
- * .word 3 # length of table
- * .word LBRANCH0 # 1st entry in table proper
- * .word LBRANCH1
- * .word LBRANCH2
- ***************************************************************************** */
+ brtab_emit: generate the fetch-prediction branch table.
+
+ See the comments above the declaration of 'br_cnt' for details on
+ branch-prediction instrumentation.
+
+ The code emitted here would be functionally equivalent to the following
+ example assembler source.
+
+ .data
+ .align 2
+ BR_TAB_NAME:
+ .word 0 # link to next table
+ .word 3 # length of table
+ .word LBRANCH0 # 1st entry in table proper
+ .word LBRANCH1
+ .word LBRANCH2
+ **************************************************************************** */
void
brtab_emit ()
{
int i;
char buf[20];
char *p; /* Where the binary was output to */
- fixS *fixP; /*->description of deferred address fixup */
+ /* Pointer to description of deferred address fixup. */
+ fixS *fixP;
if (!instrument_branches)
{
return;
}
- subseg_set (SEG_DATA, 0); /* .data */
- frag_align (2, 0); /* .align 2 */
+ subseg_set (data_section, 0); /* .data */
+ frag_align (2, 0); /* .align 2 */
record_alignment (now_seg, 2);
colon (BR_TAB_NAME); /* BR_TAB_NAME: */
- emit (0); /* .word 0 #link to next table */
- emit (br_cnt); /* .word n #length of table */
+ emit (0); /* .word 0 #link to next table */
+ emit (br_cnt); /* .word n #length of table */
for (i = 0; i < br_cnt; i++)
{
@@ -1232,25 +1225,25 @@ brtab_emit ()
}
/*****************************************************************************
- * cobr_fmt: generate a COBR-format instruction
- *
- **************************************************************************** */
+ cobr_fmt: generate a COBR-format instruction
+
+ *************************************************************************** */
static
void
cobr_fmt (arg, opcode, oP)
- char *arg[]; /* arg[0]->opcode mnemonic, arg[1-3]->operands (ascii) */
- long opcode; /* Opcode, with branch-prediction bits already set
- * if necessary.
- */
+ /* arg[0]->opcode mnemonic, arg[1-3]->operands (ascii) */
+ char *arg[];
+ /* Opcode, with branch-prediction bits already set if necessary. */
+ long opcode;
+ /* Pointer to description of instruction. */
struct i960_opcode *oP;
- /*->description of instruction */
{
long instr; /* 32-bit instruction */
struct regop regop; /* Description of register operand */
int n; /* Number of operands */
int var_frag; /* 1 if varying length code fragment should
- * be emitted; 0 if an address fix
- * should be emitted.
+ * be emitted; 0 if an address fix
+ * should be emitted.
*/
instr = opcode;
@@ -1259,17 +1252,15 @@ cobr_fmt (arg, opcode, oP)
if (n >= 1)
{
/* First operand (if any) of a COBR is always a register
- * operand. Parse it.
- */
+ operand. Parse it. */
parse_regop (&regop, arg[1], oP->operand[0]);
instr |= (regop.n << 19) | (regop.mode << 13);
}
if (n >= 2)
{
/* Second operand (if any) of a COBR is always a register
- * operand. Parse it.
- */
- parse_regop (&regop, arg[2], oP->operand[1]);
+ operand. Parse it. */
+ parse_regop (&regop, arg[2], oP->operand[1]);
instr |= (regop.n << 14) | regop.special;
}
@@ -1287,12 +1278,11 @@ cobr_fmt (arg, opcode, oP)
colon (brlab_next ());
}
- /* A third operand to a COBR is always a displacement.
- * Parse it; if it's relaxable (a cobr "j" directive, or any
- * cobr other than bbs/bbc when the "-norelax" option is not in
- * use) set up a variable code fragment; otherwise set up an
- * address fix.
- */
+ /* A third operand to a COBR is always a displacement. Parse
+ it; if it's relaxable (a cobr "j" directive, or any cobr
+ other than bbs/bbc when the "-norelax" option is not in use)
+ set up a variable code fragment; otherwise set up an address
+ fix. */
var_frag = !norelax || (oP->format == COJ); /* TRUE or FALSE */
get_cdisp (arg[3], "COBR", instr, 13, var_frag, 0);
@@ -1305,9 +1295,9 @@ cobr_fmt (arg, opcode, oP)
/*****************************************************************************
- * ctrl_fmt: generate a CTRL-format instruction
- *
- **************************************************************************** */
+ ctrl_fmt: generate a CTRL-format instruction
+
+ *************************************************************************** */
static
void
ctrl_fmt (targP, opcode, num_ops)
@@ -1316,8 +1306,8 @@ ctrl_fmt (targP, opcode, num_ops)
int num_ops; /* Number of operands */
{
int instrument; /* TRUE iff we should add instrumentation to track
- * how often the branch is taken
- */
+ * how often the branch is taken
+ */
if (num_ops == 0)
@@ -1337,8 +1327,8 @@ ctrl_fmt (targP, opcode, num_ops)
}
/* The operand MUST be an ip-relative displacment. Parse it
- * and set up address fix for the instruction we just output.
- */
+ * and set up address fix for the instruction we just output.
+ */
get_cdisp (targP, "CTRL", opcode, 24, 0, 0);
if (instrument)
@@ -1351,12 +1341,12 @@ ctrl_fmt (targP, opcode, num_ops)
/*****************************************************************************
- * emit: output instruction binary
- *
- * Output instruction binary, in target byte order, 4 bytes at a time.
- * Return pointer to where it was placed.
- *
- **************************************************************************** */
+ emit: output instruction binary
+
+ Output instruction binary, in target byte order, 4 bytes at a time.
+ Return pointer to where it was placed.
+
+ *************************************************************************** */
static
char *
emit (instr)
@@ -1371,34 +1361,32 @@ emit (instr)
/*****************************************************************************
- * get_args: break individual arguments out of comma-separated list
- *
- * Input assumptions:
- * - all comments and labels have been removed
- * - all strings of whitespace have been collapsed to a single blank.
- * - all character constants ('x') have been replaced with decimal
- *
- * Output:
- * args[0] is untouched. args[1] points to first operand, etc. All args:
- * - are NULL-terminated
- * - contain no whitespace
- *
- * Return value:
- * Number of operands (0,1,2, or 3) or -1 on error.
- *
- **************************************************************************** */
+ get_args: break individual arguments out of comma-separated list
+
+ Input assumptions:
+ - all comments and labels have been removed
+ - all strings of whitespace have been collapsed to a single blank.
+ - all character constants ('x') have been replaced with decimal
+
+ Output:
+ args[0] is untouched. args[1] points to first operand, etc. All args:
+ - are NULL-terminated
+ - contain no whitespace
+
+ Return value:
+ Number of operands (0,1,2, or 3) or -1 on error.
+
+ *************************************************************************** */
static int
get_args (p, args)
- register char *p; /* Pointer to comma-separated operands; MUCKED BY US */
- char *args[]; /* Output arg: pointers to operands placed in args[1-3].
- * MUST ACCOMMODATE 4 ENTRIES (args[0-3]).
- */
+ /* Pointer to comma-separated operands; MUCKED BY US */
+ register char *p;
+ /* Output arg: pointers to operands placed in args[1-3]. MUST
+ ACCOMMODATE 4 ENTRIES (args[0-3]). */
+ char *args[];
{
register int n; /* Number of operands */
register char *to;
- /* char buf[4]; */
- /* int len; */
-
/* Skip lead white space */
while (*p == ' ')
@@ -1415,13 +1403,14 @@ get_args (p, args)
args[1] = p;
/* Squeze blanks out by moving non-blanks toward start of string.
- * Isolate operands, whenever comma is found.
- */
+ * Isolate operands, whenever comma is found.
+ */
to = p;
while (*p != '\0')
{
- if (*p == ' ')
+ if (*p == ' '
+ && (! isalnum (p[1]) || ! isalnum (p[-1])))
{
p++;
@@ -1451,19 +1440,19 @@ get_args (p, args)
/*****************************************************************************
- * get_cdisp: handle displacement for a COBR or CTRL instruction.
- *
- * Parse displacement for a COBR or CTRL instruction.
- *
- * If successful, output the instruction opcode and set up for it,
- * depending on the arg 'var_frag', either:
- * o an address fixup to be done when all symbol values are known, or
- * o a varying length code fragment, with address fixup info. This
- * will be done for cobr instructions that may have to be relaxed
- * in to compare/branch instructions (8 bytes) if the final
- * address displacement is greater than 13 bits.
- *
- *****************************************************************************/
+ get_cdisp: handle displacement for a COBR or CTRL instruction.
+
+ Parse displacement for a COBR or CTRL instruction.
+
+ If successful, output the instruction opcode and set up for it,
+ depending on the arg 'var_frag', either:
+ o an address fixup to be done when all symbol values are known, or
+ o a varying length code fragment, with address fixup info. This
+ will be done for cobr instructions that may have to be relaxed
+ in to compare/branch instructions (8 bytes) if the final
+ address displacement is greater than 13 bits.
+
+ ****************************************************************************/
static
void
get_cdisp (dispP, ifmtP, instr, numbits, var_frag, callj)
@@ -1476,7 +1465,7 @@ get_cdisp (dispP, ifmtP, instr, numbits, var_frag, callj)
/* # bits of displacement (13 for COBR, 24 for CTRL) */
int numbits;
/* 1 if varying length code fragment should be emitted;
- * 0 if an address fix should be emitted.
+ * 0 if an address fix should be emitted.
*/
int var_frag;
/* 1 if callj relocation should be done; else 0 */
@@ -1495,15 +1484,15 @@ get_cdisp (dispP, ifmtP, instr, numbits, var_frag, callj)
as_bad ("expression syntax error");
case O_symbol:
- if (S_GET_SEGMENT (e.X_add_symbol) == text_section
+ if (S_GET_SEGMENT (e.X_add_symbol) == now_seg
|| S_GET_SEGMENT (e.X_add_symbol) == undefined_section)
- {
+ {
if (var_frag)
{
- outP = frag_more (8); /* Allocate worst-case storage */
+ outP = frag_more (8); /* Allocate worst-case storage */
md_number_to_chars (outP, instr, 4);
frag_variant (rs_machine_dependent, 4, 4, 1,
- adds (e), offs (e), outP, 0, 0);
+ adds (e), offs (e), outP);
}
else
{
@@ -1541,25 +1530,27 @@ get_cdisp (dispP, ifmtP, instr, numbits, var_frag, callj)
/*****************************************************************************
- * get_ispec: parse a memory operand for an index specification
- *
- * Here, an "index specification" is taken to be anything surrounded
- * by square brackets and NOT followed by anything else.
- *
- * If it's found, detach it from the input string, remove the surrounding
- * square brackets, and return a pointer to it. Otherwise, return NULL.
- *
- **************************************************************************** */
+ get_ispec: parse a memory operand for an index specification
+
+ Here, an "index specification" is taken to be anything surrounded
+ by square brackets and NOT followed by anything else.
+
+ If it's found, detach it from the input string, remove the surrounding
+ square brackets, and return a pointer to it. Otherwise, return NULL.
+
+ *************************************************************************** */
static
char *
get_ispec (textP)
- char *textP; /*->memory operand from source instruction, no white space */
+ /* Pointer to memory operand from source instruction, no white space. */
+ char *textP;
{
- char *start; /*->start of index specification */
- char *end; /*->end of index specification */
+ /* Points to start of index specification. */
+ char *start;
+ /* Points to end of index specification. */
+ char *end;
- /* Find opening square bracket, if any
- */
+ /* Find opening square bracket, if any. */
start = strchr (textP, '[');
if (start != NULL)
@@ -1578,8 +1569,8 @@ get_ispec (textP)
else
{
/* Eliminate ']' and make sure it was the last thing
- * in the string.
- */
+ * in the string.
+ */
*end = '\0';
if (*(end + 1) != '\0')
{
@@ -1591,12 +1582,12 @@ get_ispec (textP)
}
/*****************************************************************************
- * get_regnum:
- *
- * Look up a (suspected) register name in the register table and return the
- * associated register number (or -1 if not found).
- *
- **************************************************************************** */
+ get_regnum:
+
+ Look up a (suspected) register name in the register table and return the
+ associated register number (or -1 if not found).
+
+ *************************************************************************** */
static
int
get_regnum (regname)
@@ -1610,29 +1601,30 @@ get_regnum (regname)
/*****************************************************************************
- * i_scan: perform lexical scan of ascii assembler instruction.
- *
- * Input assumptions:
- * - input string is an i80960 instruction (not a pseudo-op)
- * - all comments and labels have been removed
- * - all strings of whitespace have been collapsed to a single blank.
- *
- * Output:
- * args[0] points to opcode, other entries point to operands. All strings:
- * - are NULL-terminated
- * - contain no whitespace
- * - have character constants ('x') replaced with a decimal number
- *
- * Return value:
- * Number of operands (0,1,2, or 3) or -1 on error.
- *
- **************************************************************************** */
+ i_scan: perform lexical scan of ascii assembler instruction.
+
+ Input assumptions:
+ - input string is an i80960 instruction (not a pseudo-op)
+ - all comments and labels have been removed
+ - all strings of whitespace have been collapsed to a single blank.
+
+ Output:
+ args[0] points to opcode, other entries point to operands. All strings:
+ - are NULL-terminated
+ - contain no whitespace
+ - have character constants ('x') replaced with a decimal number
+
+ Return value:
+ Number of operands (0,1,2, or 3) or -1 on error.
+
+ *************************************************************************** */
static int
i_scan (iP, args)
- register char *iP; /* Pointer to ascii instruction; MUCKED BY US. */
- char *args[]; /* Output arg: pointers to opcode and operands placed
- * here. MUST ACCOMMODATE 4 ENTRIES.
- */
+ /* Pointer to ascii instruction; MUCKED BY US. */
+ register char *iP;
+ /* Output arg: pointers to opcode and operands placed here. MUST
+ ACCOMMODATE 4 ENTRIES. */
+ char *args[];
{
/* Isolate opcode */
@@ -1661,9 +1653,9 @@ i_scan (iP, args)
/*****************************************************************************
- * mem_fmt: generate a MEMA- or MEMB-format instruction
- *
- **************************************************************************** */
+ mem_fmt: generate a MEMA- or MEMB-format instruction
+
+ *************************************************************************** */
static void
mem_fmt (args, oP, callx)
char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */
@@ -1676,7 +1668,8 @@ mem_fmt (args, oP, callx)
memS instr; /* Description of binary to be output */
char *outP; /* Where the binary was output to */
expressionS expr; /* Parsed expression */
- fixS *fixP; /*->description of deferred address fixup */
+ /* ->description of deferred address fixup */
+ fixS *fixP;
#ifdef OBJ_COFF
/* COFF support isn't in place yet for callx relaxing. */
@@ -1768,8 +1761,8 @@ mem_fmt (args, oP, callx)
NO_RELOC);
fixP->fx_im_disp = 2; /* 32-bit displacement fix */
/* Steve's linker relaxing hack. Mark this 32-bit relocation as
- being in the instruction stream, specifically as part of a callx
- instruction. */
+ being in the instruction stream, specifically as part of a callx
+ instruction. */
fixP->fx_bsr = callx;
break;
}
@@ -1777,15 +1770,15 @@ mem_fmt (args, oP, callx)
/*****************************************************************************
- * mema_to_memb: convert a MEMA-format opcode to a MEMB-format opcode.
- *
- * There are 2 possible MEMA formats:
- * - displacement only
- * - displacement + abase
- *
- * They are distinguished by the setting of the MEMA_ABASE bit.
- *
- **************************************************************************** */
+ mema_to_memb: convert a MEMA-format opcode to a MEMB-format opcode.
+
+ There are 2 possible MEMA formats:
+ - displacement only
+ - displacement + abase
+
+ They are distinguished by the setting of the MEMA_ABASE bit.
+
+ *************************************************************************** */
static void
mema_to_memb (opcodeP)
char *opcodeP; /* Where to find the opcode, in target byte order */
@@ -1810,18 +1803,18 @@ mema_to_memb (opcodeP)
/*****************************************************************************
- * parse_expr: parse an expression
- *
- * Use base assembler's expression parser to parse an expression.
- * It, unfortunately, runs off a global which we have to save/restore
- * in order to make it work for us.
- *
- * An empty expression string is treated as an absolute 0.
- *
- * Sets O_illegal regardless of expression evaluation if entire input
- * string is not consumed in the evaluation -- tolerate no dangling junk!
- *
- **************************************************************************** */
+ parse_expr: parse an expression
+
+ Use base assembler's expression parser to parse an expression.
+ It, unfortunately, runs off a global which we have to save/restore
+ in order to make it work for us.
+
+ An empty expression string is treated as an absolute 0.
+
+ Sets O_illegal regardless of expression evaluation if entire input
+ string is not consumed in the evaluation -- tolerate no dangling junk!
+
+ *************************************************************************** */
static void
parse_expr (textP, expP)
char *textP; /* Text of expression to be parsed */
@@ -1864,20 +1857,20 @@ parse_expr (textP, expP)
/*****************************************************************************
- * parse_ldcont:
- * Parse and replace a 'ldconst' pseudo-instruction with an appropriate
- * i80960 instruction.
- *
- * Assumes the input consists of:
- * arg[0] opcode mnemonic ('ldconst')
- * arg[1] first operand (constant)
- * arg[2] name of register to be loaded
- *
- * Replaces opcode and/or operands as appropriate.
- *
- * Returns the new number of arguments, or -1 on failure.
- *
- **************************************************************************** */
+ parse_ldcont:
+ Parse and replace a 'ldconst' pseudo-instruction with an appropriate
+ i80960 instruction.
+
+ Assumes the input consists of:
+ arg[0] opcode mnemonic ('ldconst')
+ arg[1] first operand (constant)
+ arg[2] name of register to be loaded
+
+ Replaces opcode and/or operands as appropriate.
+
+ Returns the new number of arguments, or -1 on failure.
+
+ *************************************************************************** */
static
int
parse_ldconst (arg)
@@ -1902,16 +1895,16 @@ parse_ldconst (arg)
case O_constant:
/* Try the following mappings:
- * ldconst 0,<reg> ->mov 0,<reg>
- * ldconst 31,<reg> ->mov 31,<reg>
- * ldconst 32,<reg> ->addo 1,31,<reg>
- * ldconst 62,<reg> ->addo 31,31,<reg>
- * ldconst 64,<reg> ->shlo 8,3,<reg>
- * ldconst -1,<reg> ->subo 1,0,<reg>
- * ldconst -31,<reg>->subo 31,0,<reg>
+ * ldconst 0,<reg> ->mov 0,<reg>
+ * ldconst 31,<reg> ->mov 31,<reg>
+ * ldconst 32,<reg> ->addo 1,31,<reg>
+ * ldconst 62,<reg> ->addo 31,31,<reg>
+ * ldconst 64,<reg> ->shlo 8,3,<reg>
+ * ldconst -1,<reg> ->subo 1,0,<reg>
+ * ldconst -31,<reg>->subo 31,0,<reg>
*
* anthing else becomes:
- * lda xxx,<reg>
+ * lda xxx,<reg>
*/
n = offs (e);
if ((0 <= n) && (n <= 31))
@@ -1962,36 +1955,36 @@ parse_ldconst (arg)
}
/*****************************************************************************
- * parse_memop: parse a memory operand
- *
- * This routine is based on the observation that the 4 mode bits of the
- * MEMB format, taken individually, have fairly consistent meaning:
- *
- * M3 (bit 13): 1 if displacement is present (D_BIT)
- * M2 (bit 12): 1 for MEMB instructions (MEMB_BIT)
- * M1 (bit 11): 1 if index is present (I_BIT)
- * M0 (bit 10): 1 if abase is present (A_BIT)
- *
- * So we parse the memory operand and set bits in the mode as we find
- * things. Then at the end, if we go to MEMB format, we need only set
- * the MEMB bit (M2) and our mode is built for us.
- *
- * Unfortunately, I said "fairly consistent". The exceptions:
- *
- * DBIA
- * 0100 Would seem illegal, but means "abase-only".
- *
- * 0101 Would seem to mean "abase-only" -- it means IP-relative.
- * Must be converted to 0100.
- *
- * 0110 Would seem to mean "index-only", but is reserved.
- * We turn on the D bit and provide a 0 displacement.
- *
- * The other thing to observe is that we parse from the right, peeling
- * things * off as we go: first any index spec, then any abase, then
- * the displacement.
- *
- **************************************************************************** */
+ parse_memop: parse a memory operand
+
+ This routine is based on the observation that the 4 mode bits of the
+ MEMB format, taken individually, have fairly consistent meaning:
+
+ M3 (bit 13): 1 if displacement is present (D_BIT)
+ M2 (bit 12): 1 for MEMB instructions (MEMB_BIT)
+ M1 (bit 11): 1 if index is present (I_BIT)
+ M0 (bit 10): 1 if abase is present (A_BIT)
+
+ So we parse the memory operand and set bits in the mode as we find
+ things. Then at the end, if we go to MEMB format, we need only set
+ the MEMB bit (M2) and our mode is built for us.
+
+ Unfortunately, I said "fairly consistent". The exceptions:
+
+ DBIA
+ 0100 Would seem illegal, but means "abase-only".
+
+ 0101 Would seem to mean "abase-only" -- it means IP-relative.
+ Must be converted to 0100.
+
+ 0110 Would seem to mean "index-only", but is reserved.
+ We turn on the D bit and provide a 0 displacement.
+
+ The other thing to observe is that we parse from the right, peeling
+ things * off as we go: first any index spec, then any abase, then
+ the displacement.
+
+ *************************************************************************** */
static
void
parse_memop (memP, argP, optype)
@@ -2003,18 +1996,18 @@ parse_memop (memP, argP, optype)
char *p; /* Temp char pointer */
char iprel_flag; /* True if this is an IP-relative operand */
int regnum; /* Register number */
- int scale; /* Scale factor: 1,2,4,8, or 16. Later converted
- * to internal format (0,1,2,3,4 respectively).
- */
+ /* Scale factor: 1,2,4,8, or 16. Later converted to internal format
+ (0,1,2,3,4 respectively). */
+ int scale;
int mode; /* MEMB mode bits */
int *intP; /* Pointer to register number */
/* The following table contains the default scale factors for each
- * type of memory instruction. It is accessed using (optype-MEM1)
- * as an index -- thus it assumes the 'optype' constants are assigned
- * consecutive values, in the order they appear in this table
- */
- static int def_scale[] =
+ type of memory instruction. It is accessed using (optype-MEM1)
+ as an index -- thus it assumes the 'optype' constants are
+ assigned consecutive values, in the order they appear in this
+ table. */
+ static const int def_scale[] =
{
1, /* MEM1 */
2, /* MEM2 */
@@ -2034,18 +2027,21 @@ parse_memop (memP, argP, optype)
p = strchr (indexP, '*');
if (p == NULL)
{
- /* No explicit scale -- use default for this
- *instruction type.
- */
- scale = def_scale[optype - MEM1];
+ /* No explicit scale -- use default for this instruction
+ type and assembler mode. */
+ if (flag_mri)
+ scale = 1;
+ else
+ /* GNU960 compatibility */
+ scale = def_scale[optype - MEM1];
}
else
{
*p++ = '\0'; /* Eliminate '*' */
/* Now indexP->a '\0'-terminated register name,
- * and p->a scale factor.
- */
+ * and p->a scale factor.
+ */
if (!strcmp (p, "16"))
{
@@ -2098,9 +2094,8 @@ parse_memop (memP, argP, optype)
/* Any abase (Register Indirect) specification present? */
if ((p = strrchr (argP, '(')) != NULL)
{
- /* "(" is there -- does it start a legal abase spec?
- * (If not it could be part of a displacement expression.)
- */
+ /* "(" is there -- does it start a legal abase spec? If not, it
+ could be part of a displacement expression. */
intP = (int *) hash_find (areg_hash, p);
if (intP != NULL)
{
@@ -2147,26 +2142,23 @@ parse_memop (memP, argP, optype)
{
case D_BIT | A_BIT:
/* Go with MEMA instruction format for now (grow to MEMB later
- * if 12 bits is not enough for the displacement).
- * MEMA format has a single mode bit: set it to indicate
- * that abase is present.
- */
+ if 12 bits is not enough for the displacement). MEMA format
+ has a single mode bit: set it to indicate that abase is
+ present. */
memP->opcode |= MEMA_ABASE;
memP->disp = 12;
break;
case D_BIT:
/* Go with MEMA instruction format for now (grow to MEMB later
- * if 12 bits is not enough for the displacement).
- */
+ if 12 bits is not enough for the displacement). */
memP->disp = 12;
break;
case A_BIT:
/* For some reason, the bit string for this mode is not
- * consistent: it should be 0 (exclusive of the MEMB bit),
- * so we set it "by hand" here.
- */
+ consistent: it should be 0 (exclusive of the MEMB bit), so we
+ set it "by hand" here. */
memP->opcode |= MEMB_BIT;
break;
@@ -2176,11 +2168,9 @@ parse_memop (memP, argP, optype)
break;
case I_BIT:
- /* Treat missing displacement as displacement of 0 */
+ /* Treat missing displacement as displacement of 0. */
mode |= D_BIT;
- /***********************
- * Fall into next case *
- ********************** */
+ /* Fall into next case. */
case D_BIT | A_BIT | I_BIT:
case D_BIT | I_BIT:
/* set MEMB bit in mode, and OR in mode bits */
@@ -2195,21 +2185,20 @@ parse_memop (memP, argP, optype)
}
/*****************************************************************************
- * parse_po: parse machine-dependent pseudo-op
- *
- * This is a top-level routine for machine-dependent pseudo-ops. It slurps
- * up the rest of the input line, breaks out the individual arguments,
- * and dispatches them to the correct handler.
- **************************************************************************** */
+ parse_po: parse machine-dependent pseudo-op
+
+ This is a top-level routine for machine-dependent pseudo-ops. It slurps
+ up the rest of the input line, breaks out the individual arguments,
+ and dispatches them to the correct handler.
+ *************************************************************************** */
static
void
parse_po (po_num)
int po_num; /* Pseudo-op number: currently S_LEAFPROC or S_SYSPROC */
{
- char *args[4]; /* Pointers operands, with no embedded whitespace.
- * arg[0] unused.
- * arg[1-3]->operands
- */
+ /* Pointers operands, with no embedded whitespace.
+ arg[0] unused, arg[1-3]->operands */
+ char *args[4];
int n_ops; /* Number of operands */
char *p; /* Pointer to beginning of unparsed argument string */
char eol; /* Character that indicated end of line */
@@ -2246,18 +2235,18 @@ parse_po (po_num)
break;
}
- /* Restore eol, so line numbers get updated correctly. Base assembler
- * assumes we leave input pointer pointing at char following the eol.
- */
+ /* Restore eol, so line numbers get updated correctly. Base
+ assembler assumes we leave input pointer pointing at char
+ following the eol. */
*input_line_pointer++ = eol;
}
/*****************************************************************************
- * parse_regop: parse a register operand.
- *
- * In case of illegal operand, issue a message and return some valid
- * information so instruction processing can continue.
- **************************************************************************** */
+ parse_regop: parse a register operand.
+
+ In case of illegal operand, issue a message and return some valid
+ information so instruction processing can continue.
+ *************************************************************************** */
static
void
parse_regop (regopP, optext, opdesc)
@@ -2307,9 +2296,7 @@ parse_regop (regopP, optext, opdesc)
}
else if (LIT_OK (opdesc))
{
- /*
- * How about a literal?
- */
+ /* How about a literal? */
regopP->mode = 1;
regopP->special = 0;
if (FP_OK (opdesc))
@@ -2356,9 +2343,9 @@ parse_regop (regopP, optext, opdesc)
} /* parse_regop() */
/*****************************************************************************
- * reg_fmt: generate a REG-format instruction
- *
- **************************************************************************** */
+ reg_fmt: generate a REG-format instruction
+
+ *************************************************************************** */
static void
reg_fmt (args, oP)
char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */
@@ -2379,8 +2366,8 @@ reg_fmt (args, oP)
if ((n_ops == 1) && !(instr & M3))
{
/* 1-operand instruction in which the dst field should
- * be used (instead of src1).
- */
+ * be used (instead of src1).
+ */
regop.n <<= 19;
if (regop.special)
{
@@ -2405,8 +2392,8 @@ reg_fmt (args, oP)
if ((n_ops == 2) && !(instr & M3))
{
/* 2-operand instruction in which the dst field should
- * be used instead of src2).
- */
+ * be used instead of src2).
+ */
regop.n <<= 19;
if (regop.special)
{
@@ -2437,41 +2424,40 @@ reg_fmt (args, oP)
/*****************************************************************************
- * relax_cobr:
- * Replace cobr instruction in a code fragment with equivalent branch and
- * compare instructions, so it can reach beyond a 13-bit displacement.
- * Set up an address fix/relocation for the new branch instruction.
- *
- **************************************************************************** */
-
-/* This "conditional jump" table maps cobr instructions into equivalent
- * compare and branch opcodes.
- */
-static
+ relax_cobr:
+ Replace cobr instruction in a code fragment with equivalent branch and
+ compare instructions, so it can reach beyond a 13-bit displacement.
+ Set up an address fix/relocation for the new branch instruction.
+
+ *************************************************************************** */
+
+/* This "conditional jump" table maps cobr instructions into
+ equivalent compare and branch opcodes. */
+static const
struct
- {
- long compare;
- long branch;
- }
+{
+ long compare;
+ long branch;
+}
coj[] =
{ /* COBR OPCODE: */
- { CHKBIT, BNO }, /* 0x30 - bbc */
- { CMPO, BG }, /* 0x31 - cmpobg */
- { CMPO, BE }, /* 0x32 - cmpobe */
- { CMPO, BGE }, /* 0x33 - cmpobge */
- { CMPO, BL }, /* 0x34 - cmpobl */
- { CMPO, BNE }, /* 0x35 - cmpobne */
- { CMPO, BLE }, /* 0x36 - cmpoble */
- { CHKBIT, BO }, /* 0x37 - bbs */
- { CMPI, BNO }, /* 0x38 - cmpibno */
- { CMPI, BG }, /* 0x39 - cmpibg */
- { CMPI, BE }, /* 0x3a - cmpibe */
- { CMPI, BGE }, /* 0x3b - cmpibge */
- { CMPI, BL }, /* 0x3c - cmpibl */
- { CMPI, BNE }, /* 0x3d - cmpibne */
- { CMPI, BLE }, /* 0x3e - cmpible */
- { CMPI, BO }, /* 0x3f - cmpibo */
+ { CHKBIT, BNO }, /* 0x30 - bbc */
+ { CMPO, BG }, /* 0x31 - cmpobg */
+ { CMPO, BE }, /* 0x32 - cmpobe */
+ { CMPO, BGE }, /* 0x33 - cmpobge */
+ { CMPO, BL }, /* 0x34 - cmpobl */
+ { CMPO, BNE }, /* 0x35 - cmpobne */
+ { CMPO, BLE }, /* 0x36 - cmpoble */
+ { CHKBIT, BO }, /* 0x37 - bbs */
+ { CMPI, BNO }, /* 0x38 - cmpibno */
+ { CMPI, BG }, /* 0x39 - cmpibg */
+ { CMPI, BE }, /* 0x3a - cmpibe */
+ { CMPI, BGE }, /* 0x3b - cmpibge */
+ { CMPI, BL }, /* 0x3c - cmpibl */
+ { CMPI, BNE }, /* 0x3d - cmpibne */
+ { CMPI, BLE }, /* 0x3e - cmpible */
+ { CMPI, BO }, /* 0x3f - cmpibo */
};
static
@@ -2486,7 +2472,8 @@ relax_cobr (fragP)
/* Bit fields from cobr instruction */
long bp_bits; /* Branch prediction bits from cobr instruction */
long instr; /* A single i960 instruction */
- char *iP; /*->instruction to be replaced */
+ /* ->instruction to be replaced */
+ char *iP;
fixS *fixP; /* Relocation that can be done at assembly time */
/* PICK UP & PARSE COBR INSTRUCTION */
@@ -2524,48 +2511,49 @@ relax_cobr (fragP)
/*****************************************************************************
- * reloc_callj: Relocate a 'callj' instruction
- *
- * This is a "non-(GNU)-standard" machine-dependent hook. The base
- * assembler calls it when it decides it can relocate an address at
- * assembly time instead of emitting a relocation directive.
- *
- * Check to see if the relocation involves a 'callj' instruction to a:
- * sysproc: Replace the default 'call' instruction with a 'calls'
- * leafproc: Replace the default 'call' instruction with a 'bal'.
- * other proc: Do nothing.
- *
- * See b.out.h for details on the 'n_other' field in a symbol structure.
- *
- * IMPORTANT!:
- * Assumes the caller has already figured out, in the case of a leafproc,
- * to use the 'bal' entry point, and has substituted that symbol into the
- * passed fixup structure.
- *
- **************************************************************************** */
+ reloc_callj: Relocate a 'callj' instruction
+
+ This is a "non-(GNU)-standard" machine-dependent hook. The base
+ assembler calls it when it decides it can relocate an address at
+ assembly time instead of emitting a relocation directive.
+
+ Check to see if the relocation involves a 'callj' instruction to a:
+ sysproc: Replace the default 'call' instruction with a 'calls'
+ leafproc: Replace the default 'call' instruction with a 'bal'.
+ other proc: Do nothing.
+
+ See b.out.h for details on the 'n_other' field in a symbol structure.
+
+ IMPORTANT!:
+ Assumes the caller has already figured out, in the case of a leafproc,
+ to use the 'bal' entry point, and has substituted that symbol into the
+ passed fixup structure.
+
+ *************************************************************************** */
void
reloc_callj (fixP)
- fixS *fixP; /* Relocation that can be done at assembly time */
+ /* Relocation that can be done at assembly time */
+ fixS *fixP;
{
- char *where; /*->the binary for the instruction being relocated */
+ /* Points to the binary for the instruction being relocated. */
+ char *where;
if (!fixP->fx_tcbit)
{
+ /* This wasn't a callj instruction in the first place */
return;
- } /* This wasn't a callj instruction in the first place */
+ }
where = fixP->fx_frag->fr_literal + fixP->fx_where;
if (TC_S_IS_SYSPROC (fixP->fx_addsy))
{
- /* Symbol is a .sysproc: replace 'call' with 'calls'.
- * System procedure number is (other-1).
- */
+ /* Symbol is a .sysproc: replace 'call' with 'calls'. System
+ procedure number is (other-1). */
md_number_to_chars (where, CALLS | TC_S_GET_SYSPROC (fixP->fx_addsy), 4);
- /* Nothing else needs to be done for this instruction.
- * Make sure 'md_number_to_field()' will perform a no-op.
- */
+ /* Nothing else needs to be done for this instruction. Make
+ sure 'md_number_to_field()' will perform a no-op. */
fixP->fx_bit_fixP = (bit_fixS *) 1;
}
@@ -2573,14 +2561,12 @@ reloc_callj (fixP)
{
/* Should not happen: see block comment above */
as_fatal ("Trying to 'bal' to %s", S_GET_NAME (fixP->fx_addsy));
-
}
else if (TC_S_IS_BALNAME (fixP->fx_addsy))
{
- /* Replace 'call' with 'bal'; both instructions have
- * the same format, so calling code should complete
- * relocation as if nothing happened here.
- */
+ /* Replace 'call' with 'bal'; both instructions have the same
+ format, so calling code should complete relocation as if
+ nothing happened here. */
md_number_to_chars (where, BAL, 4);
}
else if (TC_S_IS_BADPROC (fixP->fx_addsy))
@@ -2593,20 +2579,20 @@ reloc_callj (fixP)
/*****************************************************************************
- * s_leafproc: process .leafproc pseudo-op
- *
- * .leafproc takes two arguments, the second one is optional:
- * arg[1]: name of 'call' entry point to leaf procedure
- * arg[2]: name of 'bal' entry point to leaf procedure
- *
- * If the two arguments are identical, or if the second one is missing,
- * the first argument is taken to be the 'bal' entry point.
- *
- * If there are 2 distinct arguments, we must make sure that the 'bal'
- * entry point immediately follows the 'call' entry point in the linked
- * list of symbols.
- *
- **************************************************************************** */
+ s_leafproc: process .leafproc pseudo-op
+
+ .leafproc takes two arguments, the second one is optional:
+ arg[1]: name of 'call' entry point to leaf procedure
+ arg[2]: name of 'bal' entry point to leaf procedure
+
+ If the two arguments are identical, or if the second one is missing,
+ the first argument is taken to be the 'bal' entry point.
+
+ If there are 2 distinct arguments, we must make sure that the 'bal'
+ entry point immediately follows the 'call' entry point in the linked
+ list of symbols.
+
+ *************************************************************************** */
static void
s_leafproc (n_ops, args)
int n_ops; /* Number of operands */
@@ -2630,9 +2616,9 @@ s_leafproc (n_ops, args)
} /* is leafproc */
/* If that was the only argument, use it as the 'bal' entry point.
- * Otherwise, mark it as the 'call' entry point and find or create
- * another symbol for the 'bal' entry point.
- */
+ * Otherwise, mark it as the 'call' entry point and find or create
+ * another symbol for the 'bal' entry point.
+ */
if ((n_ops == 1) || !strcmp (args[1], args[2]))
{
TC_S_FORCE_TO_BALNAME (callP);
@@ -2655,17 +2641,16 @@ s_leafproc (n_ops, args)
/*
- * s_sysproc: process .sysproc pseudo-op
- *
- * .sysproc takes two arguments:
- * arg[1]: name of entry point to system procedure
- * arg[2]: 'entry_num' (index) of system procedure in the range
- * [0,31] inclusive.
- *
- * For [ab].out, we store the 'entrynum' in the 'n_other' field of
- * the symbol. Since that entry is normally 0, we bias 'entrynum'
- * by adding 1 to it. It must be unbiased before it is used.
- */
+ s_sysproc: process .sysproc pseudo-op
+
+ .sysproc takes two arguments:
+ arg[1]: name of entry point to system procedure
+ arg[2]: 'entry_num' (index) of system procedure in the range
+ [0,31] inclusive.
+
+ For [ab].out, we store the 'entrynum' in the 'n_other' field of
+ the symbol. Since that entry is normally 0, we bias 'entrynum'
+ by adding 1 to it. It must be unbiased before it is used. */
static void
s_sysproc (n_ops, args)
int n_ops; /* Number of operands */
@@ -2704,15 +2689,15 @@ s_sysproc (n_ops, args)
/*****************************************************************************
- * shift_ok:
- * Determine if a "shlo" instruction can be used to implement a "ldconst".
- * This means that some number X < 32 can be shifted left to produce the
- * constant of interest.
- *
- * Return the shift count, or 0 if we can't do it.
- * Caller calculates X by shifting original constant right 'shift' places.
- *
- **************************************************************************** */
+ shift_ok:
+ Determine if a "shlo" instruction can be used to implement a "ldconst".
+ This means that some number X < 32 can be shifted left to produce the
+ constant of interest.
+
+ Return the shift count, or 0 if we can't do it.
+ Caller calculates X by shifting original constant right 'shift' places.
+
+ *************************************************************************** */
static
int
shift_ok (n)
@@ -2740,10 +2725,8 @@ shift_ok (n)
}
-/*****************************************************************************
- * syntax: issue syntax error
- *
- **************************************************************************** */
+/* syntax: issue syntax error */
+
static void
syntax ()
{
@@ -2751,12 +2734,11 @@ syntax ()
} /* syntax() */
-/*****************************************************************************
- * targ_has_sfr:
- * Return TRUE iff the target architecture supports the specified
- * special-function register (sfr).
- *
- *****************************************************************************/
+/* targ_has_sfr:
+
+ Return TRUE iff the target architecture supports the specified
+ special-function register (sfr). */
+
static
int
targ_has_sfr (n)
@@ -2767,6 +2749,7 @@ targ_has_sfr (n)
case ARCH_KA:
case ARCH_KB:
case ARCH_MC:
+ case ARCH_XL:
return 0;
case ARCH_CA:
default:
@@ -2775,18 +2758,18 @@ targ_has_sfr (n)
}
-/*****************************************************************************
- * targ_has_iclass:
- * Return TRUE iff the target architecture supports the indicated
- * class of instructions.
- *
- *****************************************************************************/
+/* targ_has_iclass:
+
+ Return TRUE iff the target architecture supports the indicated
+ class of instructions. */
static
int
targ_has_iclass (ic)
- int ic; /* Instruction class; one of:
- * I_BASE, I_CX, I_DEC, I_KX, I_FP, I_MIL, I_CASIM
- */
+ /* Instruction class; one of:
+ I_BASE, I_CX, I_DEC, I_KX, I_FP, I_MIL, I_CASIM
+ or I_XL
+ */
+ int ic;
{
iclasses_seen |= ic;
switch (architecture)
@@ -2798,10 +2781,12 @@ targ_has_iclass (ic)
case ARCH_MC:
return ic & (I_BASE | I_KX | I_FP | I_DEC | I_MIL);
case ARCH_CA:
- return ic & (I_BASE | I_CX | I_CASIM);
+ return ic & (I_BASE | I_CX | I_CX2 | I_CASIM);
+ case ARCH_XL:
+ return ic & (I_BASE | I_CX2 | I_XL);
default:
if ((iclasses_seen & (I_KX | I_FP | I_DEC | I_MIL))
- && (iclasses_seen & I_CX))
+ && (iclasses_seen & (I_CX | I_CX2)))
{
as_warn ("architecture of opcode conflicts with that of earlier instruction(s)");
iclasses_seen &= ~ic;
@@ -2810,16 +2795,27 @@ targ_has_iclass (ic)
}
}
+/* Handle the MRI .endian pseudo-op. */
-/* Parse an operand that is machine-specific.
- We just return without modifying the expression if we have nothing
- to do. */
-
-/* ARGSUSED */
-void
-md_operand (expressionP)
- expressionS *expressionP;
+static void
+s_endian (ignore)
+ int ignore;
{
+ char *name;
+ char c;
+
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ if (strcasecmp (name, "little") == 0)
+ ;
+ else if (strcasecmp (name, "big") == 0)
+ as_bad ("big endian mode is not supported");
+ else
+ as_warn ("ignoring unrecognized .endian type `%s'", name);
+
+ *input_line_pointer = c;
+
+ demand_empty_rest_of_line ();
}
/* We have no need to default values of symbols. */
@@ -2868,7 +2864,7 @@ md_apply_fix (fixP, val)
: val),
fixP->fx_size);
break;
- case 2: /* fix requested for .long .word etc */
+ case 2: /* fix requested for .long .word etc */
md_number_to_chars (place, val, fixP->fx_size);
break;
default:
@@ -2991,6 +2987,12 @@ tc_headers_hook (headers)
{
headers->filehdr.f_flags |= F_I960CA;
}
+ else if (iclasses_seen & I_XL)
+ headers->filehdr.f_flags |= F_I960XL;
+ else if (iclasses_seen & I_CX2)
+ {
+ headers->filehdr.f_flags |= F_I960CA;
+ }
else if (iclasses_seen & I_MIL)
{
headers->filehdr.f_flags |= F_I960MC;
@@ -3004,7 +3006,7 @@ tc_headers_hook (headers)
headers->filehdr.f_flags |= F_I960KA;
} /* set arch flag */
- if (flagseen['R'])
+ if (flag_readonly_data_in_text)
{
headers->filehdr.f_magic = I960RWMAGIC;
headers->aouthdr.magic = OMAGIC;
@@ -3018,24 +3020,21 @@ tc_headers_hook (headers)
#endif /* OBJ_COFF */
-/*
- * Things going on here:
- *
- * For bout, We need to assure a couple of simplifying
- * assumptions about leafprocs for the linker: the leafproc
- * entry symbols will be defined in the same assembly in
- * which they're declared with the '.leafproc' directive;
- * and if a leafproc has both 'call' and 'bal' entry points
- * they are both global or both local.
- *
- * For coff, the call symbol has a second aux entry that
- * contains the bal entry point. The bal symbol becomes a
- * label.
- *
- * For coff representation, the call symbol has a second aux entry that
- * contains the bal entry point. The bal symbol becomes a label.
- *
- */
+/* Things going on here:
+
+ For bout, We need to assure a couple of simplifying
+ assumptions about leafprocs for the linker: the leafproc
+ entry symbols will be defined in the same assembly in
+ which they're declared with the '.leafproc' directive;
+ and if a leafproc has both 'call' and 'bal' entry points
+ they are both global or both local.
+
+ For coff, the call symbol has a second aux entry that
+ contains the bal entry point. The bal symbol becomes a
+ label.
+
+ For coff representation, the call symbol has a second aux entry that
+ contains the bal entry point. The bal symbol becomes a label. */
void
tc_crawl_symbol_chain (headers)
@@ -3080,12 +3079,10 @@ tc_crawl_symbol_chain (headers)
} /* walk the symbol chain */
}
-/*
- * For aout or bout, the bal immediately follows the call.
- *
- * For coff, we cheat and store a pointer to the bal symbol
- * in the second aux entry of the call.
- */
+/* For aout or bout, the bal immediately follows the call.
+
+ For coff, we cheat and store a pointer to the bal symbol in the
+ second aux entry of the call. */
#undef OBJ_ABOUT
#ifdef OBJ_AOUT
@@ -3112,8 +3109,8 @@ tc_set_bal_of_call (callP, balP)
#ifdef OBJ_ABOUT
/* If the 'bal' entry doesn't immediately follow the 'call'
- * symbol, unlink it from the symbol list and re-insert it.
- */
+ * symbol, unlink it from the symbol list and re-insert it.
+ */
if (symbol_next (callP) != balP)
{
symbol_remove (balP, &symbol_rootP, &symbol_lastP);
@@ -3157,8 +3154,10 @@ tc_coff_symbol_emit_hook (symbolP)
#ifdef OBJ_COFF
symbolS *balP = tc_get_bal_of_call (symbolP);
+#if 0
/* second aux entry contains the bal entry point */
- /* S_SET_NUMBER_AUXILIARY(symbolP, 2); */
+ S_SET_NUMBER_AUXILIARY (symbolP, 2);
+#endif
symbolP->sy_symbol.ost_auxent[1].x_bal.x_balntry = S_GET_VALUE (balP);
S_SET_STORAGE_CLASS (symbolP, (!SF_GET_LOCAL (symbolP) ? C_LEAFEXT : C_LEAFSTAT));
S_SET_DATA_TYPE (symbolP, S_GET_DATA_TYPE (symbolP) | (DT_FCN << N_BTSHFT));
@@ -3207,7 +3206,7 @@ i960_validate_fix (fixP, this_segment_type, add_symbolPP)
if (fixP->fx_tcbit && TC_S_IS_CALLNAME (add_symbolP))
{
/* Relocation should be done via the associated 'bal'
- entry point symbol. */
+ entry point symbol. */
if (!TC_S_IS_BALNAME (tc_get_bal_of_call (add_symbolP)))
{
@@ -3218,24 +3217,24 @@ i960_validate_fix (fixP, this_segment_type, add_symbolPP)
fixP->fx_addsy = add_symbolP = tc_get_bal_of_call (add_symbolP);
}
#if 0
- /* Still have to work out other conditions for these tests. */
- {
- if (fixP->fx_tcbit)
- {
- as_bad ("callj to difference of two symbols");
- return 1;
- }
- reloc_callj (fixP);
- if ((int) fixP->fx_bit_fixP == 13)
- {
- /* This is a COBR instruction. They have only a 13-bit
- displacement and are only to be used for local branches:
- flag as error, don't generate relocation. */
- as_bad ("can't use COBR format with external label");
- fixP->fx_addsy = NULL; /* No relocations please. */
- return 1;
- }
- }
+ /* Still have to work out other conditions for these tests. */
+ {
+ if (fixP->fx_tcbit)
+ {
+ as_bad ("callj to difference of two symbols");
+ return 1;
+ }
+ reloc_callj (fixP);
+ if ((int) fixP->fx_bit_fixP == 13)
+ {
+ /* This is a COBR instruction. They have only a 13-bit
+ displacement and are only to be used for local branches:
+ flag as error, don't generate relocation. */
+ as_bad ("can't use COBR format with external label");
+ fixP->fx_addsy = NULL; /* No relocations please. */
+ return 1;
+ }
+ }
#endif
#undef add_symbolP
return 0;