diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp
index ceb2794a2e..b7cf3d7188 100644
--- a/Source/Core/Common/Src/x64Emitter.cpp
+++ b/Source/Core/Common/Src/x64Emitter.cpp
@@ -133,21 +133,37 @@ void XEmitter::WriteSIB(int scale, int index, int base)
 	Write8((u8)((scale << 6) | ((index & 7) << 3) | (base & 7)));
 }
 
-void OpArg::WriteRex(XEmitter *emit, bool op64, int customOp) const
+void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const
 {
+	if (customOp == -1)       customOp = operandReg;
 #ifdef _M_X64
 	u8 op = 0x40;
-	if (customOp == -1)       customOp = operandReg;
-	if (op64)                 op |= 8;
-	if (customOp >> 3)        op |= 4;
-	if (indexReg >> 3)        op |= 2;
-	if (offsetOrBaseReg >> 3) op |= 1; //TODO investigate if this is dangerous
-	if (op != 0x40)
+	if (opBits == 64)         op |= 8;
+	if (customOp & 8)         op |= 4;
+	if (indexReg & 8)         op |= 2;
+	if (offsetOrBaseReg & 8)  op |= 1; //TODO investigate if this is dangerous
+	if (op != 0x40 ||
+	    (bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
+	    (opBits == 8 && (customOp & 0x10c) == 4)) {
 		emit->Write8(op);
+		_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x100) == 0 || bits != 8);
+		_dbg_assert_(DYNA_REC, (customOp & 0x100) == 0 || opBits != 8);
+	} else {
+		_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x10c) == 0 ||
+			     (offsetOrBaseReg & 0x10c) == 0x104 ||
+			     bits != 8);
+		_dbg_assert_(DYNA_REC, (customOp & 0x10c) == 0 ||
+			     (customOp & 0x10c) == 0x104 ||
+			     opBits != 8);
+	}
+
 #else
-	_dbg_assert_(DYNA_REC, (operandReg >> 3) == 0);
-	_dbg_assert_(DYNA_REC, (indexReg >> 3) == 0);
-	_dbg_assert_(DYNA_REC, (offsetOrBaseReg >> 3) == 0);
+	_dbg_assert_(DYNA_REC, opBits != 64);
+	_dbg_assert_(DYNA_REC, (customOp & 8) == 0 || customOp == -1);
+	_dbg_assert_(DYNA_REC, (indexReg & 8) == 0);
+	_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 8) == 0);
+	_dbg_assert_(DYNA_REC, opBits != 8 || (customOp & 0x10c) != 4 || customOp == -1);
+	_dbg_assert_(DYNA_REC, bits != 8 || (offsetOrBaseReg & 0x10c) != 4);
 #endif
 }
 
@@ -162,17 +178,17 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg) const
 
 	if (scale == SCALE_RIP) //Also, on 32-bit, just an immediate address
 	{
-		// Oh, RIP addressing. 
+		// Oh, RIP addressing.
 		_offsetOrBaseReg = 5;
 		emit->WriteModRM(0, _operandReg&7, 5);
 		//TODO : add some checks
 #ifdef _M_X64
 		u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes;
 		s64 distance = (s64)offset - (s64)ripAddr;
-		if (distance >= 0x0000000080000000LL
-		    || distance <  -0x0000000080000000LL) {
-		    PanicAlert("WriteRest: op out of range (0x%llx uses 0x%llx)", ripAddr, offset);
-		}
+		_assert_msg_(DYNA_REC, distance < 0x80000000LL
+			     && distance >=  -0x80000000LL,
+			     "WriteRest: op out of range (0x%llx uses 0x%llx)",
+			     ripAddr, offset);
 		s32 offs = (s32)distance;
 		emit->Write32((u32)offs);
 #else
@@ -299,17 +315,20 @@ void XEmitter::JMP(const u8 *addr, bool force5Bytes)
 	u64 fn = (u64)addr;
 	if (!force5Bytes)
 	{
-		s64 distance = (s64)(fn - ((u64)code + 2)); //TODO - sanity check
-		_assert_msg_(DYNA_REC, distance >= -0x80 && distance < 0x80, "Jump target too far away, needs force5Bytes = true");
+		s64 distance = (s64)(fn - ((u64)code + 2));
+		_assert_msg_(DYNA_REC, distance >= -0x80 && distance < 0x80,
+			     "Jump target too far away, needs force5Bytes = true");
 		//8 bits will do
 		Write8(0xEB);
 		Write8((u8)(s8)distance);
 	}
 	else
 	{
-		s64 distance = (s64)(fn - ((u64)code + 5)); //TODO - sanity check
+		s64 distance = (s64)(fn - ((u64)code + 5));
 
-		_assert_msg_(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target too far away, needs indirect register");
+		_assert_msg_(DYNA_REC, distance >= -0x80000000LL
+			     && distance < 0x80000000LL,
+			     "Jump target too far away, needs indirect register");
 		Write8(0xE9);
 		Write32((u32)(s32)distance);
 	}
@@ -320,7 +339,7 @@ void XEmitter::JMPptr(const OpArg &arg2)
 	OpArg arg = arg2;
 	if (arg.IsImm()) _assert_msg_(DYNA_REC, 0, "JMPptr - Imm argument");
 	arg.operandReg = 4;
-	arg.WriteRex(this, false);
+	arg.WriteRex(this, 0, 0);
 	Write8(0xFF);
 	arg.WriteRest(this);
 }
@@ -337,7 +356,7 @@ void XEmitter::CALLptr(OpArg arg)
 {
 	if (arg.IsImm()) _assert_msg_(DYNA_REC, 0, "CALLptr - Imm argument");
 	arg.operandReg = 2;
-	arg.WriteRex(this, false);
+	arg.WriteRex(this, 0, 0);
 	Write8(0xFF);
 	arg.WriteRest(this);
 }
@@ -345,10 +364,9 @@ void XEmitter::CALLptr(OpArg arg)
 void XEmitter::CALL(const void *fnptr)
 {
 	u64 distance = u64(fnptr) - (u64(code) + 5);
-	if (distance >= 0x0000000080000000ULL
-	 && distance <  0xFFFFFFFF80000000ULL) {
-		PanicAlert("CALL out of range (%p calls %p)", code, fnptr);
-	}
+	_assert_msg_(DYNA_REC, distance < 0x0000000080000000ULL
+		     || distance >=  0xFFFFFFFF80000000ULL,
+		     "CALL out of range (%p calls %p)", code, fnptr);
 	Write8(0xE8);
 	Write32(u32(distance));
 }
@@ -405,8 +423,10 @@ void XEmitter::J_CC(CCFlags conditionCode, const u8 * addr, bool force5Bytes)
 	}
 	else
 	{
-		s64 distance = (s64)(fn - ((u64)code + 6)); //TODO - sanity check
-		_assert_msg_(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target too far away, needs indirect register");
+		s64 distance = (s64)(fn - ((u64)code + 6));
+		_assert_msg_(DYNA_REC, distance >= -0x80000000LL
+			     && distance < 0x80000000LL,
+			     "Jump target too far away, needs indirect register");
 		Write8(0x0F);
 		Write8(0x80 + conditionCode);
 		Write32((u32)(s32)distance);
@@ -438,7 +458,7 @@ void XEmitter::INC(int bits, OpArg arg)
 	if (arg.IsImm()) _assert_msg_(DYNA_REC, 0, "INC - Imm argument");
 	arg.operandReg = 0;
 	if (bits == 16) {Write8(0x66);}
-	arg.WriteRex(this, bits == 64);
+	arg.WriteRex(this, bits, bits);
 	Write8(bits == 8 ? 0xFE : 0xFF);
 	arg.WriteRest(this);
 }
@@ -447,7 +467,7 @@ void XEmitter::DEC(int bits, OpArg arg)
 	if (arg.IsImm()) _assert_msg_(DYNA_REC, 0, "DEC - Imm argument");
 	arg.operandReg = 1;
 	if (bits == 16) {Write8(0x66);}
-	arg.WriteRex(this, bits == 64);
+	arg.WriteRex(this, bits, bits);
 	Write8(bits == 8 ? 0xFE : 0xFF);
 	arg.WriteRest(this);
 }
@@ -569,7 +589,7 @@ void XEmitter::PUSH(int bits, const OpArg &reg)
 	{
 		if (bits == 16)
 			Write8(0x66);
-		reg.WriteRex(this, bits == 64);
+		reg.WriteRex(this, bits, bits);
 		Write8(0xFF);
 		reg.WriteRest(this, 0, (X64Reg)6);
 	}
@@ -615,7 +635,7 @@ void XEmitter::PREFETCH(PrefetchLevel level, OpArg arg)
 {
 	if (arg.IsImm()) _assert_msg_(DYNA_REC, 0, "PREFETCH - Imm argument");;
 	arg.operandReg = (u8)level;
-	arg.WriteRex(this, false);
+	arg.WriteRex(this, 0, 0);
 	Write8(0x0F);
 	Write8(0x18);
 	arg.WriteRest(this);
@@ -625,7 +645,7 @@ void XEmitter::SETcc(CCFlags flag, OpArg dest)
 {
 	if (dest.IsImm()) _assert_msg_(DYNA_REC, 0, "SETcc - Imm argument");
 	dest.operandReg = 0;
-	dest.WriteRex(this, false);
+	dest.WriteRex(this, 0, 0);
 	Write8(0x0F);
 	Write8(0x90 + (u8)flag);
 	dest.WriteRest(this);
@@ -635,7 +655,7 @@ void XEmitter::CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag)
 {
 	if (src.IsImm()) _assert_msg_(DYNA_REC, 0, "CMOVcc - Imm argument");
 	src.operandReg = dest;
-	src.WriteRex(this, bits == 64);
+	src.WriteRex(this, bits, bits);
 	Write8(0x0F);
 	Write8(0x40 + (u8)flag);
 	src.WriteRest(this);
@@ -646,12 +666,12 @@ void XEmitter::WriteMulDivType(int bits, OpArg src, int ext)
 	if (src.IsImm()) _assert_msg_(DYNA_REC, 0, "WriteMulDivType - Imm argument");
 	src.operandReg = ext;
 	if (bits == 16) Write8(0x66);
-	src.WriteRex(this, bits == 64);
+	src.WriteRex(this, bits, bits);
 	if (bits == 8)
 	{
 		Write8(0xF6);
 	}
-	else 
+	else
 	{
 		Write8(0xF7);
 	}
@@ -670,7 +690,7 @@ void XEmitter::WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2)
 	if (src.IsImm()) _assert_msg_(DYNA_REC, 0, "WriteBitSearchType - Imm argument");
 	src.operandReg = (u8)dest;
 	if (bits == 16) Write8(0x66);
-	src.WriteRex(this, bits == 64);
+	src.WriteRex(this, bits, bits);
 	Write8(0x0F);
 	Write8(byte2);
 	src.WriteRest(this);
@@ -694,7 +714,7 @@ void XEmitter::MOVSX(int dbits, int sbits, X64Reg dest, OpArg src)
 	}
 	src.operandReg = (u8)dest;
 	if (dbits == 16) Write8(0x66);
-	src.WriteRex(this, dbits == 64);
+	src.WriteRex(this, dbits, sbits);
 	if (sbits == 8)
 	{
 		Write8(0x0F);
@@ -725,7 +745,8 @@ void XEmitter::MOVZX(int dbits, int sbits, X64Reg dest, OpArg src)
 	}
 	src.operandReg = (u8)dest;
 	if (dbits == 16) Write8(0x66);
-	src.WriteRex(this, dbits == 64);
+	//the 32bit result is automatically zero extended to 64bit
+	src.WriteRex(this, dbits == 64 ? 32 : dbits, sbits);
 	if (sbits == 8)
 	{
 		Write8(0x0F);
@@ -749,7 +770,7 @@ void XEmitter::LEA(int bits, X64Reg dest, OpArg src)
 	if (src.IsImm()) _assert_msg_(DYNA_REC, 0, "LEA - Imm argument");
 	src.operandReg = (u8)dest;
 	if (bits == 16) Write8(0x66); //TODO: performance warning
-	src.WriteRex(this, bits == 64);
+	src.WriteRex(this, bits, bits);
 	Write8(0x8D);
 	src.WriteRest(this);
 }
@@ -768,7 +789,7 @@ void XEmitter::WriteShift(int bits, OpArg dest, OpArg &shift, int ext)
 	}
 	dest.operandReg = ext;
 	if (bits == 16) Write8(0x66);
-	dest.WriteRex(this, bits == 64);
+	dest.WriteRex(this, bits, bits, 0);
 	if (shift.GetImmBits() == 8)
 	{
 		//ok an imm
@@ -808,7 +829,7 @@ void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bit
 		emit->Write8(0x66);
 
 	this->operandReg = (u8)_operandReg;
-	WriteRex(emit, bits == 64);
+	WriteRex(emit, bits, bits);
 	emit->Write8(op);
 	WriteRest(emit);
 }
@@ -830,7 +851,7 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
 	if (operand.IsImm())
 	{
 		_operandReg = (X64Reg)0;
-		WriteRex(emit, bits == 64);
+		WriteRex(emit, bits, bits);
 
 		if (!toRM)
 		{
@@ -875,7 +896,7 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
 	else
 	{
 		_operandReg = (X64Reg)operand.offsetOrBaseReg;
-		WriteRex(emit, bits == 64, _operandReg);
+		WriteRex(emit, bits, bits, _operandReg);
 		// mem/reg or reg/reg op
 		if (toRM)
 		{
@@ -969,7 +990,7 @@ void XEmitter::IMUL(int bits, X64Reg regOp, OpArg a1, OpArg a2)
 
 	if (bits == 16)
 		Write8(0x66);
-	a1.WriteRex(this, bits == 64, regOp);
+	a1.WriteRex(this, bits, bits, regOp);
 
 	if (a2.GetImmBits() == 8) {
 		Write8(0x6B);
@@ -1004,7 +1025,7 @@ void XEmitter::IMUL(int bits, X64Reg regOp, OpArg a)
 
 	if (bits == 16)
 		Write8(0x66);
-	a.WriteRex(this, bits == 64, regOp);
+	a.WriteRex(this, bits, bits, regOp);
 	Write8(0x0F);
 	Write8(0xAF);
 	a.WriteRest(this, 0, regOp);
@@ -1018,7 +1039,7 @@ void XEmitter::WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg a
 	if (!packed)
 		Write8(size == 64 ? 0xF2 : 0xF3);
 	arg.operandReg = regOp;
-	arg.WriteRex(this, false);
+	arg.WriteRex(this, 0, 0);
 	Write8(0x0F);
 	Write8(sseOp);
 	arg.WriteRest(this, extrabytes);
@@ -1033,7 +1054,7 @@ void XEmitter::MOVQ_xmm(X64Reg dest, OpArg arg) {
 		// This does not display correctly in MSVC's debugger, it thinks it's a MOVD
 		arg.operandReg = dest;
 		Write8(0x66);
-		arg.WriteRex(this, true);
+		arg.WriteRex(this, 64, 0);
 		Write8(0x0f);
 		Write8(0x6E);
 		arg.WriteRest(this, 0);
@@ -1055,13 +1076,13 @@ void XEmitter::MOVQ_xmm(OpArg arg, X64Reg src) {
 		// This does not display correctly in MSVC's debugger, it thinks it's a MOVD
 		arg.operandReg = src;
 		Write8(0x66);
-		arg.WriteRex(this, true);
+		arg.WriteRex(this, 64, 0);
 		Write8(0x0f);
 		Write8(0x7E);
 		arg.WriteRest(this, 0);
 	} else {
 		arg.operandReg = src;
-		arg.WriteRex(this, false);
+		arg.WriteRex(this, 0, 0);
 		Write8(0x66);
 		Write8(0x0f);
 		Write8(0xD6);
@@ -1075,7 +1096,7 @@ void XEmitter::WriteMXCSR(OpArg arg, int ext)
 		_assert_msg_(DYNA_REC, 0, "MXCSR - invalid operand");
 
 	arg.operandReg = ext;
-	arg.WriteRex(this, false);
+	arg.WriteRex(this, 0, 0);
 	Write8(0x0F);
 	Write8(0xAE);
 	arg.WriteRest(this);
@@ -1269,7 +1290,7 @@ void XEmitter::PSHUFB(X64Reg dest, OpArg arg) {
 	}
 	Write8(0x66);
 	arg.operandReg = dest;
-	arg.WriteRex(this, false);
+	arg.WriteRex(this, 0, 0);
 	Write8(0x0f);
 	Write8(0x38);
 	Write8(0x00);
diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h
index 4501ad17aa..d7decf0f38 100644
--- a/Source/Core/Common/Src/x64Emitter.h
+++ b/Source/Core/Common/Src/x64Emitter.h
@@ -37,7 +37,8 @@ enum X64Reg
 	R12 = 12,R13 = 13,R14 = 14,R15 = 15,
 
 	AL = 0, BL = 3, CL = 1, DL = 2,
-	AH = 4, BH = 7, CH = 5, DH = 6,
+	SIL = 6, DIL = 7, BPL = 5, SPL = 4,
+	AH = 0x104, BH = 0x107, CH = 0x105, DH = 0x106,
 
 	AX = 0, BX = 3, CX = 1, DX = 2,
 	SI = 6, DI = 7, BP = 5, SP = 4,
@@ -113,17 +114,17 @@ struct OpArg
 	{
 		operandReg = 0;
 		scale = (u8)_scale;
-		offsetOrBaseReg = (u8)rmReg;
-		indexReg = (u8)scaledReg;
+		offsetOrBaseReg = (u16)rmReg;
+		indexReg = (u16)scaledReg;
 		//if scale == 0 never mind offseting
 		offset = _offset;
 	}
-	void WriteRex(XEmitter *emit, bool op64, int customOp = -1) const;
+	void WriteRex(XEmitter *emit, int opBits, int bits, int customOp = -1) const;
 	void WriteRest(XEmitter *emit, int extraBytes=0, X64Reg operandReg=(X64Reg)0xFF) const;
 	void WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg operandReg, int bits);
 	// This one is public - must be written to
 	u64 offset;  // use RIP-relative as much as possible - 64-bit immediates are not available.
-	u8 operandReg;
+	u16 operandReg;
 
 	void WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &operand, int bits) const;
 	bool IsImm() const {return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64;}
@@ -162,8 +163,8 @@ struct OpArg
 	}
 private:
 	u8 scale;
-	u8 offsetOrBaseReg;
-	u8 indexReg;
+	u16 offsetOrBaseReg;
+	u16 indexReg;
 };
 
 inline OpArg M(void *ptr)	    {return OpArg((u64)ptr, (int)SCALE_RIP);}