Skip to content

Commit

Permalink
[AArch64][SVE 28/32] Add SVE FP immediate operands
Browse files Browse the repository at this point in the history
This patch adds support for the new SVE floating-point immediate
operands.  One operand uses the same 8-bit encoding as base AArch64,
but in a different position.  The others use a single bit to select
between two values.

One of the single-bit operands is a choice between 0 and 1, where 0
is not a valid 8-bit encoding.  I think the cleanest way of handling
these single-bit immediates is therefore to use the IEEE float encoding
itself as the immediate value and select between the two possible values
when encoding and decoding.

As described in the covering note for the patch that added F_STRICT,
we get better error messages by accepting unsuffixed vector registers
and leaving the qualifier matching code to report an error.  This means
that we carry on parsing the other operands, and so can try to parse FP
immediates for invalid instructions like:

	fcpy	z0, #2.5

In this case there is no suffix to tell us whether the immediate should
be treated as single or double precision.  Again, we get better error
messages by picking one (arbitrary) immediate size and reporting an error
for the missing suffix later.

include/
	* opcode/aarch64.h (AARCH64_OPND_SVE_FPIMM8): New aarch64_opnd.
	(AARCH64_OPND_SVE_I1_HALF_ONE, AARCH64_OPND_SVE_I1_HALF_TWO)
	(AARCH64_OPND_SVE_I1_ZERO_ONE): Likewise.

opcodes/
	* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE FP
	immediate operands.
	* aarch64-opc.h (FLD_SVE_i1): New aarch64_field_kind.
	* aarch64-opc.c (fields): Add corresponding entry.
	(operand_general_constraint_met_p): Handle the new SVE FP immediate
	operands.
	(aarch64_print_operand): Likewise.
	* aarch64-opc-2.c: Regenerate.
	* aarch64-asm.h (ins_sve_float_half_one, ins_sve_float_half_two)
	(ins_sve_float_zero_one): New inserters.
	* aarch64-asm.c (aarch64_ins_sve_float_half_one): New function.
	(aarch64_ins_sve_float_half_two): Likewise.
	(aarch64_ins_sve_float_zero_one): Likewise.
	* aarch64-asm-2.c: Regenerate.
	* aarch64-dis.h (ext_sve_float_half_one, ext_sve_float_half_two)
	(ext_sve_float_zero_one): New extractors.
	* aarch64-dis.c (aarch64_ext_sve_float_half_one): New function.
	(aarch64_ext_sve_float_half_two): Likewise.
	(aarch64_ext_sve_float_zero_one): Likewise.
	* aarch64-dis-2.c: Regenerate.

gas/
	* config/tc-aarch64.c (double_precision_operand_p): New function.
	(parse_operands): Use it to calculate the dp_p input to
	parse_aarch64_imm_float.  Handle the new SVE FP immediate operands.
  • Loading branch information
rsandifo-arm committed Sep 21, 2016
1 parent e950b34 commit 165d495
Show file tree
Hide file tree
Showing 15 changed files with 293 additions and 53 deletions.
6 changes: 6 additions & 0 deletions gas/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>

* config/tc-aarch64.c (double_precision_operand_p): New function.
(parse_operands): Use it to calculate the dp_p input to
parse_aarch64_imm_float. Handle the new SVE FP immediate operands.

2016-09-21 Richard Sandiford <richard.sandiford@arm.com>

* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
Expand Down
41 changes: 38 additions & 3 deletions gas/config/tc-aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -2232,6 +2232,20 @@ can_convert_double_to_float (uint64_t imm, uint32_t *fpword)
return TRUE;
}

/* Return true if we should treat OPERAND as a double-precision
floating-point operand rather than a single-precision one. */
static bfd_boolean
double_precision_operand_p (const aarch64_opnd_info *operand)
{
/* Check for unsuffixed SVE registers, which are allowed
for LDR and STR but not in instructions that require an
immediate. We get better error messages if we arbitrarily
pick one size, parse the immediate normally, and then
report the match failure in the normal way. */
return (operand->qualifier == AARCH64_OPND_QLF_NIL
|| aarch64_get_qualifier_esize (operand->qualifier) == 8);
}

/* Parse a floating-point immediate. Return TRUE on success and return the
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
Expand Down Expand Up @@ -5655,11 +5669,12 @@ parse_operands (char *str, const aarch64_opcode *opcode)

case AARCH64_OPND_FPIMM:
case AARCH64_OPND_SIMD_FPIMM:
case AARCH64_OPND_SVE_FPIMM8:
{
int qfloat;
bfd_boolean dp_p
= (aarch64_get_qualifier_esize (inst.base.operands[0].qualifier)
== 8);
bfd_boolean dp_p;

dp_p = double_precision_operand_p (&inst.base.operands[0]);
if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type)
|| !aarch64_imm_float_p (qfloat))
{
Expand All @@ -5673,6 +5688,26 @@ parse_operands (char *str, const aarch64_opcode *opcode)
}
break;

case AARCH64_OPND_SVE_I1_HALF_ONE:
case AARCH64_OPND_SVE_I1_HALF_TWO:
case AARCH64_OPND_SVE_I1_ZERO_ONE:
{
int qfloat;
bfd_boolean dp_p;

dp_p = double_precision_operand_p (&inst.base.operands[0]);
if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type))
{
if (!error_p ())
set_fatal_syntax_error (_("invalid floating-point"
" constant"));
goto failure;
}
inst.base.operands[i].imm.value = qfloat;
inst.base.operands[i].imm.is_fp = 1;
}
break;

case AARCH64_OPND_LIMM:
po_misc_or_fail (parse_shifter_operand (&str, info,
SHIFTED_LOGIC_IMM));
Expand Down
6 changes: 6 additions & 0 deletions include/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>

* opcode/aarch64.h (AARCH64_OPND_SVE_FPIMM8): New aarch64_opnd.
(AARCH64_OPND_SVE_I1_HALF_ONE, AARCH64_OPND_SVE_I1_HALF_TWO)
(AARCH64_OPND_SVE_I1_ZERO_ONE): Likewise.

2016-09-21 Richard Sandiford <richard.sandiford@arm.com>

* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
Expand Down
4 changes: 4 additions & 0 deletions include/opcode/aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ enum aarch64_opnd
AARCH64_OPND_SVE_ADDR_ZZ_UXTW, /* SVE [Zn.<T>, Zm,<T>, UXTW #<msz>]. */
AARCH64_OPND_SVE_AIMM, /* SVE unsigned arithmetic immediate. */
AARCH64_OPND_SVE_ASIMM, /* SVE signed arithmetic immediate. */
AARCH64_OPND_SVE_FPIMM8, /* SVE 8-bit floating-point immediate. */
AARCH64_OPND_SVE_I1_HALF_ONE, /* SVE choice between 0.5 and 1.0. */
AARCH64_OPND_SVE_I1_HALF_TWO, /* SVE choice between 0.5 and 2.0. */
AARCH64_OPND_SVE_I1_ZERO_ONE, /* SVE choice between 0.0 and 1.0. */
AARCH64_OPND_SVE_INV_LIMM, /* SVE inverted logical immediate. */
AARCH64_OPND_SVE_LIMM, /* SVE logical immediate. */
AARCH64_OPND_SVE_LIMM_MOV, /* SVE logical immediate for MOV. */
Expand Down
23 changes: 23 additions & 0 deletions opcodes/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>

* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE FP
immediate operands.
* aarch64-opc.h (FLD_SVE_i1): New aarch64_field_kind.
* aarch64-opc.c (fields): Add corresponding entry.
(operand_general_constraint_met_p): Handle the new SVE FP immediate
operands.
(aarch64_print_operand): Likewise.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_sve_float_half_one, ins_sve_float_half_two)
(ins_sve_float_zero_one): New inserters.
* aarch64-asm.c (aarch64_ins_sve_float_half_one): New function.
(aarch64_ins_sve_float_half_two): Likewise.
(aarch64_ins_sve_float_zero_one): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_sve_float_half_one, ext_sve_float_half_two)
(ext_sve_float_zero_one): New extractors.
* aarch64-dis.c (aarch64_ext_sve_float_half_one): New function.
(aarch64_ext_sve_float_half_two): Likewise.
(aarch64_ext_sve_float_zero_one): Likewise.
* aarch64-dis-2.c: Regenerate.

2016-09-21 Richard Sandiford <richard.sandiford@arm.com>

* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
Expand Down
57 changes: 32 additions & 25 deletions opcodes/aarch64-asm-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,21 +480,21 @@ aarch64_insert_operand (const aarch64_operand *self,
case 27:
case 35:
case 36:
case 135:
case 136:
case 137:
case 138:
case 139:
case 140:
case 141:
case 142:
case 155:
case 156:
case 157:
case 158:
case 143:
case 144:
case 145:
case 146:
case 159:
case 160:
case 161:
case 162:
case 163:
case 164:
case 167:
return aarch64_ins_regno (self, info, code, inst);
case 12:
return aarch64_ins_reg_extended (self, info, code, inst);
Expand Down Expand Up @@ -532,16 +532,16 @@ aarch64_insert_operand (const aarch64_operand *self,
case 69:
case 70:
case 71:
case 132:
case 134:
case 147:
case 148:
case 149:
case 150:
case 136:
case 138:
case 151:
case 152:
case 153:
case 154:
case 155:
case 156:
case 157:
case 158:
return aarch64_ins_imm (self, info, code, inst);
case 38:
case 39:
Expand All @@ -551,9 +551,10 @@ aarch64_insert_operand (const aarch64_operand *self,
case 42:
return aarch64_ins_advsimd_imm_modified (self, info, code, inst);
case 46:
case 129:
return aarch64_ins_fpimm (self, info, code, inst);
case 60:
case 130:
case 134:
return aarch64_ins_limm (self, info, code, inst);
case 61:
return aarch64_ins_aimm (self, info, code, inst);
Expand Down Expand Up @@ -644,22 +645,28 @@ aarch64_insert_operand (const aarch64_operand *self,
return aarch64_ins_sve_aimm (self, info, code, inst);
case 128:
return aarch64_ins_sve_asimm (self, info, code, inst);
case 129:
return aarch64_ins_inv_limm (self, info, code, inst);
case 130:
return aarch64_ins_sve_float_half_one (self, info, code, inst);
case 131:
return aarch64_ins_sve_limm_mov (self, info, code, inst);
return aarch64_ins_sve_float_half_two (self, info, code, inst);
case 132:
return aarch64_ins_sve_float_zero_one (self, info, code, inst);
case 133:
return aarch64_ins_inv_limm (self, info, code, inst);
case 135:
return aarch64_ins_sve_limm_mov (self, info, code, inst);
case 137:
return aarch64_ins_sve_scale (self, info, code, inst);
case 143:
case 144:
case 147:
case 148:
return aarch64_ins_sve_shlimm (self, info, code, inst);
case 145:
case 146:
case 149:
case 150:
return aarch64_ins_sve_shrimm (self, info, code, inst);
case 161:
case 165:
return aarch64_ins_sve_index (self, info, code, inst);
case 162:
case 164:
case 166:
case 168:
return aarch64_ins_sve_reglist (self, info, code, inst);
default: assert (0); abort ();
}
Expand Down
45 changes: 45 additions & 0 deletions opcodes/aarch64-asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,51 @@ aarch64_ins_sve_shrimm (const aarch64_operand *self,
return NULL;
}

/* Encode a single-bit immediate that selects between #0.5 and #1.0.
The fields array specifies which field to use. */
const char *
aarch64_ins_sve_float_half_one (const aarch64_operand *self,
const aarch64_opnd_info *info,
aarch64_insn *code,
const aarch64_inst *inst ATTRIBUTE_UNUSED)
{
if (info->imm.value == 0x3f000000)
insert_field (self->fields[0], code, 0, 0);
else
insert_field (self->fields[0], code, 1, 0);
return NULL;
}

/* Encode a single-bit immediate that selects between #0.5 and #2.0.
The fields array specifies which field to use. */
const char *
aarch64_ins_sve_float_half_two (const aarch64_operand *self,
const aarch64_opnd_info *info,
aarch64_insn *code,
const aarch64_inst *inst ATTRIBUTE_UNUSED)
{
if (info->imm.value == 0x3f000000)
insert_field (self->fields[0], code, 0, 0);
else
insert_field (self->fields[0], code, 1, 0);
return NULL;
}

/* Encode a single-bit immediate that selects between #0.0 and #1.0.
The fields array specifies which field to use. */
const char *
aarch64_ins_sve_float_zero_one (const aarch64_operand *self,
const aarch64_opnd_info *info,
aarch64_insn *code,
const aarch64_inst *inst ATTRIBUTE_UNUSED)
{
if (info->imm.value == 0)
insert_field (self->fields[0], code, 0, 0);
else
insert_field (self->fields[0], code, 1, 0);
return NULL;
}

/* Miscellaneous encoding functions. */

/* Encode size[0], i.e. bit 22, for
Expand Down
3 changes: 3 additions & 0 deletions opcodes/aarch64-asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_sxtw);
AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_uxtw);
AARCH64_DECL_OPD_INSERTER (ins_sve_aimm);
AARCH64_DECL_OPD_INSERTER (ins_sve_asimm);
AARCH64_DECL_OPD_INSERTER (ins_sve_float_half_one);
AARCH64_DECL_OPD_INSERTER (ins_sve_float_half_two);
AARCH64_DECL_OPD_INSERTER (ins_sve_float_zero_one);
AARCH64_DECL_OPD_INSERTER (ins_sve_index);
AARCH64_DECL_OPD_INSERTER (ins_sve_limm_mov);
AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
Expand Down
57 changes: 32 additions & 25 deletions opcodes/aarch64-dis-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -10426,21 +10426,21 @@ aarch64_extract_operand (const aarch64_operand *self,
case 27:
case 35:
case 36:
case 135:
case 136:
case 137:
case 138:
case 139:
case 140:
case 141:
case 142:
case 155:
case 156:
case 157:
case 158:
case 143:
case 144:
case 145:
case 146:
case 159:
case 160:
case 161:
case 162:
case 163:
case 164:
case 167:
return aarch64_ext_regno (self, info, code, inst);
case 8:
return aarch64_ext_regrt_sysins (self, info, code, inst);
Expand Down Expand Up @@ -10483,16 +10483,16 @@ aarch64_extract_operand (const aarch64_operand *self,
case 69:
case 70:
case 71:
case 132:
case 134:
case 147:
case 148:
case 149:
case 150:
case 136:
case 138:
case 151:
case 152:
case 153:
case 154:
case 155:
case 156:
case 157:
case 158:
return aarch64_ext_imm (self, info, code, inst);
case 38:
case 39:
Expand All @@ -10504,9 +10504,10 @@ aarch64_extract_operand (const aarch64_operand *self,
case 43:
return aarch64_ext_shll_imm (self, info, code, inst);
case 46:
case 129:
return aarch64_ext_fpimm (self, info, code, inst);
case 60:
case 130:
case 134:
return aarch64_ext_limm (self, info, code, inst);
case 61:
return aarch64_ext_aimm (self, info, code, inst);
Expand Down Expand Up @@ -10597,22 +10598,28 @@ aarch64_extract_operand (const aarch64_operand *self,
return aarch64_ext_sve_aimm (self, info, code, inst);
case 128:
return aarch64_ext_sve_asimm (self, info, code, inst);
case 129:
return aarch64_ext_inv_limm (self, info, code, inst);
case 130:
return aarch64_ext_sve_float_half_one (self, info, code, inst);
case 131:
return aarch64_ext_sve_limm_mov (self, info, code, inst);
return aarch64_ext_sve_float_half_two (self, info, code, inst);
case 132:
return aarch64_ext_sve_float_zero_one (self, info, code, inst);
case 133:
return aarch64_ext_inv_limm (self, info, code, inst);
case 135:
return aarch64_ext_sve_limm_mov (self, info, code, inst);
case 137:
return aarch64_ext_sve_scale (self, info, code, inst);
case 143:
case 144:
case 147:
case 148:
return aarch64_ext_sve_shlimm (self, info, code, inst);
case 145:
case 146:
case 149:
case 150:
return aarch64_ext_sve_shrimm (self, info, code, inst);
case 161:
case 165:
return aarch64_ext_sve_index (self, info, code, inst);
case 162:
case 164:
case 166:
case 168:
return aarch64_ext_sve_reglist (self, info, code, inst);
default: assert (0); abort ();
}
Expand Down
Loading

0 comments on commit 165d495

Please sign in to comment.