Fixed typo in previous delta and added more sanitization.
This commit is contained in:
parent
052d7984df
commit
035d8553d7
1 changed files with 289 additions and 64 deletions
|
@ -60,15 +60,17 @@ const relax_typeS md_relax_table[] = {
|
|||
{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 */
|
||||
static unsigned long v850_insert_operand
|
||||
PARAMS ((unsigned long insn, const struct v850_operand *operand,
|
||||
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 */
|
||||
|
@ -82,12 +84,6 @@ struct v850_fixup
|
|||
struct v850_fixup fixups[MAX_INSN_FIXUPS];
|
||||
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. */
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
{
|
||||
|
@ -349,19 +345,141 @@ 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
|
||||
md_show_usage (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
fprintf(stream, "V850 options:\n\
|
||||
none yet\n");
|
||||
fprintf (stream, "V850 options:\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
|
||||
md_parse_option (c, arg)
|
||||
int c;
|
||||
char *arg;
|
||||
int c;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -487,7 +605,7 @@ md_begin ()
|
|||
}
|
||||
|
||||
static bfd_reloc_code_real_type
|
||||
v850_reloc_prefix()
|
||||
v850_reloc_prefix ()
|
||||
{
|
||||
if (strncmp(input_line_pointer, "hi0(", 4) == 0)
|
||||
{
|
||||
|
@ -563,22 +681,30 @@ v850_reloc_prefix()
|
|||
|
||||
void
|
||||
md_assemble (str)
|
||||
char *str;
|
||||
char * str;
|
||||
{
|
||||
char *s;
|
||||
struct v850_opcode *opcode;
|
||||
struct v850_opcode *next_opcode;
|
||||
const unsigned char *opindex_ptr;
|
||||
int next_opindex, relaxable;
|
||||
unsigned long insn, insn_size;
|
||||
char *f;
|
||||
int i;
|
||||
int match;
|
||||
bfd_reloc_code_real_type reloc;
|
||||
char * s;
|
||||
char * start_of_operands;
|
||||
struct v850_opcode * opcode;
|
||||
struct v850_opcode * next_opcode;
|
||||
const unsigned char * opindex_ptr;
|
||||
int next_opindex;
|
||||
int relaxable;
|
||||
unsigned long insn;
|
||||
unsigned long insn_size;
|
||||
char * f;
|
||||
int i;
|
||||
int match;
|
||||
bfd_reloc_code_real_type reloc;
|
||||
boolean extra_data_after_insn = false;
|
||||
unsigned extra_data_len;
|
||||
unsigned long extra_data;
|
||||
|
||||
|
||||
/* Get the opcode. */
|
||||
for (s = str; *s != '\0' && ! isspace (*s); s++)
|
||||
;
|
||||
continue;
|
||||
|
||||
if (*s != '\0')
|
||||
*s++ = '\0';
|
||||
|
||||
|
@ -587,6 +713,7 @@ md_assemble (str)
|
|||
if (opcode == NULL)
|
||||
{
|
||||
as_bad ("Unrecognized opcode: `%s'", str);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -594,22 +721,42 @@ md_assemble (str)
|
|||
while (isspace (*str))
|
||||
++str;
|
||||
|
||||
input_line_pointer = str;
|
||||
start_of_operands = str;
|
||||
|
||||
for(;;)
|
||||
for (;;)
|
||||
{
|
||||
const char *errmsg = NULL;
|
||||
const char * errmsg = NULL;
|
||||
|
||||
relaxable = 0;
|
||||
fc = 0;
|
||||
match = 0;
|
||||
next_opindex = 0;
|
||||
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++)
|
||||
{
|
||||
const struct v850_operand *operand;
|
||||
char *hold;
|
||||
expressionS ex;
|
||||
const struct v850_operand * operand;
|
||||
char * hold;
|
||||
expressionS ex;
|
||||
|
||||
if (next_opindex == 0)
|
||||
{
|
||||
|
@ -632,12 +779,13 @@ md_assemble (str)
|
|||
/* Gather the operand. */
|
||||
hold = input_line_pointer;
|
||||
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... */
|
||||
if ((reloc = v850_reloc_prefix()) != BFD_RELOC_UNUSED)
|
||||
{
|
||||
expression(&ex);
|
||||
expression (& ex);
|
||||
|
||||
if (ex.X_op == O_constant)
|
||||
{
|
||||
|
@ -702,26 +850,27 @@ md_assemble (str)
|
|||
}
|
||||
else
|
||||
{
|
||||
errmsg = NULL;
|
||||
|
||||
if ((operand->flags & V850_OPERAND_REG) != 0)
|
||||
{
|
||||
if (!register_name(&ex))
|
||||
if (!register_name (& ex))
|
||||
{
|
||||
errmsg = "invalid register name";
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if ((operand->flags & V850_OPERAND_SRG) != 0)
|
||||
{
|
||||
if (!system_register_name(&ex))
|
||||
if (!system_register_name (& ex))
|
||||
{
|
||||
errmsg = "invalid system register name";
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if ((operand->flags & V850_OPERAND_EP) != 0)
|
||||
{
|
||||
char *start = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
char * start = input_line_pointer;
|
||||
char c = get_symbol_end ();
|
||||
|
||||
if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
|
||||
{
|
||||
/* Put things back the way we found them. */
|
||||
|
@ -730,6 +879,7 @@ md_assemble (str)
|
|||
errmsg = "expected EP register";
|
||||
goto error;
|
||||
}
|
||||
|
||||
*input_line_pointer = c;
|
||||
str = input_line_pointer;
|
||||
input_line_pointer = hold;
|
||||
|
@ -740,35 +890,92 @@ md_assemble (str)
|
|||
}
|
||||
else if ((operand->flags & V850_OPERAND_CC) != 0)
|
||||
{
|
||||
if (!cc_name(&ex))
|
||||
if (!cc_name (& ex))
|
||||
{
|
||||
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)
|
||||
&& (operand->flags & V850_OPERAND_REG) == 0)
|
||||
{
|
||||
errmsg = "syntax error: register not expected";
|
||||
goto error;
|
||||
}
|
||||
else if (system_register_name (&ex)
|
||||
&& (operand->flags & V850_OPERAND_SRG) == 0)
|
||||
{
|
||||
errmsg = "syntax error: system register not expected";
|
||||
goto error;
|
||||
}
|
||||
else if (cc_name (&ex)
|
||||
&& (operand->flags & V850_OPERAND_CC) == 0)
|
||||
{
|
||||
errmsg = "syntax error: condition code not expected";
|
||||
goto error;
|
||||
}
|
||||
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)
|
||||
{
|
||||
case O_illegal:
|
||||
|
@ -783,7 +990,13 @@ md_assemble (str)
|
|||
errmsg = "invalid operand";
|
||||
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,
|
||||
(char *) NULL, 0);
|
||||
break;
|
||||
|
@ -803,7 +1016,6 @@ md_assemble (str)
|
|||
++fc;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
str = input_line_pointer;
|
||||
|
@ -826,6 +1038,7 @@ md_assemble (str)
|
|||
}
|
||||
|
||||
as_bad ("%s", errmsg);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -853,17 +1066,28 @@ md_assemble (str)
|
|||
md_number_to_chars (f + 2, 0, 4);
|
||||
fc = 0;
|
||||
}
|
||||
else if ((insn & 0x0600) == 0x0600)
|
||||
else
|
||||
{
|
||||
insn_size = 4;
|
||||
f = frag_more (insn_size);
|
||||
md_number_to_chars (f, insn, insn_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
insn_size = 2;
|
||||
if ((insn & 0x0600) == 0x0600)
|
||||
insn_size = 4;
|
||||
else
|
||||
insn_size = 2;
|
||||
|
||||
/* Special case: 32 bit MOV */
|
||||
if ((insn & 0xffe0) == 0x0620)
|
||||
insn_size = 2;
|
||||
|
||||
f = frag_more (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
|
||||
|
@ -1072,7 +1296,7 @@ md_apply_fix3 (fixp, valuep, seg)
|
|||
static unsigned long
|
||||
v850_insert_operand (insn, operand, val, file, line)
|
||||
unsigned long insn;
|
||||
const struct v850_operand *operand;
|
||||
const struct v850_operand * operand;
|
||||
offsetT val;
|
||||
char *file;
|
||||
unsigned int line;
|
||||
|
@ -1084,7 +1308,7 @@ v850_insert_operand (insn, operand, val, file, line)
|
|||
|
||||
if ((operand->flags & V850_OPERAND_SIGNED) != 0)
|
||||
{
|
||||
max = (1 << (operand->bits - 1)) - 1;
|
||||
max = (1 << (operand->bits - 1)) - 1;
|
||||
min = - (1 << (operand->bits - 1));
|
||||
}
|
||||
else
|
||||
|
@ -1095,10 +1319,9 @@ v850_insert_operand (insn, operand, val, file, line)
|
|||
|
||||
test = val;
|
||||
|
||||
|
||||
if (test < (offsetT) min || test > (offsetT) max)
|
||||
{
|
||||
const char *err =
|
||||
const char * err =
|
||||
"operand out of range (%s not between %ld and %ld)";
|
||||
char buf[100];
|
||||
|
||||
|
@ -1112,8 +1335,9 @@ v850_insert_operand (insn, operand, val, file, line)
|
|||
|
||||
if (operand->insert)
|
||||
{
|
||||
const char *message = NULL;
|
||||
insn = (*operand->insert) (insn, val, &message);
|
||||
const char * message = NULL;
|
||||
|
||||
insn = (*operand->insert) (insn, val, & message);
|
||||
if (message != NULL)
|
||||
{
|
||||
if (file == (char *) NULL)
|
||||
|
@ -1124,6 +1348,7 @@ v850_insert_operand (insn, operand, val, file, line)
|
|||
}
|
||||
else
|
||||
insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue