#define bit(obj,st) (((obj) >> (st)) & 1)
#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
-/* Pseudo register base numbers. */
-#define AARCH64_Q0_REGNUM 0
-#define AARCH64_D0_REGNUM (AARCH64_Q0_REGNUM + AARCH64_D_REGISTER_COUNT)
-#define AARCH64_S0_REGNUM (AARCH64_D0_REGNUM + 32)
-#define AARCH64_H0_REGNUM (AARCH64_S0_REGNUM + 32)
-#define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32)
+/* A Homogeneous Floating-Point or Short-Vector Aggregate may have at most
+ four members. */
+#define HA_MAX_NUM_FLDS 4
/* All possible aarch64 target descriptors. */
struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1];
}
}
-/* Return 1 if *TY is a homogeneous floating-point aggregate or
- homogeneous short-vector aggregate as defined in the AAPCS64 ABI
- document; otherwise return 0. */
+/* Worker function for aapcs_is_vfp_call_or_return_candidate.
+
+ Return the number of register required, or -1 on failure.
+
+ When encountering a base element, if FUNDAMENTAL_TYPE is not set then set it
+ to the element, else fail if the type of this element does not match the
+ existing value. */
static int
-is_hfa_or_hva (struct type *ty)
+aapcs_is_vfp_call_or_return_candidate_1 (struct type *type,
+ struct type **fundamental_type)
{
- switch (TYPE_CODE (ty))
+ if (type == nullptr)
+ return -1;
+
+ switch (TYPE_CODE (type))
{
+ case TYPE_CODE_FLT:
+ if (TYPE_LENGTH (type) > 16)
+ return -1;
+
+ if (*fundamental_type == nullptr)
+ *fundamental_type = type;
+ else if (TYPE_LENGTH (type) != TYPE_LENGTH (*fundamental_type)
+ || TYPE_CODE (type) != TYPE_CODE (*fundamental_type))
+ return -1;
+
+ return 1;
+
+ case TYPE_CODE_COMPLEX:
+ {
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_LENGTH (target_type) > 16)
+ return -1;
+
+ if (*fundamental_type == nullptr)
+ *fundamental_type = target_type;
+ else if (TYPE_LENGTH (target_type) != TYPE_LENGTH (*fundamental_type)
+ || TYPE_CODE (target_type) != TYPE_CODE (*fundamental_type))
+ return -1;
+
+ return 2;
+ }
+
case TYPE_CODE_ARRAY:
{
- struct type *target_ty = TYPE_TARGET_TYPE (ty);
+ if (TYPE_VECTOR (type))
+ {
+ if (TYPE_LENGTH (type) != 8 && TYPE_LENGTH (type) != 16)
+ return -1;
- if (TYPE_VECTOR (ty))
- return 0;
+ if (*fundamental_type == nullptr)
+ *fundamental_type = type;
+ else if (TYPE_LENGTH (type) != TYPE_LENGTH (*fundamental_type)
+ || TYPE_CODE (type) != TYPE_CODE (*fundamental_type))
+ return -1;
- if (TYPE_LENGTH (ty) <= 4 /* HFA or HVA has at most 4 members. */
- && (TYPE_CODE (target_ty) == TYPE_CODE_FLT /* HFA */
- || (TYPE_CODE (target_ty) == TYPE_CODE_ARRAY /* HVA */
- && TYPE_VECTOR (target_ty))))
- return 1;
- break;
+ return 1;
+ }
+ else
+ {
+ struct type *target_type = TYPE_TARGET_TYPE (type);
+ int count = aapcs_is_vfp_call_or_return_candidate_1
+ (target_type, fundamental_type);
+
+ if (count == -1)
+ return count;
+
+ count *= TYPE_LENGTH (type);
+ return count;
+ }
}
- case TYPE_CODE_UNION:
case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
{
- /* HFA or HVA has at most four members. */
- if (TYPE_NFIELDS (ty) > 0 && TYPE_NFIELDS (ty) <= 4)
+ int count = 0;
+
+ for (int i = 0; i < TYPE_NFIELDS (type); i++)
{
- struct type *member0_type;
-
- member0_type = check_typedef (TYPE_FIELD_TYPE (ty, 0));
- if (TYPE_CODE (member0_type) == TYPE_CODE_FLT
- || (TYPE_CODE (member0_type) == TYPE_CODE_ARRAY
- && TYPE_VECTOR (member0_type)))
- {
- int i;
-
- for (i = 0; i < TYPE_NFIELDS (ty); i++)
- {
- struct type *member1_type;
-
- member1_type = check_typedef (TYPE_FIELD_TYPE (ty, i));
- if (TYPE_CODE (member0_type) != TYPE_CODE (member1_type)
- || (TYPE_LENGTH (member0_type)
- != TYPE_LENGTH (member1_type)))
- return 0;
- }
- return 1;
- }
+ struct type *member = check_typedef (TYPE_FIELD_TYPE (type, i));
+
+ int sub_count = aapcs_is_vfp_call_or_return_candidate_1
+ (member, fundamental_type);
+ if (sub_count == -1)
+ return -1;
+ count += sub_count;
}
- return 0;
+ return count;
}
default:
break;
}
- return 0;
+ return -1;
+}
+
+/* Return true if an argument, whose type is described by TYPE, can be passed or
+ returned in simd/fp registers, providing enough parameter passing registers
+ are available. This is as described in the AAPCS64.
+
+ Upon successful return, *COUNT returns the number of needed registers,
+ *FUNDAMENTAL_TYPE contains the type of those registers.
+
+ Candidate as per the AAPCS64 5.4.2.C is either a:
+ - float.
+ - short-vector.
+ - HFA (Homogeneous Floating-point Aggregate, 4.3.5.1). A Composite type where
+ all the members are floats and has at most 4 members.
+ - HVA (Homogeneous Short-vector Aggregate, 4.3.5.2). A Composite type where
+ all the members are short vectors and has at most 4 members.
+ - Complex (7.1.1)
+
+ Note that HFAs and HVAs can include nested structures and arrays. */
+
+static bool
+aapcs_is_vfp_call_or_return_candidate (struct type *type, int *count,
+ struct type **fundamental_type)
+{
+ if (type == nullptr)
+ return false;
+
+ *fundamental_type = nullptr;
+
+ int ag_count = aapcs_is_vfp_call_or_return_candidate_1 (type,
+ fundamental_type);
+
+ if (ag_count > 0 && ag_count <= HA_MAX_NUM_FLDS)
+ {
+ *count = ag_count;
+ return true;
+ }
+ else
+ return false;
}
/* AArch64 function call information structure. */
if (info->nsrn < 8)
{
int regnum = AARCH64_V0_REGNUM + info->nsrn;
- gdb_byte reg[V_REGISTER_SIZE];
+ /* Enough space for a full vector register. */
+ gdb_byte reg[register_size (gdbarch, regnum)];
+ gdb_assert (len <= sizeof (reg));
info->argnum++;
info->nsrn++;
}
}
-/* Pass a value in a V register, or on the stack if insufficient are
- available. */
-
-static void
-pass_in_v_or_stack (struct gdbarch *gdbarch,
- struct regcache *regcache,
- struct aarch64_call_info *info,
- struct type *type,
- struct value *arg)
+/* Pass a value, which is of type arg_type, in a V register. Assumes value is a
+ aapcs_is_vfp_call_or_return_candidate and there are enough spare V
+ registers. A return value of false is an error state as the value will have
+ been partially passed to the stack. */
+static bool
+pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache,
+ struct aarch64_call_info *info, struct type *arg_type,
+ struct value *arg)
{
- if (!pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (type),
- value_contents (arg)))
- pass_on_stack (info, type, arg);
+ switch (TYPE_CODE (arg_type))
+ {
+ case TYPE_CODE_FLT:
+ return pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (arg_type),
+ value_contents (arg));
+ break;
+
+ case TYPE_CODE_COMPLEX:
+ {
+ const bfd_byte *buf = value_contents (arg);
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (arg_type));
+
+ if (!pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (target_type),
+ buf))
+ return false;
+
+ return pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (target_type),
+ buf + TYPE_LENGTH (target_type));
+ }
+
+ case TYPE_CODE_ARRAY:
+ if (TYPE_VECTOR (arg_type))
+ return pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (arg_type),
+ value_contents (arg));
+ /* fall through. */
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ for (int i = 0; i < TYPE_NFIELDS (arg_type); i++)
+ {
+ struct value *field = value_primitive_field (arg, 0, i, arg_type);
+ struct type *field_type = check_typedef (value_type (field));
+
+ if (!pass_in_v_vfp_candidate (gdbarch, regcache, info, field_type,
+ field))
+ return false;
+ }
+ return true;
+
+ default:
+ return false;
+ }
}
/* Implement the "push_dummy_call" gdbarch method. */
for (argnum = 0; argnum < nargs; argnum++)
{
struct value *arg = args[argnum];
- struct type *arg_type;
- int len;
+ struct type *arg_type, *fundamental_type;
+ int len, elements;
arg_type = check_typedef (value_type (arg));
len = TYPE_LENGTH (arg_type);
+ /* If arg can be passed in v registers as per the AAPCS64, then do so if
+ if there are enough spare registers. */
+ if (aapcs_is_vfp_call_or_return_candidate (arg_type, &elements,
+ &fundamental_type))
+ {
+ if (info.nsrn + elements <= 8)
+ {
+ /* We know that we have sufficient registers available therefore
+ this will never need to fallback to the stack. */
+ if (!pass_in_v_vfp_candidate (gdbarch, regcache, &info, arg_type,
+ arg))
+ gdb_assert_not_reached ("Failed to push args");
+ }
+ else
+ {
+ info.nsrn = 8;
+ pass_on_stack (&info, arg_type, arg);
+ }
+ continue;
+ }
+
switch (TYPE_CODE (arg_type))
{
case TYPE_CODE_INT:
pass_in_x_or_stack (gdbarch, regcache, &info, arg_type, arg);
break;
- case TYPE_CODE_COMPLEX:
- if (info.nsrn <= 6)
- {
- const bfd_byte *buf = value_contents (arg);
- struct type *target_type =
- check_typedef (TYPE_TARGET_TYPE (arg_type));
-
- pass_in_v (gdbarch, regcache, &info,
- TYPE_LENGTH (target_type), buf);
- pass_in_v (gdbarch, regcache, &info,
- TYPE_LENGTH (target_type),
- buf + TYPE_LENGTH (target_type));
- }
- else
- {
- info.nsrn = 8;
- pass_on_stack (&info, arg_type, arg);
- }
- break;
- case TYPE_CODE_FLT:
- pass_in_v_or_stack (gdbarch, regcache, &info, arg_type, arg);
- break;
-
case TYPE_CODE_STRUCT:
case TYPE_CODE_ARRAY:
case TYPE_CODE_UNION:
- if (is_hfa_or_hva (arg_type))
- {
- int elements = TYPE_NFIELDS (arg_type);
-
- /* Homogeneous Aggregates */
- if (info.nsrn + elements < 8)
- {
- int i;
-
- for (i = 0; i < elements; i++)
- {
- /* We know that we have sufficient registers
- available therefore this will never fallback
- to the stack. */
- struct value *field =
- value_primitive_field (arg, 0, i, arg_type);
- struct type *field_type =
- check_typedef (value_type (field));
-
- pass_in_v_or_stack (gdbarch, regcache, &info,
- field_type, field);
- }
- }
- else
- {
- info.nsrn = 8;
- pass_on_stack (&info, arg_type, arg);
- }
- }
- else if (TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
- && TYPE_VECTOR (arg_type) && (len == 16 || len == 8))
- {
- /* Short vector types are passed in V registers. */
- pass_in_v_or_stack (gdbarch, regcache, &info, arg_type, arg);
- }
- else if (len > 16)
+ if (len > 16)
{
/* PCS B.7 Aggregates larger than 16 bytes are passed by
invisible reference. */
return tdep->vnb_type;
}
+/* Return the type for an AdvSISD V register. */
+
+static struct type *
+aarch64_vnv_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->vnv_type == NULL)
+ {
+ struct type *t = arch_composite_type (gdbarch, "__gdb_builtin_type_vnv",
+ TYPE_CODE_UNION);
+
+ append_composite_type_field (t, "d", aarch64_vnd_type (gdbarch));
+ append_composite_type_field (t, "s", aarch64_vns_type (gdbarch));
+ append_composite_type_field (t, "h", aarch64_vnh_type (gdbarch));
+ append_composite_type_field (t, "b", aarch64_vnb_type (gdbarch));
+ append_composite_type_field (t, "q", aarch64_vnq_type (gdbarch));
+
+ tdep->vnv_type = t;
+ }
+
+ return tdep->vnv_type;
+}
+
/* Implement the "dwarf2_reg_to_regnum" gdbarch method. */
static int
if (reg >= AARCH64_DWARF_V0 && reg <= AARCH64_DWARF_V0 + 31)
return AARCH64_V0_REGNUM + reg - AARCH64_DWARF_V0;
+ if (reg == AARCH64_DWARF_SVE_VG)
+ return AARCH64_SVE_VG_REGNUM;
+
+ if (reg == AARCH64_DWARF_SVE_FFR)
+ return AARCH64_SVE_FFR_REGNUM;
+
+ if (reg >= AARCH64_DWARF_SVE_P0 && reg <= AARCH64_DWARF_SVE_P0 + 15)
+ return AARCH64_SVE_P0_REGNUM + reg - AARCH64_DWARF_SVE_P0;
+
+ if (reg >= AARCH64_DWARF_SVE_Z0 && reg <= AARCH64_DWARF_SVE_Z0 + 15)
+ return AARCH64_SVE_Z0_REGNUM + reg - AARCH64_DWARF_SVE_Z0;
+
return -1;
}
-\f
/* Implement the "print_insn" gdbarch method. */
{
struct gdbarch *gdbarch = regs->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int elements;
+ struct type *fundamental_type;
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (aapcs_is_vfp_call_or_return_candidate (type, &elements,
+ &fundamental_type))
{
- bfd_byte buf[V_REGISTER_SIZE];
- int len = TYPE_LENGTH (type);
+ int len = TYPE_LENGTH (fundamental_type);
+
+ for (int i = 0; i < elements; i++)
+ {
+ int regno = AARCH64_V0_REGNUM + i;
+ /* Enough space for a full vector register. */
+ gdb_byte buf[register_size (gdbarch, regno)];
+ gdb_assert (len <= sizeof (buf));
- regs->cooked_read (AARCH64_V0_REGNUM, buf);
- memcpy (valbuf, buf, len);
+ if (aarch64_debug)
+ {
+ debug_printf ("read HFA or HVA return value element %d from %s\n",
+ i + 1,
+ gdbarch_register_name (gdbarch, regno));
+ }
+ regs->cooked_read (regno, buf);
+
+ memcpy (valbuf, buf, len);
+ valbuf += len;
+ }
}
else if (TYPE_CODE (type) == TYPE_CODE_INT
|| TYPE_CODE (type) == TYPE_CODE_CHAR
valbuf += X_REGISTER_SIZE;
}
}
- else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX)
- {
- int regno = AARCH64_V0_REGNUM;
- bfd_byte buf[V_REGISTER_SIZE];
- struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
- int len = TYPE_LENGTH (target_type);
-
- regs->cooked_read (regno, buf);
- memcpy (valbuf, buf, len);
- valbuf += len;
- regs->cooked_read (regno + 1, buf);
- memcpy (valbuf, buf, len);
- valbuf += len;
- }
- else if (is_hfa_or_hva (type))
- {
- int elements = TYPE_NFIELDS (type);
- struct type *member_type = check_typedef (TYPE_FIELD_TYPE (type, 0));
- int len = TYPE_LENGTH (member_type);
- int i;
-
- for (i = 0; i < elements; i++)
- {
- int regno = AARCH64_V0_REGNUM + i;
- bfd_byte buf[V_REGISTER_SIZE];
-
- if (aarch64_debug)
- {
- debug_printf ("read HFA or HVA return value element %d from %s\n",
- i + 1,
- gdbarch_register_name (gdbarch, regno));
- }
- regs->cooked_read (regno, buf);
-
- memcpy (valbuf, buf, len);
- valbuf += len;
- }
- }
- else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
- && (TYPE_LENGTH (type) == 16 || TYPE_LENGTH (type) == 8))
- {
- /* Short vector is returned in V register. */
- gdb_byte buf[V_REGISTER_SIZE];
-
- regs->cooked_read (AARCH64_V0_REGNUM, buf);
- memcpy (valbuf, buf, TYPE_LENGTH (type));
- }
else
{
/* For a structure or union the behaviour is as if the value had
aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type)
{
type = check_typedef (type);
+ int elements;
+ struct type *fundamental_type;
- if (is_hfa_or_hva (type))
+ if (aapcs_is_vfp_call_or_return_candidate (type, &elements,
+ &fundamental_type))
{
/* v0-v7 are used to return values and one register is allocated
for one member. However, HFA or HVA has at most four members. */
{
struct gdbarch *gdbarch = regs->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int elements;
+ struct type *fundamental_type;
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (aapcs_is_vfp_call_or_return_candidate (type, &elements,
+ &fundamental_type))
{
- bfd_byte buf[V_REGISTER_SIZE];
- int len = TYPE_LENGTH (type);
+ int len = TYPE_LENGTH (fundamental_type);
+
+ for (int i = 0; i < elements; i++)
+ {
+ int regno = AARCH64_V0_REGNUM + i;
+ /* Enough space for a full vector register. */
+ gdb_byte tmpbuf[register_size (gdbarch, regno)];
+ gdb_assert (len <= sizeof (tmpbuf));
- memcpy (buf, valbuf, len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len);
- regs->cooked_write (AARCH64_V0_REGNUM, buf);
+ if (aarch64_debug)
+ {
+ debug_printf ("write HFA or HVA return value element %d to %s\n",
+ i + 1,
+ gdbarch_register_name (gdbarch, regno));
+ }
+
+ memcpy (tmpbuf, valbuf,
+ len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len);
+ regs->cooked_write (regno, tmpbuf);
+ valbuf += len;
+ }
}
else if (TYPE_CODE (type) == TYPE_CODE_INT
|| TYPE_CODE (type) == TYPE_CODE_CHAR
}
}
}
- else if (is_hfa_or_hva (type))
- {
- int elements = TYPE_NFIELDS (type);
- struct type *member_type = check_typedef (TYPE_FIELD_TYPE (type, 0));
- int len = TYPE_LENGTH (member_type);
- int i;
-
- for (i = 0; i < elements; i++)
- {
- int regno = AARCH64_V0_REGNUM + i;
- bfd_byte tmpbuf[V_REGISTER_SIZE];
-
- if (aarch64_debug)
- {
- debug_printf ("write HFA or HVA return value element %d to %s\n",
- i + 1,
- gdbarch_register_name (gdbarch, regno));
- }
-
- memcpy (tmpbuf, valbuf, len);
- regs->cooked_write (regno, tmpbuf);
- valbuf += len;
- }
- }
- else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
- && (TYPE_LENGTH (type) == 8 || TYPE_LENGTH (type) == 16))
- {
- /* Short vector. */
- gdb_byte buf[V_REGISTER_SIZE];
-
- memcpy (buf, valbuf, TYPE_LENGTH (type));
- regs->cooked_write (AARCH64_V0_REGNUM, buf);
- }
else
{
/* For a structure or union the behaviour is as if the value had
static const char *
aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
static const char *const q_name[] =
{
"q0", "q1", "q2", "q3",
if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
return b_name[regnum - AARCH64_B0_REGNUM];
+ if (tdep->has_sve ())
+ {
+ static const char *const sve_v_name[] =
+ {
+ "v0", "v1", "v2", "v3",
+ "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11",
+ "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27",
+ "v28", "v29", "v30", "v31",
+ };
+
+ if (regnum >= AARCH64_SVE_V0_REGNUM
+ && regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
+ return sve_v_name[regnum - AARCH64_SVE_V0_REGNUM];
+ }
+
internal_error (__FILE__, __LINE__,
_("aarch64_pseudo_register_name: bad register number %d"),
regnum);
static struct type *
aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
regnum -= gdbarch_num_regs (gdbarch);
if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
return aarch64_vnb_type (gdbarch);
+ if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM
+ && regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
+ return aarch64_vnv_type (gdbarch);
+
internal_error (__FILE__, __LINE__,
_("aarch64_pseudo_register_type: bad register number %d"),
regnum);
aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
struct reggroup *group)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
regnum -= gdbarch_num_regs (gdbarch);
if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
return group == all_reggroup || group == vector_reggroup;
else if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
return group == all_reggroup || group == vector_reggroup;
+ else if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM
+ && regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
+ return group == all_reggroup || group == vector_reggroup;
return group == all_reggroup;
}
/* Helper for aarch64_pseudo_read_value. */
static struct value *
-aarch64_pseudo_read_value_1 (readable_regcache *regcache, int regnum_offset,
+aarch64_pseudo_read_value_1 (struct gdbarch *gdbarch,
+ readable_regcache *regcache, int regnum_offset,
int regsize, struct value *result_value)
{
- gdb_byte reg_buf[V_REGISTER_SIZE];
unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
+ /* Enough space for a full vector register. */
+ gdb_byte reg_buf[register_size (gdbarch, AARCH64_V0_REGNUM)];
+ gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
+
if (regcache->raw_read (v_regnum, reg_buf) != REG_VALID)
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else
memcpy (value_contents_raw (result_value), reg_buf, regsize);
+
return result_value;
}
aarch64_pseudo_read_value (struct gdbarch *gdbarch, readable_regcache *regcache,
int regnum)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
struct value *result_value = allocate_value (register_type (gdbarch, regnum));
VALUE_LVAL (result_value) = lval_register;
regnum -= gdbarch_num_regs (gdbarch);
if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
- return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_Q0_REGNUM,
+ return aarch64_pseudo_read_value_1 (gdbarch, regcache,
+ regnum - AARCH64_Q0_REGNUM,
Q_REGISTER_SIZE, result_value);
if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32)
- return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_D0_REGNUM,
+ return aarch64_pseudo_read_value_1 (gdbarch, regcache,
+ regnum - AARCH64_D0_REGNUM,
D_REGISTER_SIZE, result_value);
if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32)
- return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_S0_REGNUM,
+ return aarch64_pseudo_read_value_1 (gdbarch, regcache,
+ regnum - AARCH64_S0_REGNUM,
S_REGISTER_SIZE, result_value);
if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32)
- return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_H0_REGNUM,
+ return aarch64_pseudo_read_value_1 (gdbarch, regcache,
+ regnum - AARCH64_H0_REGNUM,
H_REGISTER_SIZE, result_value);
if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
- return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_B0_REGNUM,
+ return aarch64_pseudo_read_value_1 (gdbarch, regcache,
+ regnum - AARCH64_B0_REGNUM,
B_REGISTER_SIZE, result_value);
+ if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM
+ && regnum < AARCH64_SVE_V0_REGNUM + 32)
+ return aarch64_pseudo_read_value_1 (gdbarch, regcache,
+ regnum - AARCH64_SVE_V0_REGNUM,
+ V_REGISTER_SIZE, result_value);
+
gdb_assert_not_reached ("regnum out of bound");
}
/* Helper for aarch64_pseudo_write. */
static void
-aarch64_pseudo_write_1 (struct regcache *regcache, int regnum_offset,
- int regsize, const gdb_byte *buf)
+aarch64_pseudo_write_1 (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum_offset, int regsize, const gdb_byte *buf)
{
- gdb_byte reg_buf[V_REGISTER_SIZE];
unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset;
+ /* Enough space for a full vector register. */
+ gdb_byte reg_buf[register_size (gdbarch, AARCH64_V0_REGNUM)];
+ gdb_static_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM);
+
/* Ensure the register buffer is zero, we want gdb writes of the
various 'scalar' pseudo registers to behavior like architectural
writes, register width bytes are written the remainder are set to
zero. */
- memset (reg_buf, 0, sizeof (reg_buf));
+ memset (reg_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM));
memcpy (reg_buf, buf, regsize);
regcache->raw_write (v_regnum, reg_buf);
aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
int regnum, const gdb_byte *buf)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
regnum -= gdbarch_num_regs (gdbarch);
if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32)
- return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_Q0_REGNUM,
- Q_REGISTER_SIZE, buf);
+ return aarch64_pseudo_write_1 (gdbarch, regcache,
+ regnum - AARCH64_Q0_REGNUM, Q_REGISTER_SIZE,
+ buf);
if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32)
- return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_D0_REGNUM,
- D_REGISTER_SIZE, buf);
+ return aarch64_pseudo_write_1 (gdbarch, regcache,
+ regnum - AARCH64_D0_REGNUM, D_REGISTER_SIZE,
+ buf);
if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32)
- return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_S0_REGNUM,
- S_REGISTER_SIZE, buf);
+ return aarch64_pseudo_write_1 (gdbarch, regcache,
+ regnum - AARCH64_S0_REGNUM, S_REGISTER_SIZE,
+ buf);
if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32)
- return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_H0_REGNUM,
- H_REGISTER_SIZE, buf);
+ return aarch64_pseudo_write_1 (gdbarch, regcache,
+ regnum - AARCH64_H0_REGNUM, H_REGISTER_SIZE,
+ buf);
if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32)
- return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_B0_REGNUM,
- B_REGISTER_SIZE, buf);
+ return aarch64_pseudo_write_1 (gdbarch, regcache,
+ regnum - AARCH64_B0_REGNUM, B_REGISTER_SIZE,
+ buf);
+
+ if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM
+ && regnum < AARCH64_SVE_V0_REGNUM + 32)
+ return aarch64_pseudo_write_1 (gdbarch, regcache,
+ regnum - AARCH64_SVE_V0_REGNUM,
+ V_REGISTER_SIZE, buf);
gdb_assert_not_reached ("regnum out of bound");
}
const int insn_size = 4;
const int atomic_sequence_length = 16; /* Instruction sequence length. */
CORE_ADDR pc = regcache_read_pc (regcache);
- CORE_ADDR breaks[2] = { -1, -1 };
+ CORE_ADDR breaks[2] = { CORE_ADDR_MAX, CORE_ADDR_MAX };
CORE_ADDR loc = pc;
CORE_ADDR closing_insn = 0;
uint32_t insn = read_memory_unsigned_integer (loc, insn_size,
if (feature_sve == nullptr)
return 0;
- uint64_t vl = tdesc_register_size (feature_sve,
- aarch64_sve_register_names[0]);
+ uint64_t vl = tdesc_register_bitsize (feature_sve,
+ aarch64_sve_register_names[0]) / 8;
return sve_vq_from_vl (vl);
}