/* aarch64-opc.c -- AArch64 opcode support.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2009-2020 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of the GNU opcodes library.
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
-#include <stdint.h>
+#include "bfd_stdint.h"
#include <stdarg.h>
#include <inttypes.h>
{ 15, 6 }, /* imm6_2: in rmif instructions. */
{ 11, 4 }, /* imm4: in advsimd ext and advsimd ins instructions. */
{ 0, 4 }, /* imm4_2: in rmif instructions. */
+ { 10, 4 }, /* imm4_3: in adddg/subg instructions. */
{ 16, 5 }, /* imm5: in conditional compare (immediate) instructions. */
{ 15, 7 }, /* imm7: in load/store pair pre/post index instructions. */
{ 13, 8 }, /* imm8: in floating-point scalar move immediate inst. */
{ 10, 12 }, /* imm12: in ld/st unsigned imm or add/sub shifted inst. */
{ 5, 14 }, /* imm14: in test bit and branch instructions. */
{ 5, 16 }, /* imm16: in exception instructions. */
+ { 0, 16 }, /* imm16_2: in udf instruction. */
{ 0, 26 }, /* imm26: in unconditional branch instructions. */
{ 10, 6 }, /* imms: in bitfield and logical immediate instructions. */
{ 16, 6 }, /* immr: in bitfield and logical immediate instructions. */
{ 0, 5 }, /* SVE_Zt: SVE vector register, bits [4,0]. */
{ 5, 1 }, /* SVE_i1: single-bit immediate. */
{ 22, 1 }, /* SVE_i3h: high bit of 3-bit immediate. */
+ { 11, 1 }, /* SVE_i3l: low bit of 3-bit immediate. */
+ { 19, 2 }, /* SVE_i3h2: two high bits of 3bit immediate, bits [20,19]. */
+ { 20, 1 }, /* SVE_i2h: high bit of 2bit immediate, bits. */
{ 16, 3 }, /* SVE_imm3: 3-bit immediate field. */
{ 16, 4 }, /* SVE_imm4: 4-bit immediate field. */
{ 5, 5 }, /* SVE_imm5: 5-bit immediate field. */
{ 0, 4 }, /* SVE_prfop: prefetch operation for SVE PRF[BHWD]. */
{ 16, 1 }, /* SVE_rot1: 1-bit rotation amount. */
{ 10, 2 }, /* SVE_rot2: 2-bit rotation amount. */
+ { 10, 1 }, /* SVE_rot3: 1-bit rotation amount at bit 10. */
{ 22, 1 }, /* SVE_sz: 1-bit element size select. */
+ { 17, 2 }, /* SVE_size: 2-bit element size, bits [18,17]. */
+ { 30, 1 }, /* SVE_sz2: 1-bit element size select. */
{ 16, 4 }, /* SVE_tsz: triangular size select. */
{ 22, 2 }, /* SVE_tszh: triangular size select high, bits [23,22]. */
{ 8, 2 }, /* SVE_tszl_8: triangular size select low, bits [9,8]. */
{ 13, 2 }, /* rotate2: Indexed element FCMLA immediate rotate. */
{ 12, 1 }, /* rotate3: FCADD immediate rotate. */
{ 12, 2 }, /* SM3: Indexed element SM3 2 bits index immediate. */
+ { 22, 1 }, /* sz: 1-bit element size select. */
};
enum aarch64_operand_class
const struct aarch64_name_value_pair aarch64_hint_options[] =
{
- { "csync", 0x11 }, /* PSB CSYNC. */
- { NULL, 0x0 },
+ /* BTI. This is also the F_DEFAULT entry for AARCH64_OPND_BTI_TARGET. */
+ { " ", HINT_ENCODE (HINT_OPD_F_NOPRINT, 0x20) },
+ { "csync", HINT_OPD_CSYNC }, /* PSB CSYNC. */
+ { "c", HINT_OPD_C }, /* BTI C. */
+ { "j", HINT_OPD_J }, /* BTI J. */
+ { "jc", HINT_OPD_JC }, /* BTI JC. */
+ { NULL, HINT_OPD_NULL },
};
/* op -> op: load = 0 instruction = 1 store = 2
assert (width < 32);
if (width < sizeof (value) * 8)
{
- int64_t lim = (int64_t)1 << (width - 1);
+ int64_t lim = (uint64_t) 1 << (width - 1);
if (value >= -lim && value < lim)
return 1;
}
assert (width < 32);
if (width < sizeof (value) * 8)
{
- int64_t lim = (int64_t)1 << width;
+ int64_t lim = (uint64_t) 1 << width;
if (value >= 0 && value < lim)
return 1;
}
{4, 1, 0x2, "s", OQK_OPD_VARIANT},
{8, 1, 0x3, "d", OQK_OPD_VARIANT},
{16, 1, 0x4, "q", OQK_OPD_VARIANT},
- {1, 4, 0x0, "4b", OQK_OPD_VARIANT},
+ {4, 1, 0x0, "4b", OQK_OPD_VARIANT},
+ {4, 1, 0x0, "2h", OQK_OPD_VARIANT},
{1, 4, 0x0, "4b", OQK_OPD_VARIANT},
{1, 8, 0x0, "8b", OQK_OPD_VARIANT},
{0, 0, 0, "z", OQK_OPD_VARIANT},
{0, 0, 0, "m", OQK_OPD_VARIANT},
+ /* Qualifier for scaled immediate for Tag granule (stg,st2g,etc). */
+ {16, 0, 0, "tag", OQK_OPD_VARIANT},
+
/* Qualifiers constraining the value range.
First 3 fields:
Lower bound, higher bound, unused. */
amount will be returned in *SHIFT_AMOUNT. */
bfd_boolean
-aarch64_wide_constant_p (int64_t value, int is32, unsigned int *shift_amount)
+aarch64_wide_constant_p (uint64_t value, int is32, unsigned int *shift_amount)
{
int amount;
/* Allow all zeros or all ones in top 32-bits, so that
32-bit constant expressions like ~0x80000000 are
permitted. */
- uint64_t ext = value;
- if (ext >> 32 != 0 && ext >> 32 != (uint64_t) 0xffffffff)
+ if (value >> 32 != 0 && value >> 32 != 0xffffffff)
/* Immediate out of range. */
return FALSE;
- value &= (int64_t) 0xffffffff;
+ value &= 0xffffffff;
}
/* first, try movz then movn */
amount = -1;
- if ((value & ((int64_t) 0xffff << 0)) == value)
+ if ((value & ((uint64_t) 0xffff << 0)) == value)
amount = 0;
- else if ((value & ((int64_t) 0xffff << 16)) == value)
+ else if ((value & ((uint64_t) 0xffff << 16)) == value)
amount = 16;
- else if (!is32 && (value & ((int64_t) 0xffff << 32)) == value)
+ else if (!is32 && (value & ((uint64_t) 0xffff << 32)) == value)
amount = 32;
- else if (!is32 && (value & ((int64_t) 0xffff << 48)) == value)
+ else if (!is32 && (value & ((uint64_t) 0xffff << 48)) == value)
amount = 48;
if (amount == -1)
{
case AARCH64_OPND_SVE_Zm3_INDEX:
case AARCH64_OPND_SVE_Zm3_22_INDEX:
+ case AARCH64_OPND_SVE_Zm3_11_INDEX:
+ case AARCH64_OPND_SVE_Zm4_11_INDEX:
case AARCH64_OPND_SVE_Zm4_INDEX:
size = get_operand_fields_width (get_operand_from_code (type));
shift = get_operand_specific_data (&aarch64_operands[type]);
: _("z0-z7 expected"));
return 0;
}
- mask = (1 << (size - shift)) - 1;
+ mask = (1u << (size - shift)) - 1;
if (!value_in_range_p (opnd->reglane.index, 0, mask))
{
set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, mask);
}
break;
+ case AARCH64_OPND_ADDR_SIMM11:
+ /* Signed 11 bits immediate offset (multiple of 16). */
+ if (!value_in_range_p (opnd->addr.offset.imm, -1024, 1008))
+ {
+ set_offset_out_of_range_error (mismatch_detail, idx, -1024, 1008);
+ return 0;
+ }
+
+ if (!value_aligned_p (opnd->addr.offset.imm, 16))
+ {
+ set_unaligned_error (mismatch_detail, idx, 16);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_ADDR_SIMM13:
+ /* Signed 13 bits immediate offset (multiple of 16). */
+ if (!value_in_range_p (opnd->addr.offset.imm, -4096, 4080))
+ {
+ set_offset_out_of_range_error (mismatch_detail, idx, -4096, 4080);
+ return 0;
+ }
+
+ if (!value_aligned_p (opnd->addr.offset.imm, 16))
+ {
+ set_unaligned_error (mismatch_detail, idx, 16);
+ return 0;
+ }
+ break;
+
case AARCH64_OPND_SIMD_ADDR_POST:
/* AdvSIMD load/store multiple structures, post-index. */
assert (idx == 1);
break;
case AARCH64_OPND_SVE_ADDR_RI_S4x16:
+ case AARCH64_OPND_SVE_ADDR_RI_S4x32:
min_value = -8;
max_value = 7;
goto sve_imm_offset;
+ case AARCH64_OPND_SVE_ADDR_ZX:
+ /* Everything is already ensured by parse_operands or
+ aarch64_ext_sve_addr_rr_lsl (because this is a very specific
+ argument type). */
+ assert (opnd->addr.offset.is_reg);
+ assert (opnd->addr.preind);
+ assert ((aarch64_operands[type].flags & OPD_F_NO_ZR) == 0);
+ assert (opnd->shifter.kind == AARCH64_MOD_LSL);
+ assert (opnd->shifter.operator_present == 0);
+ break;
+
case AARCH64_OPND_SVE_ADDR_R:
case AARCH64_OPND_SVE_ADDR_RR:
case AARCH64_OPND_SVE_ADDR_RR_LSL1:
case AARCH64_OPND_NZCV:
case AARCH64_OPND_CCMP_IMM:
case AARCH64_OPND_EXCEPTION:
+ case AARCH64_OPND_UNDEFINED:
+ case AARCH64_OPND_TME_UIMM16:
case AARCH64_OPND_UIMM4:
+ case AARCH64_OPND_UIMM4_ADDG:
case AARCH64_OPND_UIMM7:
case AARCH64_OPND_UIMM3_OP1:
case AARCH64_OPND_UIMM3_OP2:
if (!value_fit_unsigned_field_p (opnd->imm.value, size))
{
set_imm_out_of_range_error (mismatch_detail, idx, 0,
- (1 << size) - 1);
+ (1u << size) - 1);
+ return 0;
+ }
+ break;
+
+ case AARCH64_OPND_UIMM10:
+ /* Scaled unsigned 10 bits immediate offset. */
+ if (!value_in_range_p (opnd->imm.value, 0, 1008))
+ {
+ set_imm_out_of_range_error (mismatch_detail, idx, 0, 1008);
+ return 0;
+ }
+
+ if (!value_aligned_p (opnd->imm.value, 16))
+ {
+ set_unaligned_error (mismatch_detail, idx, 16);
return 0;
}
break;
case AARCH64_OPND_IMM_ROT3:
case AARCH64_OPND_SVE_IMM_ROT1:
+ case AARCH64_OPND_SVE_IMM_ROT3:
if (opnd->imm.value != 90 && opnd->imm.value != 270)
{
set_other_error (mismatch_detail, idx,
case AARCH64_OPND_SVE_SHLIMM_PRED:
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
+ case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
if (!value_in_range_p (opnd->imm.value, 0, 8 * size - 1))
{
case AARCH64_OPND_SVE_SHRIMM_PRED:
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
- size = aarch64_get_qualifier_esize (opnds[idx - 1].qualifier);
+ case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
+ num = (type == AARCH64_OPND_SVE_SHRIMM_UNPRED_22) ? 2 : 1;
+ size = aarch64_get_qualifier_esize (opnds[idx - num].qualifier);
if (!value_in_range_p (opnd->imm.value, 1, 8 * size))
{
- set_imm_out_of_range_error (mismatch_detail, idx, 1, 8 * size);
+ set_imm_out_of_range_error (mismatch_detail, idx, 1, 8*size);
return 0;
}
break;
assert (idx == 0 && opnds[1].type == AARCH64_OPND_UIMM4);
/* MSR UAO, #uimm4
MSR PAN, #uimm4
+ MSR SSBS,#uimm4
The immediate must be #0 or #1. */
if ((opnd->pstatefield == 0x03 /* UAO. */
|| opnd->pstatefield == 0x04 /* PAN. */
+ || opnd->pstatefield == 0x19 /* SSBS. */
|| opnd->pstatefield == 0x1a) /* DIT. */
&& opnds[1].imm.value > 1)
{
else
num = 16;
num = num / aarch64_get_qualifier_esize (qualifier) - 1;
+ assert (aarch64_get_qualifier_nelem (qualifier) == 1);
/* Index out-of-range. */
if (!value_in_range_p (opnd->reglane.index, 0, num))
if (opnd->addr.writeback)
{
if (opnd->addr.preind)
- snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+ {
+ if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
+ snprintf (buf, size, "[%s]!", base);
+ else
+ snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+ }
else
snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
}
case AARCH64_OPND_Rd_SP:
case AARCH64_OPND_Rn_SP:
+ case AARCH64_OPND_Rt_SP:
case AARCH64_OPND_SVE_Rn_SP:
case AARCH64_OPND_Rm_SP:
assert (opnd->qualifier == AARCH64_OPND_QLF_W
case AARCH64_OPND_SVE_Zm3_INDEX:
case AARCH64_OPND_SVE_Zm3_22_INDEX:
+ case AARCH64_OPND_SVE_Zm3_11_INDEX:
+ case AARCH64_OPND_SVE_Zm4_11_INDEX:
case AARCH64_OPND_SVE_Zm4_INDEX:
case AARCH64_OPND_SVE_Zn_INDEX:
snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
case AARCH64_OPND_IMM0:
case AARCH64_OPND_IMMR:
case AARCH64_OPND_IMMS:
+ case AARCH64_OPND_UNDEFINED:
case AARCH64_OPND_FBITS:
+ case AARCH64_OPND_TME_UIMM16:
case AARCH64_OPND_SIMM5:
case AARCH64_OPND_SVE_SHLIMM_PRED:
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
+ case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
case AARCH64_OPND_SVE_SHRIMM_PRED:
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
+ case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
case AARCH64_OPND_SVE_SIMM5:
case AARCH64_OPND_SVE_SIMM5B:
case AARCH64_OPND_SVE_SIMM6:
case AARCH64_OPND_IMM_ROT3:
case AARCH64_OPND_SVE_IMM_ROT1:
case AARCH64_OPND_SVE_IMM_ROT2:
+ case AARCH64_OPND_SVE_IMM_ROT3:
snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
break;
case AARCH64_OPND_NZCV:
case AARCH64_OPND_EXCEPTION:
case AARCH64_OPND_UIMM4:
+ case AARCH64_OPND_UIMM4_ADDG:
case AARCH64_OPND_UIMM7:
+ case AARCH64_OPND_UIMM10:
if (optional_operand_p (opcode, idx) == TRUE
&& (opnd->imm.value ==
(int64_t) get_optional_operand_default_value (opcode)))
get_offset_int_reg_name (opnd));
break;
+ case AARCH64_OPND_SVE_ADDR_ZX:
+ print_register_offset_address
+ (buf, size, opnd,
+ get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+ get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+ break;
+
case AARCH64_OPND_SVE_ADDR_RZ:
case AARCH64_OPND_SVE_ADDR_RZ_LSL1:
case AARCH64_OPND_SVE_ADDR_RZ_LSL2:
case AARCH64_OPND_ADDR_SIMM9:
case AARCH64_OPND_ADDR_SIMM9_2:
case AARCH64_OPND_ADDR_SIMM10:
+ case AARCH64_OPND_ADDR_SIMM11:
+ case AARCH64_OPND_ADDR_SIMM13:
case AARCH64_OPND_ADDR_OFFSET:
case AARCH64_OPND_SVE_ADDR_RI_S4x16:
+ case AARCH64_OPND_SVE_ADDR_RI_S4x32:
case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
case AARCH64_OPND_SYSREG_DC:
case AARCH64_OPND_SYSREG_IC:
case AARCH64_OPND_SYSREG_TLBI:
+ case AARCH64_OPND_SYSREG_SR:
snprintf (buf, size, "%s", opnd->sysins_op->name);
break;
break;
case AARCH64_OPND_BARRIER_PSB:
- snprintf (buf, size, "%s", opnd->hint_option->name);
+ snprintf (buf, size, "csync");
+ break;
+
+ case AARCH64_OPND_BTI_TARGET:
+ if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
+ snprintf (buf, size, "%s", opnd->hint_option->name);
break;
default:
{ "pan", CPEN_(0,C2,3), F_ARCHEXT },
{ "uao", CPEN_ (0, C2, 4), F_ARCHEXT },
{ "nzcv", CPEN_(3,C2,0), 0 },
+ { "ssbs", CPEN_(3,C2,6), F_ARCHEXT },
{ "fpcr", CPEN_(3,C4,0), 0 },
{ "fpsr", CPEN_(3,C4,1), 0 },
{ "dspsr_el0", CPEN_(3,C5,0), 0 },
{ "id_dfr0_el1", CPENC(3,0,C0,C1,2), F_REG_READ }, /* RO */
{ "id_pfr0_el1", CPENC(3,0,C0,C1,0), F_REG_READ }, /* RO */
{ "id_pfr1_el1", CPENC(3,0,C0,C1,1), F_REG_READ }, /* RO */
+ { "id_pfr2_el1", CPENC(3,0,C0,C3,4), F_ARCHEXT | F_REG_READ}, /* RO */
{ "id_afr0_el1", CPENC(3,0,C0,C1,3), F_REG_READ }, /* RO */
{ "id_mmfr0_el1", CPENC(3,0,C0,C1,4), F_REG_READ }, /* RO */
{ "id_mmfr1_el1", CPENC(3,0,C0,C1,5), F_REG_READ }, /* RO */
{ "contextidr_el1", CPENC(3,0,C13,C0,1), 0 },
{ "contextidr_el2", CPENC (3, 4, C13, C0, 1), F_ARCHEXT },
{ "contextidr_el12", CPENC (3, 5, C13, C0, 1), F_ARCHEXT },
+ { "rndr", CPENC(3,3,C2,C4,0), F_ARCHEXT | F_REG_READ }, /* RO */
+ { "rndrrs", CPENC(3,3,C2,C4,1), F_ARCHEXT | F_REG_READ }, /* RO */
+ { "tco", CPENC(3,3,C4,C2,7), F_ARCHEXT },
+ { "tfsre0_el1", CPENC(3,0,C5,C6,1), F_ARCHEXT },
+ { "tfsr_el1", CPENC(3,0,C5,C6,0), F_ARCHEXT },
+ { "tfsr_el2", CPENC(3,4,C5,C6,0), F_ARCHEXT },
+ { "tfsr_el3", CPENC(3,6,C5,C6,0), F_ARCHEXT },
+ { "tfsr_el12", CPENC(3,5,C5,C6,0), F_ARCHEXT },
+ { "rgsr_el1", CPENC(3,0,C1,C0,5), F_ARCHEXT },
+ { "gcr_el1", CPENC(3,0,C1,C0,6), F_ARCHEXT },
+ { "gmid_el1", CPENC(3,1,C0,C0,4), F_ARCHEXT | F_REG_READ }, /* RO */
{ "tpidr_el0", CPENC(3,3,C13,C0,2), 0 },
{ "tpidrro_el0", CPENC(3,3,C13,C0,3), 0 }, /* RW */
{ "tpidr_el1", CPENC(3,0,C13,C0,4), 0 },
{ "tpidr_el2", CPENC(3,4,C13,C0,2), 0 },
{ "tpidr_el3", CPENC(3,6,C13,C0,2), 0 },
+ { "scxtnum_el0", CPENC(3,3,C13,C0,7), F_ARCHEXT },
+ { "scxtnum_el1", CPENC(3,0,C13,C0,7), F_ARCHEXT },
+ { "scxtnum_el2", CPENC(3,4,C13,C0,7), F_ARCHEXT },
+ { "scxtnum_el12", CPENC(3,5,C13,C0,7), F_ARCHEXT },
+ { "scxtnum_el3", CPENC(3,6,C13,C0,7), F_ARCHEXT },
{ "teecr32_el1", CPENC(2,2,C0, C0,0), 0 }, /* See section 3.9.7.1 */
{ "cntfrq_el0", CPENC(3,3,C14,C0,0), 0 }, /* RW */
{ "cntpct_el0", CPENC(3,3,C14,C0,1), F_REG_READ }, /* RO */
&& !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PAN))
return FALSE;
+ /* SCXTNUM_ELx registers. */
+ if ((reg->value == CPENC (3, 3, C13, C0, 7)
+ || reg->value == CPENC (3, 0, C13, C0, 7)
+ || reg->value == CPENC (3, 4, C13, C0, 7)
+ || reg->value == CPENC (3, 6, C13, C0, 7)
+ || reg->value == CPENC (3, 5, C13, C0, 7))
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SCXTNUM))
+ return FALSE;
+
+ /* ID_PFR2_EL1 register. */
+ if (reg->value == CPENC(3, 0, C0, C3, 4)
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_ID_PFR2))
+ return FALSE;
+
+ /* SSBS. Values are from aarch64_sys_regs. */
+ if (reg->value == CPEN_(3,C2,6)
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SSBS))
+ return FALSE;
+
/* Virtualization host extensions: system registers. */
if ((reg->value == CPENC (3, 4, C2, C0, 1)
|| reg->value == CPENC (3, 4, C13, C0, 1)
&& !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
return FALSE;
+ /* Random Number Instructions. For now they are available
+ (and optional) only with ARMv8.5-A. */
+ if ((reg->value == CPENC (3, 3, C2, C4, 0)
+ || reg->value == CPENC (3, 3, C2, C4, 1))
+ && !(AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_RNG)
+ && AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_5)))
+ return FALSE;
+
+ /* System Registers in ARMv8.5-A with AARCH64_FEATURE_MEMTAG. */
+ if ((reg->value == CPENC (3, 3, C4, C2, 7)
+ || reg->value == CPENC (3, 0, C5, C6, 1)
+ || reg->value == CPENC (3, 0, C5, C6, 0)
+ || reg->value == CPENC (3, 4, C5, C6, 0)
+ || reg->value == CPENC (3, 6, C5, C6, 0)
+ || reg->value == CPENC (3, 5, C5, C6, 0)
+ || reg->value == CPENC (3, 0, C1, C0, 5)
+ || reg->value == CPENC (3, 0, C1, C0, 6)
+ || reg->value == CPENC (3, 1, C0, C0, 4))
+ && !(AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_MEMTAG)))
+ return FALSE;
+
return TRUE;
}
{ "daifclr", 0x1f, 0 },
{ "pan", 0x04, F_ARCHEXT },
{ "uao", 0x03, F_ARCHEXT },
+ { "ssbs", 0x19, F_ARCHEXT },
{ "dit", 0x1a, F_ARCHEXT },
+ { "tco", 0x1c, F_ARCHEXT },
{ 0, CPENC(0,0,0,0,0), 0 },
};
&& !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
return FALSE;
+ /* SSBS. Values are from aarch64_pstatefields. */
+ if (reg->value == 0x19
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_SSBS))
+ return FALSE;
+
/* DIT. Values are from aarch64_pstatefields. */
if (reg->value == 0x1a
&& !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4))
return FALSE;
+ /* TCO. Values are from aarch64_pstatefields. */
+ if (reg->value == 0x1c
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_MEMTAG))
+ return FALSE;
+
return TRUE;
}
const aarch64_sys_ins_reg aarch64_sys_regs_dc[] =
{
{ "zva", CPENS (3, C7, C4, 1), F_HASXT },
+ { "gva", CPENS (3, C7, C4, 3), F_HASXT | F_ARCHEXT },
+ { "gzva", CPENS (3, C7, C4, 4), F_HASXT | F_ARCHEXT },
{ "ivac", CPENS (0, C7, C6, 1), F_HASXT },
+ { "igvac", CPENS (0, C7, C6, 3), F_HASXT | F_ARCHEXT },
+ { "igsw", CPENS (0, C7, C6, 4), F_HASXT | F_ARCHEXT },
{ "isw", CPENS (0, C7, C6, 2), F_HASXT },
+ { "igdvac", CPENS (0, C7, C6, 5), F_HASXT | F_ARCHEXT },
+ { "igdsw", CPENS (0, C7, C6, 6), F_HASXT | F_ARCHEXT },
{ "cvac", CPENS (3, C7, C10, 1), F_HASXT },
+ { "cgvac", CPENS (3, C7, C10, 3), F_HASXT | F_ARCHEXT },
+ { "cgdvac", CPENS (3, C7, C10, 5), F_HASXT | F_ARCHEXT },
{ "csw", CPENS (0, C7, C10, 2), F_HASXT },
+ { "cgsw", CPENS (0, C7, C10, 4), F_HASXT | F_ARCHEXT },
+ { "cgdsw", CPENS (0, C7, C10, 6), F_HASXT | F_ARCHEXT },
{ "cvau", CPENS (3, C7, C11, 1), F_HASXT },
{ "cvap", CPENS (3, C7, C12, 1), F_HASXT | F_ARCHEXT },
+ { "cgvap", CPENS (3, C7, C12, 3), F_HASXT | F_ARCHEXT },
+ { "cgdvap", CPENS (3, C7, C12, 5), F_HASXT | F_ARCHEXT },
+ { "cvadp", CPENS (3, C7, C13, 1), F_HASXT | F_ARCHEXT },
+ { "cgvadp", CPENS (3, C7, C13, 3), F_HASXT | F_ARCHEXT },
+ { "cgdvadp", CPENS (3, C7, C13, 5), F_HASXT | F_ARCHEXT },
{ "civac", CPENS (3, C7, C14, 1), F_HASXT },
+ { "cigvac", CPENS (3, C7, C14, 3), F_HASXT | F_ARCHEXT },
+ { "cigdvac", CPENS (3, C7, C14, 5), F_HASXT | F_ARCHEXT },
{ "cisw", CPENS (0, C7, C14, 2), F_HASXT },
+ { "cigsw", CPENS (0, C7, C14, 4), F_HASXT | F_ARCHEXT },
+ { "cigdsw", CPENS (0, C7, C14, 6), F_HASXT | F_ARCHEXT },
{ 0, CPENS(0,0,0,0), 0 }
};
{ 0, CPENS(0,0,0,0), 0 }
};
+const aarch64_sys_ins_reg aarch64_sys_regs_sr[] =
+{
+ /* RCTX is somewhat unique in a way that it has different values
+ (op2) based on the instruction in which it is used (cfp/dvp/cpp).
+ Thus op2 is masked out and instead encoded directly in the
+ aarch64_opcode_table entries for the respective instructions. */
+ { "rctx", CPENS(3,C7,C3,0), F_HASXT | F_ARCHEXT | F_REG_WRITE}, /* WO */
+
+ { 0, CPENS(0,0,0,0), 0 }
+};
+
bfd_boolean
aarch64_sys_ins_reg_has_xt (const aarch64_sys_ins_reg *sys_ins_reg)
{
&& !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
return FALSE;
+ /* DC CVADP. Values are from aarch64_sys_regs_dc. */
+ if (reg->value == CPENS (3, C7, C13, 1)
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_CVADP))
+ return FALSE;
+
+ /* DC <dc_op> for ARMv8.5-A Memory Tagging Extension. */
+ if ((reg->value == CPENS (0, C7, C6, 3)
+ || reg->value == CPENS (0, C7, C6, 4)
+ || reg->value == CPENS (0, C7, C10, 4)
+ || reg->value == CPENS (0, C7, C14, 4)
+ || reg->value == CPENS (3, C7, C10, 3)
+ || reg->value == CPENS (3, C7, C12, 3)
+ || reg->value == CPENS (3, C7, C13, 3)
+ || reg->value == CPENS (3, C7, C14, 3)
+ || reg->value == CPENS (3, C7, C4, 3)
+ || reg->value == CPENS (0, C7, C6, 5)
+ || reg->value == CPENS (0, C7, C6, 6)
+ || reg->value == CPENS (0, C7, C10, 6)
+ || reg->value == CPENS (0, C7, C14, 6)
+ || reg->value == CPENS (3, C7, C10, 5)
+ || reg->value == CPENS (3, C7, C12, 5)
+ || reg->value == CPENS (3, C7, C13, 5)
+ || reg->value == CPENS (3, C7, C14, 5)
+ || reg->value == CPENS (3, C7, C4, 4))
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_MEMTAG))
+ return FALSE;
+
/* AT S1E1RP, AT S1E1WP. Values are from aarch64_sys_regs_at. */
if ((reg->value == CPENS (0, C7, C9, 0)
|| reg->value == CPENS (0, C7, C9, 1))
&& !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_2))
return FALSE;
+ /* CFP/DVP/CPP RCTX : Value are from aarch64_sys_regs_sr. */
+ if (reg->value == CPENS (3, C7, C3, 0)
+ && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_PREDRES))
+ return FALSE;
+
return TRUE;
}
return ERR_OK;
}
+/* Verifier for vector by element 3 operands functions where the
+ conditions `if sz:L == 11 then UNDEFINED` holds. */
+
+static enum err_type
+verify_elem_sd (const struct aarch64_inst *inst, const aarch64_insn insn,
+ bfd_vma pc ATTRIBUTE_UNUSED, bfd_boolean encoding,
+ aarch64_operand_error *mismatch_detail ATTRIBUTE_UNUSED,
+ aarch64_instr_sequence *insn_sequence ATTRIBUTE_UNUSED)
+{
+ const aarch64_insn undef_pattern = 0x3;
+ aarch64_insn value;
+
+ assert (inst->opcode);
+ assert (inst->opcode->operands[2] == AARCH64_OPND_Em);
+ value = encoding ? inst->value : insn;
+ assert (value);
+
+ if (undef_pattern == extract_fields (value, 0, 2, FLD_sz, FLD_L))
+ return ERR_UND;
+
+ return ERR_OK;
+}
+
/* Initialize an instruction sequence insn_sequence with the instruction INST.
If INST is NULL the given insn_sequence is cleared and the sequence is left
uninitialized. */
{
/* Check to see if the MOVPRFX SVE instruction is followed by an SVE
instruction for better error messages. */
- if (!opcode->avariant || !(*opcode->avariant & AARCH64_FEATURE_SVE))
+ if (!opcode->avariant
+ || !(*opcode->avariant &
+ (AARCH64_FEATURE_SVE | AARCH64_FEATURE_SVE2)))
{
mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
mismatch_detail->error = _("SVE instruction expected after "
case AARCH64_OPND_Vm:
case AARCH64_OPND_Sn:
case AARCH64_OPND_Sm:
- case AARCH64_OPND_Rn:
- case AARCH64_OPND_Rm:
- case AARCH64_OPND_Rn_SP:
- case AARCH64_OPND_Rm_SP:
if (inst_op.reg.regno == blk_dest.reg.regno)
{
num_op_used++;
}
}
-done:
+ done:
/* Add the new instruction to the sequence. */
memcpy (insn_sequence->current_insns + insn_sequence->next_insn++,
inst, sizeof (aarch64_inst));