Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2016-11-05 05:19:25 +0300
committerZoltan Varga <vargaz@gmail.com>2016-11-08 19:19:00 +0300
commitace3b63d26707ccff5d48a7451fb9be41d9e2531 (patch)
tree4e76502beb511a25a3243c6f3fafb72b54218d95
parent800dbae049e70a0e8adabb40b10f162cb75501db (diff)
[arm64] Set a flag in MonoContext if the fp regs are saved, and only restore them if they are. These registers are not saved when the context is created from a ucontext. (#3890)
-rw-r--r--mono/mini/exceptions-arm64.c15
-rw-r--r--mono/utils/mono-context.h5
2 files changed, 18 insertions, 2 deletions
diff --git a/mono/mini/exceptions-arm64.c b/mono/mini/exceptions-arm64.c
index 6e8889e0b24..9b7f762e991 100644
--- a/mono/mini/exceptions-arm64.c
+++ b/mono/mini/exceptions-arm64.c
@@ -29,15 +29,21 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
int i, ctx_reg, size;
+ guint8 *labels [16];
size = 256;
code = start = mono_global_codeman_reserve (size);
arm_movx (code, ARMREG_IP0, ARMREG_R0);
ctx_reg = ARMREG_IP0;
+
/* Restore fregs */
+ arm_ldrx (code, ARMREG_IP1, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, has_fregs));
+ labels [0] = code;
+ arm_cbzx (code, ARMREG_IP1, 0);
for (i = 0; i < 32; ++i)
arm_ldrfpx (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8));
+ mono_arm_patch (labels [0], code, MONO_R_ARM64_CBZ);
/* Restore gregs */
// FIXME: Restore less registers
// FIXME: fp should be restored later
@@ -72,6 +78,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
int i, size, offset, gregs_offset, fregs_offset, ctx_offset, num_fregs, frame_size;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
+ guint8 *labels [16];
size = 512;
start = code = mono_global_codeman_reserve (size);
@@ -109,13 +116,15 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
for (i = 0; i < num_fregs; ++i)
arm_strfpx (code, ARMREG_D8 + i, ARMREG_FP, fregs_offset + (i * 8));
- /* No need to save/restore fregs, since we don't currently use them */
-
/* Load regs from ctx */
code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs));
/* Load fregs */
+ arm_ldrx (code, ARMREG_IP0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, has_fregs));
+ labels [0] = code;
+ arm_cbzx (code, ARMREG_IP0, 0);
for (i = 0; i < num_fregs; ++i)
arm_ldrfpx (code, ARMREG_D8 + i, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8));
+ mono_arm_patch (labels [0], code, MONO_R_ARM64_CBZ);
/* Load fp */
arm_ldrx (code, ARMREG_FP, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_FP * 8));
@@ -384,6 +393,7 @@ mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *
memset (&ctx, 0, sizeof (MonoContext));
memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32);
memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8);
+ ctx.has_fregs = 1;
ctx.pc = pc;
if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
@@ -412,6 +422,7 @@ mono_arm_resume_unwind (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp
memset (&ctx, 0, sizeof (MonoContext));
memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32);
memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8);
+ ctx.has_fregs = 1;
ctx.pc = pc;
mono_resume_unwind (&ctx);
diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h
index 907c62ee2eb..c5769237e7a 100644
--- a/mono/utils/mono-context.h
+++ b/mono/utils/mono-context.h
@@ -294,6 +294,11 @@ typedef struct {
mgreg_t regs [32];
double fregs [32];
mgreg_t pc;
+ /*
+ * fregs might not be initialized if this context was created from a
+ * ucontext.
+ */
+ mgreg_t has_fregs;
} MonoContext;
#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->pc = (mgreg_t)ip; } while (0)