1*87e9bf23SRichard Henderson /* 2*87e9bf23SRichard Henderson * MIPS specific prctl functions for linux-user 3*87e9bf23SRichard Henderson * 4*87e9bf23SRichard Henderson * SPDX-License-Identifier: GPL-2.0-or-later 5*87e9bf23SRichard Henderson */ 6*87e9bf23SRichard Henderson #ifndef MIPS_TARGET_PRCTL_H 7*87e9bf23SRichard Henderson #define MIPS_TARGET_PRCTL_H 8*87e9bf23SRichard Henderson do_prctl_get_fp_mode(CPUArchState * env)9*87e9bf23SRichard Hendersonstatic abi_long do_prctl_get_fp_mode(CPUArchState *env) 10*87e9bf23SRichard Henderson { 11*87e9bf23SRichard Henderson abi_long ret = 0; 12*87e9bf23SRichard Henderson 13*87e9bf23SRichard Henderson if (env->CP0_Status & (1 << CP0St_FR)) { 14*87e9bf23SRichard Henderson ret |= PR_FP_MODE_FR; 15*87e9bf23SRichard Henderson } 16*87e9bf23SRichard Henderson if (env->CP0_Config5 & (1 << CP0C5_FRE)) { 17*87e9bf23SRichard Henderson ret |= PR_FP_MODE_FRE; 18*87e9bf23SRichard Henderson } 19*87e9bf23SRichard Henderson return ret; 20*87e9bf23SRichard Henderson } 21*87e9bf23SRichard Henderson #define do_prctl_get_fp_mode do_prctl_get_fp_mode 22*87e9bf23SRichard Henderson do_prctl_set_fp_mode(CPUArchState * env,abi_long arg2)23*87e9bf23SRichard Hendersonstatic abi_long do_prctl_set_fp_mode(CPUArchState *env, abi_long arg2) 24*87e9bf23SRichard Henderson { 25*87e9bf23SRichard Henderson bool old_fr = env->CP0_Status & (1 << CP0St_FR); 26*87e9bf23SRichard Henderson bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE); 27*87e9bf23SRichard Henderson bool new_fr = arg2 & PR_FP_MODE_FR; 28*87e9bf23SRichard Henderson bool new_fre = arg2 & PR_FP_MODE_FRE; 29*87e9bf23SRichard Henderson const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE; 30*87e9bf23SRichard Henderson 31*87e9bf23SRichard Henderson /* If nothing to change, return right away, successfully. */ 32*87e9bf23SRichard Henderson if (old_fr == new_fr && old_fre == new_fre) { 33*87e9bf23SRichard Henderson return 0; 34*87e9bf23SRichard Henderson } 35*87e9bf23SRichard Henderson /* Check the value is valid */ 36*87e9bf23SRichard Henderson if (arg2 & ~known_bits) { 37*87e9bf23SRichard Henderson return -TARGET_EOPNOTSUPP; 38*87e9bf23SRichard Henderson } 39*87e9bf23SRichard Henderson /* Setting FRE without FR is not supported. */ 40*87e9bf23SRichard Henderson if (new_fre && !new_fr) { 41*87e9bf23SRichard Henderson return -TARGET_EOPNOTSUPP; 42*87e9bf23SRichard Henderson } 43*87e9bf23SRichard Henderson if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) { 44*87e9bf23SRichard Henderson /* FR1 is not supported */ 45*87e9bf23SRichard Henderson return -TARGET_EOPNOTSUPP; 46*87e9bf23SRichard Henderson } 47*87e9bf23SRichard Henderson if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64)) 48*87e9bf23SRichard Henderson && !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { 49*87e9bf23SRichard Henderson /* cannot set FR=0 */ 50*87e9bf23SRichard Henderson return -TARGET_EOPNOTSUPP; 51*87e9bf23SRichard Henderson } 52*87e9bf23SRichard Henderson if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) { 53*87e9bf23SRichard Henderson /* Cannot set FRE=1 */ 54*87e9bf23SRichard Henderson return -TARGET_EOPNOTSUPP; 55*87e9bf23SRichard Henderson } 56*87e9bf23SRichard Henderson 57*87e9bf23SRichard Henderson int i; 58*87e9bf23SRichard Henderson fpr_t *fpr = env->active_fpu.fpr; 59*87e9bf23SRichard Henderson for (i = 0; i < 32 ; i += 2) { 60*87e9bf23SRichard Henderson if (!old_fr && new_fr) { 61*87e9bf23SRichard Henderson fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX]; 62*87e9bf23SRichard Henderson } else if (old_fr && !new_fr) { 63*87e9bf23SRichard Henderson fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX]; 64*87e9bf23SRichard Henderson } 65*87e9bf23SRichard Henderson } 66*87e9bf23SRichard Henderson 67*87e9bf23SRichard Henderson if (new_fr) { 68*87e9bf23SRichard Henderson env->CP0_Status |= (1 << CP0St_FR); 69*87e9bf23SRichard Henderson env->hflags |= MIPS_HFLAG_F64; 70*87e9bf23SRichard Henderson } else { 71*87e9bf23SRichard Henderson env->CP0_Status &= ~(1 << CP0St_FR); 72*87e9bf23SRichard Henderson env->hflags &= ~MIPS_HFLAG_F64; 73*87e9bf23SRichard Henderson } 74*87e9bf23SRichard Henderson if (new_fre) { 75*87e9bf23SRichard Henderson env->CP0_Config5 |= (1 << CP0C5_FRE); 76*87e9bf23SRichard Henderson if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { 77*87e9bf23SRichard Henderson env->hflags |= MIPS_HFLAG_FRE; 78*87e9bf23SRichard Henderson } 79*87e9bf23SRichard Henderson } else { 80*87e9bf23SRichard Henderson env->CP0_Config5 &= ~(1 << CP0C5_FRE); 81*87e9bf23SRichard Henderson env->hflags &= ~MIPS_HFLAG_FRE; 82*87e9bf23SRichard Henderson } 83*87e9bf23SRichard Henderson 84*87e9bf23SRichard Henderson return 0; 85*87e9bf23SRichard Henderson } 86*87e9bf23SRichard Henderson #define do_prctl_set_fp_mode do_prctl_set_fp_mode 87*87e9bf23SRichard Henderson 88*87e9bf23SRichard Henderson #endif /* MIPS_TARGET_PRCTL_H */ 89