Skip to content

Commit

Permalink
Jit64: some byte-swapping changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Tilka committed Aug 24, 2015
1 parent 80fa9af commit f52a4fe
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 91 deletions.
45 changes: 36 additions & 9 deletions Source/Core/Common/x64Emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,30 +886,57 @@ void XEmitter::WriteMOVBE(int bits, u8 op, X64Reg reg, const OpArg& arg)
void XEmitter::MOVBE(int bits, X64Reg dest, const OpArg& src) {WriteMOVBE(bits, 0xF0, dest, src);}
void XEmitter::MOVBE(int bits, const OpArg& dest, X64Reg src) {WriteMOVBE(bits, 0xF1, src, dest);}

void XEmitter::LoadAndSwap(int size, X64Reg dst, const OpArg& src)
void XEmitter::LoadAndSwap(int size, X64Reg dst, const OpArg& src, bool sign_extend)
{
if (cpu_info.bMOVBE)
{
MOVBE(size, dst, src);
}
else
switch (size)
{
MOV(size, R(dst), src);
BSWAP(size, dst);
case 8:
if (sign_extend)
MOVSX(32, 8, dst, src);
else
MOVZX(32, 8, dst, src);
break;
case 16:
MOVZX(32, 16, dst, src);
if (sign_extend)
{
BSWAP(32, dst);
SAR(32, R(dst), Imm8(16));
}
else
{
ROL(16, R(dst), Imm8(8));
}
break;
case 32:
case 64:
if (cpu_info.bMOVBE)
{
MOVBE(size, dst, src);
}
else
{
MOV(size, R(dst), src);
BSWAP(size, dst);
}
break;
}
}

void XEmitter::SwapAndStore(int size, const OpArg& dst, X64Reg src)
u8* XEmitter::SwapAndStore(int size, const OpArg& dst, X64Reg src)
{
u8* mov_location = GetWritableCodePtr();
if (cpu_info.bMOVBE)
{
MOVBE(size, dst, src);
}
else
{
BSWAP(size, src);
mov_location = GetWritableCodePtr();
MOV(size, dst, R(src));
}
return mov_location;
}


Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Common/x64Emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,8 @@ class XEmitter
// Available only on Atom or >= Haswell so far. Test with cpu_info.bMOVBE.
void MOVBE(int bits, X64Reg dest, const OpArg& src);
void MOVBE(int bits, const OpArg& dest, X64Reg src);
void LoadAndSwap(int size, X64Reg dst, const OpArg& src);
void SwapAndStore(int size, const OpArg& dst, X64Reg src);
void LoadAndSwap(int size, X64Reg dst, const OpArg& src, bool sign_extend = false);
u8* SwapAndStore(int size, const OpArg& dst, X64Reg src);

// Available only on AMD >= Phenom or Intel >= Haswell
void LZCNT(int bits, X64Reg dest, const OpArg& src);
Expand Down
45 changes: 23 additions & 22 deletions Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,41 +86,42 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)

// Compute the start and length of the memory operation, including
// any byteswapping.
int totalSize;
int totalSize = info.instructionSize;
u8 *start = codePtr;
if (!info.isMemoryWrite)
{
int bswapNopCount;
if (info.byteSwap || info.operandSize == 1)
bswapNopCount = 0;
// Check the following BSWAP for REX byte
else if ((codePtr[info.instructionSize] & 0xF0) == 0x40)
bswapNopCount = 3;
else
bswapNopCount = 2;

totalSize = info.instructionSize + bswapNopCount;
if (info.operandSize == 2 && !info.byteSwap)
// MOVBE and single bytes don't need to be swapped.
if (!info.byteSwap && info.operandSize > 1)
{
// REX
if ((codePtr[totalSize] & 0xF0) == 0x40)
totalSize++;

// BSWAP
if (codePtr[totalSize] == 0x0F && (codePtr[totalSize + 1] & 0xF8) == 0xC8)
totalSize += 2;

if (info.operandSize == 2)
{
++totalSize;
}
if (codePtr[totalSize] != 0xc1 || codePtr[totalSize + 2] != 0x10)
{
PanicAlert("BackPatch: didn't find expected shift %p", codePtr);
return false;
// operand size override
if (codePtr[totalSize] == 0x66)
totalSize++;
// REX
if ((codePtr[totalSize] & 0xF0) == 0x40)
totalSize++;
// SAR/ROL
_assert_(codePtr[totalSize] == 0xC1 && (codePtr[totalSize + 2] == 0x10 ||
codePtr[totalSize + 2] == 0x08));
info.signExtend = (codePtr[totalSize + 1] & 0x10) != 0;
totalSize += 3;
}
info.signExtend = (codePtr[totalSize + 1] & 0x10) != 0;
totalSize += 3;
}
}
else
{
if (info.byteSwap || info.hasImmediate)
{
// The instruction is a MOVBE but it failed so the value is still in little-endian byte order.
totalSize = info.instructionSize;
}
else
{
Expand All @@ -146,7 +147,7 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
break;
}
start = codePtr - bswapSize;
totalSize = info.instructionSize + bswapSize;
totalSize += bswapSize;
}
}

Expand Down
55 changes: 10 additions & 45 deletions Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,25 @@ void EmuCodeBlock::MemoryExceptionCheck()

void EmuCodeBlock::UnsafeLoadRegToReg(X64Reg reg_addr, X64Reg reg_value, int accessSize, s32 offset, bool signExtend)
{
MOVZX(32, accessSize, reg_value, MComplex(RMEM, reg_addr, SCALE_1, offset));
OpArg src = MComplex(RMEM, reg_addr, SCALE_1, offset);
if (accessSize == 32)
{
BSWAP(32, reg_value);
LoadAndSwap(32, reg_value, src);
}
else if (accessSize == 16)
{
BSWAP(32, reg_value);
LoadAndSwap(32, reg_value, src);
if (signExtend)
SAR(32, R(reg_value), Imm8(16));
else
SHR(32, R(reg_value), Imm8(16));
}
else if (signExtend)
else
{
// TODO: bake 8-bit into the original load.
MOVSX(32, accessSize, reg_value, R(reg_value));
if (signExtend)
MOVSX(32, accessSize, reg_value, src);
else
MOVZX(32, accessSize, reg_value, src);
}
}

Expand Down Expand Up @@ -84,34 +86,7 @@ u8 *EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, OpArg opAddress, int accessS
}

result = GetWritableCodePtr();
if (accessSize == 8 && signExtend)
MOVSX(32, accessSize, reg_value, memOperand);
else
MOVZX(64, accessSize, reg_value, memOperand);

switch (accessSize)
{
case 8:
_dbg_assert_(DYNA_REC, BACKPATCH_SIZE - (GetCodePtr() - result <= 0));
break;

case 16:
BSWAP(32, reg_value);
if (signExtend)
SAR(32, R(reg_value), Imm8(16));
else
SHR(32, R(reg_value), Imm8(16));
break;

case 32:
BSWAP(32, reg_value);
break;

case 64:
BSWAP(64, reg_value);
break;
}

LoadAndSwap(accessSize, reg_value, memOperand, signExtend);
return result;
}

Expand Down Expand Up @@ -415,17 +390,7 @@ u8 *EmuCodeBlock::UnsafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acce
}
else if (swap)
{
if (cpu_info.bMOVBE)
{
MOVBE(accessSize, dest, reg_value.GetSimpleReg());
}
else
{
if (accessSize > 8)
BSWAP(accessSize, reg_value.GetSimpleReg());
result = GetWritableCodePtr();
MOV(accessSize, dest, reg_value);
}
result = SwapAndStore(accessSize, dest, reg_value.GetSimpleReg());
}
else
{
Expand Down
17 changes: 4 additions & 13 deletions Source/Core/VideoCommon/VertexLoaderX64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,12 @@ OpArg VertexLoaderX64::GetVertexAddr(int array, u64 attribute)
OpArg data = MDisp(src_reg, m_src_ofs);
if (attribute & MASK_INDEXED)
{
if (attribute == INDEX8)
{
MOVZX(64, 8, scratch1, data);
m_src_ofs += 1;
}
else
{
MOV(16, R(scratch1), data);
m_src_ofs += 2;
BSWAP(16, scratch1);
MOVZX(64, 16, scratch1, R(scratch1));
}
int bits = attribute == INDEX8 ? 8 : 16;
LoadAndSwap(bits, scratch1, data);
m_src_ofs += bits / 8;
if (array == ARRAY_POSITION)
{
CMP(attribute == INDEX8 ? 8 : 16, R(scratch1), Imm8(-1));
CMP(bits, R(scratch1), Imm8(-1));
m_skip_vertex = J_CC(CC_E, true);
}
IMUL(32, scratch1, MPIC(&g_main_cp_state.array_strides[array]));
Expand Down

0 comments on commit f52a4fe

Please sign in to comment.