[AArch64][SVE 27/32] Add SVE integer immediate operands

This patch adds the new SVE integer immediate operands.  There are
three kinds:

- simple signed and unsigned ranges, but with new widths and positions.

- 13-bit logical immediates.  These have the same form as in base AArch64,
  but at a different bit position.

  In the case of the "MOV Zn.<T>, #<limm>" alias of DUPM, the logical
  immediate <limm> is not allowed to be a valid DUP immediate, since DUP
  is preferred over DUPM for constants that both instructions can handle.

- a new 9-bit arithmetic immediate, of the form "<imm8>{, LSL #8}".
  In some contexts the operand is signed and in others it's unsigned.
  As an extension, we allow shifted immediates to be written as a single
  integer, e.g. "#256" is equivalent to "#1, LSL #8".  We also use the
  shiftless form as the preferred disassembly, except for the special
  case of "#0, LSL #8" (a redundant encoding of 0).

include/
	* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
	(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
	(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
	(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
	(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
	(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
	(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
	(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
	(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
	(AARCH64_OPND_SVE_UIMM8_53): Likewise.
	(aarch64_sve_dupm_mov_immediate_p): Declare.

opcodes/
	* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
	integer immediate operands.
	* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
	(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
	(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
	* aarch64-opc.c (fields): Add corresponding entries.
	(operand_general_constraint_met_p): Handle the new SVE integer
	immediate operands.
	(aarch64_print_operand): Likewise.
	(aarch64_sve_dupm_mov_immediate_p): New function.
	* aarch64-opc-2.c: Regenerate.
	* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
	(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
	* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
	(aarch64_ins_limm): ...here.
	(aarch64_ins_inv_limm): New function.
	(aarch64_ins_sve_aimm): Likewise.
	(aarch64_ins_sve_asimm): Likewise.
	(aarch64_ins_sve_limm_mov): Likewise.
	(aarch64_ins_sve_shlimm): Likewise.
	(aarch64_ins_sve_shrimm): Likewise.
	* aarch64-asm-2.c: Regenerate.
	* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
	(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
	* aarch64-dis.c (decode_limm): New function, split out from...
	(aarch64_ext_limm): ...here.
	(aarch64_ext_inv_limm): New function.
	(decode_sve_aimm): Likewise.
	(aarch64_ext_sve_aimm): Likewise.
	(aarch64_ext_sve_asimm): Likewise.
	(aarch64_ext_sve_limm_mov): Likewise.
	(aarch64_top_bit): Likewise.
	(aarch64_ext_sve_shlimm): Likewise.
	(aarch64_ext_sve_shrimm): Likewise.
	* aarch64-dis-2.c: Regenerate.

gas/
	* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
	immediate operands.
This commit is contained in:
Richard Sandiford 2016-09-21 16:56:57 +01:00
parent 98907a7049
commit e950b34539
15 changed files with 714 additions and 100 deletions

View File

@ -1,3 +1,8 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* config/tc-aarch64.c (parse_operands): Handle the new SVE integer
immediate operands.
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* config/tc-aarch64.c (SHIFTED_NONE, SHIFTED_MUL_VL): New

View File

@ -5501,6 +5501,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
break;
case AARCH64_OPND_CCMP_IMM:
case AARCH64_OPND_SIMM5:
case AARCH64_OPND_FBITS:
case AARCH64_OPND_UIMM4:
case AARCH64_OPND_UIMM3_OP1:
@ -5508,10 +5509,36 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_IMM_VLSL:
case AARCH64_OPND_IMM:
case AARCH64_OPND_WIDTH:
case AARCH64_OPND_SVE_INV_LIMM:
case AARCH64_OPND_SVE_LIMM:
case AARCH64_OPND_SVE_LIMM_MOV:
case AARCH64_OPND_SVE_SHLIMM_PRED:
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
case AARCH64_OPND_SVE_SHRIMM_PRED:
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
case AARCH64_OPND_SVE_SIMM5:
case AARCH64_OPND_SVE_SIMM5B:
case AARCH64_OPND_SVE_SIMM6:
case AARCH64_OPND_SVE_SIMM8:
case AARCH64_OPND_SVE_UIMM3:
case AARCH64_OPND_SVE_UIMM7:
case AARCH64_OPND_SVE_UIMM8:
case AARCH64_OPND_SVE_UIMM8_53:
po_imm_nc_or_fail ();
info->imm.value = val;
break;
case AARCH64_OPND_SVE_AIMM:
case AARCH64_OPND_SVE_ASIMM:
po_imm_nc_or_fail ();
info->imm.value = val;
skip_whitespace (str);
if (skip_past_comma (&str))
po_misc_or_fail (parse_shift (&str, info, SHIFTED_LSL));
else
inst.base.operands[i].shifter.kind = AARCH64_MOD_LSL;
break;
case AARCH64_OPND_SVE_PATTERN:
po_enum_or_fail (aarch64_sve_pattern_array);
info->imm.value = val;

View File

@ -1,3 +1,17 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* opcode/aarch64.h (AARCH64_OPND_SIMM5): New aarch64_opnd.
(AARCH64_OPND_SVE_AIMM, AARCH64_OPND_SVE_ASIMM)
(AARCH64_OPND_SVE_INV_LIMM, AARCH64_OPND_SVE_LIMM)
(AARCH64_OPND_SVE_LIMM_MOV, AARCH64_OPND_SVE_SHLIMM_PRED)
(AARCH64_OPND_SVE_SHLIMM_UNPRED, AARCH64_OPND_SVE_SHRIMM_PRED)
(AARCH64_OPND_SVE_SHRIMM_UNPRED, AARCH64_OPND_SVE_SIMM5)
(AARCH64_OPND_SVE_SIMM5B, AARCH64_OPND_SVE_SIMM6)
(AARCH64_OPND_SVE_SIMM8, AARCH64_OPND_SVE_UIMM3)
(AARCH64_OPND_SVE_UIMM7, AARCH64_OPND_SVE_UIMM8)
(AARCH64_OPND_SVE_UIMM8_53): Likewise.
(aarch64_sve_dupm_mov_immediate_p): Declare.
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_S4xVL): New aarch64_opnd.

View File

@ -200,6 +200,7 @@ enum aarch64_opnd
AARCH64_OPND_BIT_NUM, /* Immediate. */
AARCH64_OPND_EXCEPTION,/* imm16 operand in exception instructions. */
AARCH64_OPND_CCMP_IMM,/* Immediate in conditional compare instructions. */
AARCH64_OPND_SIMM5, /* 5-bit signed immediate in the imm5 field. */
AARCH64_OPND_NZCV, /* Flag bit specifier giving an alternative value for
each condition flag. */
@ -289,6 +290,11 @@ enum aarch64_opnd
AARCH64_OPND_SVE_ADDR_ZZ_LSL, /* SVE [Zn.<T>, Zm,<T>, LSL #<msz>]. */
AARCH64_OPND_SVE_ADDR_ZZ_SXTW, /* SVE [Zn.<T>, Zm,<T>, SXTW #<msz>]. */
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_INV_LIMM, /* SVE inverted logical immediate. */
AARCH64_OPND_SVE_LIMM, /* SVE logical immediate. */
AARCH64_OPND_SVE_LIMM_MOV, /* SVE logical immediate for MOV. */
AARCH64_OPND_SVE_PATTERN, /* SVE vector pattern enumeration. */
AARCH64_OPND_SVE_PATTERN_SCALED, /* Likewise, with additional MUL factor. */
AARCH64_OPND_SVE_PRFOP, /* SVE prefetch operation. */
@ -300,6 +306,18 @@ enum aarch64_opnd
AARCH64_OPND_SVE_Pm, /* SVE p0-p15 in Pm. */
AARCH64_OPND_SVE_Pn, /* SVE p0-p15 in Pn. */
AARCH64_OPND_SVE_Pt, /* SVE p0-p15 in Pt. */
AARCH64_OPND_SVE_SHLIMM_PRED, /* SVE shift left amount (predicated). */
AARCH64_OPND_SVE_SHLIMM_UNPRED, /* SVE shift left amount (unpredicated). */
AARCH64_OPND_SVE_SHRIMM_PRED, /* SVE shift right amount (predicated). */
AARCH64_OPND_SVE_SHRIMM_UNPRED, /* SVE shift right amount (unpredicated). */
AARCH64_OPND_SVE_SIMM5, /* SVE signed 5-bit immediate. */
AARCH64_OPND_SVE_SIMM5B, /* SVE secondary signed 5-bit immediate. */
AARCH64_OPND_SVE_SIMM6, /* SVE signed 6-bit immediate. */
AARCH64_OPND_SVE_SIMM8, /* SVE signed 8-bit immediate. */
AARCH64_OPND_SVE_UIMM3, /* SVE unsigned 3-bit immediate. */
AARCH64_OPND_SVE_UIMM7, /* SVE unsigned 7-bit immediate. */
AARCH64_OPND_SVE_UIMM8, /* SVE unsigned 8-bit immediate. */
AARCH64_OPND_SVE_UIMM8_53, /* SVE split unsigned 8-bit immediate. */
AARCH64_OPND_SVE_Za_5, /* SVE vector register in Za, bits [9,5]. */
AARCH64_OPND_SVE_Za_16, /* SVE vector register in Za, bits [20,16]. */
AARCH64_OPND_SVE_Zd, /* SVE vector register in Zd. */
@ -1065,6 +1083,9 @@ aarch64_get_operand_name (enum aarch64_opnd);
extern const char *
aarch64_get_operand_desc (enum aarch64_opnd);
extern bfd_boolean
aarch64_sve_dupm_mov_immediate_p (uint64_t, int);
#ifdef DEBUG_AARCH64
extern int debug_dump;

View File

@ -1,3 +1,41 @@
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE
integer immediate operands.
* aarch64-opc.h (FLD_SVE_immN, FLD_SVE_imm3, FLD_SVE_imm5)
(FLD_SVE_imm5b, FLD_SVE_imm7, FLD_SVE_imm8, FLD_SVE_imm9)
(FLD_SVE_immr, FLD_SVE_imms, FLD_SVE_tszh): New aarch64_field_kinds.
* aarch64-opc.c (fields): Add corresponding entries.
(operand_general_constraint_met_p): Handle the new SVE integer
immediate operands.
(aarch64_print_operand): Likewise.
(aarch64_sve_dupm_mov_immediate_p): New function.
* aarch64-opc-2.c: Regenerate.
* aarch64-asm.h (ins_inv_limm, ins_sve_aimm, ins_sve_asimm)
(ins_sve_limm_mov, ins_sve_shlimm, ins_sve_shrimm): New inserters.
* aarch64-asm.c (aarch64_ins_limm_1): New function, split out from...
(aarch64_ins_limm): ...here.
(aarch64_ins_inv_limm): New function.
(aarch64_ins_sve_aimm): Likewise.
(aarch64_ins_sve_asimm): Likewise.
(aarch64_ins_sve_limm_mov): Likewise.
(aarch64_ins_sve_shlimm): Likewise.
(aarch64_ins_sve_shrimm): Likewise.
* aarch64-asm-2.c: Regenerate.
* aarch64-dis.h (ext_inv_limm, ext_sve_aimm, ext_sve_asimm)
(ext_sve_limm_mov, ext_sve_shlimm, ext_sve_shrimm): New extractors.
* aarch64-dis.c (decode_limm): New function, split out from...
(aarch64_ext_limm): ...here.
(aarch64_ext_inv_limm): New function.
(decode_sve_aimm): Likewise.
(aarch64_ext_sve_aimm): Likewise.
(aarch64_ext_sve_asimm): Likewise.
(aarch64_ext_sve_limm_mov): Likewise.
(aarch64_top_bit): Likewise.
(aarch64_ext_sve_shlimm): Likewise.
(aarch64_ext_sve_shrimm): Likewise.
* aarch64-dis-2.c: Regenerate.
2016-09-21 Richard Sandiford <richard.sandiford@arm.com>
* aarch64-tbl.h (AARCH64_OPERANDS): Add entries for new MUL VL

View File

@ -480,12 +480,6 @@ aarch64_insert_operand (const aarch64_operand *self,
case 27:
case 35:
case 36:
case 129:
case 130:
case 131:
case 132:
case 133:
case 134:
case 135:
case 136:
case 137:
@ -494,7 +488,13 @@ aarch64_insert_operand (const aarch64_operand *self,
case 140:
case 141:
case 142:
case 145:
case 155:
case 156:
case 157:
case 158:
case 159:
case 160:
case 163:
return aarch64_ins_regno (self, info, code, inst);
case 12:
return aarch64_ins_reg_extended (self, info, code, inst);
@ -527,12 +527,21 @@ aarch64_insert_operand (const aarch64_operand *self,
case 56:
case 57:
case 58:
case 67:
case 59:
case 68:
case 69:
case 70:
case 126:
case 128:
case 71:
case 132:
case 134:
case 147:
case 148:
case 149:
case 150:
case 151:
case 152:
case 153:
case 154:
return aarch64_ins_imm (self, info, code, inst);
case 38:
case 39:
@ -543,61 +552,61 @@ aarch64_insert_operand (const aarch64_operand *self,
return aarch64_ins_advsimd_imm_modified (self, info, code, inst);
case 46:
return aarch64_ins_fpimm (self, info, code, inst);
case 59:
return aarch64_ins_limm (self, info, code, inst);
case 60:
return aarch64_ins_aimm (self, info, code, inst);
case 130:
return aarch64_ins_limm (self, info, code, inst);
case 61:
return aarch64_ins_imm_half (self, info, code, inst);
return aarch64_ins_aimm (self, info, code, inst);
case 62:
return aarch64_ins_imm_half (self, info, code, inst);
case 63:
return aarch64_ins_fbits (self, info, code, inst);
case 64:
case 65:
case 66:
return aarch64_ins_cond (self, info, code, inst);
case 71:
case 77:
return aarch64_ins_addr_simple (self, info, code, inst);
case 72:
return aarch64_ins_addr_regoff (self, info, code, inst);
case 78:
return aarch64_ins_addr_simple (self, info, code, inst);
case 73:
return aarch64_ins_addr_regoff (self, info, code, inst);
case 74:
case 75:
return aarch64_ins_addr_simm (self, info, code, inst);
case 76:
return aarch64_ins_addr_simm (self, info, code, inst);
case 77:
return aarch64_ins_addr_uimm12 (self, info, code, inst);
case 78:
return aarch64_ins_simd_addr_post (self, info, code, inst);
case 79:
return aarch64_ins_sysreg (self, info, code, inst);
return aarch64_ins_simd_addr_post (self, info, code, inst);
case 80:
return aarch64_ins_pstatefield (self, info, code, inst);
return aarch64_ins_sysreg (self, info, code, inst);
case 81:
return aarch64_ins_pstatefield (self, info, code, inst);
case 82:
case 83:
case 84:
return aarch64_ins_sysins_op (self, info, code, inst);
case 85:
return aarch64_ins_sysins_op (self, info, code, inst);
case 86:
return aarch64_ins_barrier (self, info, code, inst);
case 87:
return aarch64_ins_prfop (self, info, code, inst);
return aarch64_ins_barrier (self, info, code, inst);
case 88:
return aarch64_ins_hint (self, info, code, inst);
return aarch64_ins_prfop (self, info, code, inst);
case 89:
return aarch64_ins_hint (self, info, code, inst);
case 90:
case 91:
case 92:
return aarch64_ins_sve_addr_ri_s4xvl (self, info, code, inst);
case 93:
return aarch64_ins_sve_addr_ri_s6xvl (self, info, code, inst);
return aarch64_ins_sve_addr_ri_s4xvl (self, info, code, inst);
case 94:
return aarch64_ins_sve_addr_ri_s9xvl (self, info, code, inst);
return aarch64_ins_sve_addr_ri_s6xvl (self, info, code, inst);
case 95:
return aarch64_ins_sve_addr_ri_s9xvl (self, info, code, inst);
case 96:
case 97:
case 98:
return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst);
case 99:
return aarch64_ins_sve_addr_ri_u6 (self, info, code, inst);
case 100:
case 101:
case 102:
@ -609,8 +618,8 @@ aarch64_insert_operand (const aarch64_operand *self,
case 108:
case 109:
case 110:
return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst);
case 111:
return aarch64_ins_sve_addr_rr_lsl (self, info, code, inst);
case 112:
case 113:
case 114:
@ -618,24 +627,39 @@ aarch64_insert_operand (const aarch64_operand *self,
case 116:
case 117:
case 118:
return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst);
case 119:
return aarch64_ins_sve_addr_rz_xtw (self, info, code, inst);
case 120:
case 121:
case 122:
return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst);
case 123:
return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst);
return aarch64_ins_sve_addr_zi_u5 (self, info, code, inst);
case 124:
return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst);
return aarch64_ins_sve_addr_zz_lsl (self, info, code, inst);
case 125:
return aarch64_ins_sve_addr_zz_sxtw (self, info, code, inst);
case 126:
return aarch64_ins_sve_addr_zz_uxtw (self, info, code, inst);
case 127:
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 131:
return aarch64_ins_sve_limm_mov (self, info, code, inst);
case 133:
return aarch64_ins_sve_scale (self, info, code, inst);
case 143:
return aarch64_ins_sve_index (self, info, code, inst);
case 144:
return aarch64_ins_sve_shlimm (self, info, code, inst);
case 145:
case 146:
return aarch64_ins_sve_shrimm (self, info, code, inst);
case 161:
return aarch64_ins_sve_index (self, info, code, inst);
case 162:
case 164:
return aarch64_ins_sve_reglist (self, info, code, inst);
default: assert (0); abort ();
}

View File

@ -452,17 +452,18 @@ aarch64_ins_aimm (const aarch64_operand *self, const aarch64_opnd_info *info,
return NULL;
}
/* Insert logical/bitmask immediate for e.g. the last operand in
ORR <Wd|WSP>, <Wn>, #<imm>. */
const char *
aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
aarch64_insn *code, const aarch64_inst *inst ATTRIBUTE_UNUSED)
/* Common routine shared by aarch64_ins{,_inv}_limm. INVERT_P says whether
the operand should be inverted before encoding. */
static const char *
aarch64_ins_limm_1 (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst, bfd_boolean invert_p)
{
aarch64_insn value;
uint64_t imm = info->imm.value;
int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
if (inst->opcode->op == OP_BIC)
if (invert_p)
imm = ~imm;
if (aarch64_logical_immediate_p (imm, esize, &value) == FALSE)
/* The constraint check should have guaranteed this wouldn't happen. */
@ -473,6 +474,25 @@ aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
return NULL;
}
/* Insert logical/bitmask immediate for e.g. the last operand in
ORR <Wd|WSP>, <Wn>, #<imm>. */
const char *
aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
aarch64_insn *code, const aarch64_inst *inst)
{
return aarch64_ins_limm_1 (self, info, code, inst,
inst->opcode->op == OP_BIC);
}
/* Insert a logical/bitmask immediate for the BIC alias of AND (etc.). */
const char *
aarch64_ins_inv_limm (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst)
{
return aarch64_ins_limm_1 (self, info, code, inst, TRUE);
}
/* Encode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
const char *
@ -903,6 +923,30 @@ aarch64_ins_sve_addr_zz_uxtw (const aarch64_operand *self,
return aarch64_ext_sve_addr_zz (self, info, code);
}
/* Encode an SVE ADD/SUB immediate. */
const char *
aarch64_ins_sve_aimm (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst ATTRIBUTE_UNUSED)
{
if (info->shifter.amount == 8)
insert_all_fields (self, code, (info->imm.value & 0xff) | 256);
else if (info->imm.value != 0 && (info->imm.value & 0xff) == 0)
insert_all_fields (self, code, ((info->imm.value / 256) & 0xff) | 256);
else
insert_all_fields (self, code, info->imm.value & 0xff);
return NULL;
}
/* Encode an SVE CPY/DUP immediate. */
const char *
aarch64_ins_sve_asimm (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst)
{
return aarch64_ins_sve_aimm (self, info, code, inst);
}
/* Encode Zn[MM], where MM has a 7-bit triangular encoding. The fields
array specifies which field to use for Zn. MM is encoded in the
concatenation of imm5 and SVE_tszh, with imm5 being the less
@ -919,6 +963,15 @@ aarch64_ins_sve_index (const aarch64_operand *self,
return NULL;
}
/* Encode a logical/bitmask immediate for the MOV alias of SVE DUPM. */
const char *
aarch64_ins_sve_limm_mov (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst)
{
return aarch64_ins_limm (self, info, code, inst);
}
/* Encode {Zn.<T> - Zm.<T>}. The fields array specifies which field
to use for Zn. */
const char *
@ -943,6 +996,38 @@ aarch64_ins_sve_scale (const aarch64_operand *self,
return NULL;
}
/* Encode an SVE shift left immediate. */
const char *
aarch64_ins_sve_shlimm (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst)
{
const aarch64_opnd_info *prev_operand;
unsigned int esize;
assert (info->idx > 0);
prev_operand = &inst->operands[info->idx - 1];
esize = aarch64_get_qualifier_esize (prev_operand->qualifier);
insert_all_fields (self, code, 8 * esize + info->imm.value);
return NULL;
}
/* Encode an SVE shift right immediate. */
const char *
aarch64_ins_sve_shrimm (const aarch64_operand *self,
const aarch64_opnd_info *info, aarch64_insn *code,
const aarch64_inst *inst)
{
const aarch64_opnd_info *prev_operand;
unsigned int esize;
assert (info->idx > 0);
prev_operand = &inst->operands[info->idx - 1];
esize = aarch64_get_qualifier_esize (prev_operand->qualifier);
insert_all_fields (self, code, 16 * esize - info->imm.value);
return NULL;
}
/* Miscellaneous encoding functions. */
/* Encode size[0], i.e. bit 22, for

View File

@ -54,6 +54,7 @@ AARCH64_DECL_OPD_INSERTER (ins_fpimm);
AARCH64_DECL_OPD_INSERTER (ins_fbits);
AARCH64_DECL_OPD_INSERTER (ins_aimm);
AARCH64_DECL_OPD_INSERTER (ins_limm);
AARCH64_DECL_OPD_INSERTER (ins_inv_limm);
AARCH64_DECL_OPD_INSERTER (ins_ft);
AARCH64_DECL_OPD_INSERTER (ins_addr_simple);
AARCH64_DECL_OPD_INSERTER (ins_addr_regoff);
@ -79,9 +80,14 @@ AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zi_u5);
AARCH64_DECL_OPD_INSERTER (ins_sve_addr_zz_lsl);
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_index);
AARCH64_DECL_OPD_INSERTER (ins_sve_limm_mov);
AARCH64_DECL_OPD_INSERTER (ins_sve_reglist);
AARCH64_DECL_OPD_INSERTER (ins_sve_scale);
AARCH64_DECL_OPD_INSERTER (ins_sve_shlimm);
AARCH64_DECL_OPD_INSERTER (ins_sve_shrimm);
#undef AARCH64_DECL_OPD_INSERTER

View File

@ -10426,12 +10426,6 @@ aarch64_extract_operand (const aarch64_operand *self,
case 27:
case 35:
case 36:
case 129:
case 130:
case 131:
case 132:
case 133:
case 134:
case 135:
case 136:
case 137:
@ -10440,7 +10434,13 @@ aarch64_extract_operand (const aarch64_operand *self,
case 140:
case 141:
case 142:
case 145:
case 155:
case 156:
case 157:
case 158:
case 159:
case 160:
case 163:
return aarch64_ext_regno (self, info, code, inst);
case 8:
return aarch64_ext_regrt_sysins (self, info, code, inst);
@ -10477,13 +10477,22 @@ aarch64_extract_operand (const aarch64_operand *self,
case 56:
case 57:
case 58:
case 66:
case 59:
case 67:
case 68:
case 69:
case 70:
case 126:
case 128:
case 71:
case 132:
case 134:
case 147:
case 148:
case 149:
case 150:
case 151:
case 152:
case 153:
case 154:
return aarch64_ext_imm (self, info, code, inst);
case 38:
case 39:
@ -10496,61 +10505,61 @@ aarch64_extract_operand (const aarch64_operand *self,
return aarch64_ext_shll_imm (self, info, code, inst);
case 46:
return aarch64_ext_fpimm (self, info, code, inst);
case 59:
return aarch64_ext_limm (self, info, code, inst);
case 60:
return aarch64_ext_aimm (self, info, code, inst);
case 130:
return aarch64_ext_limm (self, info, code, inst);
case 61:
return aarch64_ext_imm_half (self, info, code, inst);
return aarch64_ext_aimm (self, info, code, inst);
case 62:
return aarch64_ext_imm_half (self, info, code, inst);
case 63:
return aarch64_ext_fbits (self, info, code, inst);
case 64:
case 65:
case 66:
return aarch64_ext_cond (self, info, code, inst);
case 71:
case 77:
return aarch64_ext_addr_simple (self, info, code, inst);
case 72:
return aarch64_ext_addr_regoff (self, info, code, inst);
case 78:
return aarch64_ext_addr_simple (self, info, code, inst);
case 73:
return aarch64_ext_addr_regoff (self, info, code, inst);
case 74:
case 75:
return aarch64_ext_addr_simm (self, info, code, inst);
case 76:
return aarch64_ext_addr_simm (self, info, code, inst);
case 77:
return aarch64_ext_addr_uimm12 (self, info, code, inst);
case 78:
return aarch64_ext_simd_addr_post (self, info, code, inst);
case 79:
return aarch64_ext_sysreg (self, info, code, inst);
return aarch64_ext_simd_addr_post (self, info, code, inst);
case 80:
return aarch64_ext_pstatefield (self, info, code, inst);
return aarch64_ext_sysreg (self, info, code, inst);
case 81:
return aarch64_ext_pstatefield (self, info, code, inst);
case 82:
case 83:
case 84:
return aarch64_ext_sysins_op (self, info, code, inst);
case 85:
return aarch64_ext_sysins_op (self, info, code, inst);
case 86:
return aarch64_ext_barrier (self, info, code, inst);
case 87:
return aarch64_ext_prfop (self, info, code, inst);
return aarch64_ext_barrier (self, info, code, inst);
case 88:
return aarch64_ext_hint (self, info, code, inst);
return aarch64_ext_prfop (self, info, code, inst);
case 89:
return aarch64_ext_hint (self, info, code, inst);
case 90:
case 91:
case 92:
return aarch64_ext_sve_addr_ri_s4xvl (self, info, code, inst);
case 93:
return aarch64_ext_sve_addr_ri_s6xvl (self, info, code, inst);
return aarch64_ext_sve_addr_ri_s4xvl (self, info, code, inst);
case 94:
return aarch64_ext_sve_addr_ri_s9xvl (self, info, code, inst);
return aarch64_ext_sve_addr_ri_s6xvl (self, info, code, inst);
case 95:
return aarch64_ext_sve_addr_ri_s9xvl (self, info, code, inst);
case 96:
case 97:
case 98:
return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst);
case 99:
return aarch64_ext_sve_addr_ri_u6 (self, info, code, inst);
case 100:
case 101:
case 102:
@ -10562,8 +10571,8 @@ aarch64_extract_operand (const aarch64_operand *self,
case 108:
case 109:
case 110:
return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst);
case 111:
return aarch64_ext_sve_addr_rr_lsl (self, info, code, inst);
case 112:
case 113:
case 114:
@ -10571,24 +10580,39 @@ aarch64_extract_operand (const aarch64_operand *self,
case 116:
case 117:
case 118:
return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst);
case 119:
return aarch64_ext_sve_addr_rz_xtw (self, info, code, inst);
case 120:
case 121:
case 122:
return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst);
case 123:
return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst);
return aarch64_ext_sve_addr_zi_u5 (self, info, code, inst);
case 124:
return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst);
return aarch64_ext_sve_addr_zz_lsl (self, info, code, inst);
case 125:
return aarch64_ext_sve_addr_zz_sxtw (self, info, code, inst);
case 126:
return aarch64_ext_sve_addr_zz_uxtw (self, info, code, inst);
case 127:
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 131:
return aarch64_ext_sve_limm_mov (self, info, code, inst);
case 133:
return aarch64_ext_sve_scale (self, info, code, inst);
case 143:
return aarch64_ext_sve_index (self, info, code, inst);
case 144:
return aarch64_ext_sve_shlimm (self, info, code, inst);
case 145:
case 146:
return aarch64_ext_sve_shrimm (self, info, code, inst);
case 161:
return aarch64_ext_sve_index (self, info, code, inst);
case 162:
case 164:
return aarch64_ext_sve_reglist (self, info, code, inst);
default: assert (0); abort ();
}

View File

@ -734,32 +734,21 @@ aarch64_ext_aimm (const aarch64_operand *self ATTRIBUTE_UNUSED,
return 1;
}
/* Decode logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */
int
aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst ATTRIBUTE_UNUSED)
/* Return true if VALUE is a valid logical immediate encoding, storing the
decoded value in *RESULT if so. ESIZE is the number of bytes in the
decoded immediate. */
static int
decode_limm (uint32_t esize, aarch64_insn value, int64_t *result)
{
uint64_t imm, mask;
uint32_t sf;
uint32_t N, R, S;
unsigned simd_size;
aarch64_insn value;
value = extract_fields (code, 0, 3, FLD_N, FLD_immr, FLD_imms);
assert (inst->operands[0].qualifier == AARCH64_OPND_QLF_W
|| inst->operands[0].qualifier == AARCH64_OPND_QLF_X);
sf = aarch64_get_qualifier_esize (inst->operands[0].qualifier) != 4;
/* value is N:immr:imms. */
S = value & 0x3f;
R = (value >> 6) & 0x3f;
N = (value >> 12) & 0x1;
if (sf == 0 && N == 1)
return 0;
/* The immediate value is S+1 bits to 1, left rotated by SIMDsize - R
(in other words, right rotated by R), then replicated. */
if (N != 0)
@ -782,6 +771,10 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
/* Top bits are IGNORED. */
R &= simd_size - 1;
}
if (simd_size > esize * 8)
return 0;
/* NOTE: if S = simd_size - 1 we get 0xf..f which is rejected. */
if (S == simd_size - 1)
return 0;
@ -803,11 +796,38 @@ aarch64_ext_limm (const aarch64_operand *self ATTRIBUTE_UNUSED,
default: assert (0); return 0;
}
info->imm.value = sf ? imm : imm & 0xffffffff;
*result = imm & ~((uint64_t) -1 << (esize * 4) << (esize * 4));
return 1;
}
/* Decode a logical immediate for e.g. ORR <Wd|WSP>, <Wn>, #<imm>. */
int
aarch64_ext_limm (const aarch64_operand *self,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst)
{
uint32_t esize;
aarch64_insn value;
value = extract_fields (code, 0, 3, self->fields[0], self->fields[1],
self->fields[2]);
esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
return decode_limm (esize, value, &info->imm.value);
}
/* Decode a logical immediate for the BIC alias of AND (etc.). */
int
aarch64_ext_inv_limm (const aarch64_operand *self,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst)
{
if (!aarch64_ext_limm (self, info, code, inst))
return 0;
info->imm.value = ~info->imm.value;
return 1;
}
/* Decode Ft for e.g. STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}]
or LDP <Qt1>, <Qt2>, [<Xn|SP>], #<imm>. */
int
@ -1404,6 +1424,47 @@ aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self,
return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW);
}
/* Finish decoding an SVE arithmetic immediate, given that INFO already
has the raw field value and that the low 8 bits decode to VALUE. */
static int
decode_sve_aimm (aarch64_opnd_info *info, int64_t value)
{
info->shifter.kind = AARCH64_MOD_LSL;
info->shifter.amount = 0;
if (info->imm.value & 0x100)
{
if (value == 0)
/* Decode 0x100 as #0, LSL #8. */
info->shifter.amount = 8;
else
value *= 256;
}
info->shifter.operator_present = (info->shifter.amount != 0);
info->shifter.amount_present = (info->shifter.amount != 0);
info->imm.value = value;
return 1;
}
/* Decode an SVE ADD/SUB immediate. */
int
aarch64_ext_sve_aimm (const aarch64_operand *self,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst)
{
return (aarch64_ext_imm (self, info, code, inst)
&& decode_sve_aimm (info, (uint8_t) info->imm.value));
}
/* Decode an SVE CPY/DUP immediate. */
int
aarch64_ext_sve_asimm (const aarch64_operand *self,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst)
{
return (aarch64_ext_imm (self, info, code, inst)
&& decode_sve_aimm (info, (int8_t) info->imm.value));
}
/* Decode Zn[MM], where MM has a 7-bit triangular encoding. The fields
array specifies which field to use for Zn. MM is encoded in the
concatenation of imm5 and SVE_tszh, with imm5 being the less
@ -1425,6 +1486,17 @@ aarch64_ext_sve_index (const aarch64_operand *self,
return 1;
}
/* Decode a logical immediate for the MOV alias of SVE DUPM. */
int
aarch64_ext_sve_limm_mov (const aarch64_operand *self,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst)
{
int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
return (aarch64_ext_limm (self, info, code, inst)
&& aarch64_sve_dupm_mov_immediate_p (info->imm.value, esize));
}
/* Decode {Zn.<T> - Zm.<T>}. The fields array specifies which field
to use for Zn. The opcode-dependent value specifies the number
of registers in the list. */
@ -1457,6 +1529,44 @@ aarch64_ext_sve_scale (const aarch64_operand *self,
info->shifter.amount_present = (val != 0);
return 1;
}
/* Return the top set bit in VALUE, which is expected to be relatively
small. */
static uint64_t
get_top_bit (uint64_t value)
{
while ((value & -value) != value)
value -= value & -value;
return value;
}
/* Decode an SVE shift-left immediate. */
int
aarch64_ext_sve_shlimm (const aarch64_operand *self,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst)
{
if (!aarch64_ext_imm (self, info, code, inst)
|| info->imm.value == 0)
return 0;
info->imm.value -= get_top_bit (info->imm.value);
return 1;
}
/* Decode an SVE shift-right immediate. */
int
aarch64_ext_sve_shrimm (const aarch64_operand *self,
aarch64_opnd_info *info, const aarch64_insn code,
const aarch64_inst *inst)
{
if (!aarch64_ext_imm (self, info, code, inst)
|| info->imm.value == 0)
return 0;
info->imm.value = get_top_bit (info->imm.value) * 2 - info->imm.value;
return 1;
}
/* Bitfields that are commonly used to encode certain operands' information
may be partially used as part of the base opcode in some instructions.

View File

@ -76,6 +76,7 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_fpimm);
AARCH64_DECL_OPD_EXTRACTOR (ext_fbits);
AARCH64_DECL_OPD_EXTRACTOR (ext_aimm);
AARCH64_DECL_OPD_EXTRACTOR (ext_limm);
AARCH64_DECL_OPD_EXTRACTOR (ext_inv_limm);
AARCH64_DECL_OPD_EXTRACTOR (ext_ft);
AARCH64_DECL_OPD_EXTRACTOR (ext_addr_simple);
AARCH64_DECL_OPD_EXTRACTOR (ext_addr_regoff);
@ -101,9 +102,14 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zi_u5);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_lsl);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_sxtw);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_addr_zz_uxtw);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_aimm);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_asimm);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_index);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_limm_mov);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_reglist);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shlimm);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shrimm);
#undef AARCH64_DECL_OPD_EXTRACTOR

View File

@ -82,6 +82,7 @@ const struct aarch64_operand aarch64_operands[] =
{AARCH64_OPND_CLASS_IMMEDIATE, "BIT_NUM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_b5, FLD_b40}, "the bit number to be tested"},
{AARCH64_OPND_CLASS_IMMEDIATE, "EXCEPTION", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm16}, "a 16-bit unsigned immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "CCMP_IMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5}, "a 5-bit unsigned immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SIMM5", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5}, "a 5-bit signed immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "NZCV", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_nzcv}, "a flag bit specifier giving an alternative value for each flag"},
{AARCH64_OPND_CLASS_IMMEDIATE, "LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_N,FLD_immr,FLD_imms}, "Logical immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "AIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_shift,FLD_imm12}, "a 12-bit unsigned immediate with optional left shift of 12 bits"},
@ -150,6 +151,11 @@ const struct aarch64_operand aarch64_operands[] =
{AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_LSL", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
{AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_SXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
{AARCH64_OPND_CLASS_ADDRESS, "SVE_ADDR_ZZ_UXTW", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zn,FLD_SVE_Zm_16}, "an address with a vector register offset"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_AIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm9}, "a 9-bit unsigned arithmetic operand"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_ASIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm9}, "a 9-bit signed arithmetic operand"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_INV_LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "an inverted 13-bit logical immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_LIMM", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "a 13-bit logical immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_LIMM_MOV", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms}, "a 13-bit logical move immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PATTERN_SCALED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_pattern}, "an enumeration value such as POW2"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_PRFOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_prfop}, "an enumeration value such as PLDL1KEEP"},
@ -161,6 +167,18 @@ const struct aarch64_operand aarch64_operands[] =
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pm}, "an SVE predicate register"},
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pn}, "an SVE predicate register"},
{AARCH64_OPND_CLASS_PRED_REG, "SVE_Pt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Pt}, "an SVE predicate register"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHLIMM_PRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_SVE_imm5}, "a shift-left immediate operand"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHLIMM_UNPRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_imm5}, "a shift-left immediate operand"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHRIMM_PRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_SVE_imm5}, "a shift-right immediate operand"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SHRIMM_UNPRED", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_tszh,FLD_imm5}, "a shift-right immediate operand"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM5", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm5}, "a 5-bit signed immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM5B", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm5b}, "a 5-bit signed immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM6", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imms}, "a 6-bit signed immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_SIMM8", OPD_F_SEXT | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm8}, "an 8-bit signed immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM3", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm3}, "a 3-bit unsigned immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM7", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm7}, "a 7-bit unsigned immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM8", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_imm8}, "an 8-bit unsigned immediate"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SVE_UIMM8_53", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm5,FLD_imm3}, "an 8-bit unsigned immediate"},
{AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_5", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_5}, "an SVE vector register"},
{AARCH64_OPND_CLASS_SVE_REG, "SVE_Za_16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Za_16}, "an SVE vector register"},
{AARCH64_OPND_CLASS_SVE_REG, "SVE_Zd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zd}, "an SVE vector register"},

View File

@ -264,6 +264,7 @@ const aarch64_field fields[] =
{ 31, 1 }, /* b5: in the test bit and branch instructions. */
{ 19, 5 }, /* b40: in the test bit and branch instructions. */
{ 10, 6 }, /* scale: in the fixed-point scalar to fp converting inst. */
{ 17, 1 }, /* SVE_N: SVE equivalent of N. */
{ 0, 4 }, /* SVE_Pd: p0-p15, bits [3,0]. */
{ 10, 3 }, /* SVE_Pg3: p0-p7, bits [12,10]. */
{ 5, 4 }, /* SVE_Pg4_5: p0-p15, bits [8,5]. */
@ -279,8 +280,16 @@ const aarch64_field fields[] =
{ 16, 5 }, /* SVE_Zm_16: SVE vector register, bits [20,16]. */
{ 5, 5 }, /* SVE_Zn: SVE vector register, bits [9,5]. */
{ 0, 5 }, /* SVE_Zt: SVE vector register, bits [4,0]. */
{ 16, 3 }, /* SVE_imm3: 3-bit immediate field. */
{ 16, 4 }, /* SVE_imm4: 4-bit immediate field. */
{ 5, 5 }, /* SVE_imm5: 5-bit immediate field. */
{ 16, 5 }, /* SVE_imm5b: secondary 5-bit immediate field. */
{ 16, 6 }, /* SVE_imm6: 6-bit immediate field. */
{ 14, 7 }, /* SVE_imm7: 7-bit immediate field. */
{ 5, 8 }, /* SVE_imm8: 8-bit immediate field. */
{ 5, 9 }, /* SVE_imm9: 9-bit immediate field. */
{ 11, 6 }, /* SVE_immr: SVE equivalent of immr. */
{ 5, 6 }, /* SVE_imms: SVE equivalent of imms. */
{ 10, 2 }, /* SVE_msz: 2-bit shift amount for ADR. */
{ 5, 5 }, /* SVE_pattern: vector pattern enumeration. */
{ 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */
@ -1374,9 +1383,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
const aarch64_opcode *opcode,
aarch64_operand_error *mismatch_detail)
{
unsigned num, modifiers;
unsigned num, modifiers, shift;
unsigned char size;
int64_t imm, min_value, max_value;
uint64_t uvalue, mask;
const aarch64_opnd_info *opnd = opnds + idx;
aarch64_opnd_qualifier_t qualifier = opnd->qualifier;
@ -1977,6 +1987,10 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
case AARCH64_OPND_UIMM7:
case AARCH64_OPND_UIMM3_OP1:
case AARCH64_OPND_UIMM3_OP2:
case AARCH64_OPND_SVE_UIMM3:
case AARCH64_OPND_SVE_UIMM7:
case AARCH64_OPND_SVE_UIMM8:
case AARCH64_OPND_SVE_UIMM8_53:
size = get_operand_fields_width (get_operand_from_code (type));
assert (size < 32);
if (!value_fit_unsigned_field_p (opnd->imm.value, size))
@ -1987,6 +2001,22 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
}
break;
case AARCH64_OPND_SIMM5:
case AARCH64_OPND_SVE_SIMM5:
case AARCH64_OPND_SVE_SIMM5B:
case AARCH64_OPND_SVE_SIMM6:
case AARCH64_OPND_SVE_SIMM8:
size = get_operand_fields_width (get_operand_from_code (type));
assert (size < 32);
if (!value_fit_signed_field_p (opnd->imm.value, size))
{
set_imm_out_of_range_error (mismatch_detail, idx,
-(1 << (size - 1)),
(1 << (size - 1)) - 1);
return 0;
}
break;
case AARCH64_OPND_WIDTH:
assert (idx > 1 && opnds[idx-1].type == AARCH64_OPND_IMM
&& opnds[0].type == AARCH64_OPND_Rd);
@ -2001,6 +2031,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
break;
case AARCH64_OPND_LIMM:
case AARCH64_OPND_SVE_LIMM:
{
int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
uint64_t uimm = opnd->imm.value;
@ -2171,6 +2202,90 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
}
break;
case AARCH64_OPND_SVE_AIMM:
min_value = 0;
sve_aimm:
assert (opnd->shifter.kind == AARCH64_MOD_LSL);
size = aarch64_get_qualifier_esize (opnds[0].qualifier);
mask = ~((uint64_t) -1 << (size * 4) << (size * 4));
uvalue = opnd->imm.value;
shift = opnd->shifter.amount;
if (size == 1)
{
if (shift != 0)
{
set_other_error (mismatch_detail, idx,
_("no shift amount allowed for"
" 8-bit constants"));
return 0;
}
}
else
{
if (shift != 0 && shift != 8)
{
set_other_error (mismatch_detail, idx,
_("shift amount must be 0 or 8"));
return 0;
}
if (shift == 0 && (uvalue & 0xff) == 0)
{
shift = 8;
uvalue = (int64_t) uvalue / 256;
}
}
mask >>= shift;
if ((uvalue & mask) != uvalue && (uvalue | ~mask) != uvalue)
{
set_other_error (mismatch_detail, idx,
_("immediate too big for element size"));
return 0;
}
uvalue = (uvalue - min_value) & mask;
if (uvalue > 0xff)
{
set_other_error (mismatch_detail, idx,
_("invalid arithmetic immediate"));
return 0;
}
break;
case AARCH64_OPND_SVE_ASIMM:
min_value = -128;
goto sve_aimm;
case AARCH64_OPND_SVE_INV_LIMM:
{
int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
uint64_t uimm = ~opnd->imm.value;
if (!aarch64_logical_immediate_p (uimm, esize, NULL))
{
set_other_error (mismatch_detail, idx,
_("immediate out of range"));
return 0;
}
}
break;
case AARCH64_OPND_SVE_LIMM_MOV:
{
int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
uint64_t uimm = opnd->imm.value;
if (!aarch64_logical_immediate_p (uimm, esize, NULL))
{
set_other_error (mismatch_detail, idx,
_("immediate out of range"));
return 0;
}
if (!aarch64_sve_dupm_mov_immediate_p (uimm, esize))
{
set_other_error (mismatch_detail, idx,
_("invalid replicated MOV immediate"));
return 0;
}
}
break;
case AARCH64_OPND_SVE_PATTERN_SCALED:
assert (opnd->shifter.kind == AARCH64_MOD_MUL);
if (!value_in_range_p (opnd->shifter.amount, 1, 16))
@ -2180,6 +2295,27 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
}
break;
case AARCH64_OPND_SVE_SHLIMM_PRED:
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
if (!value_in_range_p (opnd->imm.value, 0, 8 * size - 1))
{
set_imm_out_of_range_error (mismatch_detail, idx,
0, 8 * size - 1);
return 0;
}
break;
case AARCH64_OPND_SVE_SHRIMM_PRED:
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
if (!value_in_range_p (opnd->imm.value, 1, 8 * size))
{
set_imm_out_of_range_error (mismatch_detail, idx, 1, 8 * size);
return 0;
}
break;
default:
break;
}
@ -2953,6 +3089,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
case AARCH64_OPND_IMMR:
case AARCH64_OPND_IMMS:
case AARCH64_OPND_FBITS:
case AARCH64_OPND_SIMM5:
case AARCH64_OPND_SVE_SHLIMM_PRED:
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
case AARCH64_OPND_SVE_SHRIMM_PRED:
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
case AARCH64_OPND_SVE_SIMM5:
case AARCH64_OPND_SVE_SIMM5B:
case AARCH64_OPND_SVE_SIMM6:
case AARCH64_OPND_SVE_SIMM8:
case AARCH64_OPND_SVE_UIMM3:
case AARCH64_OPND_SVE_UIMM7:
case AARCH64_OPND_SVE_UIMM8:
case AARCH64_OPND_SVE_UIMM8_53:
snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
break;
@ -3021,6 +3170,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
case AARCH64_OPND_LIMM:
case AARCH64_OPND_AIMM:
case AARCH64_OPND_HALF:
case AARCH64_OPND_SVE_INV_LIMM:
case AARCH64_OPND_SVE_LIMM:
case AARCH64_OPND_SVE_LIMM_MOV:
if (opnd->shifter.amount)
snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
opnd->shifter.amount);
@ -3039,6 +3191,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
opnd->shifter.amount);
break;
case AARCH64_OPND_SVE_AIMM:
case AARCH64_OPND_SVE_ASIMM:
if (opnd->shifter.amount)
snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
opnd->shifter.amount);
else
snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
break;
case AARCH64_OPND_FPIMM:
case AARCH64_OPND_SIMD_FPIMM:
switch (aarch64_get_qualifier_esize (opnds[0].qualifier))
@ -3967,6 +4128,33 @@ verify_ldpsw (const struct aarch64_opcode * opcode ATTRIBUTE_UNUSED,
return TRUE;
}
/* Return true if VALUE cannot be moved into an SVE register using DUP
(with any element size, not just ESIZE) and if using DUPM would
therefore be OK. ESIZE is the number of bytes in the immediate. */
bfd_boolean
aarch64_sve_dupm_mov_immediate_p (uint64_t uvalue, int esize)
{
int64_t svalue = uvalue;
uint64_t upper = (uint64_t) -1 << (esize * 4) << (esize * 4);
if ((uvalue & ~upper) != uvalue && (uvalue | upper) != uvalue)
return FALSE;
if (esize <= 4 || (uint32_t) uvalue == (uint32_t) (uvalue >> 32))
{
svalue = (int32_t) uvalue;
if (esize <= 2 || (uint16_t) uvalue == (uint16_t) (uvalue >> 16))
{
svalue = (int16_t) uvalue;
if (esize == 1 || (uint8_t) uvalue == (uint8_t) (uvalue >> 8))
return FALSE;
}
}
if ((svalue & 0xff) == 0)
svalue /= 256;
return svalue < -128 || svalue >= 128;
}
/* Include the opcode description table as well as the operand description
table. */
#define VERIFIER(x) verify_##x

View File

@ -91,6 +91,7 @@ enum aarch64_field_kind
FLD_b5,
FLD_b40,
FLD_scale,
FLD_SVE_N,
FLD_SVE_Pd,
FLD_SVE_Pg3,
FLD_SVE_Pg4_5,
@ -106,8 +107,16 @@ enum aarch64_field_kind
FLD_SVE_Zm_16,
FLD_SVE_Zn,
FLD_SVE_Zt,
FLD_SVE_imm3,
FLD_SVE_imm4,
FLD_SVE_imm5,
FLD_SVE_imm5b,
FLD_SVE_imm6,
FLD_SVE_imm7,
FLD_SVE_imm8,
FLD_SVE_imm9,
FLD_SVE_immr,
FLD_SVE_imms,
FLD_SVE_msz,
FLD_SVE_pattern,
FLD_SVE_prfop,

View File

@ -2761,6 +2761,8 @@ struct aarch64_opcode aarch64_opcode_table[] =
"a 16-bit unsigned immediate") \
Y(IMMEDIATE, imm, "CCMP_IMM", 0, F(FLD_imm5), \
"a 5-bit unsigned immediate") \
Y(IMMEDIATE, imm, "SIMM5", OPD_F_SEXT, F(FLD_imm5), \
"a 5-bit signed immediate") \
Y(IMMEDIATE, imm, "NZCV", 0, F(FLD_nzcv), \
"a flag bit specifier giving an alternative value for each flag") \
Y(IMMEDIATE, limm, "LIMM", 0, F(FLD_N,FLD_immr,FLD_imms), \
@ -2925,6 +2927,19 @@ struct aarch64_opcode aarch64_opcode_table[] =
Y(ADDRESS, sve_addr_zz_uxtw, "SVE_ADDR_ZZ_UXTW", 0, \
F(FLD_SVE_Zn,FLD_SVE_Zm_16), \
"an address with a vector register offset") \
Y(IMMEDIATE, sve_aimm, "SVE_AIMM", 0, F(FLD_SVE_imm9), \
"a 9-bit unsigned arithmetic operand") \
Y(IMMEDIATE, sve_asimm, "SVE_ASIMM", 0, F(FLD_SVE_imm9), \
"a 9-bit signed arithmetic operand") \
Y(IMMEDIATE, inv_limm, "SVE_INV_LIMM", 0, \
F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \
"an inverted 13-bit logical immediate") \
Y(IMMEDIATE, limm, "SVE_LIMM", 0, \
F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \
"a 13-bit logical immediate") \
Y(IMMEDIATE, sve_limm_mov, "SVE_LIMM_MOV", 0, \
F(FLD_SVE_N,FLD_SVE_immr,FLD_SVE_imms), \
"a 13-bit logical move immediate") \
Y(IMMEDIATE, imm, "SVE_PATTERN", 0, F(FLD_SVE_pattern), \
"an enumeration value such as POW2") \
Y(IMMEDIATE, sve_scale, "SVE_PATTERN_SCALED", 0, \
@ -2947,6 +2962,30 @@ struct aarch64_opcode aarch64_opcode_table[] =
"an SVE predicate register") \
Y(PRED_REG, regno, "SVE_Pt", 0, F(FLD_SVE_Pt), \
"an SVE predicate register") \
Y(IMMEDIATE, sve_shlimm, "SVE_SHLIMM_PRED", 0, \
F(FLD_SVE_tszh,FLD_SVE_imm5), "a shift-left immediate operand") \
Y(IMMEDIATE, sve_shlimm, "SVE_SHLIMM_UNPRED", 0, \
F(FLD_SVE_tszh,FLD_imm5), "a shift-left immediate operand") \
Y(IMMEDIATE, sve_shrimm, "SVE_SHRIMM_PRED", 0, \
F(FLD_SVE_tszh,FLD_SVE_imm5), "a shift-right immediate operand") \
Y(IMMEDIATE, sve_shrimm, "SVE_SHRIMM_UNPRED", 0, \
F(FLD_SVE_tszh,FLD_imm5), "a shift-right immediate operand") \
Y(IMMEDIATE, imm, "SVE_SIMM5", OPD_F_SEXT, F(FLD_SVE_imm5), \
"a 5-bit signed immediate") \
Y(IMMEDIATE, imm, "SVE_SIMM5B", OPD_F_SEXT, F(FLD_SVE_imm5b), \
"a 5-bit signed immediate") \
Y(IMMEDIATE, imm, "SVE_SIMM6", OPD_F_SEXT, F(FLD_SVE_imms), \
"a 6-bit signed immediate") \
Y(IMMEDIATE, imm, "SVE_SIMM8", OPD_F_SEXT, F(FLD_SVE_imm8), \
"an 8-bit signed immediate") \
Y(IMMEDIATE, imm, "SVE_UIMM3", 0, F(FLD_SVE_imm3), \
"a 3-bit unsigned immediate") \
Y(IMMEDIATE, imm, "SVE_UIMM7", 0, F(FLD_SVE_imm7), \
"a 7-bit unsigned immediate") \
Y(IMMEDIATE, imm, "SVE_UIMM8", 0, F(FLD_SVE_imm8), \
"an 8-bit unsigned immediate") \
Y(IMMEDIATE, imm, "SVE_UIMM8_53", 0, F(FLD_imm5,FLD_imm3), \
"an 8-bit unsigned immediate") \
Y(SVE_REG, regno, "SVE_Za_5", 0, F(FLD_SVE_Za_5), \
"an SVE vector register") \
Y(SVE_REG, regno, "SVE_Za_16", 0, F(FLD_SVE_Za_16), \