Add get/set native FPU state functions.

This commit is contained in:
Tyler Stachecki 2014-07-27 14:57:54 -04:00
parent 850c278cd9
commit e7417bee66
4 changed files with 243 additions and 5 deletions

View file

@ -10,6 +10,22 @@
#ifndef __os_fpu_h__
#define __os_fpu_h__
#include "common.h"
#include <emmintrin.h>
typedef unsigned int fpu_state_t;
#define FPU_ROUND_NEAREST 0x0000
#define FPU_ROUND_NEGINF 0x2000
#define FPU_ROUND_POSINF 0x4000
#define FPU_ROUND_TOZERO 0x6000
static inline fpu_state_t fpu_get_state(void) {
return _mm_getcsr();
}
static inline void fpu_set_state(fpu_state_t state) {
_mm_setcsr(state);
}
#include "os/unix/fpu/x86_64/fpu_abs_32.h"
#include "os/unix/fpu/x86_64/fpu_abs_64.h"

View file

@ -26,13 +26,23 @@ int VR4300_CP1_ABS(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
}
if (fmt != VR4300_FMT_S && fmt != VR4300_FMT_D) {
VR4300_INV(vr4300);
return 1;
}
fpu_set_state(vr4300->cp1.native_state);
if (fmt == VR4300_FMT_S) {
uint32_t fs32 = fs;
uint32_t fd32;
@ -41,11 +51,11 @@ int VR4300_CP1_ABS(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
result = fd32;
}
else if (fmt == VR4300_FMT_D)
else
fpu_abs_64(&fs, &result);
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
@ -62,8 +72,11 @@ int VR4300_CP1_ADD(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -84,6 +97,9 @@ int VR4300_CP1_ADD(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -153,8 +169,11 @@ int VR4300_CP1_C_EQ(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -171,6 +190,9 @@ int VR4300_CP1_C_EQ(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -187,8 +209,11 @@ int VR4300_CP1_C_F(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -198,6 +223,9 @@ int VR4300_CP1_C_F(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -214,8 +242,11 @@ int VR4300_CP1_C_LE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -232,6 +263,9 @@ int VR4300_CP1_C_LE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -248,8 +282,11 @@ int VR4300_CP1_C_LT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -266,6 +303,9 @@ int VR4300_CP1_C_LT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -282,8 +322,11 @@ int VR4300_CP1_C_NGE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -300,6 +343,9 @@ int VR4300_CP1_C_NGE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -316,8 +362,11 @@ int VR4300_CP1_C_NGL(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -334,6 +383,9 @@ int VR4300_CP1_C_NGL(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -350,8 +402,11 @@ int VR4300_CP1_C_NGLE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -368,6 +423,9 @@ int VR4300_CP1_C_NGLE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -384,8 +442,11 @@ int VR4300_CP1_C_NGT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -402,6 +463,9 @@ int VR4300_CP1_C_NGT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -418,8 +482,11 @@ int VR4300_CP1_C_OLE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -436,6 +503,9 @@ int VR4300_CP1_C_OLE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -452,8 +522,11 @@ int VR4300_CP1_C_OLT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -470,6 +543,9 @@ int VR4300_CP1_C_OLT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -486,8 +562,11 @@ int VR4300_CP1_C_SEQ(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -504,6 +583,9 @@ int VR4300_CP1_C_SEQ(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -520,8 +602,11 @@ int VR4300_CP1_C_SF(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -538,6 +623,9 @@ int VR4300_CP1_C_SF(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -554,8 +642,11 @@ int VR4300_CP1_C_UEQ(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -572,6 +663,9 @@ int VR4300_CP1_C_UEQ(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -588,8 +682,11 @@ int VR4300_CP1_C_ULE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -606,6 +703,9 @@ int VR4300_CP1_C_ULE(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -622,8 +722,11 @@ int VR4300_CP1_C_ULT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -640,6 +743,9 @@ int VR4300_CP1_C_ULT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -656,8 +762,11 @@ int VR4300_CP1_C_UN(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = VR4300_CP1_FCR31;
uint64_t result = vr4300->regs[dest];
fpu_state_t saved_state;
uint8_t flag;
saved_state = fpu_get_state();
// Clear out C bit.
result &= ~(1 << 23);
@ -674,6 +783,9 @@ int VR4300_CP1_C_UN(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result | (flag << 23);
exdc_latch->dest = dest;
return 0;
@ -689,10 +801,13 @@ int VR4300_CP1_CEIL_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -713,6 +828,9 @@ int VR4300_CP1_CEIL_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
fesetround(oldround);
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -728,10 +846,13 @@ int VR4300_CP1_CEIL_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint32_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -752,6 +873,9 @@ int VR4300_CP1_CEIL_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
fesetround(oldround);
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -846,10 +970,13 @@ int VR4300_CP1_CVT_D(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -862,6 +989,9 @@ int VR4300_CP1_CVT_D(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
case VR4300_FMT_L: fpu_cvt_f64_i64(&fs, &result); break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -877,10 +1007,13 @@ int VR4300_CP1_CVT_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -896,6 +1029,9 @@ int VR4300_CP1_CVT_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -911,10 +1047,13 @@ int VR4300_CP1_CVT_S(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint32_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -927,6 +1066,9 @@ int VR4300_CP1_CVT_S(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
case VR4300_FMT_L: fpu_cvt_f32_i64(&fs, &result); break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -942,10 +1084,13 @@ int VR4300_CP1_CVT_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint32_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -961,6 +1106,9 @@ int VR4300_CP1_CVT_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -976,8 +1124,11 @@ int VR4300_CP1_DIV(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -998,6 +1149,9 @@ int VR4300_CP1_DIV(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1013,10 +1167,13 @@ int VR4300_CP1_FLOOR_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1037,6 +1194,9 @@ int VR4300_CP1_FLOOR_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
fesetround(oldround);
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1052,10 +1212,13 @@ int VR4300_CP1_FLOOR_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint32_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1076,6 +1239,9 @@ int VR4300_CP1_FLOOR_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
fesetround(oldround);
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1163,8 +1329,11 @@ int VR4300_CP1_MUL(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1185,6 +1354,9 @@ int VR4300_CP1_MUL(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1196,11 +1368,9 @@ int VR4300_CP1_MUL(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
int VR4300_MFC1(struct vr4300 *vr4300, uint64_t fs, uint64_t unused(rt)) {
struct vr4300_rfex_latch *rfex_latch = &vr4300->pipeline.rfex_latch;
struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
uint32_t status = vr4300->regs[VR4300_CP0_REGISTER_STATUS];
uint64_t result;
uint32_t iw = rfex_latch->iw;
unsigned fs_reg = GET_FS(iw);
unsigned dest = GET_RT(iw);
if (!vr4300_cp1_usable(vr4300)) {
@ -1277,8 +1447,11 @@ int VR4300_CP1_NEG(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1298,6 +1471,9 @@ int VR4300_CP1_NEG(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1313,10 +1489,13 @@ int VR4300_CP1_ROUND_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1332,6 +1511,9 @@ int VR4300_CP1_ROUND_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1347,10 +1529,13 @@ int VR4300_CP1_ROUND_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint32_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1366,6 +1551,9 @@ int VR4300_CP1_ROUND_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1406,8 +1594,11 @@ int VR4300_CP1_SQRT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1427,6 +1618,9 @@ int VR4300_CP1_SQRT(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1442,8 +1636,11 @@ int VR4300_CP1_SUB(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1464,6 +1661,9 @@ int VR4300_CP1_SUB(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
else
assert(0 && "Invalid instruction.");
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1509,10 +1709,13 @@ int VR4300_CP1_TRUNC_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint64_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1528,6 +1731,9 @@ int VR4300_CP1_TRUNC_L(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1543,10 +1749,13 @@ int VR4300_CP1_TRUNC_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
uint32_t iw = rfex_latch->iw;
enum vr4300_fmt fmt = GET_FMT(iw);
unsigned dest = GET_FD(iw);
fpu_state_t saved_state;
uint32_t fs32 = fs;
uint32_t result;
saved_state = fpu_get_state();
if (!vr4300_cp1_usable(vr4300)) {
VR4300_CPU(vr4300);
return 1;
@ -1562,6 +1771,9 @@ int VR4300_CP1_TRUNC_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
break;
}
vr4300->cp1.native_state = fpu_get_state();
fpu_set_state(saved_state);
exdc_latch->result = result;
exdc_latch->dest = dest;
return 0;
@ -1569,6 +1781,7 @@ int VR4300_CP1_TRUNC_W(struct vr4300 *vr4300, uint64_t fs, uint64_t ft) {
// Initializes the coprocessor.
void vr4300_cp1_init(struct vr4300 *vr4300) {
vr4300->cp1.native_state = FPU_ROUND_NEAREST;
}
// Determines if the coprocessor was used yet.

View file

@ -11,9 +11,15 @@
#ifndef __vr4300_cp1_h__
#define __vr4300_cp1_h__
#include "common.h"
#include "fpu.h"
struct vr4300;
struct vr4300_cp1 {
fpu_state_t native_state;
fpu_state_t native_enables;
};
int VR4300_BC1(struct vr4300 *vr4300, uint64_t fs, uint64_t ft);
int VR4300_CFC1(struct vr4300 *vr4300, uint64_t rs, uint64_t rt);
int VR4300_CTC1(struct vr4300 *vr4300, uint64_t rs, uint64_t rt);

View file

@ -12,6 +12,7 @@
#define __vr4300_cpu_h__
#include "common.h"
#include "vr4300/cp0.h"
#include "vr4300/cp1.h"
#include "vr4300/dcache.h"
#include "vr4300/icache.h"
#include "vr4300/pipeline.h"
@ -85,7 +86,9 @@ struct vr4300 {
struct vr4300_dcache dcache;
struct vr4300_icache icache;
struct vr4300_pipeline pipeline;
struct vr4300_cp1 cp1;
struct bus_controller *bus;
unsigned long long cycles;