linux-user: Add prctl() PR_SET_FP_MODE and PR_GET_FP_MODE implementations
Implement MIPS specific prctl() PR_SET_FP_MODE and PR_GET_FP_MODE emulation. Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com> Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
This commit is contained in:
parent
0c1bbedc10
commit
64ea3d676d
@ -247,5 +247,7 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
||||
/* MIPS-specific prctl() options */
|
||||
#define TARGET_PR_SET_FP_MODE 45
|
||||
#define TARGET_PR_GET_FP_MODE 46
|
||||
#define TARGET_PR_FP_MODE_FR (1 << 0)
|
||||
#define TARGET_PR_FP_MODE_FRE (1 << 1)
|
||||
|
||||
#endif /* MIPS_TARGET_SYSCALL_H */
|
||||
|
@ -244,5 +244,7 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
||||
/* MIPS-specific prctl() options */
|
||||
#define TARGET_PR_SET_FP_MODE 45
|
||||
#define TARGET_PR_GET_FP_MODE 46
|
||||
#define TARGET_PR_FP_MODE_FR (1 << 0)
|
||||
#define TARGET_PR_FP_MODE_FRE (1 << 1)
|
||||
|
||||
#endif /* MIPS64_TARGET_SYSCALL_H */
|
||||
|
@ -9529,11 +9529,65 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
#endif
|
||||
#ifdef TARGET_MIPS
|
||||
case TARGET_PR_GET_FP_MODE:
|
||||
/* TODO: Implement TARGET_PR_SET_FP_MODE handling.*/
|
||||
return -TARGET_EINVAL;
|
||||
{
|
||||
CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
|
||||
ret = 0;
|
||||
if (env->CP0_Status & (1 << CP0St_FR)) {
|
||||
ret |= TARGET_PR_FP_MODE_FR;
|
||||
}
|
||||
if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
|
||||
ret |= TARGET_PR_FP_MODE_FRE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
case TARGET_PR_SET_FP_MODE:
|
||||
/* TODO: Implement TARGET_PR_GET_FP_MODE handling.*/
|
||||
return -TARGET_EINVAL;
|
||||
{
|
||||
CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
|
||||
bool old_fr = env->CP0_Status & (1 << CP0St_FR);
|
||||
bool new_fr = arg2 & TARGET_PR_FP_MODE_FR;
|
||||
bool new_fre = arg2 & TARGET_PR_FP_MODE_FRE;
|
||||
|
||||
if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
|
||||
/* FR1 is not supported */
|
||||
return -TARGET_EOPNOTSUPP;
|
||||
}
|
||||
if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
|
||||
&& !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
|
||||
/* cannot set FR=0 */
|
||||
return -TARGET_EOPNOTSUPP;
|
||||
}
|
||||
if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
|
||||
/* Cannot set FRE=1 */
|
||||
return -TARGET_EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int i;
|
||||
fpr_t *fpr = env->active_fpu.fpr;
|
||||
for (i = 0; i < 32 ; i += 2) {
|
||||
if (!old_fr && new_fr) {
|
||||
fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
|
||||
} else if (old_fr && !new_fr) {
|
||||
fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
|
||||
}
|
||||
}
|
||||
|
||||
if (new_fr) {
|
||||
env->CP0_Status |= (1 << CP0St_FR);
|
||||
env->hflags |= MIPS_HFLAG_F64;
|
||||
} else {
|
||||
env->CP0_Status &= ~(1 << CP0St_FR);
|
||||
}
|
||||
if (new_fre) {
|
||||
env->CP0_Config5 |= (1 << CP0C5_FRE);
|
||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||
env->hflags |= MIPS_HFLAG_FRE;
|
||||
}
|
||||
} else {
|
||||
env->CP0_Config5 &= ~(1 << CP0C5_FRE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MIPS */
|
||||
#ifdef TARGET_AARCH64
|
||||
case TARGET_PR_SVE_SET_VL:
|
||||
|
Loading…
Reference in New Issue
Block a user