aboutsummaryrefslogtreecommitdiff
path: root/target-mips/op_helper.c
diff options
context:
space:
mode:
authorPetar Jovanovic <petar.jovanovic@imgtec.com>2014-01-22 18:35:32 +0100
committerPetar Jovanovic <petar.jovanovic@imgtec.com>2014-02-10 16:46:38 +0100
commit736d120af4bf5f3e13b2f90c464b3a24847f78f0 (patch)
tree01cb88023c2ee383af3dcde2793e756d13b1833e /target-mips/op_helper.c
parentb4dd99a3636f5a3044dfd9dba7653ca377a9aeba (diff)
target-mips: add user-mode FR switch support for MIPS32r5
Description of UFR feature: Required in MIPS32r5 if floating point is implemented and user-mode FR switching is supported. The UFR register allows user-mode to clear StatusFR by executing a CTC1 to UFR with GPR[0] as input, and read StatusFR by executing a CFC1 to UFR. helper_ctc1 has been extended with an additional parameter rt to check requirements for UFR feature. Definition of mips32r5-generic has been modified to include support for UFR. Signed-off-by: Petar Jovanovic <petar.jovanovic@imgtec.com> Reviewed-by: Eric Johnson <eric.johnson@imgtec.com>
Diffstat (limited to 'target-mips/op_helper.c')
-rw-r--r--target-mips/op_helper.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index eaf4d2621a..2ef6633f47 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2199,12 +2199,23 @@ static inline void restore_flush_mode(CPUMIPSState *env)
target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
{
- target_ulong arg1;
+ target_ulong arg1 = 0;
switch (reg) {
case 0:
arg1 = (int32_t)env->active_fpu.fcr0;
break;
+ case 1:
+ /* UFR Support - Read Status FR */
+ if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) {
+ if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
+ arg1 = (int32_t)
+ ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ }
+ break;
case 25:
arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
break;
@@ -2222,9 +2233,33 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
return arg1;
}
-void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t reg)
+void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
{
- switch(reg) {
+ switch (fs) {
+ case 1:
+ /* UFR Alias - Reset Status FR */
+ if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
+ return;
+ }
+ if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
+ env->CP0_Status &= ~(1 << CP0St_FR);
+ compute_hflags(env);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ break;
+ case 4:
+ /* UNFR Alias - Set Status FR */
+ if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) {
+ return;
+ }
+ if (env->CP0_Config5 & (1 << CP0C5_UFR)) {
+ env->CP0_Status |= (1 << CP0St_FR);
+ compute_hflags(env);
+ } else {
+ helper_raise_exception(env, EXCP_RI);
+ }
+ break;
case 25:
if (arg1 & 0xffffff00)
return;