From 0c6f7c60d5f14b29c98bca0a996aa2b4ba22abae Mon Sep 17 00:00:00 2001 From: mio Date: Mon, 17 Feb 2025 20:16:36 +0800 Subject: [PATCH] Implement mips floating point related registers --- include/unicorn/mips.h | 4 ++ qemu/target/mips/unicorn.c | 94 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/include/unicorn/mips.h b/include/unicorn/mips.h index a1240a2a..64283ed5 100644 --- a/include/unicorn/mips.h +++ b/include/unicorn/mips.h @@ -220,6 +220,10 @@ typedef enum UC_MIPS_REG { UC_MIPS_REG_CP0_USERLOCAL, UC_MIPS_REG_CP0_STATUS, + // FCR(s) Ref: https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00083-2B-MIPS64INT-AFP-06.01.pdf + UC_MIPS_REG_FIR, + UC_MIPS_REG_FCSR, + UC_MIPS_REG_ENDING, // <-- mark the end of the list or registers // alias registers diff --git a/qemu/target/mips/unicorn.c b/qemu/target/mips/unicorn.c index 58348511..71a6e73a 100644 --- a/qemu/target/mips/unicorn.c +++ b/qemu/target/mips/unicorn.c @@ -103,6 +103,49 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value, CHECK_REG_TYPE(mipsreg_t); *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; break; + case UC_MIPS_REG_F0: + case UC_MIPS_REG_F1: + case UC_MIPS_REG_F2: + case UC_MIPS_REG_F3: + case UC_MIPS_REG_F4: + case UC_MIPS_REG_F5: + case UC_MIPS_REG_F6: + case UC_MIPS_REG_F7: + case UC_MIPS_REG_F8: + case UC_MIPS_REG_F9: + case UC_MIPS_REG_F10: + case UC_MIPS_REG_F11: + case UC_MIPS_REG_F12: + case UC_MIPS_REG_F13: + case UC_MIPS_REG_F14: + case UC_MIPS_REG_F15: + case UC_MIPS_REG_F16: + case UC_MIPS_REG_F17: + case UC_MIPS_REG_F18: + case UC_MIPS_REG_F19: + case UC_MIPS_REG_F20: + case UC_MIPS_REG_F21: + case UC_MIPS_REG_F22: + case UC_MIPS_REG_F23: + case UC_MIPS_REG_F24: + case UC_MIPS_REG_F25: + case UC_MIPS_REG_F26: + case UC_MIPS_REG_F27: + case UC_MIPS_REG_F28: + case UC_MIPS_REG_F29: + case UC_MIPS_REG_F30: + case UC_MIPS_REG_F31: + CHECK_REG_TYPE(uint64_t); + *(uint64_t *)value = env->active_fpu.fpr[regid - UC_MIPS_REG_F0].d; + break; + case UC_MIPS_REG_FIR: + CHECK_REG_TYPE(uint32_t); + *(uint32_t *)value = env->active_fpu.fcr0; + break; + case UC_MIPS_REG_FCSR: + CHECK_REG_TYPE(uint32_t); + *(uint32_t *)value = env->active_fpu.fcr31; + break; } } @@ -158,6 +201,57 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value, CHECK_REG_TYPE(mipsreg_t); env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; break; + case UC_MIPS_REG_F0: + case UC_MIPS_REG_F1: + case UC_MIPS_REG_F2: + case UC_MIPS_REG_F3: + case UC_MIPS_REG_F4: + case UC_MIPS_REG_F5: + case UC_MIPS_REG_F6: + case UC_MIPS_REG_F7: + case UC_MIPS_REG_F8: + case UC_MIPS_REG_F9: + case UC_MIPS_REG_F10: + case UC_MIPS_REG_F11: + case UC_MIPS_REG_F12: + case UC_MIPS_REG_F13: + case UC_MIPS_REG_F14: + case UC_MIPS_REG_F15: + case UC_MIPS_REG_F16: + case UC_MIPS_REG_F17: + case UC_MIPS_REG_F18: + case UC_MIPS_REG_F19: + case UC_MIPS_REG_F20: + case UC_MIPS_REG_F21: + case UC_MIPS_REG_F22: + case UC_MIPS_REG_F23: + case UC_MIPS_REG_F24: + case UC_MIPS_REG_F25: + case UC_MIPS_REG_F26: + case UC_MIPS_REG_F27: + case UC_MIPS_REG_F28: + case UC_MIPS_REG_F29: + case UC_MIPS_REG_F30: + case UC_MIPS_REG_F31: + CHECK_REG_TYPE(uint64_t); + env->active_fpu.fpr[regid - UC_MIPS_REG_F0].d = *(uint64_t*)value; + break; + case UC_MIPS_REG_FCSR: { + CHECK_REG_TYPE(uint32_t); + uint32_t arg1 = *(uint32_t *)value; + uint32_t original = env->active_fpu.fcr31; + env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) | + (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask)); + if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & + GET_FP_CAUSE(env->active_fpu.fcr31)) { + env->active_fpu.fcr31 = original; + ret = UC_ERR_EXCEPTION; + } else { + restore_fp_status(env); + set_float_exception_flags(0, &env->active_fpu.fp_status); + } + break; + } } }