uint32_t TR::AMD64FPConversionSnippet::getLength(int32_t estimatedSnippetStart) { // *this swipeable for debugging purposes uint32_t length = 11; TR::Machine *machine = cg()->machine(); if (toRealRegister(_convertInstruction->getTargetRegister())->getRegisterNumber() != TR::RealRegister::eax) { // MOV R, rax // XCHG R, rax // // 3 instruction/modRM bytes + 2 REX prefixes // length += (3 + 2); } TR::X86RegRegInstruction *instr = _convertInstruction->getIA32RegRegInstruction(); TR_ASSERT(instr != NULL, "f2i conversion instruction must be either L4RegMem or CVTTSS2SIRegReg\n"); TR::RealRegister *sourceRegister = toRealRegister(instr->getSourceRegister()); if (sourceRegister->getRegisterNumber() != TR::RealRegister::xmm0) { length += sizeof(pushBinary) + sizeof(popBinary) // push and pop + 4 + (sourceRegister->rexBits(TR::RealRegister::REX_B, false)? 1 : 0) // MOVSD xmm0, source ; } return length + estimateRestartJumpLength(estimatedSnippetStart + length); }
uint8_t *TR::AMD64FPConversionSnippet::genFPConversion(uint8_t *buffer) { // *this swipeable for debugging purposes // This didn't end up as clean as I thought. TODO:AMD64: Separate out the 64-bit code into another class. TR::ILOpCodes opCode = _convertInstruction->getNode()->getOpCodeValue(); TR::RealRegister *targetRegister = toRealRegister(_convertInstruction->getTargetRegister()); TR::RealRegister::RegNum targetReg = targetRegister->getRegisterNumber(); TR::Machine *machine = cg()->machine(); const TR::X86LinkageProperties &properties = cg()->getProperties(); uint8_t *originalBuffer = buffer; TR_ASSERT(properties.getIntegerReturnRegister() == TR::RealRegister::eax, "Only support integer return in eax"); if (targetReg != TR::RealRegister::eax) { // MOV R, rax // *buffer++ = TR::RealRegister::REX | TR::RealRegister::REX_W | targetRegister->rexBits(TR::RealRegister::REX_R, false); *buffer++ = 0x8b; *buffer = 0xc0; targetRegister->setRegisterFieldInModRM(buffer); buffer++; } TR_ASSERT(properties.getFloatArgumentRegister(0) == TR::RealRegister::xmm0, "Only support 1st FP arg in xmm0"); TR::X86RegRegInstruction *instr = _convertInstruction->getIA32RegRegInstruction(); TR_ASSERT(instr != NULL, "conversion instruction must be CVTTSS2SIRegReg\n"); TR::RealRegister *sourceRegister = toRealRegister(instr->getSourceRegister()); TR::RealRegister::RegNum sourceReg = sourceRegister->getRegisterNumber(); // Save xmm0 if necessary // if (sourceReg != TR::RealRegister::xmm0) { TR_ASSERT(TR::Compiler->target.is64Bit(), "This push sequence only works on AMD64"); memcpy(buffer, pushBinary, sizeof(pushBinary)); buffer += sizeof(pushBinary); // MOVSD xmm0, source // *buffer++ = 0xf2; if( (*buffer = sourceRegister->rexBits(TR::RealRegister::REX_B, false)) ) buffer++; *buffer++ = 0x0f; *buffer++ = 0x10; *buffer = 0xc0; sourceRegister->setRegisterFieldInOpcode(buffer); buffer++; } // Call the helper // buffer = emitCallToConversionHelper(buffer); // Restore xmm0 if necessary // if (sourceReg != TR::RealRegister::xmm0) { TR_ASSERT(TR::Compiler->target.is64Bit(), "This pop sequence only works on AMD64"); memcpy(buffer, popBinary, sizeof(popBinary)); buffer += sizeof(popBinary); } if (targetReg != TR::RealRegister::eax) { // XCHG R, rax // *buffer++ = TR::RealRegister::REX | TR::RealRegister::REX_W | targetRegister->rexBits(TR::RealRegister::REX_B, false); *buffer = 0x90; targetRegister->setRegisterFieldInOpcode(buffer); buffer++; } return buffer; }