2008-02-29 02:43:49 +00:00
|
|
|
#include "CodeGen.h"
|
|
|
|
#include "CodeGen_StackPatterns.h"
|
|
|
|
|
|
|
|
using namespace std;
|
2008-06-30 16:31:28 +00:00
|
|
|
using namespace std::tr1::placeholders;
|
2008-02-29 02:43:49 +00:00
|
|
|
|
|
|
|
bool CCodeGen::Register128HasNextUse(XMMREGISTER registerId)
|
|
|
|
{
|
|
|
|
unsigned int nCount = m_Shadow.GetCount();
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < nCount; i += 2)
|
|
|
|
{
|
|
|
|
if(m_Shadow.GetAt(i) == REGISTER128)
|
|
|
|
{
|
|
|
|
if(m_Shadow.GetAt(i + 1) == registerId) return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::CopyRegister128(XMMREGISTER destination, XMMREGISTER source)
|
|
|
|
{
|
|
|
|
m_Assembler.MovapsVo(CX86Assembler::MakeXmmRegisterAddress(destination),
|
|
|
|
source);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::LoadRelative128InRegister(XMMREGISTER registerId, uint32 offset)
|
|
|
|
{
|
|
|
|
m_Assembler.MovapsVo(registerId,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_PushRel(size_t offset)
|
|
|
|
{
|
|
|
|
m_Shadow.Push(static_cast<uint32>(offset));
|
|
|
|
m_Shadow.Push(RELATIVE128);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_PushRelExpand(size_t offset)
|
|
|
|
{
|
|
|
|
//Need to convert to a register
|
2008-02-28 02:16:54 +00:00
|
|
|
|
|
|
|
XMMREGISTER valueRegister = AllocateXmmRegister();
|
|
|
|
m_Assembler.MovssEd(valueRegister,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(offset)));
|
|
|
|
m_Assembler.ShufpsVo(valueRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(valueRegister), 0x00);
|
|
|
|
|
|
|
|
MD_PushReg(valueRegister);
|
2008-02-29 02:43:49 +00:00
|
|
|
}
|
|
|
|
|
2008-03-06 03:14:33 +00:00
|
|
|
void CCodeGen::MD_PushCstExpand(float constant)
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = AllocateXmmRegister();
|
|
|
|
unsigned int tempRegister = AllocateRegister();
|
|
|
|
m_Assembler.MovId(m_nRegisterLookupEx[tempRegister],
|
|
|
|
*reinterpret_cast<uint32*>(&constant));
|
|
|
|
m_Assembler.MovdVo(valueRegister,
|
|
|
|
CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[tempRegister]));
|
|
|
|
m_Assembler.ShufpsVo(valueRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(valueRegister), 0x00);
|
|
|
|
MD_PushReg(valueRegister);
|
|
|
|
FreeRegister(tempRegister);
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_PullRel(size_t offset)
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRegister128>())
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = static_cast<XMMREGISTER>(GetPattern<SingleRegister128>());
|
|
|
|
m_Assembler.MovdquVo(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(offset)),
|
|
|
|
valueRegister);
|
|
|
|
FreeXmmRegister(valueRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_PullRel(size_t offset0, size_t offset1, size_t offset2, size_t offset3)
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRegister128>())
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = static_cast<XMMREGISTER>(GetPattern<SingleRegister128>());
|
|
|
|
|
2008-02-27 02:23:28 +00:00
|
|
|
if(
|
|
|
|
offset0 != SIZE_MAX &&
|
|
|
|
offset1 != SIZE_MAX &&
|
|
|
|
offset2 != SIZE_MAX &&
|
|
|
|
offset3 != SIZE_MAX
|
|
|
|
)
|
|
|
|
{
|
|
|
|
//All elements are non-null
|
|
|
|
if((offset1 == offset0 + 4) && (offset2 == offset1 + 4) && (offset3 == offset2 + 4))
|
|
|
|
{
|
2008-02-29 02:43:49 +00:00
|
|
|
m_Assembler.MovapsVo(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(offset0)),
|
2008-02-27 02:23:28 +00:00
|
|
|
valueRegister);
|
|
|
|
}
|
2008-06-23 01:35:05 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
2008-02-27 02:23:28 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size_t offset[4];
|
|
|
|
uint8 shuffle[4] = { 0x00, 0xE5, 0xEA, 0xFF };
|
|
|
|
|
|
|
|
offset[0] = offset0;
|
|
|
|
offset[1] = offset1;
|
|
|
|
offset[2] = offset2;
|
|
|
|
offset[3] = offset3;
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if(offset[i] != SIZE_MAX)
|
|
|
|
{
|
|
|
|
if(i != 0)
|
|
|
|
{
|
|
|
|
m_Assembler.ShufpsVo(valueRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(valueRegister), shuffle[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Assembler.MovssEd(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(offset[i])),
|
|
|
|
valueRegister);
|
|
|
|
}
|
2008-02-29 02:43:49 +00:00
|
|
|
}
|
2008-02-27 02:23:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FreeXmmRegister(valueRegister);
|
2008-02-29 02:43:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-20 17:26:08 +00:00
|
|
|
void CCodeGen::MD_PullRel(size_t registerId, bool has0, bool has1, bool has2, bool has3)
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
|
|
|
|
uint8 partCount =
|
|
|
|
(has0 ? 1 : 0) +
|
|
|
|
(has1 ? 1 : 0) +
|
|
|
|
(has2 ? 1 : 0) +
|
|
|
|
(has3 ? 1 : 0);
|
|
|
|
|
|
|
|
uint8 lonelySrcPart =
|
|
|
|
(has0 ? 1 : 0) +
|
|
|
|
(has1 ? 2 : 0) +
|
|
|
|
(has2 ? 3 : 0) +
|
|
|
|
(has3 ? 4 : 0) -
|
|
|
|
1;
|
|
|
|
|
|
|
|
uint8 lonelyDstPart =
|
|
|
|
(has0 ? 0 : 1) +
|
|
|
|
(has1 ? 0 : 2) +
|
|
|
|
(has2 ? 0 : 3) +
|
|
|
|
(has3 ? 0 : 4) -
|
|
|
|
1;
|
|
|
|
/*
|
|
|
|
if(FitsPattern<SingleRegister128>())
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = static_cast<XMMREGISTER>(GetPattern<SingleRegister128>());
|
|
|
|
assert(!Register128HasNextUse(valueRegister));
|
|
|
|
|
|
|
|
if(partCount == 4)
|
|
|
|
{
|
|
|
|
m_Assembler.MovapsVo(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(registerId)),
|
|
|
|
valueRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
XMMREGISTER tempRegister = AllocateXmmRegister();
|
|
|
|
m_Assembler.MovapsVo(tempRegister,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(registerId)));
|
|
|
|
//Check if we need to copy either 0 or 1
|
|
|
|
if(has0 || has1)
|
|
|
|
{
|
|
|
|
uint8 mask = (has0 ? 0x00)
|
|
|
|
}
|
|
|
|
m_Assembler.ShufpsVo(tempRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(valueRegister), shuffle[i]);
|
|
|
|
m_Assembler.MovapsVo(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(registerId)),
|
|
|
|
tempRegister);
|
|
|
|
}
|
|
|
|
FreeXmmRegister(tempRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
XMMREGISTER tempRegister = AllocateXmmRegister();
|
|
|
|
if(has3 || has2)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
m_Assembler.MovapsVo(tempRegister,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast<uint32>(registerId)));
|
|
|
|
m_Assembler.ShufpsVo(tempRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(valueRegister), shuffle[i]);
|
|
|
|
FreeXmmRegister(tempRegister);
|
|
|
|
//has0 has1 has2 has3
|
|
|
|
// 0 0 0 0 -> Shouldn't happen
|
|
|
|
// 1 0 0 0 -> res[src0, dst1, dst2, dst3]
|
|
|
|
// 0 1 0 0 -> res[dst0, src1, dst2, dst3]
|
|
|
|
// 0 1 1 0 -> res[dst0, src1, src2, dst3]
|
|
|
|
// 1 1 0 1 -> res[src0, src1, dst2, src3]
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeXmmRegister(valueRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_PushReg(XMMREGISTER registerId)
|
|
|
|
{
|
|
|
|
m_Shadow.Push(registerId);
|
|
|
|
m_Shadow.Push(REGISTER128);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_GenericPackedShift(const PackedShiftFunction& instruction, uint8 amount)
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRelative128>())
|
|
|
|
{
|
|
|
|
SingleRelative128::PatternValue op(GetPattern<SingleRelative128>());
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
LoadRelative128InRegister(resultRegister, op);
|
|
|
|
instruction(resultRegister, amount);
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-16 22:31:37 +00:00
|
|
|
void CCodeGen::MD_GenericOneOperand(const MdTwoOperandFunction& instruction)
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRelative128>())
|
|
|
|
{
|
|
|
|
SingleRelative128::PatternValue op = GetPattern<SingleRelative128>();
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
instruction(resultRegister,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, op));
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else if(FitsPattern<SingleRegister128>())
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = static_cast<XMMREGISTER>(GetPattern<SingleRegister128>());
|
|
|
|
assert(!Register128HasNextUse(valueRegister));
|
|
|
|
instruction(valueRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(valueRegister));
|
|
|
|
MD_PushReg(valueRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_GenericTwoOperand(const MdTwoOperandFunction& instruction)
|
|
|
|
{
|
|
|
|
if(FitsPattern<RelativeRelative128>())
|
|
|
|
{
|
|
|
|
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
LoadRelative128InRegister(resultRegister, ops.first);
|
|
|
|
instruction(resultRegister,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second));
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
2008-06-09 00:06:58 +00:00
|
|
|
else if(FitsPattern<RegisterRegister128>())
|
|
|
|
{
|
|
|
|
RegisterRegister128::PatternValue ops(GetPattern<RegisterRegister128>());
|
|
|
|
XMMREGISTER resultRegister;
|
|
|
|
XMMREGISTER dstRegister = static_cast<XMMREGISTER>(ops.first);
|
|
|
|
XMMREGISTER srcRegister = static_cast<XMMREGISTER>(ops.second);
|
|
|
|
if(!Register128HasNextUse(dstRegister))
|
|
|
|
{
|
|
|
|
resultRegister = dstRegister;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
resultRegister = AllocateXmmRegister();
|
|
|
|
}
|
|
|
|
instruction(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(srcRegister));
|
|
|
|
if(!Register128HasNextUse(srcRegister))
|
|
|
|
{
|
|
|
|
FreeXmmRegister(srcRegister);
|
|
|
|
}
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
2008-02-29 02:43:49 +00:00
|
|
|
else if(FitsPattern<RelativeRegister128>())
|
|
|
|
{
|
|
|
|
RelativeRegister128::PatternValue ops(GetPattern<RelativeRegister128>());
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = static_cast<XMMREGISTER>(ops.second);
|
|
|
|
LoadRelative128InRegister(resultRegister, ops.first);
|
|
|
|
instruction(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(valueRegister));
|
|
|
|
if(!Register128HasNextUse(valueRegister))
|
|
|
|
{
|
|
|
|
FreeXmmRegister(valueRegister);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_GenericTwoOperandReversed(const MdTwoOperandFunction& instruction)
|
|
|
|
{
|
|
|
|
if(FitsPattern<RelativeRelative128>())
|
|
|
|
{
|
|
|
|
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
LoadRelative128InRegister(resultRegister, ops.second);
|
|
|
|
instruction(resultRegister,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first));
|
|
|
|
MD_PushReg(resultRegister);
|
2008-04-04 01:50:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_AbsS()
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRelative128>())
|
|
|
|
{
|
|
|
|
SingleRelative128::PatternValue op(GetPattern<SingleRelative128>());
|
|
|
|
XMMREGISTER maskRegister = AllocateXmmRegister();
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
|
|
|
|
LoadRelative128InRegister(resultRegister, op);
|
|
|
|
|
|
|
|
m_Assembler.PcmpeqdVo(maskRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(maskRegister));
|
|
|
|
m_Assembler.PsrldVo(maskRegister, 1);
|
|
|
|
|
|
|
|
m_Assembler.PandVo(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(maskRegister));
|
|
|
|
|
|
|
|
FreeXmmRegister(maskRegister);
|
|
|
|
MD_PushReg(resultRegister);
|
2008-02-29 02:43:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_AddH()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PaddwVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-03-08 15:51:03 +00:00
|
|
|
void CCodeGen::MD_AddWSS()
|
|
|
|
{
|
|
|
|
if(FitsPattern<RelativeRelative128>())
|
|
|
|
{
|
|
|
|
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
|
|
|
|
{
|
|
|
|
unsigned int tempRegister = AllocateRegister();
|
|
|
|
unsigned int positiveValueRegister = AllocateRegister();
|
|
|
|
unsigned int negativeValueRegister = AllocateRegister();
|
|
|
|
|
|
|
|
//Prepare registers
|
|
|
|
m_Assembler.MovId(m_nRegisterLookupEx[positiveValueRegister],
|
|
|
|
0x7FFFFFFF);
|
|
|
|
m_Assembler.MovId(m_nRegisterLookupEx[negativeValueRegister],
|
|
|
|
0x80000000);
|
|
|
|
for(int i = 3; i >= 0; i--)
|
|
|
|
{
|
|
|
|
CX86Assembler::LABEL doneLabel = m_Assembler.CreateLabel();
|
|
|
|
m_Assembler.MovEd(m_nRegisterLookupEx[tempRegister],
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first + (i * 4)));
|
|
|
|
m_Assembler.AddEd(m_nRegisterLookupEx[tempRegister],
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second + (i * 4)));
|
|
|
|
m_Assembler.JnoJb(doneLabel);
|
|
|
|
m_Assembler.CmovsEd(m_nRegisterLookupEx[tempRegister],
|
|
|
|
CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[negativeValueRegister]));
|
|
|
|
m_Assembler.CmovnsEd(m_nRegisterLookupEx[tempRegister],
|
|
|
|
CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[positiveValueRegister]));
|
|
|
|
m_Assembler.MarkLabel(doneLabel);
|
|
|
|
m_Assembler.Push(m_nRegisterLookupEx[tempRegister]);
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeRegister(tempRegister);
|
|
|
|
FreeRegister(positiveValueRegister);
|
|
|
|
FreeRegister(negativeValueRegister);
|
|
|
|
}
|
|
|
|
m_Assembler.ResolveLabelReferences();
|
|
|
|
m_Assembler.MovdquVo(resultRegister,
|
|
|
|
CX86Assembler::MakeIndRegAddress(CX86Assembler::rSP));
|
|
|
|
m_Assembler.AddId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP),
|
|
|
|
0x10);
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_AddWUS()
|
|
|
|
{
|
|
|
|
if(FitsPattern<RelativeRelative128>())
|
|
|
|
{
|
|
|
|
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
|
|
|
unsigned int tempRegister = AllocateRegister();
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
for(int i = 3; i >= 0; i--)
|
|
|
|
{
|
|
|
|
CX86Assembler::LABEL overflowLabel = m_Assembler.CreateLabel();
|
|
|
|
CX86Assembler::LABEL doneLabel = m_Assembler.CreateLabel();
|
|
|
|
m_Assembler.MovEd(m_nRegisterLookupEx[tempRegister],
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first + (i * 4)));
|
|
|
|
m_Assembler.AddEd(m_nRegisterLookupEx[tempRegister],
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second + (i * 4)));
|
|
|
|
m_Assembler.JcJb(overflowLabel);
|
|
|
|
m_Assembler.PushEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[tempRegister]));
|
|
|
|
m_Assembler.JmpJb(doneLabel);
|
|
|
|
m_Assembler.MarkLabel(overflowLabel);
|
|
|
|
m_Assembler.PushId(0xFFFFFFFF);
|
|
|
|
m_Assembler.MarkLabel(doneLabel);
|
|
|
|
}
|
|
|
|
FreeRegister(tempRegister);
|
|
|
|
m_Assembler.ResolveLabelReferences();
|
|
|
|
m_Assembler.MovdquVo(resultRegister,
|
|
|
|
CX86Assembler::MakeIndRegAddress(CX86Assembler::rSP));
|
|
|
|
m_Assembler.AddId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP),
|
|
|
|
0x10);
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_AddS()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::AddpsVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_And()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PandVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-03-16 22:31:37 +00:00
|
|
|
void CCodeGen::MD_CmpEqW()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PcmpeqdVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_CmpGtH()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PcmpgtwVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-06-09 00:06:58 +00:00
|
|
|
void CCodeGen::MD_DivS()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::DivpsVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_IsNegative()
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRegister128>())
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = static_cast<XMMREGISTER>(GetPattern<SingleRegister128>());
|
|
|
|
XMMREGISTER resultRegister;
|
|
|
|
if(Register128HasNextUse(valueRegister))
|
|
|
|
{
|
|
|
|
resultRegister = AllocateXmmRegister();
|
|
|
|
CopyRegister128(resultRegister, valueRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
resultRegister = valueRegister;
|
|
|
|
}
|
|
|
|
XMMREGISTER maskRegister = AllocateXmmRegister();
|
|
|
|
m_Assembler.PcmpeqdVo(maskRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(maskRegister));
|
|
|
|
m_Assembler.PslldVo(maskRegister, 31);
|
|
|
|
m_Assembler.PandVo(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(maskRegister));
|
|
|
|
FreeXmmRegister(maskRegister);
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_IsZero()
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRegister128>())
|
|
|
|
{
|
|
|
|
XMMREGISTER valueRegister = static_cast<XMMREGISTER>(GetPattern<SingleRegister128>());
|
|
|
|
XMMREGISTER resultRegister;
|
|
|
|
if(Register128HasNextUse(valueRegister))
|
|
|
|
{
|
|
|
|
resultRegister = AllocateXmmRegister();
|
|
|
|
CopyRegister128(resultRegister, valueRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
resultRegister = valueRegister;
|
|
|
|
}
|
|
|
|
XMMREGISTER zeroRegister = AllocateXmmRegister();
|
|
|
|
m_Assembler.PandnVo(zeroRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(zeroRegister));
|
|
|
|
m_Assembler.PcmpeqdVo(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(zeroRegister));
|
|
|
|
FreeXmmRegister(zeroRegister);
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_MaxH()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PmaxswVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-03-15 16:20:36 +00:00
|
|
|
void CCodeGen::MD_MaxS()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::MaxpsVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_MinH()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PminswVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-03-15 16:20:36 +00:00
|
|
|
void CCodeGen::MD_MinS()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::MinpsVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_MulS()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::MulpsVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_Not()
|
|
|
|
{
|
|
|
|
if(FitsPattern<SingleRegister128>())
|
|
|
|
{
|
|
|
|
XMMREGISTER resultRegister(static_cast<XMMREGISTER>(GetPattern<SingleRegister128>()));
|
|
|
|
assert(!Register128HasNextUse(resultRegister));
|
|
|
|
XMMREGISTER tempRegister = AllocateXmmRegister();
|
|
|
|
m_Assembler.PcmpeqdVo(tempRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(tempRegister));
|
|
|
|
m_Assembler.PxorVo(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(tempRegister));
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_Or()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PorVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_PackHB()
|
|
|
|
{
|
|
|
|
if(FitsPattern<RelativeRelative128>())
|
|
|
|
{
|
|
|
|
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
XMMREGISTER tempRegister = AllocateXmmRegister();
|
|
|
|
XMMREGISTER maskRegister = AllocateXmmRegister();
|
|
|
|
LoadRelative128InRegister(resultRegister, ops.second);
|
|
|
|
LoadRelative128InRegister(tempRegister, ops.first);
|
|
|
|
|
|
|
|
//Generate mask (0x00FF x8)
|
|
|
|
m_Assembler.PcmpeqdVo(maskRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(maskRegister));
|
|
|
|
m_Assembler.PsrlwVo(maskRegister, 0x08);
|
|
|
|
|
|
|
|
//Mask both operands
|
|
|
|
m_Assembler.PandVo(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(maskRegister));
|
|
|
|
m_Assembler.PandVo(tempRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(maskRegister));
|
|
|
|
|
|
|
|
//Pack
|
2008-03-16 22:31:37 +00:00
|
|
|
m_Assembler.PackuswbVo(resultRegister,
|
2008-02-29 02:43:49 +00:00
|
|
|
CX86Assembler::MakeXmmRegisterAddress(tempRegister));
|
|
|
|
|
|
|
|
FreeXmmRegister(maskRegister);
|
|
|
|
FreeXmmRegister(tempRegister);
|
|
|
|
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-16 22:31:37 +00:00
|
|
|
void CCodeGen::MD_PackWH()
|
|
|
|
{
|
|
|
|
if(FitsPattern<RelativeRelative128>())
|
|
|
|
{
|
|
|
|
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
XMMREGISTER tempRegister = AllocateXmmRegister();
|
|
|
|
LoadRelative128InRegister(resultRegister, ops.second);
|
|
|
|
LoadRelative128InRegister(tempRegister, ops.first);
|
|
|
|
|
|
|
|
//Sign extend the lower half word of our registers
|
|
|
|
m_Assembler.PslldVo(resultRegister, 0x10);
|
|
|
|
m_Assembler.PsradVo(resultRegister, 0x10);
|
|
|
|
|
|
|
|
m_Assembler.PslldVo(tempRegister, 0x10);
|
|
|
|
m_Assembler.PsradVo(tempRegister, 0x10);
|
|
|
|
|
|
|
|
//Pack
|
|
|
|
m_Assembler.PackssdwVo(resultRegister,
|
|
|
|
CX86Assembler::MakeXmmRegisterAddress(tempRegister));
|
|
|
|
|
|
|
|
FreeXmmRegister(tempRegister);
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw exception();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_SllH(uint8 amount)
|
|
|
|
{
|
|
|
|
MD_GenericPackedShift(bind(&CX86Assembler::PsllwVo, &m_Assembler, _1, _2), amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_SraH(uint8 amount)
|
|
|
|
{
|
|
|
|
MD_GenericPackedShift(bind(&CX86Assembler::PsrawVo, &m_Assembler, _1, _2), amount);
|
|
|
|
}
|
|
|
|
|
2008-06-09 00:06:58 +00:00
|
|
|
void CCodeGen::MD_SraW(uint8 amount)
|
|
|
|
{
|
|
|
|
MD_GenericPackedShift(bind(&CX86Assembler::PsradVo, &m_Assembler, _1, _2), amount);
|
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_SrlH(uint8 amount)
|
|
|
|
{
|
|
|
|
MD_GenericPackedShift(bind(&CX86Assembler::PsrlwVo, &m_Assembler, _1, _2), amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_Srl256()
|
|
|
|
{
|
|
|
|
if(m_Shadow.Pull() != RELATIVE) assert(0);
|
|
|
|
uint32 shiftAmount = m_Shadow.Pull();
|
|
|
|
if(m_Shadow.Pull() != RELATIVE128) assert(0);
|
|
|
|
uint32 operand2 = m_Shadow.Pull();
|
|
|
|
if(m_Shadow.Pull() != RELATIVE128) assert(0);
|
|
|
|
uint32 operand1 = m_Shadow.Pull();
|
|
|
|
|
|
|
|
assert(m_nRegisterAllocated[1] == false); //eCX
|
|
|
|
assert(m_nRegisterAllocated[4] == false); //eSI
|
|
|
|
assert(m_nRegisterAllocated[5] == false); //eDI
|
|
|
|
|
|
|
|
XMMREGISTER resultRegister = AllocateXmmRegister();
|
|
|
|
|
|
|
|
//Copy both registers on the stack
|
|
|
|
//-----------------------------
|
|
|
|
m_Assembler.SubId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), 0x30);
|
|
|
|
m_Assembler.MovGd(CX86Assembler::MakeRegisterAddress(CX86Assembler::rDI), CX86Assembler::rSP);
|
|
|
|
m_Assembler.LeaGd(CX86Assembler::rSI, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, operand2));
|
|
|
|
m_Assembler.MovId(CX86Assembler::rCX, 0x10);
|
|
|
|
m_Assembler.RepMovsb();
|
|
|
|
m_Assembler.LeaGd(CX86Assembler::rSI, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, operand1));
|
|
|
|
m_Assembler.MovId(CX86Assembler::rCX, 0x10);
|
|
|
|
m_Assembler.RepMovsb();
|
|
|
|
|
|
|
|
//Setup SA
|
|
|
|
//-----------------------------
|
|
|
|
m_Assembler.MovEd(CX86Assembler::rAX, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, shiftAmount));
|
|
|
|
m_Assembler.AndId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX), 0x7F);
|
|
|
|
m_Assembler.ShrEd(CX86Assembler::MakeRegisterAddress(CX86Assembler::rAX), 0x03);
|
|
|
|
|
|
|
|
//Setup ESI
|
|
|
|
//-----------------------------
|
|
|
|
m_Assembler.LeaGd(CX86Assembler::rSI,
|
|
|
|
CX86Assembler::MakeBaseIndexScaleAddress(CX86Assembler::rSP, CX86Assembler::rAX, 1));
|
|
|
|
|
|
|
|
//Setup ECX
|
|
|
|
//-----------------------------
|
|
|
|
m_Assembler.MovId(CX86Assembler::rCX, 0x10);
|
|
|
|
|
|
|
|
//Generate result
|
|
|
|
//-----------------------------
|
|
|
|
m_Assembler.RepMovsb();
|
|
|
|
|
|
|
|
//Load result and free Stack
|
|
|
|
//-----------------------------
|
|
|
|
m_Assembler.MovdquVo(resultRegister,
|
|
|
|
CX86Assembler::MakeIndRegOffAddress(CX86Assembler::rSP, 0x20));
|
|
|
|
m_Assembler.AddId(CX86Assembler::MakeRegisterAddress(CX86Assembler::rSP), 0x30);
|
|
|
|
|
|
|
|
MD_PushReg(resultRegister);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_SubB()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PsubbVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_SubW()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PsubdVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_SubS()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::SubpsVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-03-16 22:31:37 +00:00
|
|
|
void CCodeGen::MD_ToSingle()
|
|
|
|
{
|
|
|
|
MD_GenericOneOperand(bind(&CX86Assembler::Cvtdq2psVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
2008-03-06 03:14:33 +00:00
|
|
|
void CCodeGen::MD_ToWordTruncate()
|
|
|
|
{
|
2008-03-16 22:31:37 +00:00
|
|
|
MD_GenericOneOperand(bind(&CX86Assembler::Cvttps2dqVo, m_Assembler, _1, _2));
|
2008-03-06 03:14:33 +00:00
|
|
|
}
|
|
|
|
|
2008-02-29 02:43:49 +00:00
|
|
|
void CCodeGen::MD_UnpackLowerBH()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperandReversed(bind(&CX86Assembler::PunpcklbwVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_UnpackLowerHW()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperandReversed(bind(&CX86Assembler::PunpcklwdVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_UnpackLowerWD()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperandReversed(bind(&CX86Assembler::PunpckldqVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_UnpackUpperBH()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperandReversed(bind(&CX86Assembler::PunpckhbwVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_UnpackUpperWD()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperandReversed(bind(&CX86Assembler::PunpckhdqVo, m_Assembler, _1, _2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCodeGen::MD_Xor()
|
|
|
|
{
|
|
|
|
MD_GenericTwoOperand(bind(&CX86Assembler::PxorVo, m_Assembler, _1, _2));
|
|
|
|
}
|