Fixed typo in previous delta and added more sanitization.

This commit is contained in:
Nick Clifton 1997-08-14 19:55:03 +00:00
parent 052d7984df
commit 035d8553d7

View file

@ -60,15 +60,17 @@ const relax_typeS md_relax_table[] = {
{0x1fffff, -0x200000, 6, 0}, {0x1fffff, -0x200000, 6, 0},
}; };
/* start-sanitize-v850e */
static boolean support_v850e = false;
/* end-sanitize-v850e */
/* start-sanitize-v850eq */
static boolean support_v850eq = false;
/* end-sanitize-v850eq */
/* local functions */ /* local functions */
static unsigned long v850_insert_operand static unsigned long v850_insert_operand
PARAMS ((unsigned long insn, const struct v850_operand *operand, PARAMS ((unsigned long insn, const struct v850_operand *operand,
offsetT val, char *file, unsigned int line)); offsetT val, char *file, unsigned int line));
static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
static boolean register_name PARAMS ((expressionS *expressionP));
static boolean system_register_name PARAMS ((expressionS *expressionP));
static boolean cc_name PARAMS ((expressionS *expressionP));
static bfd_reloc_code_real_type v850_reloc_prefix PARAMS ((void));
/* fixups */ /* fixups */
@ -82,12 +84,6 @@ struct v850_fixup
struct v850_fixup fixups[MAX_INSN_FIXUPS]; struct v850_fixup fixups[MAX_INSN_FIXUPS];
static int fc; static int fc;
const char *md_shortopts = "";
struct option md_longopts[] = {
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof(md_longopts);
/* The target specific pseudo-ops which we support. */ /* The target specific pseudo-ops which we support. */
const pseudo_typeS md_pseudo_table[] = const pseudo_typeS md_pseudo_table[] =
{ {
@ -349,12 +345,117 @@ cc_name (expressionP)
} }
} }
/* start-sanitize-v850e */
/* Summary of parse_register_list ().
*
* in: Input_line_pointer points to 1st char of a list of registers.
* insn is the partially constructed instruction.
* operand is the operand being inserted.
*
* out: True if the parse completed successfully, False otherwise.
* If the parse completes the correct bit fields in the
* instruction will be filled in.
*/
static boolean
parse_register_list
(
unsigned long * insn,
const struct v850_operand * operand
)
{
static int type1_regs[ 32 ] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
/* start-sanitize-v850eq */
static int type2_regs[ 32 ] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
static int type3_regs[ 32 ] = { 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 };
/* end-sanitize-v850eq */
int * regs;
/* Select a register array to parse. */
switch (operand->shift)
{
case 0xffe00001: regs = type1_regs; break;
/* start-sanitize-v850eq */
case 0xfff8000f: regs = type2_regs; break;
case 0xfff8001f: regs = type3_regs; break;
/* end-sanitize-v850eq */
default:
fprintf (stderr, "unknown operand shift: %x\n", operand->shift );
return false;
}
/* Parse the register list until a terminator (comma or new-line) is found. */
for (;;)
{
expressionS exp;
int i;
if (register_name (& exp))
{
/* Locate the given register in the list, and if it is there, insert the corresponding bit into the instruction. */
for (i = 0; i < 32; i++)
{
if (regs[ i ] == exp.X_add_number)
{
* insn |= (1 << i);
break;
}
}
if (i == 32)
{
as_bad( "unable to insert register r%d into list\n", exp.X_add_number );
return false;
}
}
else if (system_register_name (& exp))
{
if (regs == type1_regs)
{
as_bad ("system registers cannot be included in this register list" );
return false;
}
else if (exp.X_add_number == 5)
{
if (regs == type2_regs)
as_bad ("PSW cannot be included in this register list" );
else
* insn |= 0x8;
}
else
* insn |= 0x80000;
}
else
break;
/* Skip white space. */
while (* input_line_pointer == ' ' || * input_line_pointer == '\t')
++ input_line_pointer;
}
return true;
}
/* end-sanitize-v850e */
CONST char * md_shortopts = "m:";
struct option md_longopts[] =
{
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof md_longopts;
void void
md_show_usage (stream) md_show_usage (stream)
FILE *stream; FILE *stream;
{ {
fprintf(stream, "V850 options:\n\ fprintf (stream, "V850 options:\n");
none yet\n"); /* start-sanitize-v850e */
fprintf (stream, " -mcpu=v850e target the V850E processor\n");
/* end-sanitize-v850e */
/* start-sanitize-v850eq */
fprintf (stream, " -mcpu=v850eq target the V850E processor with Quantum's extensions\n");
/* end-sanitize-v850eq */
} }
int int
@ -362,6 +463,23 @@ md_parse_option (c, arg)
int c; int c;
char * arg; char * arg;
{ {
/* start-sanitize-v850e */
if ((c == 'm') && arg != NULL && (strcmp (arg, "cpu=v850e") == 0))
{
support_v850e = true;
return 1;
}
/* end-sanitize-v850e */
/* start-sanitize-v850eq */
if ((c == 'm') && arg != NULL && (strcmp (arg, "cpu=v850eq") == 0))
{
support_v850e = true;
support_v850eq = true;
return 1;
}
/* end-sanitize-v850eq */
return 0; return 0;
} }
@ -566,19 +684,27 @@ md_assemble (str)
char * str; char * str;
{ {
char * s; char * s;
char * start_of_operands;
struct v850_opcode * opcode; struct v850_opcode * opcode;
struct v850_opcode * next_opcode; struct v850_opcode * next_opcode;
const unsigned char * opindex_ptr; const unsigned char * opindex_ptr;
int next_opindex, relaxable; int next_opindex;
unsigned long insn, insn_size; int relaxable;
unsigned long insn;
unsigned long insn_size;
char * f; char * f;
int i; int i;
int match; int match;
bfd_reloc_code_real_type reloc; bfd_reloc_code_real_type reloc;
boolean extra_data_after_insn = false;
unsigned extra_data_len;
unsigned long extra_data;
/* Get the opcode. */ /* Get the opcode. */
for (s = str; *s != '\0' && ! isspace (*s); s++) for (s = str; *s != '\0' && ! isspace (*s); s++)
; continue;
if (*s != '\0') if (*s != '\0')
*s++ = '\0'; *s++ = '\0';
@ -587,6 +713,7 @@ md_assemble (str)
if (opcode == NULL) if (opcode == NULL)
{ {
as_bad ("Unrecognized opcode: `%s'", str); as_bad ("Unrecognized opcode: `%s'", str);
ignore_rest_of_line ();
return; return;
} }
@ -594,7 +721,7 @@ md_assemble (str)
while (isspace (*str)) while (isspace (*str))
++str; ++str;
input_line_pointer = str; start_of_operands = str;
for (;;) for (;;)
{ {
@ -605,6 +732,26 @@ md_assemble (str)
match = 0; match = 0;
next_opindex = 0; next_opindex = 0;
insn = opcode->opcode; insn = opcode->opcode;
extra_data_after_insn = false;
input_line_pointer = str = start_of_operands;
/* start-sanitize-v850e */
if ((opcode->flags & V850E_INSTRUCTION) && ! support_v850e)
{
errmsg = "V850E instructions not allowed";
goto error;
}
/* end-sanitize-v850e */
/* start-sanitize-v850eq */
if ((opcode->flags & V850EQ_INSTRUCTION) && ! support_v850eq)
{
errmsg = "V850EQ instructions not allowed";
goto error;
}
/* end-sanitize-v850eq */
for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++) for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
{ {
const struct v850_operand * operand; const struct v850_operand * operand;
@ -633,6 +780,7 @@ md_assemble (str)
hold = input_line_pointer; hold = input_line_pointer;
input_line_pointer = str; input_line_pointer = str;
// fprintf (stderr, "operand: %s index = %d, opcode = %s\n", input_line_pointer, opindex_ptr - opcode->operands, opcode->name );
/* lo(), hi(), hi0(), etc... */ /* lo(), hi(), hi0(), etc... */
if ((reloc = v850_reloc_prefix()) != BFD_RELOC_UNUSED) if ((reloc = v850_reloc_prefix()) != BFD_RELOC_UNUSED)
@ -702,12 +850,13 @@ md_assemble (str)
} }
else else
{ {
errmsg = NULL;
if ((operand->flags & V850_OPERAND_REG) != 0) if ((operand->flags & V850_OPERAND_REG) != 0)
{ {
if (!register_name (& ex)) if (!register_name (& ex))
{ {
errmsg = "invalid register name"; errmsg = "invalid register name";
goto error;
} }
} }
else if ((operand->flags & V850_OPERAND_SRG) != 0) else if ((operand->flags & V850_OPERAND_SRG) != 0)
@ -715,13 +864,13 @@ md_assemble (str)
if (!system_register_name (& ex)) if (!system_register_name (& ex))
{ {
errmsg = "invalid system register name"; errmsg = "invalid system register name";
goto error;
} }
} }
else if ((operand->flags & V850_OPERAND_EP) != 0) else if ((operand->flags & V850_OPERAND_EP) != 0)
{ {
char * start = input_line_pointer; char * start = input_line_pointer;
char c = get_symbol_end (); char c = get_symbol_end ();
if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0) if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
{ {
/* Put things back the way we found them. */ /* Put things back the way we found them. */
@ -730,6 +879,7 @@ md_assemble (str)
errmsg = "expected EP register"; errmsg = "expected EP register";
goto error; goto error;
} }
*input_line_pointer = c; *input_line_pointer = c;
str = input_line_pointer; str = input_line_pointer;
input_line_pointer = hold; input_line_pointer = hold;
@ -743,32 +893,89 @@ md_assemble (str)
if (!cc_name (& ex)) if (!cc_name (& ex))
{ {
errmsg = "invalid condition code name"; errmsg = "invalid condition code name";
goto error;
} }
} }
else if (operand->flags & V850E_PUSH_POP)
{
if (! parse_register_list (& insn, operand))
{
errmsg = "invalid register list";
}
/* The parse_register_list() function has already done everything, so fake a dummy expression. */
ex.X_op = O_constant;
ex.X_add_number = 0;
}
else if (operand->flags & V850E_IMMEDIATE16)
{
expression (& ex);
if (ex.X_op != O_constant)
errmsg = "constant expression expected";
else if (ex.X_add_number & 0xffff0000)
{
if (ex.X_add_number & 0xffff)
errmsg = "constant too big to fit into instruction";
else if ((insn & 0x001fffc0) == 0x00130780)
ex.X_add_number >>= 16;
else
errmsg = "constant too big to fit into instruction";
}
extra_data_after_insn = true;
extra_data_len = 2;
extra_data = ex.X_add_number;
ex.X_add_number = 0;
}
else if (operand->flags & V850E_IMMEDIATE32)
{
expression (& ex);
if (ex.X_op != O_constant)
errmsg = "constant expression expected";
extra_data_after_insn = true;
extra_data_len = 4;
extra_data = ex.X_add_number;
ex.X_add_number = 0;
}
else if (register_name (&ex) else if (register_name (&ex)
&& (operand->flags & V850_OPERAND_REG) == 0) && (operand->flags & V850_OPERAND_REG) == 0)
{ {
errmsg = "syntax error: register not expected"; errmsg = "syntax error: register not expected";
goto error;
} }
else if (system_register_name (&ex) else if (system_register_name (&ex)
&& (operand->flags & V850_OPERAND_SRG) == 0) && (operand->flags & V850_OPERAND_SRG) == 0)
{ {
errmsg = "syntax error: system register not expected"; errmsg = "syntax error: system register not expected";
goto error;
} }
else if (cc_name (&ex) else if (cc_name (&ex)
&& (operand->flags & V850_OPERAND_CC) == 0) && (operand->flags & V850_OPERAND_CC) == 0)
{ {
errmsg = "syntax error: condition code not expected"; errmsg = "syntax error: condition code not expected";
goto error;
} }
else else
{ {
expression (& ex); expression (& ex);
/* start-sanitize-v850e */
/* Special case:
If we are assembling a MOV instruction (or a CALLT.... :-)
and the immediate value does not fit into the bits available
and we are supporting V850e instructions
then create a fake error so that the next MOV instruction
will be selected. This one has a 32 bit immediate field. */
if (((insn & 0x07e0) == 0x0200)
&& ex.X_op == O_constant
&& (ex.X_add_number < (- (1 << (operand->bits - 1))) || ex.X_add_number > ((1 << operand->bits) - 1))
&& support_v850e)
errmsg = "use bigger instruction";
/* end-sanitize-v850e */
} }
if (errmsg)
goto error;
switch (ex.X_op) switch (ex.X_op)
{ {
case O_illegal: case O_illegal:
@ -783,7 +990,13 @@ md_assemble (str)
errmsg = "invalid operand"; errmsg = "invalid operand";
goto error; goto error;
} }
#if 0
if (ex.X_add_number == 0
&& (operand->shift == 11))
{
as_warn ("register 0 being used as destination of instruction" );
}
#endif
insn = v850_insert_operand (insn, operand, ex.X_add_number, insn = v850_insert_operand (insn, operand, ex.X_add_number,
(char *) NULL, 0); (char *) NULL, 0);
break; break;
@ -803,7 +1016,6 @@ md_assemble (str)
++fc; ++fc;
break; break;
} }
} }
str = input_line_pointer; str = input_line_pointer;
@ -826,6 +1038,7 @@ md_assemble (str)
} }
as_bad ("%s", errmsg); as_bad ("%s", errmsg);
ignore_rest_of_line ();
return; return;
} }
break; break;
@ -853,17 +1066,28 @@ md_assemble (str)
md_number_to_chars (f + 2, 0, 4); md_number_to_chars (f + 2, 0, 4);
fc = 0; fc = 0;
} }
else if ((insn & 0x0600) == 0x0600)
{
insn_size = 4;
f = frag_more (insn_size);
md_number_to_chars (f, insn, insn_size);
}
else else
{ {
if ((insn & 0x0600) == 0x0600)
insn_size = 4;
else
insn_size = 2; insn_size = 2;
/* Special case: 32 bit MOV */
if ((insn & 0xffe0) == 0x0620)
insn_size = 2;
f = frag_more (insn_size); f = frag_more (insn_size);
md_number_to_chars (f, insn, insn_size); md_number_to_chars (f, insn, insn_size);
if (extra_data_after_insn)
{
f = frag_more (extra_data_len);
md_number_to_chars (f, extra_data, extra_data_len);
extra_data_after_insn = false;
}
} }
/* Create any fixups. At this point we do not use a /* Create any fixups. At this point we do not use a
@ -1095,7 +1319,6 @@ v850_insert_operand (insn, operand, val, file, line)
test = val; test = val;
if (test < (offsetT) min || test > (offsetT) max) if (test < (offsetT) min || test > (offsetT) max)
{ {
const char * err = const char * err =
@ -1113,6 +1336,7 @@ v850_insert_operand (insn, operand, val, file, line)
if (operand->insert) if (operand->insert)
{ {
const char * message = NULL; const char * message = NULL;
insn = (*operand->insert) (insn, val, & message); insn = (*operand->insert) (insn, val, & message);
if (message != NULL) if (message != NULL)
{ {
@ -1124,6 +1348,7 @@ v850_insert_operand (insn, operand, val, file, line)
} }
else else
insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift); insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
return insn; return insn;
} }