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; }
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; }