/* tc-vax.c - vax-specific -
Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2001, 2002,
- 2003, 2004, 2005
+ 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
fixP->fx_done = 1;
}
-long
-md_chars_to_number (unsigned char con[], /* Low order byte 1st. */
- int nbytes) /* Number of bytes in the input. */
+/* Convert a number from VAX byte order (little endian)
+ into host byte order.
+ con is the buffer to convert,
+ nbytes is the length of the given buffer. */
+static long
+md_chars_to_number (unsigned char con[], int nbytes)
{
long retval;
cases, we do the same idea. JACBxxx are all marked with a 'b!'
JAOBxxx & JSOBxxx are marked with a 'b:'. */
#if (VIT_OPCODE_SYNTHETIC != 0x80000000)
-You have just broken the encoding below, which assumes the sign bit
- means 'I am an imaginary instruction'.
+#error "You have just broken the encoding below, which assumes the sign bit means 'I am an imaginary instruction'."
#endif
#if (VIT_OPCODE_SPECIAL != 0x40000000)
- You have just broken the encoding below, which assumes the 0x40 M bit means
- 'I am not to be "optimised" the way normal branches are'.
+#error "You have just broken the encoding below, which assumes the 0x40 M bit means 'I am not to be "optimised" the way normal branches are'."
#endif
static const struct vot
op_hash = hash_new ();
for (vP = votstrs; *vP->vot_name && !retval; vP++)
- retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+ retval = hash_insert (op_hash, vP->vot_name, (void *) &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);
+ retval = hash_insert (op_hash, vP->vot_name, (void *) &vP->vot_detail);
#ifndef CONST_TABLE
vip_op_defaults (immediate, indirect, displen);
R14 SP
R15 PC */
-#define AP (12)
-#define FP (13)
-#define SP (14)
-#define PC (15)
+#define AP 12
+#define FP 13
+#define SP 14
+#define PC 15
-static int /* Return -1 or 0:15. */
-vax_reg_parse (char c1, char c2, /* 3 chars of register name. */
- char c3, char c4) /* c3 == 0 if 2-character reg name. */
+/* Returns the register number of something like '%r15' or 'ap', supplied
+ in four single chars. Returns -1 if the register isn't recognized,
+ 0..15 otherwise. */
+static int
+vax_reg_parse (char c1, char c2, char c3, char c4)
{
- int retval;
-
- retval = -1;
+ int retval = -1;
#ifdef OBJ_ELF
if (c1 != '%') /* Register prefixes are mandatory for ELF. */
{@}#foo, no S^ 8+@ PC " i" optional
{@}{q^}{(Rn)} 10+@+q option " bwl" optional */
+/* Dissect user-input 'optext' (which is something like "@B^foo@bar(AP)[FP]:")
+ using the vop in vopP. vopP's vop_access and vop_width. We fill _ndx, _reg,
+ _mode, _short, _warn, _error, _expr_begin, _expr_end and _nbytes. */
+
static void
-vip_op (char *optext, /* user's input string e.g.: "@B^foo@bar(AP)[FP]:" */
- struct vop *vopP) /* 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. */
+vip_op (char *optext, struct vop *vopP)
{
/* Track operand text forward. */
char *p;
We declare arrays non-local in case some of our tiny-minded machines
default to small stacks. Also, helps with some debuggers. */
-#include <stdio.h>
-
char answer[100]; /* Human types into here. */
char *p; /* */
char *myerr;
}
}
-mumble (text, value)
- char *text;
- int value;
+void
+mumble (char *text, int value)
{
printf ("%s:", text);
if (value >= 0)
{
#ifdef OBJ_ELF
#define OPTION_PIC (OPTION_MD_BASE)
- {"pic", no_argument, NULL, OPTION_PIC},
+ { "pic", no_argument, NULL, OPTION_PIC },
#endif
- {NULL, no_argument, NULL, 0}
+ { NULL, no_argument, NULL, 0 }
};
size_t md_longopts_size = sizeof (md_longopts);
return reloc;
}
+/* vax:md_assemble() emit frags for 1 instruction given in textual form. */
void
md_assemble (char *instruction_string)
{
fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];
}
}
+
+static char *vax_cons_special_reloc;
+
+void
+vax_cons (expressionS *exp, int size)
+{
+ char *save;
+
+ SKIP_WHITESPACE ();
+ vax_cons_special_reloc = NULL;
+ save = input_line_pointer;
+ if (input_line_pointer[0] == '%')
+ {
+ if (strncmp (input_line_pointer + 1, "pcrel", 5) == 0)
+ {
+ input_line_pointer += 6;
+ vax_cons_special_reloc = "pcrel";
+ }
+ if (vax_cons_special_reloc)
+ {
+ int bad = 0;
+
+ switch (size)
+ {
+ case 1:
+ if (*input_line_pointer != '8')
+ bad = 1;
+ input_line_pointer--;
+ break;
+ case 2:
+ if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
+ bad = 1;
+ break;
+ case 4:
+ if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
+ bad = 1;
+ break;
+ default:
+ bad = 1;
+ break;
+ }
+
+ if (bad)
+ {
+ as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
+ vax_cons_special_reloc, size * 8, size);
+ }
+ else
+ {
+ input_line_pointer += 2;
+ if (*input_line_pointer != '(')
+ {
+ as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+ vax_cons_special_reloc, size * 8);
+ bad = 1;
+ }
+ }
+
+ if (bad)
+ {
+ input_line_pointer = save;
+ vax_cons_special_reloc = NULL;
+ }
+ else
+ {
+ int c;
+ char *end = ++input_line_pointer;
+ int npar = 0;
+
+ while (! is_end_of_line[(c = *end)])
+ {
+ if (c == '(')
+ npar++;
+ else if (c == ')')
+ {
+ if (!npar)
+ break;
+ npar--;
+ }
+ end++;
+ }
+
+ if (c != ')')
+ as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+ vax_cons_special_reloc, size * 8);
+ else
+ {
+ *end = '\0';
+ expression (exp);
+ *end = c;
+ if (input_line_pointer != end)
+ {
+ as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+ vax_cons_special_reloc, size * 8);
+ }
+ else
+ {
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ c = *input_line_pointer;
+ if (! is_end_of_line[c] && c != ',')
+ as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
+ vax_cons_special_reloc, size * 8);
+ }
+ }
+ }
+ }
+ }
+ if (vax_cons_special_reloc == NULL)
+ expression (exp);
+}
+
+/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
+ reloc for a cons. */
+
+void
+vax_cons_fix_new (fragS *frag, int where, unsigned int nbytes, expressionS *exp)
+{
+ bfd_reloc_code_real_type r;
+
+ r = (nbytes == 1 ? BFD_RELOC_8 :
+ (nbytes == 2 ? BFD_RELOC_16 : BFD_RELOC_32));
+
+ if (vax_cons_special_reloc)
+ {
+ if (*vax_cons_special_reloc == 'p')
+ {
+ switch (nbytes)
+ {
+ case 1: r = BFD_RELOC_8_PCREL; break;
+ case 2: r = BFD_RELOC_16_PCREL; break;
+ case 4: r = BFD_RELOC_32_PCREL; break;
+ default: abort ();
+ }
+ }
+ }
+
+ fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
+ vax_cons_special_reloc = NULL;
+}
+
+char *
+md_atof (int type, char * litP, int * sizeP)
+{
+ return vax_md_atof (type, litP, sizeP);
+}