target_prctl.h 2.5 KB

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