* [PATCH 1/2] aarch64: handle big endian float registers correctly
2014-10-27 3:14 [PATCH 0/2] aarch64 couple big endian fixes Victor Kamensky
@ 2014-10-27 3:14 ` Victor Kamensky
2014-10-27 3:14 ` [PATCH 2/2] aarch64: tramp_frame_start function need to read instrs correctly in be8 case Victor Kamensky
1 sibling, 0 replies; 4+ messages in thread
From: Victor Kamensky @ 2014-10-27 3:14 UTC (permalink / raw)
To: gdb-patches; +Cc: Yao Qi, Andrew Pinski, victor.kamensky
In big endian case vreg memory is in big endian format and all
pseudo registers will be in big endian format. But all smaller
pseudo registers are at higher memory addresses (least siginificant
part of vreg memory).
Introduce reg_addr_in_vreg function would return correct address
of pseudo register memory depending on current target endianity.
aarch64_pseudo_read_value and aarch64_pseudo_write and other
functions use that function to get address within vreg to copy
into/from target pseudo register memory.
That fixes numerous floating point gdb testsuite failures on
aarch64 big endian target. For example gdb.base/structs.exp,
gdb.base/float.exp, gdb.base/call-ar-st.exp and many others.
gdb/ChangeLog:
2014-10-24 Victor Kamensky <victor.kamensky@linaro.org>
* aarch64-tdep.c (reg_addr_in_vreg): New function.
(pass_in_v): Added type parameter. Use reg_addr_in_vreg
to place memory in vreg depending on endianity and type
size.
(pass_in_v_or_stack): Pass type to pass_in_v function.
(aarch64_push_dummy_call): Handle big endian case
correctly.
(aarch64_extract_return_value): Ditto.
(aarch64_store_return_value): Ditto.
(aarch64_pseudo_read_value): Ditto.
(aarch64_pseudo_write): Ditto.
---
gdb/aarch64-tdep.c | 57 ++++++++++++++++++++++++++++++++++--------------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 1898f6b..959035e 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -1382,6 +1382,16 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache,
}
}
+static gdb_byte * reg_addr_in_vreg (struct gdbarch *gdbarch,
+ gdb_byte *vreg_addr,
+ size_t size)
+{
+ gdb_byte *ret = vreg_addr;
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ ret = vreg_addr + (V_REGISTER_SIZE - size);
+ return ret;
+}
+
/* Attempt to marshall a value in a V register. Return 1 if
successful, or 0 if insufficient registers are available. This
function, unlike the equivalent pass_in_x() function does not
@@ -1391,17 +1401,21 @@ static int
pass_in_v (struct gdbarch *gdbarch,
struct regcache *regcache,
struct aarch64_call_info *info,
+ struct type *type,
const bfd_byte *buf)
{
if (info->nsrn < 8)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ bfd_byte xbuf[V_REGISTER_SIZE];
+ int len = TYPE_LENGTH (type);
+ int copy_len = len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len;
int regnum = AARCH64_V0_REGNUM + info->nsrn;
info->argnum++;
info->nsrn++;
- regcache_cooked_write (regcache, regnum, buf);
+ memcpy (reg_addr_in_vreg (gdbarch, xbuf, copy_len), buf, copy_len);
+ regcache_cooked_write (regcache, regnum, xbuf);
if (aarch64_debug)
fprintf_unfiltered (gdb_stdlog, "arg %d in %s\n",
info->argnum,
@@ -1491,7 +1505,7 @@ pass_in_v_or_stack (struct gdbarch *gdbarch,
struct type *type,
const bfd_byte *buf)
{
- if (!pass_in_v (gdbarch, regcache, info, buf))
+ if (!pass_in_v (gdbarch, regcache, info, type, buf))
pass_on_stack (info, type, buf);
}
@@ -1616,8 +1630,8 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct type *target_type =
check_typedef (TYPE_TARGET_TYPE (arg_type));
- pass_in_v (gdbarch, regcache, &info, buf);
- pass_in_v (gdbarch, regcache, &info,
+ pass_in_v (gdbarch, regcache, &info, target_type, buf);
+ pass_in_v (gdbarch, regcache, &info, target_type,
buf + TYPE_LENGTH (target_type));
}
else
@@ -1925,7 +1939,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
int len = TYPE_LENGTH (type);
regcache_cooked_read (regs, AARCH64_V0_REGNUM, buf);
- memcpy (valbuf, buf, len);
+ memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
}
else if (TYPE_CODE (type) == TYPE_CODE_INT
|| TYPE_CODE (type) == TYPE_CODE_CHAR
@@ -1961,10 +1975,10 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
int len = TYPE_LENGTH (target_type);
regcache_cooked_read (regs, regno, buf);
- memcpy (valbuf, buf, len);
+ memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
valbuf += len;
regcache_cooked_read (regs, regno + 1, buf);
- memcpy (valbuf, buf, len);
+ memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
valbuf += len;
}
else if (is_hfa (type))
@@ -1986,7 +2000,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
gdbarch_register_name (gdbarch, regno));
regcache_cooked_read (regs, regno, buf);
- memcpy (valbuf, buf, len);
+ memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
valbuf += len;
}
}
@@ -2058,8 +2072,9 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
{
bfd_byte buf[V_REGISTER_SIZE];
int len = TYPE_LENGTH (type);
+ int copy_len = len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len;
- memcpy (buf, valbuf, len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len);
+ memcpy (reg_addr_in_vreg (gdbarch, buf, copy_len), valbuf, copy_len);
regcache_cooked_write (regs, AARCH64_V0_REGNUM, buf);
}
else if (TYPE_CODE (type) == TYPE_CODE_INT
@@ -2113,7 +2128,7 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
i + 1,
gdbarch_register_name (gdbarch, regno));
- memcpy (tmpbuf, valbuf, len);
+ memcpy (reg_addr_in_vreg (gdbarch, tmpbuf, len), valbuf, len);
regcache_cooked_write (regs, regno, tmpbuf);
valbuf += len;
}
@@ -2360,7 +2375,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else
- memcpy (buf, reg_buf, Q_REGISTER_SIZE);
+ memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, Q_REGISTER_SIZE), Q_REGISTER_SIZE);
return result_value;
}
@@ -2375,7 +2390,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else
- memcpy (buf, reg_buf, D_REGISTER_SIZE);
+ memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, D_REGISTER_SIZE), D_REGISTER_SIZE);
return result_value;
}
@@ -2386,7 +2401,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_S0_REGNUM;
status = regcache_raw_read (regcache, v_regnum, reg_buf);
- memcpy (buf, reg_buf, S_REGISTER_SIZE);
+ memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, S_REGISTER_SIZE), S_REGISTER_SIZE);
return result_value;
}
@@ -2401,7 +2416,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else
- memcpy (buf, reg_buf, H_REGISTER_SIZE);
+ memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, H_REGISTER_SIZE), H_REGISTER_SIZE);
return result_value;
}
@@ -2416,7 +2431,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
mark_value_bytes_unavailable (result_value, 0,
TYPE_LENGTH (value_type (result_value)));
else
- memcpy (buf, reg_buf, B_REGISTER_SIZE);
+ memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, B_REGISTER_SIZE), B_REGISTER_SIZE);
return result_value;
}
@@ -2445,7 +2460,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
unsigned v_regnum;
v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_Q0_REGNUM;
- memcpy (reg_buf, buf, Q_REGISTER_SIZE);
+ memcpy (reg_addr_in_vreg (gdbarch, reg_buf, Q_REGISTER_SIZE), buf, Q_REGISTER_SIZE);
regcache_raw_write (regcache, v_regnum, reg_buf);
return;
}
@@ -2456,7 +2471,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
unsigned v_regnum;
v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_D0_REGNUM;
- memcpy (reg_buf, buf, D_REGISTER_SIZE);
+ memcpy (reg_addr_in_vreg (gdbarch, reg_buf, D_REGISTER_SIZE), buf, D_REGISTER_SIZE);
regcache_raw_write (regcache, v_regnum, reg_buf);
return;
}
@@ -2466,7 +2481,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
unsigned v_regnum;
v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_S0_REGNUM;
- memcpy (reg_buf, buf, S_REGISTER_SIZE);
+ memcpy (reg_addr_in_vreg (gdbarch, reg_buf, S_REGISTER_SIZE), buf, S_REGISTER_SIZE);
regcache_raw_write (regcache, v_regnum, reg_buf);
return;
}
@@ -2477,7 +2492,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
unsigned v_regnum;
v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_H0_REGNUM;
- memcpy (reg_buf, buf, H_REGISTER_SIZE);
+ memcpy (reg_addr_in_vreg (gdbarch, reg_buf, H_REGISTER_SIZE), buf, H_REGISTER_SIZE);
regcache_raw_write (regcache, v_regnum, reg_buf);
return;
}
@@ -2488,7 +2503,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
unsigned v_regnum;
v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_B0_REGNUM;
- memcpy (reg_buf, buf, B_REGISTER_SIZE);
+ memcpy (reg_addr_in_vreg (gdbarch, reg_buf, B_REGISTER_SIZE), buf, B_REGISTER_SIZE);
regcache_raw_write (regcache, v_regnum, reg_buf);
return;
}
--
1.8.1.4
^ permalink raw reply [flat|nested] 4+ messages in thread