#include "CodeGen.h" #include "CodeGen_StackPatterns.h" using namespace std; bool CCodeGen::RegisterFpSingleHasNextUse(XMMREGISTER registerId) { unsigned int nCount = m_Shadow.GetCount(); for(unsigned int i = 0; i < nCount; i += 2) { if(m_Shadow.GetAt(i) == FP_SINGLE_REGISTER) { if(m_Shadow.GetAt(i + 1) == registerId) return true; } } return false; } void CCodeGen::FP_PushSingleReg(XMMREGISTER registerId) { m_Shadow.Push(registerId); m_Shadow.Push(FP_SINGLE_REGISTER); } void CCodeGen::FP_PushSingle(size_t offset) { m_Shadow.Push(static_cast(offset)); m_Shadow.Push(FP_SINGLE_RELATIVE); } void CCodeGen::FP_LoadSingleRelativeInRegister(XMMREGISTER destination, uint32 source) { m_Assembler.MovssEd(destination, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, source)); } void CCodeGen::FP_PushWord(size_t offset) { XMMREGISTER resultRegister = AllocateXmmRegister(); m_Assembler.Cvtsi2ssEd(resultRegister, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast(offset))); FP_PushSingleReg(resultRegister); } void CCodeGen::FP_PullSingle(size_t offset) { if(FitsPattern()) { XMMREGISTER valueRegister = static_cast(GetPattern()); m_Assembler.MovssEd(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast(offset)), valueRegister); FreeXmmRegister(valueRegister); } else { assert(0); } } void CCodeGen::FP_PullWordTruncate(size_t offset) { if(FitsPattern()) { SingleFpSingleRelative::PatternValue op = GetPattern(); unsigned int valueRegister = AllocateRegister(); m_Assembler.Cvttss2siEd(m_nRegisterLookupEx[valueRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, op)); m_Assembler.MovGd(CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, static_cast(offset)), m_nRegisterLookupEx[valueRegister]); FreeRegister(valueRegister); } else { assert(0); } } CCodeGen::XMMREGISTER CCodeGen::FP_GetResultRegister(uint32 registerId) { XMMREGISTER destRegister = static_cast(registerId); XMMREGISTER resultRegister; if(!RegisterFpSingleHasNextUse(destRegister)) { resultRegister = destRegister; } else { resultRegister = AllocateXmmRegister(); CopyRegister128(resultRegister, destRegister); } return resultRegister; } void CCodeGen::FP_GenericOneOperand(const MdTwoOperandFunction& instruction) { if(FitsPattern()) { SingleFpSingleRelative::PatternValue op = GetPattern(); XMMREGISTER resultRegister = AllocateXmmRegister(); instruction(resultRegister, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, op)); FP_PushSingleReg(resultRegister); } else if(FitsPattern()) { SingleFpSingleRegister::PatternValue op = GetPattern(); XMMREGISTER resultRegister = FP_GetResultRegister(op); XMMREGISTER sourceRegister = static_cast(op); instruction(resultRegister, CX86Assembler::MakeXmmRegisterAddress(sourceRegister)); FP_PushSingleReg(resultRegister); } else { throw runtime_error("Not implemented."); } } void CCodeGen::FP_GenericTwoOperand(const MdTwoOperandFunction& instruction) { if(FitsPattern()) { DualFpSingleRelative::PatternValue ops = GetPattern(); XMMREGISTER resultRegister = AllocateXmmRegister(); FP_LoadSingleRelativeInRegister(resultRegister, ops.first); instruction(resultRegister, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second)); FP_PushSingleReg(resultRegister); } else if(FitsPattern()) { FpSingleRelativeRegister::PatternValue ops = GetPattern(); XMMREGISTER resultRegister = AllocateXmmRegister(); { XMMREGISTER sourceRegister = static_cast(ops.second); FP_LoadSingleRelativeInRegister(resultRegister, ops.first); instruction(resultRegister, CX86Assembler::MakeXmmRegisterAddress(sourceRegister)); if(!RegisterFpSingleHasNextUse(sourceRegister)) { FreeXmmRegister(sourceRegister); } } FP_PushSingleReg(resultRegister); } else if(FitsPattern()) { DualFpSingleRegister::PatternValue ops = GetPattern(); XMMREGISTER resultRegister = FP_GetResultRegister(ops.first); { XMMREGISTER sourceRegister = static_cast(ops.second); instruction(resultRegister, CX86Assembler::MakeXmmRegisterAddress(sourceRegister)); if(!RegisterFpSingleHasNextUse(sourceRegister)) { FreeXmmRegister(sourceRegister); } } FP_PushSingleReg(resultRegister); } else { throw exception(); } } void CCodeGen::FP_CmpHelper(XMMREGISTER dst, const CX86Assembler::CAddress& src, CCodeGen::CONDITION condition) { CX86Assembler::SSE_CMP_TYPE conditionCode; switch(condition) { case CONDITION_EQ: conditionCode = CX86Assembler::SSE_CMP_EQ; break; case CONDITION_BL: conditionCode = CX86Assembler::SSE_CMP_LT; break; case CONDITION_BE: conditionCode = CX86Assembler::SSE_CMP_LE; break; case CONDITION_AB: conditionCode = CX86Assembler::SSE_CMP_NLE; break; default: assert(0); break; } unsigned int resultRegister = AllocateRegister(); assert(!RegisterFpSingleHasNextUse(dst)); m_Assembler.CmpssEd(dst, src, conditionCode); //Can't move directly to register using MOVSS, so we use CVTTSS2SI //0x00000000 -- CVT -> zero //0xFFFFFFFF -- CVT -> not zero m_Assembler.Cvttss2siEd(m_nRegisterLookupEx[resultRegister], CX86Assembler::MakeXmmRegisterAddress(dst)); PushReg(resultRegister); } void CCodeGen::FP_GenericNeg(XMMREGISTER dst, const CX86Assembler::CAddress& src) { XMMREGISTER zeroRegister = AllocateXmmRegister(); m_Assembler.PxorVo(zeroRegister, CX86Assembler::MakeXmmRegisterAddress(zeroRegister)); m_Assembler.SubssEd(zeroRegister, src); CopyRegister128(dst, zeroRegister); FreeXmmRegister(zeroRegister); } void CCodeGen::FP_Add() { FP_GenericTwoOperand(bind(&CX86Assembler::AddssEd, m_Assembler, _1, _2)); } void CCodeGen::FP_Abs() { if(FitsPattern()) { SingleFpSingleRelative::PatternValue op = GetPattern(); XMMREGISTER resultRegister = AllocateXmmRegister(); unsigned int tempRegister = AllocateRegister(); m_Assembler.MovId(m_nRegisterLookupEx[tempRegister], 0x7FFFFFFF); m_Assembler.AndEd(m_nRegisterLookupEx[tempRegister], CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, op)); m_Assembler.MovdVo(resultRegister, CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[tempRegister])); FreeRegister(tempRegister); FP_PushSingleReg(resultRegister); } else { throw runtime_error("Not implemented."); } } void CCodeGen::FP_Sub() { FP_GenericTwoOperand(bind(&CX86Assembler::SubssEd, m_Assembler, _1, _2)); } void CCodeGen::FP_Mul() { FP_GenericTwoOperand(bind(&CX86Assembler::MulssEd, m_Assembler, _1, _2)); } void CCodeGen::FP_Div() { FP_GenericTwoOperand(bind(&CX86Assembler::DivssEd, m_Assembler, _1, _2)); } void CCodeGen::FP_Cmp(CCodeGen::CONDITION condition) { //Compare second - first if(FitsPattern()) { DualFpSingleRelative::PatternValue ops = GetPattern(); XMMREGISTER tempResultRegister = AllocateXmmRegister(); FP_LoadSingleRelativeInRegister(tempResultRegister, ops.second); FP_CmpHelper(tempResultRegister, CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first), condition); FreeXmmRegister(tempResultRegister); } else if(FitsPattern()) { FpSingleConstantRegister::PatternValue ops = GetPattern(); XMMREGISTER tempRegister = AllocateXmmRegister(); XMMREGISTER dstRegister = static_cast(ops.second); if(ops.first == 0) { m_Assembler.PxorVo(tempRegister, CX86Assembler::MakeXmmRegisterAddress(tempRegister)); } else { throw runtime_error("Not zero constant."); } FP_CmpHelper(dstRegister, CX86Assembler::MakeXmmRegisterAddress(tempRegister), condition); //Free registers FreeXmmRegister(tempRegister); if(!RegisterFpSingleHasNextUse(dstRegister)) { FreeXmmRegister(dstRegister); } } else if(FitsPattern()) { FpSingleRegisterRelative::PatternValue ops = GetPattern(); XMMREGISTER tempResultRegister = AllocateXmmRegister(); XMMREGISTER sourceRegister = static_cast(ops.first); FP_LoadSingleRelativeInRegister(tempResultRegister, ops.second); FP_CmpHelper(tempResultRegister, CX86Assembler::MakeXmmRegisterAddress(sourceRegister), condition); FreeXmmRegister(tempResultRegister); if(!RegisterFpSingleHasNextUse(sourceRegister)) { FreeXmmRegister(sourceRegister); } } else { throw runtime_error("Not implemented."); } } void CCodeGen::FP_Neg() { FP_GenericOneOperand(bind(&CCodeGen::FP_GenericNeg, this, _1, _2)); } void CCodeGen::FP_Rcpl() { FP_GenericOneOperand(bind(&CX86Assembler::RcpssEd, m_Assembler, _1, _2)); } void CCodeGen::FP_Sqrt() { FP_GenericOneOperand(bind(&CX86Assembler::SqrtssEd, m_Assembler, _1, _2)); } void CCodeGen::FP_Rsqrt() { FP_GenericOneOperand(bind(&CX86Assembler::RsqrtssEd, m_Assembler, _1, _2)); }