summaryrefslogtreecommitdiff
path: root/linux-user/sparc
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-04-25 19:53:31 -0700
committerLaurent Vivier <laurent@vivier.eu>2021-05-15 21:43:23 +0200
commit11670e849227890e7ab3f1413bae28bf6a0f6707 (patch)
treebe560755bccebf8b205cf4a4787718fd2fd14619 /linux-user/sparc
parent1176e57a8b34c845a89b2b0f86e424a825d40faa (diff)
downloadqemu-11670e849227890e7ab3f1413bae28bf6a0f6707.zip
linux-user/sparc: Add 64-bit support to fpu save/restore
The shape of the kernel's __siginfo_fpu_t is dependent on the cpu type, not the abi. Which is weird, but there ya go. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20210426025334.1168495-23-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'linux-user/sparc')
-rw-r--r--linux-user/sparc/signal.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index 0ff57af43d..41a8b33bac 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -44,6 +44,12 @@ struct target_stackf {
};
struct target_siginfo_fpu {
+#ifdef TARGET_SPARC64
+ uint64_t si_double_regs[32];
+ uint64_t si_fsr;
+ uint64_t si_gsr;
+ uint64_t si_fprs;
+#else
/* It is more convenient for qemu to move doubles, not singles. */
uint64_t si_double_regs[16];
uint32_t si_fsr;
@@ -52,6 +58,7 @@ struct target_siginfo_fpu {
uint32_t insn_addr;
uint32_t insn;
} si_fpqueue [16];
+#endif
};
struct target_signal_frame {
@@ -167,21 +174,50 @@ static void save_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
{
int i;
+#ifdef TARGET_SPARC64
+ for (i = 0; i < 32; ++i) {
+ __put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
+ }
+ __put_user(env->fsr, &fpu->si_fsr);
+ __put_user(env->gsr, &fpu->si_gsr);
+ __put_user(env->fprs, &fpu->si_fprs);
+#else
for (i = 0; i < 16; ++i) {
__put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
}
__put_user(env->fsr, &fpu->si_fsr);
__put_user(0, &fpu->si_fpqdepth);
+#endif
}
static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
{
int i;
+#ifdef TARGET_SPARC64
+ uint64_t fprs;
+ __get_user(fprs, &fpu->si_fprs);
+
+ /* In case the user mucks about with FPRS, restore as directed. */
+ if (fprs & FPRS_DL) {
+ for (i = 0; i < 16; ++i) {
+ __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
+ }
+ }
+ if (fprs & FPRS_DU) {
+ for (i = 16; i < 32; ++i) {
+ __get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
+ }
+ }
+ __get_user(env->fsr, &fpu->si_fsr);
+ __get_user(env->gsr, &fpu->si_gsr);
+ env->fprs |= fprs;
+#else
for (i = 0; i < 16; ++i) {
__get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
}
__get_user(env->fsr, &fpu->si_fsr);
+#endif
}
void setup_frame(int sig, struct target_sigaction *ka,