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>
This commit is contained in:
parent
1176e57a8b
commit
11670e8492
@ -44,6 +44,12 @@ struct target_stackf {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct target_siginfo_fpu {
|
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. */
|
/* It is more convenient for qemu to move doubles, not singles. */
|
||||||
uint64_t si_double_regs[16];
|
uint64_t si_double_regs[16];
|
||||||
uint32_t si_fsr;
|
uint32_t si_fsr;
|
||||||
@ -52,6 +58,7 @@ struct target_siginfo_fpu {
|
|||||||
uint32_t insn_addr;
|
uint32_t insn_addr;
|
||||||
uint32_t insn;
|
uint32_t insn;
|
||||||
} si_fpqueue [16];
|
} si_fpqueue [16];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct target_signal_frame {
|
struct target_signal_frame {
|
||||||
@ -167,21 +174,50 @@ static void save_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
|
|||||||
{
|
{
|
||||||
int i;
|
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) {
|
for (i = 0; i < 16; ++i) {
|
||||||
__put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
__put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
||||||
}
|
}
|
||||||
__put_user(env->fsr, &fpu->si_fsr);
|
__put_user(env->fsr, &fpu->si_fsr);
|
||||||
__put_user(0, &fpu->si_fpqdepth);
|
__put_user(0, &fpu->si_fpqdepth);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
|
static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
|
||||||
{
|
{
|
||||||
int i;
|
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) {
|
for (i = 0; i < 16; ++i) {
|
||||||
__get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
__get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
||||||
}
|
}
|
||||||
__get_user(env->fsr, &fpu->si_fsr);
|
__get_user(env->fsr, &fpu->si_fsr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_frame(int sig, struct target_sigaction *ka,
|
void setup_frame(int sig, struct target_sigaction *ka,
|
||||||
|
Loading…
Reference in New Issue
Block a user