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::X86FPConvertToIntSnippet::genFPConversion(uint8_t *buffer) { TR::ILOpCodes opcode = _convertInstruction->getNode()->getOpCodeValue(); TR::RealRegister *targetRegister = toRealRegister(_convertInstruction->getTargetRegister()); TR::RealRegister::RegNum targetReg = targetRegister->getRegisterNumber(); TR::Machine *machine = cg()->machine(); TR_ASSERT(cg()->getProperties().getIntegerReturnRegister() == TR::RealRegister::eax, "Only support integer return in eax"); if (targetReg != TR::RealRegister::eax) { // MOV R, eax // *buffer++ = 0x8b; *buffer = 0xc0; targetRegister->setRegisterFieldInModRM(buffer); buffer++; } // Push the floating-point value on to the stack before calling the helper. // // SUB esp, 4/8 // *buffer++ = 0x83; *buffer++ = 0xec; if (opcode == TR::f2i) *buffer++ = 0x04; else *buffer++ = 0x08; if (_convertInstruction->getIA32RegMemInstruction()) { // FST [esp], st0 // if (opcode == TR::f2i) *buffer++ = 0xd9; else *buffer++ = 0xdd; *buffer++ = 0x14; *buffer++ = 0x24; } else { 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()); // MOVSS/MOVSD [esp], source // if (opcode == TR::f2i) *buffer++ = 0xf3; else *buffer++ = 0xf2; *buffer++ = 0x0f; *buffer++ = 0x11; *buffer = 0x04; sourceRegister->setRegisterFieldInModRM(buffer); buffer++; *buffer++ = 0x24; } // Call the helper // buffer = emitCallToConversionHelper(buffer); // ADD esp, 4/8 // *buffer++ = 0x83; *buffer++ = 0xc4; if (opcode == TR::f2i) *buffer++ = 0x04; else *buffer++ = 0x08; if (targetReg != TR::RealRegister::eax) { // XCHG R, eax // *buffer = 0x90; targetRegister->setRegisterFieldInOpcode(buffer); buffer++; } return buffer; }
void TR_Debug::print(TR::FILE *pOutFile, TR::X86FPConvertToIntSnippet * snippet) { if (pOutFile == NULL) return; uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation(); printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet)); TR::RealRegister *targetRegister = toRealRegister(snippet->getConvertInstruction()->getTargetRegister()); uint8_t reg = targetRegister->getRegisterNumber(); if (reg != TR::RealRegister::eax) { printPrefix(pOutFile, NULL, bufferPos, 2); trfprintf(pOutFile, "mov\t"); print(pOutFile, targetRegister, TR_WordReg); trfprintf(pOutFile, ", eax\t\t%s preserve helper return reg", commentString()); bufferPos += 2; } printPrefix(pOutFile, NULL, bufferPos, 3); trfprintf(pOutFile, "sub\tesp, 4\t\t%s push parameter", commentString()); bufferPos += 3; TR::X86RegRegInstruction *instr = snippet->getConvertInstruction()->getIA32RegRegInstruction(); if (instr) { printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "movss\t dword ptr [esp], "); print(pOutFile, toRealRegister(instr->getSourceRegister()), TR_QuadWordReg); bufferPos += 5; } else { printPrefix(pOutFile, NULL, bufferPos, 3); trfprintf(pOutFile, "fst\tdword ptr [esp]"); bufferPos += 3; } printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "call\t%s", getName(snippet->getHelperSymRef())); bufferPos += 5; printPrefix(pOutFile, NULL, bufferPos, 3); trfprintf(pOutFile, "add\tesp, 4\t\t%s pop parameter", commentString()); bufferPos += 3; if (reg != TR::RealRegister::eax) { printPrefix(pOutFile, NULL, bufferPos, 1); trfprintf(pOutFile, "xchg\teax, "); print(pOutFile, targetRegister, TR_WordReg); trfprintf(pOutFile, "\t\t%s restore eax", commentString()); bufferPos++; } printRestartJump(pOutFile, snippet, bufferPos); }
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; }