summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2016-06-14 21:28:13 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2016-08-23 09:41:02 +0100
commitea3c894d35ea6d875a08c36e273e26b828f54b37 (patch)
tree53bc1c1bdb5313b1d9a152ba6e5dc8c1dc5796d5
parent65a4acbb08de761519ce44ac8bc8c78db78b69eb (diff)
downloadbinutils-gdb-ea3c894d35ea6d875a08c36e273e26b828f54b37.tar.gz
[AArch64][SVE 07/32] Replace hard-coded uses of REG_TYPE_R_Z_BHSDQ_V
To remove parsing ambiguities and to avoid register names being accidentally added to the symbol table, the immediate parsing routines reject things like: .equ x0, 0 add v0.4s, v0.4s, x0 An explicit '#' must be used instead: .equ x0, 0 add v0.4s, v0.4s, #x0 Of course, it wasn't possible to predict what other register names might be added in future, so this behaviour was restricted to the register names that were defined at the time. For backwards compatibility, we should continue to allow things like: .equ p0, 0 add v0.4s, v0.4s, p0 even though p0 is now an SVE register. However, it seems reasonable to extend the x0 behaviour above to SVE registers when parsing SVE instructions, especially since none of the SVE immediate formats are relocatable. Doing so removes the same parsing ambiguity for SVE instructions as the x0 behaviour removes for base AArch64 instructions. As a prerequisite, we then need to be able to tell the parsing routines which registers to reject. This patch changes the interface to make that possible, although the set of rejected registers doesn't change at this stage. gas/ * config/tc-aarch64.c (parse_immediate_expression): Add a reg_type parameter. (parse_constant_immediate): Likewise, and update calls. (parse_aarch64_imm_float): Likewise. (parse_big_immediate): Likewise. (po_imm_nc_or_fail): Update accordingly, passing down a new imm_reg_type variable. (po_imm_of_fail): Likewise. (parse_operands): Likewise. Change-Id: I315ee16d17c768d25bb9e0848bb14c4609435ecb
-rw-r--r--gas/config/tc-aarch64.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index e65cc7a9c42..eec08c7dd30 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -2004,14 +2004,14 @@ reg_name_p (char *str, aarch64_reg_type reg_type)
To prevent the expression parser from pushing a register name
into the symbol table as an undefined symbol, firstly a check is
- done to find out whether STR is a valid register name followed
- by a comma or the end of line. Return FALSE if STR is such a
- string. */
+ done to find out whether STR is a register of type REG_TYPE followed
+ by a comma or the end of line. Return FALSE if STR is such a string. */
static bfd_boolean
-parse_immediate_expression (char **str, expressionS *exp)
+parse_immediate_expression (char **str, expressionS *exp,
+ aarch64_reg_type reg_type)
{
- if (reg_name_p (*str, REG_TYPE_R_Z_BHSDQ_V))
+ if (reg_name_p (*str, reg_type))
{
set_recoverable_error (_("immediate operand required"));
return FALSE;
@@ -2030,16 +2030,17 @@ parse_immediate_expression (char **str, expressionS *exp)
/* Constant immediate-value read function for use in insn parsing.
STR points to the beginning of the immediate (with the optional
- leading #); *VAL receives the value.
+ leading #); *VAL receives the value. REG_TYPE says which register
+ names should be treated as registers rather than as symbolic immediates.
Return TRUE on success; otherwise return FALSE. */
static bfd_boolean
-parse_constant_immediate (char **str, int64_t * val)
+parse_constant_immediate (char **str, int64_t *val, aarch64_reg_type reg_type)
{
expressionS exp;
- if (! parse_immediate_expression (str, &exp))
+ if (! parse_immediate_expression (str, &exp, reg_type))
return FALSE;
if (exp.X_op != O_constant)
@@ -2148,12 +2149,14 @@ aarch64_double_precision_fmovable (uint64_t imm, uint32_t *fpword)
value in *IMMED in the format of IEEE754 single-precision encoding.
*CCP points to the start of the string; DP_P is TRUE when the immediate
is expected to be in double-precision (N.B. this only matters when
- hexadecimal representation is involved).
+ hexadecimal representation is involved). REG_TYPE says which register
+ names should be treated as registers rather than as symbolic immediates.
N.B. 0.0 is accepted by this function. */
static bfd_boolean
-parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p)
+parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p,
+ aarch64_reg_type reg_type)
{
char *str = *ccp;
char *fpnum;
@@ -2173,7 +2176,7 @@ parse_aarch64_imm_float (char **ccp, int *immed, bfd_boolean dp_p)
/* Support the hexadecimal representation of the IEEE754 encoding.
Double-precision is expected when DP_P is TRUE, otherwise the
representation should be in single-precision. */
- if (! parse_constant_immediate (&str, &val))
+ if (! parse_constant_immediate (&str, &val, reg_type))
goto invalid_fp;
if (dp_p)
@@ -2237,15 +2240,15 @@ invalid_fp:
To prevent the expression parser from pushing a register name into the
symbol table as an undefined symbol, a check is firstly done to find
- out whether STR is a valid register name followed by a comma or the end
- of line. Return FALSE if STR is such a register. */
+ out whether STR is a register of type REG_TYPE followed by a comma or
+ the end of line. Return FALSE if STR is such a register. */
static bfd_boolean
-parse_big_immediate (char **str, int64_t *imm)
+parse_big_immediate (char **str, int64_t *imm, aarch64_reg_type reg_type)
{
char *ptr = *str;
- if (reg_name_p (ptr, REG_TYPE_R_Z_BHSDQ_V))
+ if (reg_name_p (ptr, reg_type))
{
set_syntax_error (_("immediate operand required"));
return FALSE;
@@ -3736,12 +3739,12 @@ parse_sys_ins_reg (char **str, struct hash_control *sys_ins_regs)
} while (0)
#define po_imm_nc_or_fail() do { \
- if (! parse_constant_immediate (&str, &val)) \
+ if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
goto failure; \
} while (0)
#define po_imm_or_fail(min, max) do { \
- if (! parse_constant_immediate (&str, &val)) \
+ if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
goto failure; \
if (val < min || val > max) \
{ \
@@ -4980,10 +4983,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
int i;
char *backtrack_pos = 0;
const enum aarch64_opnd *operands = opcode->operands;
+ aarch64_reg_type imm_reg_type;
clear_error ();
skip_whitespace (str);
+ imm_reg_type = REG_TYPE_R_Z_BHSDQ_V;
+
for (i = 0; operands[i] != AARCH64_OPND_NIL; i++)
{
int64_t val;
@@ -5219,8 +5225,10 @@ parse_operands (char *str, const aarch64_opcode *opcode)
bfd_boolean res1 = FALSE, res2 = FALSE;
/* N.B. -0.0 will be rejected; although -0.0 shouldn't be rejected,
it is probably not worth the effort to support it. */
- if (!(res1 = parse_aarch64_imm_float (&str, &qfloat, FALSE))
- && !(res2 = parse_constant_immediate (&str, &val)))
+ if (!(res1 = parse_aarch64_imm_float (&str, &qfloat, FALSE,
+ imm_reg_type))
+ && !(res2 = parse_constant_immediate (&str, &val,
+ imm_reg_type)))
goto failure;
if ((res1 && qfloat == 0) || (res2 && val == 0))
{
@@ -5253,7 +5261,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_SIMD_IMM:
case AARCH64_OPND_SIMD_IMM_SFT:
- if (! parse_big_immediate (&str, &val))
+ if (! parse_big_immediate (&str, &val, imm_reg_type))
goto failure;
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
/* addr_off_p */ 0,
@@ -5284,7 +5292,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
bfd_boolean dp_p
= (aarch64_get_qualifier_esize (inst.base.operands[0].qualifier)
== 8);
- if (! parse_aarch64_imm_float (&str, &qfloat, dp_p))
+ if (! parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type))
goto failure;
if (qfloat == 0)
{
@@ -5372,7 +5380,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
break;
case AARCH64_OPND_EXCEPTION:
- po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp));
+ po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp,
+ imm_reg_type));
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
/* addr_off_p */ 0,
/* need_libopcodes_p */ 0,