uint8_t *TR::X86FPConversionSnippet::emitCallToConversionHelper(uint8_t *buffer) { intptrj_t callInstructionAddress = (intptrj_t)buffer; intptrj_t nextInstructionAddress = callInstructionAddress+5; *buffer++ = 0xe8; // CallImm4 intptrj_t helperAddress = (intptrj_t)getHelperSymRef()->getMethodAddress(); if (cg()->directCallRequiresTrampoline(helperAddress, callInstructionAddress)) { helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(getHelperSymRef()->getReferenceNumber(), (void *)buffer); TR_ASSERT_FATAL(TR::Compiler->target.cpu.isTargetWithinRIPRange(helperAddress, nextInstructionAddress), "Local helper trampoline must be reachable directly"); } *(int32_t *)buffer = (int32_t)(helperAddress - nextInstructionAddress); cg()->addProjectSpecializedRelocation(buffer, (uint8_t *)getHelperSymRef(), NULL, TR_HelperAddress, __FILE__, __LINE__, getNode()); buffer += 4; gcMap().registerStackMap(buffer, cg()); return buffer; }
uint32_t TR::S390HelperCallSnippet::getLength(int32_t) { uint32_t length; TR::SymbolReference * helperSymRef = getHelperSymRef(); // LARL + BRASL/BRCL length = 12; if (helperSymRef == cg()->symRefTab()->element(TR_induceOSRAtCurrentPC)) { length += TR::S390CallSnippet::instructionCountForArguments(getNode(), cg()); } length += getLoadVMThreadInstructionLength(cg()); length += getRuntimeInstrumentationOnOffInstructionLength(cg()); return length; }
uint8_t * TR::S390HelperCallSnippet::emitSnippetBody() { uint8_t * cursor = cg()->getBinaryBufferCursor(); getSnippetLabel()->setCodeLocation(cursor); TR::Node * callNode = getNode(); TR::SymbolReference * helperSymRef = getHelperSymRef(); bool jitInduceOSR = helperSymRef == cg()->symRefTab()->element(TR_induceOSRAtCurrentPC); if (jitInduceOSR) { // Flush in-register arguments back to the stack for interpreter cursor = TR::S390CallSnippet::S390flushArgumentsToStack(cursor, callNode, getSizeOfArguments(), cg()); } uint32_t rEP = (uint32_t) cg()->getEntryPointRegister() - 1; //load vm thread into gpr13 cursor = generateLoadVMThreadInstruction(cg(), cursor); // Generate RIOFF if RI is supported. cursor = generateRuntimeInstrumentationOnOffInstruction(cg(), cursor, TR::InstOpCode::RIOFF); if ( // Methods that require alwaysExcept()) // R14 to point to snippet: { // For trace method entry/exit, we need to set up R14 to point to the // beginning of the data segment. We will use BRASL to automatically // set R14 correctly. // For methods that lead to exceptions, and never return to the // main code, we set up R14, so that if GC occurs, the stackwalker // will see R14 is pointing to this snippet, and pick up the correct // stack map. *(int16_t *) cursor = 0xC0E5; // BRASL R14, <Helper Addr> cursor += sizeof(int16_t); } else // Otherwise: { // We're not sure if the helper will return. So, we need to provide // the return addr of the main line code, so that when helper call // completes, it can jump back properly. // Load Return Address into R14. intptrj_t returnAddr = (intptrj_t)getReStartLabel()->getCodeLocation(); // LARL R14, <Return Addr> *(int16_t *) cursor = 0xC0E0; cursor += sizeof(int16_t); *(int32_t *) cursor = (int32_t)((returnAddr - (intptrj_t)(cursor - 2)) / 2); cursor += sizeof(int32_t); *(int16_t *) cursor = 0xC0F4; // BRCL <Helper Addr> cursor += sizeof(int16_t); } // Calculate the relative offset to get to helper method. // If MCC is not supported, everything should be reachable. // If MCC is supported, we will look up the appropriate trampoline, if // necessary. intptrj_t destAddr = (intptrj_t)(helperSymRef->getSymbol()->castToMethodSymbol()->getMethodAddress()); #if defined(TR_TARGET_64BIT) #if defined(J9ZOS390) if (cg()->comp()->getOption(TR_EnableRMODE64)) #endif { if (NEEDS_TRAMPOLINE(destAddr, cursor, cg())) { destAddr = cg()->fe()->indexedTrampolineLookup(helperSymRef->getReferenceNumber(), (void *)cursor); this->setUsedTrampoline(true); // We clobber rEP if we take a trampoline. Update our register map if necessary. if (gcMap().getStackMap() != NULL) { gcMap().getStackMap()->maskRegisters(~(0x1 << (rEP))); } } } #endif TR_ASSERT(CHECK_32BIT_TRAMPOLINE_RANGE(destAddr, cursor), "Helper Call is not reachable."); this->setSnippetDestAddr(destAddr); *(int32_t *) cursor = (int32_t)((destAddr - (intptrj_t)(cursor - 2)) / 2); AOTcgDiag1(cg()->comp(), "add TR_HelperAddress cursor=%x\n", cursor); cg()->addProjectSpecializedRelocation(cursor, (uint8_t*) helperSymRef, NULL, TR_HelperAddress, __FILE__, __LINE__, getNode()); cursor += sizeof(int32_t); gcMap().registerStackMap(cursor, cg()); return cursor; }