/* tc-vax.c - vax-specific -
- Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+ Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2001, 2002,
+ 2003, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* JF I moved almost all the vax specific stuff into this one file 'cuz RMS
- seems to think its a good idea. I hope I managed to get all the VAX-isms */
-
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#include "as.h"
#include "vax-inst.h"
#include "obstack.h" /* For FRAG_APPEND_1_CHAR macro in "frags.h" */
+#include "subsegs.h"
+
+#ifdef OBJ_ELF
+#include "elf/vax.h"
+#endif
+
+#if defined (OBJ_AOUT) && !defined (BFD_ASSEMBLER) && defined (TE_NetBSD)
+#include <netinet/in.h>
+#endif
/* These chars start a comment anywhere in a source file (except inside
another comment */
const char comment_chars[] = "#";
-/* These chars only start a comment at the beginning of a line. */
-/* Note that for the VAX the are the same as comment_chars above. */
+/* These chars only start a comment at the beginning of a line. */
+/* Note that for the VAX the are the same as comment_chars above. */
const char line_comment_chars[] = "#";
-const char line_separator_chars[] = "";
+const char line_separator_chars[] = ";";
/* Chars that can be used to separate mant from exp in floating point nums */
const char EXP_CHARS[] = "eE";
/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
changed in read.c . Ideally it shouldn't have to know about it at all,
- but nothing is ideal around here.
- */
+ but nothing is ideal around here. */
-static expressionS /* Hold details of an operand expression */
- exp_of_operand[VIT_MAX_OPERANDS];
+/* Hold details of an operand expression */
+static expressionS exp_of_operand[VIT_MAX_OPERANDS];
+static segT seg_of_operand[VIT_MAX_OPERANDS];
-static struct vit
- v; /* A vax instruction after decoding. */
+/* A vax instruction after decoding. */
+static struct vit v;
+/* Hold details of big operands. */
LITTLENUM_TYPE big_operand_bits[VIT_MAX_OPERANDS][SIZE_OF_LARGE_NUMBER];
-/* Hold details of big operands. */
FLONUM_TYPE float_operand[VIT_MAX_OPERANDS];
-/* Above is made to point into */
-/* big_operand_bits by md_begin(). */
+/* Above is made to point into big_operand_bits by md_begin(). */
+
+#ifdef OBJ_ELF
+#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
+#define PROCEDURE_LINKAGE_TABLE_NAME "_PROCEDURE_LINKAGE_TABLE_"
+symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
+symbolS *PLT_symbol; /* Pre-defined "_PROCEDURE_LINKAGE_TABLE_" */
+#endif
+
+int flag_hash_long_names; /* -+ */
+int flag_one; /* -1 */
+int flag_show_after_trunc; /* -H */
+int flag_no_hash_mixed_case; /* -h NUM */
+#ifdef OBJ_ELF
+int flag_want_pic; /* -k */
+#endif
\f
/*
* For VAX, relative addresses of "just the right length" are easy.
bbcs e3
bbsc e4
bbcc e5
- bbssi e6
- bbcci e7
Always, you complement 0th bit to reverse condition.
Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement
after relax() what the original addressing mode was.
*/
\f
-/* These displacements are relative to */
-/* the start address of the displacement. */
-/* The first letter is Byte, Word. */
-/* 2nd letter is Forward, Backward. */
+/* These displacements are relative to the start address of the
+ displacement. The first letter is Byte, Word. 2nd letter is
+ Forward, Backward. */
#define BF (1+ 127)
#define BB (1+-128)
#define WF (2+ 32767)
#define WB (2+-32768)
-/* Dont need LF, LB because they always */
-/* reach. [They are coded as 0.] */
-
+/* Dont need LF, LB because they always reach. [They are coded as 0.] */
#define C(a,b) ENCODE_RELAX(a,b)
-/* This macro has no side-effects. */
+/* This macro has no side-effects. */
#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+#define RELAX_STATE(s) ((s) >> 2)
+#define RELAX_LENGTH(s) ((s) & 3)
-const relax_typeS
- md_relax_table[] =
+const relax_typeS md_relax_table[] =
{
{1, 1, 0, 0}, /* error sentinel 0,0 */
{1, 1, 0, 0}, /* unused 0,1 */
{1, 1, 0, 0}, /* unused 0,2 */
{1, 1, 0, 0}, /* unused 0,3 */
+
{BF + 1, BB + 1, 2, C (1, 1)},/* B^"foo" 1,0 */
{WF + 1, WB + 1, 3, C (1, 2)},/* W^"foo" 1,1 */
{0, 0, 5, 0}, /* L^"foo" 1,2 */
{1, 1, 0, 0}, /* unused 1,3 */
+
{BF, BB, 1, C (2, 1)}, /* b<cond> B^"foo" 2,0 */
{WF + 2, WB + 2, 4, C (2, 2)},/* br.+? brw X 2,1 */
{0, 0, 7, 0}, /* br.+? jmp X 2,2 */
{1, 1, 0, 0}, /* unused 2,3 */
+
{BF, BB, 1, C (3, 1)}, /* brb B^foo 3,0 */
{WF, WB, 2, C (3, 2)}, /* brw W^foo 3,1 */
{0, 0, 5, 0}, /* Jmp L^foo 3,2 */
{1, 1, 0, 0}, /* unused 3,3 */
+
{1, 1, 0, 0}, /* unused 4,0 */
{WF, WB, 2, C (4, 2)}, /* acb_ ^Wfoo 4,1 */
{0, 0, 10, 0}, /* acb_,br,jmp L^foo4,2 */
{1, 1, 0, 0}, /* unused 4,3 */
+
{BF, BB, 1, C (5, 1)}, /* Xob___,,foo 5,0 */
{WF + 4, WB + 4, 6, C (5, 2)},/* Xob.+2,brb.+3,brw5,1 */
{0, 0, 9, 0}, /* Xob.+2,brb.+6,jmp5,2 */
+ {1, 1, 0, 0}, /* unused 5,3 */
};
#undef C
#undef WF
#undef WB
-void float_cons ();
+void float_cons PARAMS ((int));
const pseudo_typeS md_pseudo_table[] =
{
{"ffloat", float_cons, 'f'},
{"gfloat", float_cons, 'g'},
{"hfloat", float_cons, 'h'},
- {0},
+ {NULL, NULL, 0},
};
#define STATE_PC_RELATIVE (1)
#define STATE_CONDITIONAL_BRANCH (2)
-#define STATE_ALWAYS_BRANCH (3) /* includes BSB... */
+#define STATE_ALWAYS_BRANCH (3) /* includes BSB... */
#define STATE_COMPLEX_BRANCH (4)
#define STATE_COMPLEX_HOP (5)
#define STATE_LONG (2)
#define STATE_UNDF (3) /* Symbol undefined in pass1 */
-
#define min(a, b) ((a) < (b) ? (a) : (b))
-#if __STDC__ == 1
-
-int flonum_gen2vax (char format_letter, FLONUM_TYPE * f, LITTLENUM_TYPE * words);
-static void vip_end (void);
-static void vip_op_defaults (char *immediate, char *indirect, char *displen);
-
-#else /* not __STDC__ */
+int flonum_gen2vax PARAMS ((char format_letter, FLONUM_TYPE * f,
+ LITTLENUM_TYPE * words));
+static const char *vip_begin PARAMS ((int, const char *, const char *,
+ const char *));
+static void vip_op_1 PARAMS ((int, const char *));
+static void vip_op_defaults PARAMS ((const char *, const char *, const char *));
+static void vip_op PARAMS ((char *, struct vop *));
+static void vip PARAMS ((struct vit *, char *));
-int flonum_gen2vax ();
-static void vip_end ();
-static void vip_op_defaults ();
-
-#endif /* not __STDC__ */
+static int vax_reg_parse PARAMS ((char, char, char, char));
void
md_begin ()
{
- char *vip_begin ();
- char *errtxt;
+ const char *errtxt;
FLONUM_TYPE *fP;
int i;
- if (*(errtxt = vip_begin (1, "$", "*", "`")))
+ if ((errtxt = vip_begin (1, "$", "*", "`")) != 0)
{
- as_fatal ("VIP_BEGIN error:%s", errtxt);
+ as_fatal (_("VIP_BEGIN error:%s"), errtxt);
}
for (i = 0, fP = float_operand;
fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];
}
}
-
-void
-md_end ()
-{
- vip_end ();
-}
\f
-void /* Knows about order of bytes in address. */
+void
md_number_to_chars (con, value, nbytes)
- char con[]; /* Return 'nbytes' of chars here. */
- valueT value; /* The value of the bits. */
- int nbytes; /* Number of bytes in the output. */
+ char con[];
+ valueT value;
+ int nbytes;
{
- int n;
- valueT v;
-
- n = nbytes;
- v = value;
- while (nbytes--)
- {
- *con++ = value; /* Lint wants & MASK_CHAR. */
- value >>= BITS_PER_CHAR;
- }
- /* XXX line number probably botched for this warning message. */
- if (value != 0 && value != -1)
- as_bad ("Displacement (%ld) long for instruction field length (%d).", v, n);
+ number_to_chars_littleendian (con, value, nbytes);
}
/* Fix up some data or instructions after we find out the value of a symbol
that they reference. */
-void /* Knows about order of bytes in address. */
-md_apply_fix (fixP, value)
- fixS *fixP; /* Fixup struct pointer */
- long value; /* The value of the bits. */
+void /* Knows about order of bytes in address. */
+md_apply_fix3 (fixP, valueP, seg)
+ fixS *fixP;
+ valueT *valueP;
+ segT seg ATTRIBUTE_UNUSED;
{
- char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
- int nbytes; /* Number of bytes in the output. */
+ valueT value = * valueP;
+#ifdef BFD_ASSEMBLER
+ if (((fixP->fx_addsy == NULL && fixP->fx_subsy == NULL)
+ && fixP->fx_r_type != BFD_RELOC_32_PLT_PCREL
+ && fixP->fx_r_type != BFD_RELOC_32_GOT_PCREL)
+ || fixP->fx_r_type == NO_RELOC)
+#endif
+ number_to_chars_littleendian (fixP->fx_where + fixP->fx_frag->fr_literal,
+ value, fixP->fx_size);
- nbytes = fixP->fx_size;
- while (nbytes--)
- {
- *buf++ = value; /* Lint wants & MASK_CHAR. */
- value >>= BITS_PER_CHAR;
- }
+ if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
+ fixP->fx_done = 1;
}
-long /* Knows about the byte order in a word. */
+long
md_chars_to_number (con, nbytes)
- unsigned char con[]; /* Low order byte 1st. */
- int nbytes; /* Number of bytes in the input. */
+ unsigned char con[]; /* Low order byte 1st. */
+ int nbytes; /* Number of bytes in the input. */
{
long retval;
for (retval = 0, con += nbytes - 1; nbytes--; con--)
void
md_assemble (instruction_string)
- char *instruction_string; /* A string: assemble 1 instruction. */
+ char *instruction_string; /* A string: assemble 1 instruction. */
{
- /* We saw no errors in any operands - try to make frag(s) */
- int is_undefined; /* 1 if operand expression's */
- /* segment not known yet. */
- int length_code;
+ /* Non-zero if operand expression's segment is not known yet. */
+ int is_undefined;
+ /* Non-zero if operand expression's segment is absolute. */
+ int is_absolute;
+ int length_code;
char *p;
- register struct vop *operandP;/* An operand. Scans all operands. */
+ /* An operand. Scans all operands. */
+ struct vop *operandP;
char *save_input_line_pointer;
- char c_save; /* What used to live after an expression. */
- /* fixme: unused? */
- /* struct frag *fragP; *//* Fragment of code we just made. */
- register int goofed; /* 1: instruction_string bad for all passes. */
- register struct vop *end_operandP; /* -> slot just after last operand */
- /* Limit of the for (each operand). */
- register expressionS *expP; /* -> expression values for this operand */
-
- /* These refer to an instruction operand expression. */
- segT to_seg; /* Target segment of the address. */
- register valueT this_add_number;
- register struct symbol *this_add_symbol; /* +ve (minuend) symbol. */
- register struct symbol *this_subtract_symbol; /* -ve(subtrahend) symbol. */
-
- long opcode_as_number; /* As a number. */
- char *opcode_as_chars; /* Least significant byte 1st. */
- /* As an array of characters. */
- char *opcode_low_byteP; /* Least significant byte 1st */
- /* richfix: unused? */
- /* struct details *detP; *//* The details of an ADxxx frag. */
- int length; /* length (bytes) meant by vop_short. */
- int at; /* 0, or 1 if '@' is in addressing mode. */
- int nbytes; /* From vop_nbytes: vax_operand_width (in bytes) */
+ /* What used to live after an expression. */
+ char c_save;
+ /* 1: instruction_string bad for all passes. */
+ int goofed;
+ /* Points to slot just after last operand. */
+ struct vop *end_operandP;
+ /* Points to expression values for this operand. */
+ expressionS *expP;
+ segT *segP;
+
+ /* These refer to an instruction operand expression. */
+ /* Target segment of the address. */
+ segT to_seg;
+ valueT this_add_number;
+ /* Positive (minuend) symbol. */
+ symbolS *this_add_symbol;
+ /* As a number. */
+ long opcode_as_number;
+ /* Least significant byte 1st. */
+ char *opcode_as_chars;
+ /* As an array of characters. */
+ /* Least significant byte 1st */
+ char *opcode_low_byteP;
+ /* length (bytes) meant by vop_short. */
+ int length;
+ /* 0, or 1 if '@' is in addressing mode. */
+ int at;
+ /* From vop_nbytes: vax_operand_width (in bytes) */
+ int nbytes;
FLONUM_TYPE *floatP;
- char *vip ();
LITTLENUM_TYPE literal_float[8];
- /* Big enough for any floating point literal. */
+ /* Big enough for any floating point literal. */
+
+ vip (&v, instruction_string);
- if (*(p = vip (&v, instruction_string)))
- {
- as_fatal ("vax_assemble\"%s\" in=\"%s\"", p, instruction_string);
- }
/*
* Now we try to find as many as_warn()s as we can. If we do any as_warn()s
* then goofed=1. Notice that we don't make any frags yet.
* and we can safely flush it, without causing interpass symbol phase
* errors. That is, without changing label values in different passes.
*/
- if (goofed = (*v.vit_error))
+ if ((goofed = (*v.vit_error)) != 0)
{
- as_warn ("Ignoring statement due to \"%s\"", v.vit_error);
+ as_fatal (_("Ignoring statement due to \"%s\""), v.vit_error);
}
/*
* We need to use expression() and friends, which require us to diddle
save_input_line_pointer = input_line_pointer;
for (operandP = v.vit_operand,
expP = exp_of_operand,
+ segP = seg_of_operand,
floatP = float_operand,
end_operandP = v.vit_operand + v.vit_operands;
operandP < end_operandP;
- operandP++, expP++, floatP++)
+ operandP++, expP++, segP++, floatP++)
{ /* for each operand */
- if (*(operandP->vop_error))
+ if (operandP->vop_error)
{
- as_warn ("Ignoring statement because \"%s\"", (operandP->vop_error));
+ as_fatal (_("Aborting because statement has \"%s\""), operandP->vop_error);
goofed = 1;
}
else
{
- /* statement has no syntax goofs: lets sniff the expression */
- int can_be_short = 0; /* 1 if a bignum can be reduced to a short literal. */
+ /* Statement has no syntax goofs: let's sniff the expression. */
+ int can_be_short = 0; /* 1 if a bignum can be reduced to a short literal. */
input_line_pointer = operandP->vop_expr_begin;
c_save = operandP->vop_expr_end[1];
operandP->vop_expr_end[1] = '\0';
- /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = 1. */
- switch (to_seg = expression (expP))
+ /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = 1. */
+ *segP = expression (expP);
+ switch (expP->X_op)
{
- case SEG_ABSENT:
+ case O_absent:
/* for BSD4.2 compatibility, missing expression is absolute 0 */
- to_seg = expP->X_seg = SEG_ABSOLUTE;
+ expP->X_op = O_constant;
expP->X_add_number = 0;
- /* For SEG_ABSOLUTE, we shouldn't need to set X_subtract_symbol,
+ /* For SEG_ABSOLUTE, we shouldn't need to set X_op_symbol,
X_add_symbol to any particular value. But, we will program
defensively. Since this situation occurs rarely so it costs
us little to do, and stops Dean worrying about the origin of
random bits in expressionS's. */
expP->X_add_symbol = NULL;
- expP->X_subtract_symbol = NULL;
- case SEG_TEXT:
- case SEG_DATA:
- case SEG_BSS:
- case SEG_ABSOLUTE:
- case SEG_UNKNOWN:
+ expP->X_op_symbol = NULL;
break;
- case SEG_DIFFERENCE:
- case SEG_PASS1:
+ case O_symbol:
+ case O_constant:
+ break;
+
+ default:
/*
* Major bug. We can't handle the case of a
- * SEG_DIFFERENCE expression in a VIT_OPCODE_SYNTHETIC
+ * SEG_OP expression in a VIT_OPCODE_SYNTHETIC
* variable-length instruction.
* We don't have a frag type that is smart enough to
- * relax a SEG_DIFFERENCE, and so we just force all
- * SEG_DIFFERENCEs to behave like SEG_PASS1s.
+ * relax a SEG_OP, and so we just force all
+ * SEG_OPs to behave like SEG_PASS1s.
* Clearly, if there is a demand we can invent a new or
* modified frag type and then coding up a frag for this
- * case will be easy. SEG_DIFFERENCE was invented for the
+ * case will be easy. SEG_OP was invented for the
* .words after a CASE opcode, and was never intended for
* instruction operands.
*/
need_pass_2 = 1;
- as_warn ("Can't relocate expression");
+ as_fatal (_("Can't relocate expression"));
break;
- case SEG_BIG:
- /* Preserve the bits. */
+ case O_big:
+ /* Preserve the bits. */
if (expP->X_add_number > 0)
{
bignum_copy (generic_bignum, expP->X_add_number,
flonum_copy (&generic_floating_point_number,
floatP);
if (strchr ("s i", operandP->vop_short))
- { /* Could possibly become S^# */
+ {
+ /* Could possibly become S^# */
flonum_gen2vax (-expP->X_add_number, floatP, literal_float);
switch (-expP->X_add_number)
{
&& operandP->vop_reg == 0xF
&& (operandP->vop_mode & 0xE) == 0x8))
{
- /* Saw a '#'. */
+ /* Saw a '#'. */
if (operandP->vop_short == ' ')
- { /* We must chose S^ or I^. */
+ {
+ /* We must chose S^ or I^. */
if (expP->X_add_number > 0)
- { /* Bignum: Short literal impossible. */
+ {
+ /* Bignum: Short literal impossible. */
operandP->vop_short = 'i';
operandP->vop_mode = 8;
- operandP->vop_reg = 0xF; /* VAX PC. */
+ operandP->vop_reg = 0xF; /* VAX PC. */
}
else
- { /* Flonum: Try to do it. */
+ {
+ /* Flonum: Try to do it. */
if (can_be_short)
{
operandP->vop_short = 's';
operandP->vop_mode = 0;
operandP->vop_ndx = -1;
operandP->vop_reg = -1;
- /* JF hope this is the right thing */
- expP->X_seg = SEG_ABSOLUTE;
+ expP->X_op = O_constant;
}
else
{
operandP->vop_reg = 0xF; /* VAX PC */
}
} /* bignum or flonum ? */
- } /* if #, but no S^ or I^ seen. */
- /* No more ' ' case: either 's' or 'i'. */
+ } /* if #, but no S^ or I^ seen. */
+ /* No more ' ' case: either 's' or 'i'. */
if (operandP->vop_short == 's')
{
- /* Wants to be a short literal. */
+ /* Wants to be a short literal. */
if (expP->X_add_number > 0)
{
- as_warn ("Bignum not permitted in short literal. Immediate mode assumed.");
+ as_warn (_("Bignum not permitted in short literal. Immediate mode assumed."));
operandP->vop_short = 'i';
operandP->vop_mode = 8;
- operandP->vop_reg = 0xF; /* VAX PC. */
+ operandP->vop_reg = 0xF; /* VAX PC. */
}
else
{
if (!can_be_short)
{
- as_warn ("Can't do flonum short literal: immediate mode used.");
+ as_warn (_("Can't do flonum short literal: immediate mode used."));
operandP->vop_short = 'i';
operandP->vop_mode = 8;
- operandP->vop_reg = 0xF; /* VAX PC. */
+ operandP->vop_reg = 0xF; /* VAX PC. */
}
else
- { /* Encode short literal now. */
+ { /* Encode short literal now. */
int temp = 0;
switch (-expP->X_add_number)
} /* flonum or bignum ? */
}
else
- { /* I^# seen: set it up if float. */
+ { /* I^# seen: set it up if float. */
if (expP->X_add_number < 0)
{
memcpy (floatP->low, literal_float, sizeof (literal_float));
}
- } /* if S^# seen. */
+ } /* if S^# seen. */
}
else
{
- as_warn ("A bignum/flonum may not be a displacement: 0x%x used",
- expP->X_add_number = 0x80000000);
- /* Chosen so luser gets the most offset bits to patch later. */
+ as_warn (_("A bignum/flonum may not be a displacement: 0x%lx used"),
+ (expP->X_add_number = 0x80000000L));
+ /* Chosen so luser gets the most offset bits to patch later. */
}
expP->X_add_number = floatP->low[0]
| ((LITTLENUM_MASK & (floatP->low[1])) << LITTLENUM_NUMBER_OF_BITS);
/*
- * For the SEG_BIG case we have:
- * If vop_short == 's' then a short floating literal is in the
- * lowest 6 bits of floatP -> low [0], which is
- * big_operand_bits [---] [0].
- * If vop_short == 'i' then the appropriate number of elements
- * of big_operand_bits [---] [...] are set up with the correct
- * bits.
- * Also, just in case width is byte word or long, we copy the lowest
- * 32 bits of the number to X_add_number.
- */
- break;
-
- default:
- BAD_CASE (to_seg);
+ * For the O_big case we have:
+ * If vop_short == 's' then a short floating literal is in the
+ * lowest 6 bits of floatP -> low [0], which is
+ * big_operand_bits [---] [0].
+ * If vop_short == 'i' then the appropriate number of elements
+ * of big_operand_bits [---] [...] are set up with the correct
+ * bits.
+ * Also, just in case width is byte word or long, we copy the lowest
+ * 32 bits of the number to X_add_number.
+ */
break;
}
if (input_line_pointer != operandP->vop_expr_end + 1)
{
- as_warn ("Junk at end of expression \"%s\"", input_line_pointer);
+ as_fatal ("Junk at end of expression \"%s\"", input_line_pointer);
goofed = 1;
}
operandP->vop_expr_end[1] = c_save;
return;
}
-
- /* Emit op-code. */
- /* Remember where it is, in case we want to modify the op-code later. */
+ /* Emit op-code. */
+ /* Remember where it is, in case we want to modify the op-code later. */
opcode_low_byteP = frag_more (v.vit_opcode_nbytes);
memcpy (opcode_low_byteP, v.vit_opcode, v.vit_opcode_nbytes);
opcode_as_number = md_chars_to_number (opcode_as_chars = v.vit_opcode, 4);
for (operandP = v.vit_operand,
expP = exp_of_operand,
+ segP = seg_of_operand,
floatP = float_operand,
end_operandP = v.vit_operand + v.vit_operands;
operandP++,
floatP++,
+ segP++,
expP++)
- { /* for each operand */
+ {
if (operandP->vop_ndx >= 0)
{
/* indexed addressing byte */
FRAG_APPEND_1_CHAR (0x40 + operandP->vop_ndx);
} /* if(vop_ndx>=0) */
- /* Here to make main operand frag(s). */
+ /* Here to make main operand frag(s). */
this_add_number = expP->X_add_number;
this_add_symbol = expP->X_add_symbol;
- this_subtract_symbol = expP->X_subtract_symbol;
- to_seg = expP->X_seg;
+ to_seg = *segP;
+#ifdef BFD_ASSEMBLER
+ is_undefined = (to_seg == undefined_section);
+ is_absolute = (to_seg == absolute_section);
+#else
is_undefined = (to_seg == SEG_UNKNOWN);
- know (to_seg == SEG_UNKNOWN
- || to_seg == SEG_ABSOLUTE
- || to_seg == SEG_DATA
- || to_seg == SEG_TEXT
- || to_seg == SEG_BSS
- || to_seg == SEG_BIG);
+ is_absolute = (to_seg == SEG_ABSOLUTE);
+#endif
at = operandP->vop_mode & 1;
length = (operandP->vop_short == 'b'
? 1 : (operandP->vop_short == 'w'
{
if (to_seg == now_seg || is_undefined)
{
- /* If is_undefined, then it might BECOME now_seg. */
+ /* If is_undefined, then it might BECOME now_seg. */
if (nbytes)
{
p = frag_more (nbytes);
fix_new (frag_now, p - frag_now->fr_literal, nbytes,
- this_add_symbol, 0, this_add_number, 1, NO_RELOC);
+ this_add_symbol, this_add_number, 1, NO_RELOC);
}
else
{ /* to_seg==now_seg || to_seg == SEG_UNKNOWN */
}
}
else
- { /* to_seg != now_seg && to_seg != SEG_UNKNOWN */
+ {
+ /* to_seg != now_seg && to_seg != SEG_UNKNOWN */
/*
- * --- SEG FLOAT MAY APPEAR HERE ----
- */
- if (to_seg == SEG_ABSOLUTE)
+ * --- SEG FLOAT MAY APPEAR HERE ----
+ */
+ if (is_absolute)
{
if (nbytes)
{
know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
p = frag_more (nbytes);
- /* Conventional relocation. */
- fix_new (frag_now, p - frag_now->fr_literal,
- nbytes, &abs_symbol, 0, this_add_number, 1, NO_RELOC);
+ /* Conventional relocation. */
+ fix_new (frag_now, p - frag_now->fr_literal, nbytes,
+#ifdef BFD_ASSEMBLER
+ section_symbol (absolute_section),
+#else
+ &abs_symbol,
+#endif
+ this_add_number, 1, NO_RELOC);
}
else
{
*opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG;
know (opcode_as_chars[1] == 0);
p = frag_more (5);
- p[0] = VAX_ABSOLUTE_MODE; /* @#... */
+ p[0] = VAX_ABSOLUTE_MODE; /* @#... */
md_number_to_chars (p + 1, this_add_number, 4);
- /* Now (eg) JMP @#foo or JSB @#foo. */
+ /* Now (eg) JMP @#foo or JSB @#foo. */
}
else
{
p[2] = VAX_BRB;
p[3] = 6;
p[4] = VAX_JMP;
- p[5] = VAX_ABSOLUTE_MODE; /* @#... */
+ p[5] = VAX_ABSOLUTE_MODE; /* @#... */
md_number_to_chars (p + 6, this_add_number, 4);
/*
- * Now (eg) ACBx 1f
- * BRB 2f
- * 1: JMP @#foo
- * 2:
- */
+ * Now (eg) ACBx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
}
else
{
p[1] = VAX_BRB;
p[2] = 6;
p[3] = VAX_JMP;
- p[4] = VAX_PC_RELATIVE_MODE + 1; /* @#... */
+ p[4] = VAX_ABSOLUTE_MODE; /* @#... */
md_number_to_chars (p + 5, this_add_number, 4);
/*
- * Now (eg) xOBxxx 1f
- * BRB 2f
- * 1: JMP @#foo
- * 2:
- */
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
}
}
}
{
/* b<cond> */
*opcode_low_byteP ^= 1;
- /* To reverse the condition in a VAX branch, complement the lowest order
- bit. */
+ /* To reverse the condition in a VAX branch,
+ complement the lowest order bit. */
p = frag_more (7);
p[0] = 6;
p[1] = VAX_JMP;
- p[2] = VAX_ABSOLUTE_MODE; /* @#... */
+ p[2] = VAX_ABSOLUTE_MODE; /* @#... */
md_number_to_chars (p + 3, this_add_number, 4);
/*
- * Now (eg) BLEQ 1f
- * JMP @#foo
- * 1:
- */
+ * Now (eg) BLEQ 1f
+ * JMP @#foo
+ * 1:
+ */
}
}
}
else
- { /* to_seg != now_seg && to_seg != SEG_UNKNOWN && to_Seg != SEG_ABSOLUTE */
+ {
+ /* to_seg != now_seg && !is_undefinfed && !is_absolute */
if (nbytes > 0)
{
- /* Pc-relative. Conventional relocation. */
+ /* Pc-relative. Conventional relocation. */
know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
p = frag_more (nbytes);
- fix_new (frag_now, p - frag_now->fr_literal,
- nbytes, &abs_symbol, 0, this_add_number, 1, NO_RELOC);
+ fix_new (frag_now, p - frag_now->fr_literal, nbytes,
+#ifdef BFD_ASSEMBLER
+ section_symbol (absolute_section),
+#else
+ &abs_symbol,
+#endif
+ this_add_number, 1, NO_RELOC);
}
else
{
p[0] = VAX_PC_RELATIVE_MODE;
fix_new (frag_now,
p + 1 - frag_now->fr_literal, 4,
- this_add_symbol, 0,
+ this_add_symbol,
this_add_number, 1, NO_RELOC);
- /* Now eg JMP foo or JSB foo. */
+ /* Now eg JMP foo or JSB foo. */
}
else
{
p[5] = VAX_PC_RELATIVE_MODE;
fix_new (frag_now,
p + 6 - frag_now->fr_literal, 4,
- this_add_symbol, 0,
+ this_add_symbol,
this_add_number, 1, NO_RELOC);
/*
- * Now (eg) ACBx 1f
- * BRB 2f
- * 1: JMP foo
- * 2:
- */
+ * Now (eg) ACBx 1f
+ * BRB 2f
+ * 1: JMP foo
+ * 2:
+ */
}
else
{
p[4] = VAX_PC_RELATIVE_MODE;
fix_new (frag_now,
p + 5 - frag_now->fr_literal,
- 4, this_add_symbol, 0,
+ 4, this_add_symbol,
this_add_number, 1, NO_RELOC);
/*
- * Now (eg) xOBxxx 1f
- * BRB 2f
- * 1: JMP foo
- * 2:
- */
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP foo
+ * 2:
+ */
}
}
}
else
{
know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP);
- *opcode_low_byteP ^= 1; /* Reverse branch condition. */
+ *opcode_low_byteP ^= 1; /* Reverse branch condition. */
p = frag_more (7);
p[0] = 6;
p[1] = VAX_JMP;
p[2] = VAX_PC_RELATIVE_MODE;
fix_new (frag_now, p + 3 - frag_now->fr_literal,
- 4, this_add_symbol, 0,
+ 4, this_add_symbol,
this_add_number, 1, NO_RELOC);
}
}
}
else
{
- know (operandP->vop_access != 'b'); /* So it is ordinary operand. */
- know (operandP->vop_access != ' '); /* ' ' target-independent: elsewhere. */
+ know (operandP->vop_access != 'b'); /* So it is ordinary operand. */
+ know (operandP->vop_access != ' '); /* ' ' target-independent: elsewhere. */
know (operandP->vop_access == 'a'
|| operandP->vop_access == 'm'
|| operandP->vop_access == 'r'
|| operandP->vop_access == 'w');
if (operandP->vop_short == 's')
{
- if (to_seg == SEG_ABSOLUTE)
+ if (is_absolute)
{
- if (this_add_number < 0 || this_add_number >= 64)
+ if (this_add_number >= 64)
{
- as_warn ("Short literal overflow(%d.), immediate mode assumed.", this_add_number);
+ as_warn (_("Short literal overflow(%ld.), immediate mode assumed."),
+ (long) this_add_number);
operandP->vop_short = 'i';
operandP->vop_mode = 8;
operandP->vop_reg = 0xF;
}
else
{
- as_warn ("Forced short literal to immediate mode. now_seg=%s to_seg=%s",
+ as_warn (_("Forced short literal to immediate mode. now_seg=%s to_seg=%s"),
segment_name (now_seg), segment_name (to_seg));
operandP->vop_short = 'i';
operandP->vop_mode = 8;
if (operandP->vop_reg >= 0 && (operandP->vop_mode < 8
|| (operandP->vop_reg != 0xF && operandP->vop_mode < 10)))
{
- /* One byte operand. */
+ /* One byte operand. */
know (operandP->vop_mode > 3);
FRAG_APPEND_1_CHAR (operandP->vop_mode << 4 | operandP->vop_reg);
- /* All 1-bytes except S^# happen here. */
+ /* All 1-bytes except S^# happen here. */
}
else
- { /* {@}{q^}foo{(Rn)} or S^#foo */
+ {
+ /* {@}{q^}foo{(Rn)} or S^#foo */
if (operandP->vop_reg == -1 && operandP->vop_short != 's')
{
/* "{@}{q^}foo" */
if (length == 0)
{
know (operandP->vop_short == ' ');
+ length_code = STATE_BYTE;
+#ifdef OBJ_ELF
+ if (S_IS_EXTERNAL (this_add_symbol)
+ || S_IS_WEAK (this_add_symbol))
+ length_code = STATE_UNDF;
+#endif
p = frag_var (rs_machine_dependent, 10, 2,
- ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE),
+ ENCODE_RELAX (STATE_PC_RELATIVE, length_code),
this_add_symbol, this_add_number,
opcode_low_byteP);
know (operandP->vop_mode == 10 + at);
*p = at << 4;
- /* At is the only context we need to carry to */
- /* other side of relax() process. */
- /* Must be in the correct bit position of VAX */
- /* operand spec. byte. */
+ /* At is the only context we need to carry
+ to other side of relax() process. Must
+ be in the correct bit position of VAX
+ operand spec. byte. */
}
else
{
know (length);
know (operandP->vop_short != ' ');
p = frag_more (length + 1);
- /* JF is this array stuff really going to work? */
p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
fix_new (frag_now, p + 1 - frag_now->fr_literal,
- length, this_add_symbol, 0,
+ length, this_add_symbol,
this_add_number, 1, NO_RELOC);
}
}
{ /* to_seg != now_seg */
if (this_add_symbol == NULL)
{
- know (to_seg == SEG_ABSOLUTE);
- /* Do @#foo: simpler relocation than foo-.(pc) anyway. */
+ know (is_absolute);
+ /* Do @#foo: simpler relocation than foo-.(pc) anyway. */
p = frag_more (5);
- p[0] = VAX_ABSOLUTE_MODE; /* @#... */
+ p[0] = VAX_ABSOLUTE_MODE; /* @#... */
md_number_to_chars (p + 1, this_add_number, 4);
if (length && length != 4)
{
- as_warn ("Length specification ignored. Address mode 9F used");
+ as_warn (_("Length specification ignored. Address mode 9F used"));
}
}
else
/* {@}{q^}other_seg */
know ((length == 0 && operandP->vop_short == ' ')
|| (length > 0 && operandP->vop_short != ' '));
- if (is_undefined)
+ if (is_undefined
+#ifdef OBJ_ELF
+ || S_IS_WEAK(this_add_symbol)
+ || S_IS_EXTERNAL(this_add_symbol)
+#endif
+ )
{
+ switch (length)
+ {
+ default: length_code = STATE_UNDF; break;
+ case 1: length_code = STATE_BYTE; break;
+ case 2: length_code = STATE_WORD; break;
+ case 4: length_code = STATE_LONG; break;
+ }
/*
- * We have a SEG_UNKNOWN symbol. It might
- * turn out to be in the same segment as
- * the instruction, permitting relaxation.
- */
+ * We have a SEG_UNKNOWN symbol. It might
+ * turn out to be in the same segment as
+ * the instruction, permitting relaxation.
+ */
p = frag_var (rs_machine_dependent, 5, 2,
- ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),
+ ENCODE_RELAX (STATE_PC_RELATIVE, length_code),
this_add_symbol, this_add_number,
- 0);
+ opcode_low_byteP);
p[0] = at << 4;
}
else
if (length == 0)
{
know (operandP->vop_short == ' ');
- length = 4; /* Longest possible. */
+ length = 4; /* Longest possible. */
}
p = frag_more (length + 1);
p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
md_number_to_chars (p + 1, this_add_number, length);
fix_new (frag_now,
p + 1 - frag_now->fr_literal,
- length, this_add_symbol, 0,
+ length, this_add_symbol,
this_add_number, 1, NO_RELOC);
}
}
}
}
else
- { /* {@}{q^}foo(Rn) or S^# or I^# or # */
+ {
+ /* {@}{q^}foo(Rn) or S^# or I^# or # */
if (operandP->vop_mode < 0xA)
- { /* # or S^# or I^# */
- /* know( (length == 0 && operandP->vop_short == ' ')
- || (length > 0 && operandP->vop_short != ' ')); */
+ {
+ /* # or S^# or I^# */
+ if (operandP->vop_access == 'v'
+ || operandP->vop_access == 'a')
+ {
+ if (operandP->vop_access == 'v')
+ as_warn (_("Invalid operand: immediate value used as base address."));
+ else
+ as_warn (_("Invalid operand: immediate value used as address."));
+ /* gcc 2.6.3 is known to generate these in at least
+ one case. */
+ }
if (length == 0
- && to_seg == SEG_ABSOLUTE
- && operandP->vop_mode == 8 /* No '@'. */
- && this_add_number < 64
- && this_add_number >= 0)
+ && is_absolute && (expP->X_op != O_big)
+ && operandP->vop_mode == 8 /* No '@'. */
+ && this_add_number < 64)
{
operandP->vop_short = 's';
}
FRAG_APPEND_1_CHAR (this_add_number);
}
else
- { /* I^#... */
+ {
+ /* I^#... */
know (nbytes);
p = frag_more (nbytes + 1);
know (operandP->vop_reg == 0xF);
+#ifdef OBJ_ELF
+ if (flag_want_pic && operandP->vop_mode == 8
+ && this_add_symbol != NULL)
+ {
+ as_warn (_("Symbol used as immediate operand in PIC mode."));
+ }
+#endif
p[0] = (operandP->vop_mode << 4) | 0xF;
- if (to_seg == SEG_ABSOLUTE)
+ if ((is_absolute) && (expP->X_op != O_big))
{
/*
- * If nbytes > 4, then we are scrod. We don't know if the
- * high order bytes are to be 0xFF or 0x00.
- * BSD4.2 & RMS say use 0x00. OK --- but this
- * assembler needs ANOTHER rewrite to
- * cope properly with this bug.
- */
+ * If nbytes > 4, then we are scrod. We
+ * don't know if the high order bytes
+ * are to be 0xFF or 0x00. BSD4.2 & RMS
+ * say use 0x00. OK --- but this
+ * assembler needs ANOTHER rewrite to
+ * cope properly with this bug. */
md_number_to_chars (p + 1, this_add_number, min (4, nbytes));
if (nbytes > 4)
{
}
else
{
- if (to_seg == SEG_BIG)
+ if (expP->X_op == O_big)
{
/*
- * Problem here is to get the bytes in the right order.
- * We stored our constant as LITTLENUMs, not bytes.
- */
+ * Problem here is to get the bytes
+ * in the right order. We stored
+ * our constant as LITTLENUMs, not
+ * bytes. */
LITTLENUM_TYPE *lP;
lP = floatP->low;
else
{
fix_new (frag_now, p + 1 - frag_now->fr_literal,
- nbytes, this_add_symbol, 0,
+ nbytes, this_add_symbol,
this_add_number, 0, NO_RELOC);
}
}
|| (length > 0 && operandP->vop_short != ' '));
if (length == 0)
{
- if (to_seg == SEG_ABSOLUTE)
+ if (is_absolute)
{
- register long test;
+ long test;
test = this_add_number;
know (operandP->vop_reg >= 0);
p[0] = operandP->vop_reg
| ((at | "?\12\14?\16"[length]) << 4);
- if (to_seg == SEG_ABSOLUTE)
+ if (is_absolute)
{
md_number_to_chars (p + 1, this_add_number, length);
}
else
{
fix_new (frag_now, p + 1 - frag_now->fr_literal,
- length, this_add_symbol, 0,
+ length, this_add_symbol,
this_add_number, 0, NO_RELOC);
}
}
} /* for(operandP) */
} /* vax_assemble() */
\f
-/*
- * md_estimate_size_before_relax()
- *
- * Called just before relax().
- * Any symbol that is now undefined will not become defined.
- * Return the correct fr_subtype in the frag.
- * Return the initial "guess for fr_var" to caller.
- * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
- * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
- * Although it may not be explicit in the frag, pretend fr_var starts with a
- * 0 value.
- */
+/* md_estimate_size_before_relax(), called just before relax().
+ Any symbol that is now undefined will not become defined.
+ Return the correct fr_subtype in the frag and the growth beyond
+ fr_fix. */
int
md_estimate_size_before_relax (fragP, segment)
- register fragS *fragP;
- register segT segment;
+ fragS *fragP;
+ segT segment;
{
- register char *p;
- register int old_fr_fix;
-
- old_fr_fix = fragP->fr_fix;
- switch (fragP->fr_subtype)
+ if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF)
{
- case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF):
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
- { /* A relaxable case. */
- fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
- }
- else
+ if (S_GET_SEGMENT (fragP->fr_symbol) != segment
+#ifdef OBJ_ELF
+ || S_IS_WEAK (fragP->fr_symbol)
+ || S_IS_EXTERNAL (fragP->fr_symbol)
+#endif
+ )
{
- p = fragP->fr_literal + old_fr_fix;
- p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */
- fragP->fr_fix += 1 + 4;
- fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
- fragP->fr_offset, 1, NO_RELOC);
- frag_wane (fragP);
- }
- break;
+ /* Non-relaxable cases. */
+ int reloc_type = NO_RELOC;
+ char *p;
+ int old_fr_fix;
- case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
- {
- fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
- }
- else
- {
+ old_fr_fix = fragP->fr_fix;
p = fragP->fr_literal + old_fr_fix;
- *fragP->fr_opcode ^= 1; /* Reverse sense of branch. */
- p[0] = 6;
- p[1] = VAX_JMP;
- p[2] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
- fragP->fr_fix += 1 + 1 + 1 + 4;
- fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol, 0,
- fragP->fr_offset, 1, NO_RELOC);
- frag_wane (fragP);
- }
- break;
+#ifdef OBJ_ELF
+ /* If this is to an undefined symbol, then if it's an indirect
+ reference indicate that is can mutated into a GLOB_DAT or
+ JUMP_SLOT by the loader. We restrict ourselves to no offset
+ due to a limitation in the NetBSD linker. */
+
+ if (GOT_symbol == NULL)
+ GOT_symbol = symbol_find (GLOBAL_OFFSET_TABLE_NAME);
+ if (PLT_symbol == NULL)
+ PLT_symbol = symbol_find (PROCEDURE_LINKAGE_TABLE_NAME);
+ if ((GOT_symbol == NULL || fragP->fr_symbol != GOT_symbol)
+ && (PLT_symbol == NULL || fragP->fr_symbol != PLT_symbol)
+ && fragP->fr_symbol != NULL
+ && flag_want_pic
+ && (!S_IS_DEFINED (fragP->fr_symbol)
+ || S_IS_WEAK (fragP->fr_symbol)
+ || S_IS_EXTERNAL (fragP->fr_symbol)))
+ {
+ if (p[0] & 0x10)
+ {
+ if (flag_want_pic)
+ as_fatal ("PIC reference to %s is indirect.\n",
+ S_GET_NAME (fragP->fr_symbol));
+ }
+ else
+ {
+ if (((unsigned char *) fragP->fr_opcode)[0] == VAX_CALLS
+ || ((unsigned char *) fragP->fr_opcode)[0] == VAX_CALLG
+ || ((unsigned char *) fragP->fr_opcode)[0] == VAX_JSB
+ || ((unsigned char *) fragP->fr_opcode)[0] == VAX_JMP
+ || S_IS_FUNCTION (fragP->fr_symbol))
+ reloc_type = BFD_RELOC_32_PLT_PCREL;
+ else
+ reloc_type = BFD_RELOC_32_GOT_PCREL;
+ }
+ }
+#endif
+ switch (RELAX_STATE (fragP->fr_subtype))
+ {
+ case STATE_PC_RELATIVE:
+ p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, reloc_type);
+ break;
- case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_UNDF):
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
- {
- fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD);
- }
- else
- {
- p = fragP->fr_literal + old_fr_fix;
- p[0] = 2;
- p[1] = 0;
- p[2] = VAX_BRB;
- p[3] = 6;
- p[4] = VAX_JMP;
- p[5] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
- fragP->fr_fix += 2 + 2 + 1 + 1 + 4;
- fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol, 0,
- fragP->fr_offset, 1, NO_RELOC);
- frag_wane (fragP);
- }
- break;
+ case STATE_CONDITIONAL_BRANCH:
+ *fragP->fr_opcode ^= 1; /* Reverse sense of branch. */
+ p[0] = 6;
+ p[1] = VAX_JMP;
+ p[2] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
+ fragP->fr_fix += 1 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ break;
- case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_UNDF):
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
- {
- fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE);
- }
- else
- {
- p = fragP->fr_literal + old_fr_fix;
- p[0] = 2;
- p[1] = VAX_BRB;
- p[2] = 6;
- p[3] = VAX_JMP;
- p[4] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
- fragP->fr_fix += 1 + 2 + 1 + 1 + 4;
- fix_new (fragP, old_fr_fix + 5, 4, fragP->fr_symbol, 0,
- fragP->fr_offset, 1, NO_RELOC);
+ case STATE_COMPLEX_BRANCH:
+ p[0] = 2;
+ p[1] = 0;
+ p[2] = VAX_BRB;
+ p[3] = 6;
+ p[4] = VAX_JMP;
+ p[5] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
+ fragP->fr_fix += 2 + 2 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ break;
+
+ case STATE_COMPLEX_HOP:
+ p[0] = 2;
+ p[1] = VAX_BRB;
+ p[2] = 6;
+ p[3] = VAX_JMP;
+ p[4] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
+ fragP->fr_fix += 1 + 2 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 5, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ break;
+
+ case STATE_ALWAYS_BRANCH:
+ *fragP->fr_opcode += VAX_WIDEN_LONG;
+ p[0] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ break;
+
+ default:
+ abort ();
+ }
frag_wane (fragP);
+
+ /* Return the growth in the fixed part of the frag. */
+ return fragP->fr_fix - old_fr_fix;
}
- break;
- case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF):
- if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
+ /* Relaxable cases. Set up the initial guess for the variable
+ part of the frag. */
+ switch (RELAX_STATE (fragP->fr_subtype))
{
+ case STATE_PC_RELATIVE:
+ fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
+ break;
+ case STATE_CONDITIONAL_BRANCH:
+ fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
+ break;
+ case STATE_COMPLEX_BRANCH:
+ fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD);
+ break;
+ case STATE_COMPLEX_HOP:
+ fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE);
+ break;
+ case STATE_ALWAYS_BRANCH:
fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE);
+ break;
}
- else
- {
- p = fragP->fr_literal + old_fr_fix;
- *fragP->fr_opcode += VAX_WIDEN_LONG;
- p[0] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
- fragP->fr_fix += 1 + 4;
- fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
- fragP->fr_offset, 1, NO_RELOC);
- frag_wane (fragP);
- }
- break;
-
- default:
- break;
}
- return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
-} /* md_estimate_size_before_relax() */
+
+ if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
+ abort ();
+
+ /* Return the size of the variable part of the frag. */
+ return md_relax_table[fragP->fr_subtype].rlx_length;
+}
\f
/*
* md_convert_frag();
* Out: Any fixSs and constants are set up.
* Caller will turn frag into a ".space 0".
*/
+#ifdef BFD_ASSEMBLER
void
-md_convert_frag (headers, fragP)
- object_headers *headers;
- register fragS *fragP;
+md_convert_frag (headers, seg, fragP)
+ bfd *headers ATTRIBUTE_UNUSED;
+ segT seg ATTRIBUTE_UNUSED;
+ fragS *fragP;
+#else
+void
+md_convert_frag (headers, seg, fragP)
+ object_headers *headers ATTRIBUTE_UNUSED;
+ segT seg ATTRIBUTE_UNUSED;
+ fragS *fragP;
+#endif
{
- char *addressP; /* -> _var to change. */
- char *opcodeP; /* -> opcode char(s) to change. */
- short int length_code; /* 2=long 1=word 0=byte */
- short int extension = 0; /* Size of relaxed address. */
- /* Added to fr_fix: incl. ALL var chars. */
+ char *addressP; /* -> _var to change. */
+ char *opcodeP; /* -> opcode char(s) to change. */
+ short int extension = 0; /* Size of relaxed address. */
+ /* Added to fr_fix: incl. ALL var chars. */
symbolS *symbolP;
long where;
- long address_of_var;
- /* Where, in file space, is _var of *fragP? */
- long target_address = 0;
- /* Where, in file space, does addr point? */
know (fragP->fr_type == rs_machine_dependent);
- length_code = fragP->fr_subtype & 3; /* depends on ENCODE_RELAX() */
- know (length_code >= 0 && length_code < 3);
where = fragP->fr_fix;
addressP = fragP->fr_literal + where;
opcodeP = fragP->fr_opcode;
symbolP = fragP->fr_symbol;
know (symbolP);
- target_address = S_GET_VALUE (symbolP) + fragP->fr_offset;
- address_of_var = fragP->fr_address + where;
switch (fragP->fr_subtype)
{
case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE):
- know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
addressP[0] |= 0xAF; /* Byte displacement. */
- addressP[1] = target_address - (address_of_var + 2);
+ fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 2;
break;
case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD):
- know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
addressP[0] |= 0xCF; /* Word displacement. */
- md_number_to_chars (addressP + 1, target_address - (address_of_var + 3), 2);
+ fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 3;
break;
case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG):
- know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */
addressP[0] |= 0xEF; /* Long word displacement. */
- md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4);
+ fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 5;
break;
case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):
- addressP[0] = target_address - (address_of_var + 1);
+ fix_new (fragP, fragP->fr_fix, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 1;
break;
case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
- opcodeP[0] ^= 1; /* Reverse sense of test. */
+ opcodeP[0] ^= 1; /* Reverse sense of test. */
addressP[0] = 3;
- addressP[1] = VAX_BRB + VAX_WIDEN_WORD;
- md_number_to_chars (addressP + 2, target_address - (address_of_var + 4), 2);
+ addressP[1] = VAX_BRW;
+ fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 4;
break;
case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG):
- opcodeP[0] ^= 1; /* Reverse sense of test. */
+ opcodeP[0] ^= 1; /* Reverse sense of test. */
addressP[0] = 6;
addressP[1] = VAX_JMP;
addressP[2] = VAX_PC_RELATIVE_MODE;
- md_number_to_chars (addressP + 3, target_address, 4);
+ fix_new (fragP, fragP->fr_fix + 3, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 7;
break;
case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE):
- addressP[0] = target_address - (address_of_var + 1);
+ fix_new (fragP, fragP->fr_fix, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 1;
break;
case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD):
opcodeP[0] += VAX_WIDEN_WORD; /* brb -> brw, bsbb -> bsbw */
- md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
+ 1, NO_RELOC);
extension = 2;
break;
case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG):
opcodeP[0] += VAX_WIDEN_LONG; /* brb -> jmp, bsbb -> jsb */
addressP[0] = VAX_PC_RELATIVE_MODE;
- md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4);
+ fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 5;
break;
case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD):
- md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 2;
break;
addressP[3] = 6;
addressP[4] = VAX_JMP;
addressP[5] = VAX_PC_RELATIVE_MODE;
- md_number_to_chars (addressP + 6, target_address, 4);
+ fix_new (fragP, fragP->fr_fix + 6, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 10;
break;
case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE):
- addressP[0] = target_address - (address_of_var + 1);
+ fix_new (fragP, fragP->fr_fix, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 1;
break;
addressP[1] = VAX_BRB;
addressP[2] = 3;
addressP[3] = VAX_BRW;
- md_number_to_chars (addressP + 4, target_address - (address_of_var + 6), 2);
+ fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 6;
break;
addressP[2] = 6;
addressP[3] = VAX_JMP;
addressP[4] = VAX_PC_RELATIVE_MODE;
- md_number_to_chars (addressP + 5, target_address, 4);
+ fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
extension = 9;
break;
On vax: first 4 bytes are normal unsigned long, next three bytes
are symbolnum, least sig. byte first. Last byte is broken up with
the upper nibble as nuthin, bit 3 as extern, bits 2 & 1 as length, and
- bit 0 as pcrel. */
+ bit 0 as pcrel. */
#ifdef comment
void
md_ri_to_chars (the_bytes, ri)
#endif /* comment */
-void
+#ifdef OBJ_AOUT
+#ifndef BFD_ASSEMBLER
+void
tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
char *where;
fixS *fixP;
relax_addressT segment_address_in_file;
{
/*
- * In: length of relocation (or of address) in chars: 1, 2 or 4.
- * Out: GNU LD relocation length code: 0, 1, or 2.
- */
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
- static unsigned char nbytes_r_length[] =
- {42, 0, 1, 42, 2};
+ static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2};
long r_symbolnum;
know (fixP->fx_addsy != NULL);
where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08)
| ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
| (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));
-
- return;
-} /* tc_aout_fix_to_chars() */
+}
+#endif /* !BFD_ASSEMBLER */
+#endif /* OBJ_AOUT */
/*
* BUGS, GRIPES, APOLOGIA, etc.
* That is, AFTER we hash it with hash_...(), we want most-used opcodes
* to come out of the hash table faster.
*
- * I am sorry to inflict
- * yet another VAX assembler on the world, but RMS says we must
- * do everything from scratch, to prevent pin-heads restricting
- * this software.
+ * I am sorry to inflict yet another VAX assembler on the world, but
+ * RMS says we must do everything from scratch, to prevent pin-heads
+ * restricting this software.
*/
/*
* source file, and changed the makefile.
*/
-static struct hash_control *op_hash = NULL; /* handle of the OPCODE hash table */
-/* NULL means any use before vip_begin() */
-/* will crash */
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash;
/*
* In: 1 character, from "bdfghloqpw" being the data-type of an operand
static const short int vax_operand_width_size[256] =
{
-
-#define _ 0
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */
- _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */
- _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */
- _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _};
-#undef _
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16, /* ..b.d.fgh...l..o */
+ 0, 8, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* .q.....w........ */
+ 0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16, /* ..b.d.fgh...l..o */
+ 0, 8, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* .q.....w........ */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
\f
/*
* This perversion encodes all the vax opcodes as a bunch of strings.
{"jbcs", {"rlvbb?", 0x800000e3}},
{"jbsc", {"rlvbb?", 0x800000e4}},
{"jbcc", {"rlvbb?", 0x800000e5}},
- {"jbssi", {"rlvbb?", 0x800000e6}},
- {"jbcci", {"rlvbb?", 0x800000e7}},
- {"jlbs", {"rlb?", 0x800000e8}}, /* JF changed from rlvbb? */
- {"jlbc", {"rlb?", 0x800000e9}}, /* JF changed from rlvbb? */
+ {"jlbs", {"rlb?", 0x800000e8}},
+ {"jlbc", {"rlb?", 0x800000e9}},
{"jaoblss", {"rlmlb:", 0xC00000f2}},
{"jaobleq", {"rlmlb:", 0xC00000f3}},
- {"jsobgeq", {"mlb:", 0xC00000f4}}, /* JF was rlmlb: */
- {"jsobgtr", {"mlb:", 0xC00000f5}}, /* JF was rlmlb: */
+ {"jsobgeq", {"mlb:", 0xC00000f4}},
+ {"jsobgtr", {"mlb:", 0xC00000f5}},
-/* CASEx has no branch addresses in our conception of it. */
-/* You should use ".word ..." statements after the "case ...". */
+/* CASEx has no branch addresses in our conception of it. */
+/* You should use ".word ..." statements after the "case ...". */
- {"", ""} /* empty is end sentinel */
+ {"", {"", 0}} /* empty is end sentinel */
}; /* synthetic_votstrs */
\f
*
* Call me once before you decode any lines.
* I decode votstrs into a hash table at op_hash (which I create).
- * I return an error text: hopefully "".
+ * I return an error text or null.
* If you want, I will include the 'synthetic' jXXX instructions in the
* instruction table.
* You must nominate metacharacters for eg DEC's "#", "@", "^".
*/
-char *
+static const char *
vip_begin (synthetic_too, immediate, indirect, displen)
- int synthetic_too; /* 1 means include jXXX op-codes. */
- char *immediate, *indirect, *displen;
+ int synthetic_too; /* 1 means include jXXX op-codes. */
+ const char *immediate, *indirect, *displen;
{
const struct vot *vP; /* scan votstrs */
- char *retval; /* error text */
+ const char *retval = 0; /* error text */
+
+ op_hash = hash_new ();
+
+ for (vP = votstrs; *vP->vot_name && !retval; vP++)
+ retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+
+ if (synthetic_too)
+ for (vP = synthetic_votstrs; *vP->vot_name && !retval; vP++)
+ retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
- if ((op_hash = hash_new ()))
- {
- retval = ""; /* OK so far */
- for (vP = votstrs; *vP->vot_name && !*retval; vP++)
- {
- retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail);
- }
- if (synthetic_too)
- {
- for (vP = synthetic_votstrs; *vP->vot_name && !*retval; vP++)
- {
- retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail);
- }
- }
- }
- else
- {
- retval = "virtual memory exceeded";
- }
#ifndef CONST_TABLE
vip_op_defaults (immediate, indirect, displen);
#endif
- return (retval);
-}
-
-
-/*
- * v i p _ e n d ( )
- *
- * Call me once after you have decoded all lines.
- * I do any cleaning-up needed.
- *
- * We don't have to do any cleanup ourselves: all of our operand
- * symbol table is static, and free()ing it is naughty.
- */
-static void
-vip_end ()
-{
+ return retval;
}
/*
* No argument string should generate such an error string:
* it means a bug in our code, not in the user's text.
*
- * You MUST have called vip_begin() once and vip_end() never before using
- * this function.
+ * You MUST have called vip_begin() once before using this function.
*/
-char * /* "" or bug string */
+static void
vip (vitP, instring)
- struct vit *vitP; /* We build an exploded instruction here. */
- char *instring; /* Text of a vax instruction: we modify. */
+ struct vit *vitP; /* We build an exploded instruction here. */
+ char *instring; /* Text of a vax instruction: we modify. */
{
- register struct vot_wot *vwP; /* How to bit-encode this opcode. */
- register char *p; /* 1/skip whitespace.2/scan vot_how */
- register char *q; /* */
- register char *bug; /* "" or program logic error */
- register unsigned char count; /* counts number of operands seen */
- register struct vop *operandp;/* scan operands in struct vit */
- register char *alloperr; /* error over all operands */
- register char c; /* Remember char, (we clobber it */
- /* with '\0' temporarily). */
- register vax_opcodeT oc; /* Op-code of this instruction. */
-
- char *vip_op ();
-
- bug = "";
+ /* How to bit-encode this opcode. */
+ struct vot_wot *vwP;
+ /* 1/skip whitespace.2/scan vot_how */
+ char *p;
+ char *q;
+ /* counts number of operands seen */
+ unsigned char count;
+ /* scan operands in struct vit */
+ struct vop *operandp;
+ /* error over all operands */
+ const char *alloperr;
+ /* Remember char, (we clobber it with '\0' temporarily). */
+ char c;
+ /* Op-code of this instruction. */
+ vax_opcodeT oc;
+
if (*instring == ' ')
- ++instring; /* Skip leading whitespace. */
- for (p = instring; *p && *p != ' '; p++);; /* MUST end in end-of-string or exactly 1 space. */
- /* Scanned up to end of operation-code. */
- /* Operation-code is ended with whitespace. */
+ ++instring; /* Skip leading whitespace. */
+ for (p = instring; *p && *p != ' '; p++);; /* MUST end in end-of-string or exactly 1 space. */
+ /* Scanned up to end of operation-code. */
+ /* Operation-code is ended with whitespace. */
if (p - instring == 0)
{
- vitP->vit_error = "No operator";
+ vitP->vit_error = _("No operator");
count = 0;
memset (vitP->vit_opcode, '\0', sizeof (vitP->vit_opcode));
}
* We trust instring points to an op-name, with no whitespace.
*/
vwP = (struct vot_wot *) hash_find (op_hash, instring);
- *p = c; /* Restore char after op-code. */
+ *p = c; /* Restore char after op-code. */
if (vwP == 0)
{
- vitP->vit_error = "Unknown operator";
+ vitP->vit_error = _("Unknown operator");
count = 0;
memset (vitP->vit_opcode, '\0', sizeof (vitP->vit_opcode));
}
else
{
/*
- * We found a match! So lets pick up as many operands as the
+ * We found a match! So let's pick up as many operands as the
* instruction wants, and even gripe if there are too many.
- * We expect comma to seperate each operand.
+ * We expect comma to separate each operand.
* We let instring track the text, while p tracks a part of the
* struct vot.
*/
+ const char *howp;
/*
* The lines below know about 2-byte opcodes starting FD,FE or FF.
* They also understand synthetic opcodes. Note:
* we return 32 bits of opcode, including bucky bits, BUT
* an opcode length is either 8 or 16 bits for vit_opcode_nbytes.
*/
- oc = vwP->vot_code; /* The op-code. */
+ oc = vwP->vot_code; /* The op-code. */
vitP->vit_opcode_nbytes = (oc & 0xFF) >= 0xFD ? 2 : 1;
md_number_to_chars (vitP->vit_opcode, oc, 4);
count = 0; /* no operands seen yet */
instring = p; /* point just past operation code */
alloperr = "";
- for (p = vwP->vot_how, operandp = vitP->vit_operand;
- !*alloperr && !*bug && *p;
- operandp++, p += 2
- )
+ for (howp = vwP->vot_how, operandp = vitP->vit_operand;
+ !(alloperr && *alloperr) && *howp;
+ operandp++, howp += 2)
{
/*
* Here to parse one operand. Leave instring pointing just
* past any one ',' that marks the end of this operand.
*/
- if (!p[1])
- bug = "p"; /* ODD(!!) number of bytes in vot_how?? */
+ if (!howp[1])
+ as_fatal (_("odd number of bytes in operand description"));
else if (*instring)
{
for (q = instring; (c = *q) && c != ','; q++)
* character.
*/
*q = 0;
- operandp->vop_width = p[1];
- operandp->vop_nbytes = vax_operand_width_size[p[1]];
- operandp->vop_access = p[0];
- bug = vip_op (instring, operandp);
- *q = c; /* Restore input text. */
- if (*(operandp->vop_error))
- alloperr = "Bad operand";
+ operandp->vop_width = howp[1];
+ operandp->vop_nbytes = vax_operand_width_size[(unsigned) howp[1]];
+ operandp->vop_access = howp[0];
+ vip_op (instring, operandp);
+ *q = c; /* Restore input text. */
+ if (operandp->vop_error)
+ alloperr = _("Bad operand");
instring = q + (c ? 1 : 0); /* next operand (if any) */
count++; /* won another argument, may have an operr */
}
else
- alloperr = "Not enough operands";
+ alloperr = _("Not enough operands");
}
if (!*alloperr)
{
if (*instring == ' ')
- instring++; /* Skip whitespace. */
+ instring++; /* Skip whitespace. */
if (*instring)
- alloperr = "Too many operands";
+ alloperr = _("Too many operands");
}
vitP->vit_error = alloperr;
}
}
vitP->vit_operands = count;
- return (bug);
}
\f
#ifdef test
char *mybug; /* "" or an internal logic diagnostic */
int mycount; /* number of operands */
struct vop *myvop; /* scan operands from myvit */
-int mysynth; /* 1 means want synthetic opcodes. */
+int mysynth; /* 1 means want synthetic opcodes. */
char my_immediate[200];
char my_indirect[200];
char my_displen[200];
-char *vip ();
-
main ()
{
char *p;
- char *vip_begin ();
printf ("0 means no synthetic instructions. ");
printf ("Value for vip_begin? ");
gets (my_indirect);
printf ("enter displen symbols eg enter ^ ");
gets (my_displen);
- if (*(p = vip_begin (mysynth, my_immediate, my_indirect, my_displen)))
+ if (p = vip_begin (mysynth, my_immediate, my_indirect, my_displen))
{
error ("vip_begin=%s", p);
}
{
break; /* out of for each input text loop */
}
- mybug = vip (&myvit, answer);
- if (*mybug)
- {
- printf ("BUG:\"%s\"\n", mybug);
- }
+ vip (&myvit, answer);
if (*myvit.vit_error)
{
printf ("ERR:\"%s\"\n", myvit.vit_error);
putchar (*p);
}
printf ("\"\n");
- if (*myvop->vop_error)
+ if (myvop->vop_error)
{
printf (" err:\"%s\"\n", myvop->vop_error);
}
- if (*myvop->vop_warn)
+ if (myvop->vop_warn)
{
printf (" wrn:\"%s\"\n", myvop->vop_warn);
}
}
}
vip_end ();
- exit ();
+ exit (EXIT_SUCCESS);
}
#endif /* #ifdef test */
/* end of vax_ins_parse.c */
-/* JF this used to be a separate file also */
/* vax_reg_parse.c - convert a VAX register name to a number */
-/* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU. */
+/* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU. */
/*
* v a x _ r e g _ p a r s e ( )
*
*/
-#include <ctype.h>
+#include "safe-ctype.h"
#define AP (12)
#define FP (13)
#define SP (14)
#define PC (15)
\f
int /* return -1 or 0:15 */
-vax_reg_parse (c1, c2, c3) /* 3 chars of register name */
- char c1, c2, c3; /* c3 == 0 if 2-character reg name */
+vax_reg_parse (c1, c2, c3, c4) /* 3 chars of register name */
+ char c1, c2, c3, c4; /* c3 == 0 if 2-character reg name */
{
- register int retval; /* return -1:15 */
+ int retval; /* return -1:15 */
retval = -1;
- if (isupper (c1))
- c1 = tolower (c1);
- if (isupper (c2))
- c2 = tolower (c2);
- if (isdigit (c2) && c1 == 'r')
+#ifdef OBJ_ELF
+ if (c1 != '%') /* register prefixes are mandatory for ELF */
+ return retval;
+ c1 = c2;
+ c2 = c3;
+ c3 = c4;
+#endif
+#ifdef OBJ_VMS
+ if (c4 != 0) /* register prefixes are not allowed under VMS */
+ return retval;
+#endif
+#ifdef OBJ_AOUT
+ if (c1 == '%') /* register prefixes are optional under a.out */
+ {
+ c1 = c2;
+ c2 = c3;
+ c3 = c4;
+ }
+ else if (c3 && c4) /* can't be 4 characters long. */
+ return retval;
+#endif
+
+ c1 = TOLOWER (c1);
+ c2 = TOLOWER (c2);
+ if (ISDIGIT (c2) && c1 == 'r')
{
retval = c2 - '0';
- if (isdigit (c3))
+ if (ISDIGIT (c3))
{
retval = retval * 10 + c3 - '0';
retval = (retval > 15) ? -1 : retval;
* There were a number of 'mismatched argument type' bugs to vip_op.
* The most general solution is to typedef each (of many) arguments.
* We used instead a typedef'd argument block. This is less modular
- * than using seperate return pointers for each result, but runs faster
+ * than using separate return pointers for each result, but runs faster
* on most engines, and seems to keep programmers happy. It will have
* to be done properly if we ever want to use vip_op as a general-purpose
* module (it was designed to be).
* if the other outputs are to be taken seriously.
*/
-
-/* vax registers we need to know */
-/* JF #define SP (14) */
-/* JF for one big happy file #define PC (15) */
-
/*
* Because this module is useful for both VMS and UN*X style assemblers
* and because of the variety of UN*X assemblers we must recognise
#define S VIP_INDIRECT,
#define D VIP_DISPLEN,
static const char
- vip_metacharacters[256] =
+vip_metacharacters[256] =
{
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /* ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O*/
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /* ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
#else
static char vip_metacharacters[256];
-/* Macro is faster under GCC; The constant table is faster yet, but only works with ASCII */
-#if 0
-static
-#ifdef __GNUC__
- inline
-#endif
static void
vip_op_1 (bit, syms)
int bit;
- char *syms;
+ const char *syms;
{
unsigned char t;
- while (t = *syms++)
+ while ((t = *syms++) != 0)
vip_metacharacters[t] |= bit;
}
-#else
-#define vip_op_1(bit,syms) { \
- unsigned char t; \
- char *table=vip_metacharacters; \
- while(t= *syms++) \
- table[t]|=bit; \
- }
-#endif
-
-static void
-vip_op_defaults (immediate, indirect, displen) /* can be called any time */
- char *immediate; /* Strings of characters for each job. */
- char *indirect;
- char *displen; /* more arguments may appear in future! */
+/* Can be called any time. More arguments may appear in future. */
+static void
+vip_op_defaults (immediate, indirect, displen)
+ const char *immediate;
+ const char *indirect;
+ const char *displen;
{
vip_op_1 (VIP_IMMEDIATE, immediate);
vip_op_1 (VIP_INDIRECT, indirect);
vip_op_1 (VIP_DISPLEN, displen);
-
- return;
}
#endif
* We don't limit your choice of width character.
*
* DEC operands are hard work to parse. For example, '@' as the first
- * character means indirect (deferred) mode but elswhere it is a shift
+ * character means indirect (deferred) mode but elsewhere it is a shift
* operator.
* The long-winded explanation of how this is supposed to work is
* cancelled. Read a DEC vax manual.
* Again, I dare not explain it: just trace ALL the code!
*/
\f
-char * /* (code here) bug message, "" = OK */
-/* our code bug, NOT bad assembly language */
+static void
vip_op (optext, vopP)
/* user's input string e.g.: "@B^foo@bar(AP)[FP]:" */
char *optext;
/* Input fields: vop_access, vop_width.
Output fields: _ndx, _reg, _mode, _short, _warn,
_error _expr_begin, _expr_end, _nbytes.
- vop_nbytes : number of bytes in a datum. */
+ vop_nbytes : number of bytes in a datum. */
struct vop *vopP;
{
- char *p; /* track operand text forward */
- char *q; /* track operand text backward */
- int at; /* 1 if leading '@' ('*') seen */
- char len; /* one of " bilsw" */
- int hash; /* 1 if leading '#' ('$') seen */
- int sign = 0; /* -1, 0 or +1 */
- int paren = 0; /* 1 if () surround register */
- int reg = 0; /* register number, -1:absent */
- int ndx = 0; /* index register number -1:absent */
- char *bug; /* report any logic error in here, ""==OK */
- char *err; /* report illegal operand, ""==OK */
+ /* track operand text forward */
+ char *p;
+ /* track operand text backward */
+ char *q;
+ /* 1 if leading '@' ('*') seen */
+ int at;
+ /* one of " bilsw" */
+ char len;
+ /* 1 if leading '#' ('$') seen */
+ int hash;
+ /* -1, 0 or +1 */
+ int sign = 0;
+ /* 1 if () surround register */
+ int paren = 0;
+ /* register number, -1:absent */
+ int reg = 0;
+ /* index register number -1:absent */
+ int ndx = 0;
+ /* report illegal operand, ""==OK */
/* " " is a FAKE error: means we won */
- /* ANY err that begins with ' ' is a fake. */
+ /* ANY err that begins with ' ' is a fake. */
/* " " is converted to "" before return */
- char *wrn; /* warn about weird modes pf address */
- char *oldq = NULL; /* preserve q in case we backup */
- int mode = 0; /* build up 4-bit operand mode here */
+ const char *err;
+ /* warn about weird modes pf address */
+ const char *wrn;
+ /* preserve q in case we backup */
+ char *oldq = NULL;
+ /* build up 4-bit operand mode here */
/* note: index mode is in ndx, this is */
/* the major mode of operand address */
+ int mode = 0;
/*
- * Notice how we move wrong-arg-type bugs INSIDE this module: if we
- * get the types wrong below, we lose at compile time rather than at
- * lint or run time.
- */
- char access; /* vop_access. */
- char width; /* vop_width. */
-
- int vax_reg_parse (); /* returns 0:15 or -1 if not a register */
+ * Notice how we move wrong-arg-type bugs INSIDE this module: if we
+ * get the types wrong below, we lose at compile time rather than at
+ * lint or run time.
+ */
+ char access_mode; /* vop_access. */
+ char width; /* vop_width. */
- access = vopP->vop_access;
+ access_mode = vopP->vop_access;
width = vopP->vop_width;
- bug = /* none of our code bugs (yet) */
- err = /* no user text errors */
- wrn = ""; /* no warnings even */
+ /* None of our code bugs (yet), no user text errors, no warnings
+ even. */
+ err = wrn = 0;
p = optext;
- if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
p++; /* skip over whitespace */
- if (at = INDIRECTP (*p))
+ if ((at = INDIRECTP (*p)) != 0)
{ /* 1 if *p=='@'(or '*' for Un*x) */
p++; /* at is determined */
- if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
p++; /* skip over whitespace */
}
/*
- * This code is subtle. It tries to detect all legal (letter)'^'
- * but it doesn't waste time explicitly testing for premature '\0' because
- * this case is rejected as a mismatch against either (letter) or '^'.
- */
+ * This code is subtle. It tries to detect all legal (letter)'^'
+ * but it doesn't waste time explicitly testing for premature '\0' because
+ * this case is rejected as a mismatch against either (letter) or '^'.
+ */
{
- register char c;
+ char c;
c = *p;
- if (isupper (c))
- c = tolower (c);
+ c = TOLOWER (c);
if (DISPLENP (p[1]) && strchr ("bilws", len = c))
p += 2; /* skip (letter) '^' */
else /* no (letter) '^' seen */
len = ' '; /* len is determined */
}
- if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
p++; /* skip over whitespace */
- if (hash = IMMEDIATEP (*p)) /* 1 if *p=='#' ('$' for Un*x) */
+ if ((hash = IMMEDIATEP (*p)) != 0) /* 1 if *p=='#' ('$' for Un*x) */
p++; /* hash is determined */
/*
- * p points to what may be the beginning of an expression.
- * We have peeled off the front all that is peelable.
- * We know at, len, hash.
- *
- * Lets point q at the end of the text and parse that (backwards).
- */
+ * p points to what may be the beginning of an expression.
+ * We have peeled off the front all that is peelable.
+ * We know at, len, hash.
+ *
+ * Lets point q at the end of the text and parse that (backwards).
+ */
for (q = p; *q; q++)
;
q--; /* now q points at last char of text */
\f
- if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
q--;
/* reverse over whitespace, but don't */
/* run back over *p */
/*
- * As a matter of policy here, we look for [Rn], although both Rn and S^#
- * forbid [Rn]. This is because it is easy, and because only a sick
- * cyborg would have [...] trailing an expression in a VAX-like assembler.
- * A meticulous parser would first check for Rn followed by '(' or '['
- * and not parse a trailing ']' if it found another. We just ban expressions
- * ending in ']'.
- */
+ * As a matter of policy here, we look for [Rn], although both Rn and S^#
+ * forbid [Rn]. This is because it is easy, and because only a sick
+ * cyborg would have [...] trailing an expression in a VAX-like assembler.
+ * A meticulous parser would first check for Rn followed by '(' or '['
+ * and not parse a trailing ']' if it found another. We just ban expressions
+ * ending in ']'.
+ */
if (*q == ']')
{
while (q >= p && *q != '[')
q--;
/* either q<p or we got matching '[' */
if (q < p)
- err = "no '[' to match ']'";
+ err = _("no '[' to match ']'");
else
{
/*
* name error. So again we don't need to check for early '\0'.
*/
if (q[3] == ']')
- ndx = vax_reg_parse (q[1], q[2], 0);
+ ndx = vax_reg_parse (q[1], q[2], 0, 0);
else if (q[4] == ']')
- ndx = vax_reg_parse (q[1], q[2], q[3]);
+ ndx = vax_reg_parse (q[1], q[2], q[3], 0);
+ else if (q[5] == ']')
+ ndx = vax_reg_parse (q[1], q[2], q[3], q[4]);
else
ndx = -1;
/*
- * Since we saw a ']' we will demand a register name in the [].
- * If luser hasn't given us one: be rude.
- */
+ * Since we saw a ']' we will demand a register name in the [].
+ * If luser hasn't given us one: be rude.
+ */
if (ndx < 0)
- err = "bad register in []";
+ err = _("bad register in []");
else if (ndx == PC)
- err = "[PC] index banned";
+ err = _("[PC] index banned");
else
q--; /* point q just before "[...]" */
}
ndx = -1; /* no ']', so no iNDeX register */
/*
- * If err = "..." then we lost: run away.
- * Otherwise ndx == -1 if there was no "[...]".
- * Otherwise, ndx is index register number, and q points before "[...]".
- */
+ * If err = "..." then we lost: run away.
+ * Otherwise ndx == -1 if there was no "[...]".
+ * Otherwise, ndx is index register number, and q points before "[...]".
+ */
\f
- if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
q--;
/* reverse over whitespace, but don't */
/* run back over *p */
- if (!*err)
+ if (!err || !*err)
{
sign = 0; /* no ()+ or -() seen yet */
q--;
/* either q<p or we got matching '(' */
if (q < p)
- err = "no '(' to match ')'";
+ err = _("no '(' to match ')'");
else
{
/*
* name error. So again we don't need to check for early '\0'.
*/
if (q[3] == ')')
- reg = vax_reg_parse (q[1], q[2], 0);
+ reg = vax_reg_parse (q[1], q[2], 0, 0);
else if (q[4] == ')')
- reg = vax_reg_parse (q[1], q[2], q[3]);
+ reg = vax_reg_parse (q[1], q[2], q[3], 0);
+ else if (q[5] == ')')
+ reg = vax_reg_parse (q[1], q[2], q[3], q[4]);
else
reg = -1;
/*
*/
if (reg < 0)
{
- /* JF allow parenthasized expressions. I hope this works */
+ /* JF allow parenthesized expressions. I hope this works */
paren = 0;
while (*q != ')')
q++;
* We don't check len. We want a specific error message later if
* user tries "x^...-(Rn)". This is a feature not a bug.
*/
- if (!*err)
+ if (!err || !*err)
{
if (paren && sign < 1)/* !sign is adequate test */
{
*/
if (!paren)
{
- if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
q--;
/* reverse over whitespace, but don't */
/* run back over *p */
- if (q > p && q < p + 3) /* room for Rn or Rnn exactly? */
- reg = vax_reg_parse (p[0], p[1], q < p + 2 ? 0 : p[2]);
+ /* room for Rn or Rnn (include prefix) exactly? */
+ if (q > p && q < p + 4)
+ reg = vax_reg_parse (p[0], p[1],
+ q < p + 2 ? 0 : p[2],
+ q < p + 3 ? 0 : p[3]);
else
reg = -1; /* always comes here if no register at all */
/*
* err " " or error message, and other outputs trashed
*/
/* branch operands have restricted forms */
- if (!*err && access == 'b')
+ if ((!err || !*err) && access_mode == 'b')
{
if (at || hash || sign || paren || ndx >= 0 || reg >= 0 || len != ' ')
- err = "invalid branch operand";
+ err = _("invalid branch operand");
else
err = " ";
}
\f
- /* Since nobody seems to use it: comment this 'feature'(?) out for now. */
+ /* Since nobody seems to use it: comment this 'feature'(?) out for now. */
#ifdef NEVER
/*
* Case of stand-alone operand. e.g. ".long foo"
* ndx -1
* err " " or error message, and other outputs trashed
*/
- if (!*err)
+ if ((!err || !*err) && access_mode == ' ')
{
- if (access == ' ')
- { /* addresses have restricted forms */
- if (at)
- err = "address prohibits @";
+ if (at)
+ err = _("address prohibits @");
+ else if (hash)
+ err = _("address prohibits #");
+ else if (sign)
+ {
+ if (sign < 0)
+ err = _("address prohibits -()");
else
- {
- if (hash)
- err = "address prohibits #";
- else
- {
- if (sign)
- {
- if (sign < 0)
- err = "address prohibits -()";
- else
- err = "address prohibits ()+";
- }
- else
- {
- if (paren)
- err = "address prohibits ()";
- else
- {
- if (ndx >= 0)
- err = "address prohibits []";
- else
- {
- if (reg >= 0)
- err = "address prohibits register";
- else
- {
- if (len != ' ')
- err = "address prohibits displacement length specifier";
- else
- {
- err = " "; /* succeed */
- mode = 0;
- }
- }
- }
- }
- }
- }
- }
+ err = _("address prohibits ()+");
+ }
+ else if (paren)
+ err = _("address prohibits ()");
+ else if (ndx >= 0)
+ err = _("address prohibits []");
+ else if (reg >= 0)
+ err = _("address prohibits register");
+ else if (len != ' ')
+ err = _("address prohibits displacement length specifier");
+ else
+ {
+ err = " "; /* succeed */
+ mode = 0;
}
}
#endif /*#Ifdef NEVER*/
* exp
* ndx -1
*/
- if (!*err && len == 's')
+ if ((!err || !*err) && len == 's')
{
if (!hash || paren || at || ndx >= 0)
- err = "invalid operand of S^#";
+ err = _("invalid operand of S^#");
else
{
if (reg >= 0)
reg = 0;
}
/*
- * We have all the expression we will ever get.
- */
+ * We have all the expression we will ever get.
+ */
if (p > q)
- err = "S^# needs expression";
- else if (access == 'r')
+ err = _("S^# needs expression");
+ else if (access_mode == 'r')
{
err = " "; /* WIN! */
mode = 0;
}
else
- err = "S^# may only read-access";
+ err = _("S^# may only read-access");
}
}
\f
* exp "" enforce empty expression
* ndx optional warn if same as reg
*/
- if (!*err && sign < 0)
+ if ((!err || !*err) && sign < 0)
{
if (len != ' ' || hash || at || p <= q)
- err = "invalid operand of -()";
+ err = _("invalid operand of -()");
else
{
err = " "; /* win */
mode = 7;
if (reg == PC)
- wrn = "-(PC) unpredictable";
+ wrn = _("-(PC) unpredictable");
else if (reg == ndx)
- wrn = "[]index same as -()register: unpredictable";
+ wrn = _("[]index same as -()register: unpredictable");
}
}
\f
* exp "" enforce empty expression
* ndx optional warn if same as reg
*/
- if (!*err && sign > 0)
+ if ((!err || !*err) && sign > 0)
{
if (len != ' ' || hash || p <= q)
- err = "invalid operand of ()+";
+ err = _("invalid operand of ()+");
else
{
err = " "; /* win */
mode = 8 + (at ? 1 : 0);
if (reg == PC)
- wrn = "(PC)+ unpredictable";
+ wrn = _("(PC)+ unpredictable");
else if (reg == ndx)
- wrn = "[]index same as ()+register: unpredictable";
+ wrn = _("[]index same as ()+register: unpredictable");
}
}
\f
* exp
* ndx optional
*/
- if (!*err && hash)
+ if ((!err || !*err) && hash)
{
if (len != 'i' && len != ' ')
- err = "# conflicts length";
+ err = _("# conflicts length");
else if (paren)
- err = "# bars register";
+ err = _("# bars register");
else
{
if (reg >= 0)
err = " "; /* win */
/* JF a bugfix, I think! */
- if (at && access == 'a')
+ if (at && access_mode == 'a')
vopP->vop_nbytes = 4;
mode = (at ? 9 : 8);
reg = PC;
- if ((access == 'm' || access == 'w') && !at)
- wrn = "writing or modifying # is unpredictable";
+ if ((access_mode == 'm' || access_mode == 'w') && !at)
+ wrn = _("writing or modifying # is unpredictable");
}
}
/*
*/
\f
/*
- * Case of Rn. We seperate this one because it has a few special
+ * Case of Rn. We separate this one because it has a few special
* errors the remaining modes lack.
*
* in: at optional
* exp "" enforce empty expression
* ndx optional warn if same as reg
*/
- if (!*err && !paren && reg >= 0)
+ if ((!err || !*err) && !paren && reg >= 0)
{
if (len != ' ')
- err = "length not needed";
+ err = _("length not needed");
else if (at)
{
err = " "; /* win */
mode = 6; /* @Rn */
}
else if (ndx >= 0)
- err = "can't []index a register, because it has no address";
- else if (access == 'a')
- err = "a register has no address";
+ err = _("can't []index a register, because it has no address");
+ else if (access_mode == 'a')
+ err = _("a register has no address");
else
{
/*
* Compute highest byte affected, compare to PC0.
*/
if ((vopP->vop_nbytes + reg * 4) > 60)
- wrn = "PC part of operand unpredictable";
+ wrn = _("PC part of operand unpredictable");
err = " "; /* win */
mode = 5; /* Rn */
}
}
/*
- * If !*err, sign == 0
- * hash == 0
- * paren == 1 OR reg==-1
- */
+ * If !*err, sign == 0
+ * hash == 0
+ * paren == 1 OR reg==-1
+ */
\f
/*
- * Rest of cases fit into one bunch.
- *
- * in: at optional
- * len ' ' or 'b' or 'w' or 'l'
- * hash 0 by program logic
- * p:q expected (empty is not an error)
- * sign 0 by program logic
- * paren optional
- * reg optional
- * ndx optional
- *
- * out: mode 10 + @ + len
- * reg optional
- * len ' ' or 'b' or 'w' or 'l'
- * exp maybe empty
- * ndx optional warn if same as reg
- */
- if (!*err)
+ * Rest of cases fit into one bunch.
+ *
+ * in: at optional
+ * len ' ' or 'b' or 'w' or 'l'
+ * hash 0 by program logic
+ * p:q expected (empty is not an error)
+ * sign 0 by program logic
+ * paren optional
+ * reg optional
+ * ndx optional
+ *
+ * out: mode 10 + @ + len
+ * reg optional
+ * len ' ' or 'b' or 'w' or 'l'
+ * exp maybe empty
+ * ndx optional warn if same as reg
+ */
+ if (!err || !*err)
{
err = " "; /* win (always) */
mode = 10 + (at ? 1 : 0);
*/
if (*err == ' ')
- err = ""; /* " " is no longer an error */
+ err = 0; /* " " is no longer an error */
vopP->vop_mode = mode;
vopP->vop_reg = reg;
vopP->vop_ndx = ndx;
vopP->vop_error = err;
vopP->vop_warn = wrn;
- return (bug);
-
-} /* vip_op() */
+}
\f
/*
*/
\f
-#ifdef TEST /* #Define to use this testbed. */
+#ifdef TEST /* #Define to use this testbed. */
/*
* Follows a test program for this function.
main ()
{
- char *vip_op (); /* make cc happy */
-
printf ("enter immediate symbols eg enter # ");
gets (my_immediate);
printf ("enter indirect symbols eg enter @ ");
fflush (stdout);
gets (answer);
if (!answer[0])
- exit (0);
+ exit (EXIT_SUCCESS);
myaccess = answer[0];
mywidth = answer[1];
switch (mywidth)
/* end: vip_op.c */
-const int md_short_jump_size = 3;
-const int md_long_jump_size = 6;
+int md_short_jump_size = 3;
+int md_long_jump_size = 6;
const int md_reloc_size = 8; /* Size of relocation record */
void
md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
- addressT from_addr, to_addr;
- fragS *frag;
- symbolS *to_symbol;
+ addressT from_addr;
+ addressT to_addr ATTRIBUTE_UNUSED;
+ fragS *frag ATTRIBUTE_UNUSED;
+ symbolS *to_symbol ATTRIBUTE_UNUSED;
{
valueT offset;
- offset = to_addr - (from_addr + 1);
- *ptr++ = 0x31;
+ /* This former calculation was off by two:
+ offset = to_addr - (from_addr + 1);
+ We need to account for the one byte instruction and also its
+ two byte operand. */
+ offset = to_addr - (from_addr + 1 + 2);
+ *ptr++ = VAX_BRW; /* branch with word (16 bit) offset */
md_number_to_chars (ptr, offset, 2);
}
void
md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
char *ptr;
- addressT from_addr, to_addr;
+ addressT from_addr ATTRIBUTE_UNUSED;
+ addressT to_addr;
fragS *frag;
symbolS *to_symbol;
{
valueT offset;
offset = to_addr - S_GET_VALUE (to_symbol);
- *ptr++ = 0x17;
- *ptr++ = 0x9F;
+ *ptr++ = VAX_JMP; /* arbitrary jump */
+ *ptr++ = VAX_ABSOLUTE_MODE;
md_number_to_chars (ptr, offset, 4);
- fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (symbolS *) 0, (long) 0, 0, NO_RELOC);
+ fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (long) 0, 0, NO_RELOC);
}
+\f
+#ifdef OBJ_VMS
+const char *md_shortopts = "d:STt:V+1h:Hv::";
+#elif defined(OBJ_ELF)
+const char *md_shortopts = "d:STt:VkKQ:";
+#else
+const char *md_shortopts = "d:STt:V";
+#endif
+struct option md_longopts[] = {
+#ifdef OBJ_ELF
+#define OPTION_PIC (OPTION_MD_BASE)
+ {"pic", no_argument, NULL, OPTION_PIC},
+#endif
+ {NULL, no_argument, NULL, 0}
+};
+size_t md_longopts_size = sizeof (md_longopts);
int
-md_parse_option (argP, cntP, vecP)
- char **argP;
- int *cntP;
- char ***vecP;
+md_parse_option (c, arg)
+ int c;
+ char *arg;
{
- char *temp_name; /* name for -t or -d options */
- char opt;
-
- switch (**argP)
+ switch (c)
{
- case 'J':
- /* as_warn ("I can do better than -J!"); */
- break;
-
case 'S':
- as_warn ("SYMBOL TABLE not implemented");
- break; /* SYMBOL TABLE not implemented */
+ as_warn (_("SYMBOL TABLE not implemented"));
+ break;
case 'T':
- as_warn ("TOKEN TRACE not implemented");
- break; /* TOKEN TRACE not implemented */
+ as_warn (_("TOKEN TRACE not implemented"));
+ break;
case 'd':
- case 't':
- opt = **argP;
- if (**argP)
- { /* Rest of argument is filename. */
- temp_name = *argP;
- while (**argP)
- (*argP)++;
- }
- else if (*cntP)
- {
- while (**argP)
- (*argP)++;
- --(*cntP);
- temp_name = *++(*vecP);
- **vecP = NULL; /* Remember this is not a file-name. */
- }
- else
- {
- as_warn ("I expected a filename after -%c.", opt);
- temp_name = "{absent}";
- }
+ as_warn (_("Displacement length %s ignored!"), arg);
+ break;
- if (opt == 'd')
- as_warn ("Displacement length %s ignored!", temp_name);
- else
- as_warn ("I don't need or use temp. file \"%s\".", temp_name);
+ case 't':
+ as_warn (_("I don't need or use temp. file \"%s\"."), arg);
break;
case 'V':
- as_warn ("I don't use an interpass file! -V ignored");
+ as_warn (_("I don't use an interpass file! -V ignored"));
break;
#ifdef OBJ_VMS
- case '+': /* For g++ */
+ case '+': /* For g++. Hash any name > 31 chars long. */
+ flag_hash_long_names = 1;
break;
case '1': /* For backward compatibility */
+ flag_one = 1;
break;
-
+
+ case 'H': /* Show new symbol after hash truncation */
+ flag_show_after_trunc = 1;
+ break;
+
case 'h': /* No hashing of mixed-case names */
+ {
+ extern char vms_name_mapping;
+ vms_name_mapping = atoi (arg);
+ flag_no_hash_mixed_case = 1;
+ }
break;
- case 'H': /* Show new symbol after hash truncation */
+ case 'v':
+ {
+ extern char *compiler_version_string;
+ if (!arg || !*arg || access (arg, 0) == 0)
+ return 0; /* have caller show the assembler version */
+ compiler_version_string = arg;
+ }
+ break;
+#endif
+
+#ifdef OBJ_ELF
+ case OPTION_PIC:
+ case 'k':
+ flag_want_pic = 1;
+ break; /* -pic, Position Independent Code */
+
+ /* -Qy, -Qn: SVR4 arguments controlling whether a .comment
+ section should be emitted or not. FIXME: Not implemented. */
+ case 'Q':
break;
#endif
default:
return 0;
-
}
+
return 1;
}
+void
+md_show_usage (stream)
+ FILE *stream;
+{
+ fprintf (stream, _("\
+VAX options:\n\
+-d LENGTH ignored\n\
+-J ignored\n\
+-S ignored\n\
+-t FILE ignored\n\
+-T ignored\n\
+-V ignored\n"));
+#ifdef OBJ_VMS
+ fprintf (stream, _("\
+VMS options:\n\
+-+ hash encode names longer than 31 characters\n\
+-1 `const' handling compatible with gcc 1.x\n\
+-H show new symbol after hash truncation\n\
+-h NUM don't hash mixed-case names, and adjust case:\n\
+ 0 = upper, 2 = lower, 3 = preserve case\n\
+-v\"VERSION\" code being assembled was produced by compiler \"VERSION\"\n"));
+#endif
+}
+\f
/* We have no need to default values of symbols. */
-/* ARGSUSED */
symbolS *
md_undefined_symbol (name)
- char *name;
+ char *name ATTRIBUTE_UNUSED;
{
return 0;
}
-/* 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;
-{
-}
-
/* Round up a section size to the appropriate boundary. */
valueT
md_section_align (segment, size)
- segT segment;
+ segT segment ATTRIBUTE_UNUSED;
valueT size;
{
return size; /* Byte alignment is fine */
/* Exactly what point is a PC-relative offset relative TO?
On the vax, they're relative to the address of the offset, plus
- its size. (??? Is this right? FIXME-SOON) */
+ its size. */
long
md_pcrel_from (fixP)
fixS *fixP;
return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
}
+#ifdef OBJ_AOUT
+#ifndef BFD_ASSEMBLER
+void
+tc_headers_hook(headers)
+ object_headers *headers;
+{
+#ifdef TE_NetBSD
+ N_SET_INFO(headers->header, OMAGIC, M_VAX4K_NETBSD, 0);
+ headers->header.a_info = htonl (headers->header.a_info);
+#endif
+}
+#endif /* !BFD_ASSEMBLER */
+#endif /* OBJ_AOUT */
+
+#ifdef BFD_ASSEMBLER
+arelent *
+tc_gen_reloc (section, fixp)
+ asection *section ATTRIBUTE_UNUSED;
+ fixS *fixp;
+{
+ arelent *reloc;
+ bfd_reloc_code_real_type code;
+
+ if (fixp->fx_tcbit)
+ abort();
+
+ if (fixp->fx_r_type != BFD_RELOC_NONE)
+ {
+ code = fixp->fx_r_type;
+
+ if (fixp->fx_pcrel)
+ {
+ switch (code)
+ {
+ case BFD_RELOC_8_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_32_PCREL:
+#ifdef OBJ_ELF
+ case BFD_RELOC_8_GOT_PCREL:
+ case BFD_RELOC_16_GOT_PCREL:
+ case BFD_RELOC_32_GOT_PCREL:
+ case BFD_RELOC_8_PLT_PCREL:
+ case BFD_RELOC_16_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+#endif
+ break;
+ default:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("Cannot make %s relocation PC relative"),
+ bfd_get_reloc_code_name (code));
+ }
+ }
+ }
+ else
+ {
+#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
+ switch (F (fixp->fx_size, fixp->fx_pcrel))
+ {
+#define MAP(SZ,PCREL,TYPE) case F(SZ,PCREL): code = (TYPE); break
+ MAP (1, 0, BFD_RELOC_8);
+ MAP (2, 0, BFD_RELOC_16);
+ MAP (4, 0, BFD_RELOC_32);
+ MAP (1, 1, BFD_RELOC_8_PCREL);
+ MAP (2, 1, BFD_RELOC_16_PCREL);
+ MAP (4, 1, BFD_RELOC_32_PCREL);
+ default:
+ abort ();
+ }
+ }
+#undef F
+#undef MAP
+
+ reloc = (arelent *) xmalloc (sizeof (arelent));
+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+#ifndef OBJ_ELF
+ if (fixp->fx_pcrel)
+ reloc->addend = fixp->fx_addnumber;
+ else
+ reloc->addend = 0;
+#else
+ reloc->addend = fixp->fx_offset;
+#endif
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+ assert (reloc->howto != 0);
+
+ return reloc;
+}
+#endif /* BFD_ASSEMBLER */
+
/* end of tc-vax.c */