Ensure ARM VPUSH and VPOP instructions do not affect more than 16 registers.
PR gas/20429 * config/tc-arm.c (do_vfp_nsyn_push): Check that no more than 16 registers are pushed. (do_vfp_nsyn_pop): Check that no more than 16 registers are popped. * testsuite/gas/arm/pr20429.s: New test. * testsuite/gas/arm/pr20429.d: New test driver. * testsuite/gas/arm/pr20429.1: Expected error output.
This commit is contained in:
parent
7ea12e5c3a
commit
b126985ec3
|
@ -1,5 +1,14 @@
|
|||
2016-08-05 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR gas/20429
|
||||
* config/tc-arm.c (do_vfp_nsyn_push): Check that no more than 16
|
||||
registers are pushed.
|
||||
(do_vfp_nsyn_pop): Check that no more than 16 registers are
|
||||
popped.
|
||||
* testsuite/gas/arm/pr20429.s: New test.
|
||||
* testsuite/gas/arm/pr20429.d: New test driver.
|
||||
* testsuite/gas/arm/pr20429.1: Expected error output.
|
||||
|
||||
PR gas/20364
|
||||
* config/tc-aarch64.c (s_ltorg): Change the mapping state after
|
||||
aligning the frag.
|
||||
|
|
|
@ -14390,6 +14390,11 @@ static void
|
|||
do_vfp_nsyn_push (void)
|
||||
{
|
||||
nsyn_insert_sp ();
|
||||
|
||||
constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
|
||||
_("register list must contain at least 1 and at most 16 "
|
||||
"registers"));
|
||||
|
||||
if (inst.operands[1].issingle)
|
||||
do_vfp_nsyn_opcode ("fstmdbs");
|
||||
else
|
||||
|
@ -14400,6 +14405,11 @@ static void
|
|||
do_vfp_nsyn_pop (void)
|
||||
{
|
||||
nsyn_insert_sp ();
|
||||
|
||||
constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16,
|
||||
_("register list must contain at least 1 and at most 16 "
|
||||
"registers"));
|
||||
|
||||
if (inst.operands[1].issingle)
|
||||
do_vfp_nsyn_opcode ("fldmias");
|
||||
else
|
||||
|
|
|
@ -108,7 +108,7 @@ static int cmp_opcode (struct xgate_opcode *, struct xgate_opcode *);
|
|||
static void xgate_print_table (void);
|
||||
static unsigned int xgate_get_operands (char *, s_operand []);
|
||||
static register_id reg_name_search (char *);
|
||||
static op_modifiers xgate_determine_modifiers(char **);
|
||||
static op_modifiers xgate_determine_modifiers (char **);
|
||||
static void xgate_scan_operands (struct xgate_opcode *opcode, s_operand []);
|
||||
static unsigned int xgate_parse_operand (struct xgate_opcode *, int *, int,
|
||||
char **, s_operand);
|
||||
|
@ -191,7 +191,7 @@ struct option md_longopts[] =
|
|||
{ NULL, no_argument, NULL, 0 }
|
||||
};
|
||||
|
||||
size_t md_longopts_size = sizeof(md_longopts);
|
||||
size_t md_longopts_size = sizeof (md_longopts);
|
||||
|
||||
const char *
|
||||
md_atof (int type, char *litP, int *sizeP)
|
||||
|
@ -301,13 +301,13 @@ md_begin (void)
|
|||
xgate_op_table = XNEWVEC (struct xgate_opcode, xgate_num_opcodes);
|
||||
|
||||
memset (xgate_op_table, 0,
|
||||
sizeof(struct xgate_opcode) * (xgate_num_opcodes));
|
||||
sizeof (struct xgate_opcode) * (xgate_num_opcodes));
|
||||
|
||||
for (xgate_opcode_ptr = (struct xgate_opcode*) xgate_opcodes, i = 0;
|
||||
i < xgate_num_opcodes; i++)
|
||||
xgate_op_table[i] = xgate_opcode_ptr[i];
|
||||
|
||||
qsort (xgate_op_table, xgate_num_opcodes, sizeof(struct xgate_opcode),
|
||||
qsort (xgate_op_table, xgate_num_opcodes, sizeof (struct xgate_opcode),
|
||||
(int (*)(const void *, const void *)) cmp_opcode);
|
||||
|
||||
/* Calculate number of handles since this will be
|
||||
|
@ -457,7 +457,7 @@ xgate_listing_header (void)
|
|||
symbolS *
|
||||
md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* GAS will call this function for each section at the end of the assembly,
|
||||
|
@ -486,7 +486,7 @@ md_assemble (char *input_line)
|
|||
|
||||
fixup_required = 0;
|
||||
oper_check = 0; /* set error flags */
|
||||
input_line = extract_word (input_line, op_name, sizeof(op_name));
|
||||
input_line = extract_word (input_line, op_name, sizeof (op_name));
|
||||
|
||||
/* Check to make sure we are not reading a bogus line. */
|
||||
if (!op_name[0])
|
||||
|
@ -552,10 +552,10 @@ md_assemble (char *input_line)
|
|||
}
|
||||
else
|
||||
{
|
||||
operandCount = xgate_get_operands(input_line, new_operands);
|
||||
operandCount = xgate_get_operands (input_line, new_operands);
|
||||
macro_opcode = xgate_find_match (opcode_handle,
|
||||
opcode_handle->number_of_modes, new_operands,
|
||||
operandCount);
|
||||
operandCount);
|
||||
xgate_scan_operands (macro_opcode, new_operands);
|
||||
}
|
||||
}
|
||||
|
@ -889,7 +889,8 @@ static char *
|
|||
xgate_parse_exp (char *s, expressionS * op)
|
||||
{
|
||||
input_line_pointer = s;
|
||||
expression(op);
|
||||
|
||||
expression (op);
|
||||
if (op->X_op == O_absent)
|
||||
as_bad (_("missing operand"));
|
||||
return input_line_pointer;
|
||||
|
@ -915,51 +916,55 @@ xgate_find_match (struct xgate_opcode_handle *opcode_handle,
|
|||
switch (operandCount)
|
||||
{
|
||||
case 0:
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_INH))
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_INH))
|
||||
return opcode_handle->opc0[i];
|
||||
break;
|
||||
case 1:
|
||||
if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_MON))
|
||||
return opcode_handle->opc0[i];
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_DYA_MON))
|
||||
return opcode_handle->opc0[i];
|
||||
{
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_MON))
|
||||
return opcode_handle->opc0[i];
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_DYA_MON))
|
||||
return opcode_handle->opc0[i];
|
||||
}
|
||||
if (oprs[0].reg == REG_NONE)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM3))
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM3))
|
||||
return opcode_handle->opc0[i];
|
||||
break;
|
||||
case 2:
|
||||
if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
|
||||
{
|
||||
if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_DYA))
|
||||
return opcode_handle->opc0[i];
|
||||
{
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_DYA))
|
||||
return opcode_handle->opc0[i];
|
||||
}
|
||||
if (oprs[1].reg == REG_CCR)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints,
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_MON_R_C))
|
||||
return opcode_handle->opc0[i];
|
||||
if (oprs[1].reg == REG_PC)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints,
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_MON_R_P))
|
||||
return opcode_handle->opc0[i];
|
||||
if (oprs[1].reg == REG_NONE)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM16)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM8)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_IMM4)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints,
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM16)
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM8)
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_IMM4)
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_IMM16mADD)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints,
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_IMM16mAND)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints,
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_IMM16mCPC)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints,
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_IMM16mSUB)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints,
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_IMM16mLDW))
|
||||
return opcode_handle->opc0[i];
|
||||
}
|
||||
if (oprs[0].reg == REG_CCR)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints, XGATE_OP_MON_C_R))
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints, XGATE_OP_MON_C_R))
|
||||
return opcode_handle->opc0[i];
|
||||
break;
|
||||
case 3:
|
||||
|
@ -969,22 +974,22 @@ xgate_find_match (struct xgate_opcode_handle *opcode_handle,
|
|||
{
|
||||
if (oprs[2].reg >= REG_R0 && oprs[2].reg <= REG_R7)
|
||||
{
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints,
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_IDR)
|
||||
|| !strcmp(opcode_handle->opc0[i]->constraints,
|
||||
|| !strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_TRI))
|
||||
return opcode_handle->opc0[i];
|
||||
}
|
||||
|
||||
if (oprs[2].reg == REG_NONE)
|
||||
if (!strcmp(opcode_handle->opc0[i]->constraints,
|
||||
if (!strcmp (opcode_handle->opc0[i]->constraints,
|
||||
XGATE_OP_IDO5))
|
||||
return opcode_handle->opc0[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
as_bad(_("unknown operand count"));
|
||||
as_bad (_("unknown operand count"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1004,7 +1009,7 @@ xgate_frob_symbol (symbolS *sym)
|
|||
bfdsym = symbol_get_bfdsym (sym);
|
||||
elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
|
||||
|
||||
gas_assert(elfsym);
|
||||
gas_assert (elfsym);
|
||||
|
||||
/* Mark the symbol as being *from XGATE */
|
||||
elfsym->internal_elf_sym.st_target_internal = 1;
|
||||
|
@ -1051,6 +1056,7 @@ xgate_get_operands (char *line, s_operand oprs[])
|
|||
|
||||
/* reg_name_search() finds the register number given its name.
|
||||
Returns the register number or REG_NONE on failure. */
|
||||
|
||||
static register_id
|
||||
reg_name_search (char *name)
|
||||
{
|
||||
|
@ -1080,7 +1086,7 @@ reg_name_search (char *name)
|
|||
/* Parse operand modifiers such as inc/dec/hi/low. */
|
||||
|
||||
static op_modifiers
|
||||
xgate_determine_modifiers(char **line)
|
||||
xgate_determine_modifiers (char **line)
|
||||
{
|
||||
char *local_line = line[0];
|
||||
|
||||
|
@ -1149,7 +1155,7 @@ xgate_scan_operands (struct xgate_opcode *opcode, s_operand oprs[])
|
|||
++op;
|
||||
bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
|
||||
|
||||
if(first_operand_equals_second)
|
||||
if (first_operand_equals_second)
|
||||
bin = xgate_apply_operand (operand, &oper_mask, bin,
|
||||
operand_bit_length);
|
||||
/* Parse second operand. */
|
||||
|
@ -1229,9 +1235,9 @@ xgate_parse_operand (struct xgate_opcode *opcode,
|
|||
if (operand.reg == REG_NONE)
|
||||
as_bad (_(": expected register name r0-r7 ") );
|
||||
op_mask = operand.reg;
|
||||
if(operand.mod == MOD_POSTINC)
|
||||
if (operand.mod == MOD_POSTINC)
|
||||
pp_fix = INCREMENT;
|
||||
if(operand.mod == MOD_PREDEC)
|
||||
if (operand.mod == MOD_PREDEC)
|
||||
pp_fix = DECREMENT;
|
||||
op_mask <<= 2;
|
||||
op_mask |= pp_fix;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# name: PR 20429: Too many registers in VPUSH/VPOP
|
||||
# as: -mfpu=neon
|
||||
# error-output: pr20429.l
|
|
@ -0,0 +1,11 @@
|
|||
[^:]*: Assembler messages:
|
||||
[^:]*:5: Error: register list must contain at least 1 and at most 16 registers -- `vpush {d0-d31}'
|
||||
[^:]*:6: Error: register list must contain at least 1 and at most 16 registers -- `vpush {d1-d17}'
|
||||
[^:]*:7: Error: register list must contain at least 1 and at most 16 registers -- `vpop {d1-d17}'
|
||||
[^:]*:8: Error: register list must contain at least 1 and at most 16 registers -- `vpop {d0-d31}'
|
||||
[^:]*:10: Error: register list must contain at least 1 and at most 16 registers -- `vpush {q0-q15}'
|
||||
[^:]*:11: Error: register list must contain at least 1 and at most 16 registers -- `vpush {q1-q9}'
|
||||
[^:]*:12: Error: register list must contain at least 1 and at most 16 registers -- `vpop {q1-q9}'
|
||||
[^:]*:13: Error: register list must contain at least 1 and at most 16 registers -- `vpop {q0-q15}'
|
||||
#pass
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
.syntax unified
|
||||
.arm
|
||||
|
||||
.text
|
||||
vpush {d0-d31} // 32 > 16, not catched.
|
||||
vpush {d1-d17} // 17 > 16, not catched.
|
||||
vpop {d1-d17} // 17 > 16, not catched.
|
||||
vpop {d0-d31} // 32 > 16, not catched.
|
||||
|
||||
vpush {q0-q15} // 32 > 16, not catched.
|
||||
vpush {q1-q9} // 18 > 16, not catched.
|
||||
vpop {q1-q9} // 18 > 16, not catched.
|
||||
vpop {q0-q15} // 32 > 16, not catched.
|
Loading…
Reference in New Issue