From 377c94b125760a4381fdac6d89237397f52aad1b Mon Sep 17 00:00:00 2001
From: Henrik Rydgard <hrydgard@gmail.com>
Date: Wed, 6 Feb 2013 20:29:49 +0100
Subject: [PATCH] JIT x86: cvt.s.w

---
 Common/x64Emitter.cpp     |  2 ++
 Common/x64Emitter.h       |  2 ++
 Core/MIPS/MIPSTables.cpp  |  4 ++--
 Core/MIPS/x86/CompFPU.cpp | 15 +++++++++------
 4 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/Common/x64Emitter.cpp b/Common/x64Emitter.cpp
index 516dfa5fb..a4b16d7a8 100644
--- a/Common/x64Emitter.cpp
+++ b/Common/x64Emitter.cpp
@@ -1292,6 +1292,8 @@ void XEmitter::CVTDQ2PS(X64Reg regOp, OpArg arg) {WriteSSEOp(32, 0x5B, true, reg
 void XEmitter::CVTPD2DQ(X64Reg regOp, OpArg arg) {WriteSSEOp(64, 0xE6, false, regOp, arg);}
 void XEmitter::CVTPS2DQ(X64Reg regOp, OpArg arg) {WriteSSEOp(64, 0x5B, true, regOp, arg);}
 
+void XEmitter::CVTSI2SS(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x2A, false, xregdest, arg);}
+void XEmitter::CVTSS2SI(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x2D, false, xregdest, arg);}
 void XEmitter::CVTTSS2SI(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x2C, false, xregdest, arg);}
 void XEmitter::CVTTPS2DQ(X64Reg xregdest, OpArg arg) {WriteSSEOp(32, 0x5B, false, xregdest, arg);}
 
diff --git a/Common/x64Emitter.h b/Common/x64Emitter.h
index 7099c95f9..c2fc30535 100644
--- a/Common/x64Emitter.h
+++ b/Common/x64Emitter.h
@@ -564,6 +564,8 @@ public:
 	void CVTDQ2PS(X64Reg regOp, OpArg arg);
 	void CVTPS2DQ(X64Reg regOp, OpArg arg);
 
+	void CVTSI2SS(X64Reg xregdest, OpArg arg);  // Yeah, destination really is a GPR like EAX!
+	void CVTSS2SI(X64Reg xregdest, OpArg arg);  // Yeah, destination really is a GPR like EAX!
 	void CVTTSS2SI(X64Reg xregdest, OpArg arg);  // Yeah, destination really is a GPR like EAX!
 	void CVTTPS2DQ(X64Reg regOp, OpArg arg);
 
diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp
index f19c93be4..580ce9051 100644
--- a/Core/MIPS/MIPSTables.cpp
+++ b/Core/MIPS/MIPSTables.cpp
@@ -266,10 +266,10 @@ const MIPSInstruction tableSpecial2[64] =
 //24
 	{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
 //32
-	INSTR("cvt.s.w", &Jit::Comp_Generic, Dis_FPU2op, Int_FPU2op, 0),
+	INSTR("cvt.s.w", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
 	{-2}, {-2}, {-2}, 
 //36
-	INSTR("cvt.w.s", &Jit::Comp_Generic, Dis_FPU2op, Int_FPU2op, 0),
+	INSTR("cvt.w.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
 	{-2}, 
 	INSTR("dis.int", &Jit::Comp_Generic, Dis_Generic, Int_Interrupt, 0), 
 	{-2}, 
diff --git a/Core/MIPS/x86/CompFPU.cpp b/Core/MIPS/x86/CompFPU.cpp
index c7981b8d3..7494d649f 100644
--- a/Core/MIPS/x86/CompFPU.cpp
+++ b/Core/MIPS/x86/CompFPU.cpp
@@ -181,15 +181,12 @@ void Jit::Comp_FPU2op(u32 op)
 		fpr.ReleaseSpillLocks();
 		break;
 
-	case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
 
 	case 4:	//F(fd)	= sqrtf(F(fs)); break; //sqrt
-/*		fpr.Lock(fd, fs); // this probably works, just badly tested
+		fpr.SpillLock(fd, fs); // this probably works, just badly tested
 		fpr.BindToRegister(fd, fd == fs, true);
 		SQRTSS(fpr.RX(fd), fpr.R(fs));
-		fpr.UnlockAll();
-		break;*/ 
-		Comp_Generic(op);
+		fpr.ReleaseSpillLocks();
 		return;
 
 	case 13: //FsI(fd) = F(fs)>=0 ? (int)floorf(F(fs)) : (int)ceilf(F(fs)); break;//trunc.w.s
@@ -200,9 +197,15 @@ void Jit::Comp_FPU2op(u32 op)
 		fpr.ReleaseSpillLocks();
 		break;
 
+	case 32: //F(fd)	= (float)FsI(fs);			break; //cvt.s.w
+		fpr.StoreFromRegister(fs);
+		CVTSI2SS(XMM0, fpr.R(fs));
+		MOVSS(fpr.R(fd), XMM0);
+		break;
+
+	case 12: //FsI(fd) = (int)floorf(F(fs)+0.5f); break; //round.w.s
 	case 14: //FsI(fd) = (int)ceilf (F(fs)); break; //ceil.w.s
 	case 15: //FsI(fd) = (int)floorf(F(fs)); break; //floor.w.s
-	case 32: //F(fd)	= (float)FsI(fs);			break; //cvt.s.w
 	case 36: //FsI(fd) = (int)	F(fs);			 break; //cvt.w.s
 	default:
 		Comp_Generic(op);