summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonid Chistov <lchistov@pathscale.com>2015-10-01 11:23:50 +0300
committerDave Watson <davejwatson@fb.com>2017-08-18 09:56:06 -0700
commit5a491cb2d889f03952182d611d2ac6e15c3c5845 (patch)
tree718139c2c66015194ad9af46e4ef59994fe95267
parent1c190a8f9eb88578388340c5b14b2d683856c9c9 (diff)
downloadlibunwind-5a491cb2d889f03952182d611d2ac6e15c3c5845.tar.gz
arm64: Support for restore of ARM64 Neon callee-saved registers during unwind
-rw-r--r--src/aarch64/Ginit.c4
-rw-r--r--src/aarch64/Gregs.c7
-rw-r--r--src/aarch64/Gresume.c21
-rw-r--r--src/aarch64/unwind_i.h2
4 files changed, 27 insertions, 7 deletions
diff --git a/src/aarch64/Ginit.c b/src/aarch64/Ginit.c
index 667c4764..ab3999f3 100644
--- a/src/aarch64/Ginit.c
+++ b/src/aarch64/Ginit.c
@@ -43,8 +43,10 @@ PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space;
static inline void *
uc_addr (ucontext_t *uc, int reg)
{
- if (reg >= UNW_AARCH64_X0 && reg <= UNW_AARCH64_V31)
+ if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_V0)
return &uc->uc_mcontext.regs[reg];
+ else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31)
+ return &GET_FPCTX(uc)->vregs[reg - UNW_AARCH64_V0];
else
return NULL;
}
diff --git a/src/aarch64/Gregs.c b/src/aarch64/Gregs.c
index 104fd62a..a8843734 100644
--- a/src/aarch64/Gregs.c
+++ b/src/aarch64/Gregs.c
@@ -110,6 +110,9 @@ HIDDEN int
tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp,
int write)
{
- Debug (1, "bad register number %u\n", reg);
- return -UNW_EBADREG;
+ dwarf_loc_t loc = c->dwarf.loc[reg];
+ if (write)
+ return dwarf_putfp (&c->dwarf, loc, *valp);
+ else
+ return dwarf_getfp (&c->dwarf, loc, valp);
}
diff --git a/src/aarch64/Gresume.c b/src/aarch64/Gresume.c
index d9acfa7c..65517a25 100644
--- a/src/aarch64/Gresume.c
+++ b/src/aarch64/Gresume.c
@@ -40,7 +40,7 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
{
/* Since there are no signals involved here we restore EH and non scratch
registers only. */
- unsigned long regs[15];
+ unsigned long regs[24];
regs[0] = uc->uc_mcontext.regs[0];
regs[1] = uc->uc_mcontext.regs[1];
regs[2] = uc->uc_mcontext.regs[2];
@@ -55,7 +55,16 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
regs[11] = uc->uc_mcontext.regs[26];
regs[12] = uc->uc_mcontext.regs[27];
regs[13] = uc->uc_mcontext.regs[28];
- regs[14] = uc->uc_mcontext.regs[30]; /* LR */
+ regs[14] = uc->uc_mcontext.regs[29]; /* FP */
+ regs[15] = uc->uc_mcontext.regs[30]; /* LR */
+ regs[16] = GET_FPCTX(uc)->vregs[8];
+ regs[17] = GET_FPCTX(uc)->vregs[9];
+ regs[18] = GET_FPCTX(uc)->vregs[10];
+ regs[19] = GET_FPCTX(uc)->vregs[11];
+ regs[20] = GET_FPCTX(uc)->vregs[12];
+ regs[21] = GET_FPCTX(uc)->vregs[13];
+ regs[22] = GET_FPCTX(uc)->vregs[14];
+ regs[23] = GET_FPCTX(uc)->vregs[15];
unsigned long sp = uc->uc_mcontext.sp;
struct regs_overlay {
@@ -72,7 +81,11 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
"ldp x23, x24, [x4,64]\n"
"ldp x25, x26, [x4,80]\n"
"ldp x27, x28, [x4,96]\n"
- "ldr x30, [x4,112]\n"
+ "ldp x29, x30, [x4,112]\n"
+ "ldp d8, d9, [x4,128]\n"
+ "ldp d10, d11, [x4,144]\n"
+ "ldp d12, d13, [x4,160]\n"
+ "ldp d14, d15, [x4,176]\n"
"mov sp, x5\n"
"ret \n"
:
@@ -147,7 +160,7 @@ establish_machine_state (struct cursor *c)
Debug (8, "copying out cursor state\n");
- for (reg = 0; reg <= UNW_AARCH64_PSTATE; ++reg)
+ for (reg = 0; reg <= UNW_AARCH64_V31; ++reg)
{
Debug (16, "copying %s %d\n", unw_regname (reg), reg);
if (unw_is_fpreg (reg))
diff --git a/src/aarch64/unwind_i.h b/src/aarch64/unwind_i.h
index 79b342cd..3d324c2b 100644
--- a/src/aarch64/unwind_i.h
+++ b/src/aarch64/unwind_i.h
@@ -59,4 +59,6 @@ extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor,
} while (0)
#endif
+#define GET_FPCTX(uc) ((struct fpsimd_context *)(&uc->uc_mcontext.__reserved))
+
#endif /* unwind_i_h */