S390HelperCallSnippet(TR::CodeGenerator *cg, TR::Node *node, TR::LabelSymbol *snippetlab, TR::SymbolReference *helper, TR::LabelSymbol *restartlab = NULL, int32_t s = 0) : TR::Snippet(cg, node, snippetlab, (restartlab == NULL)), _reStartLabel(restartlab), _helperSymRef(helper), sizeOfArguments(s) { // If we don't have a restart label, then we must not be returning to the mainline code - // hence, always except. TR_ASSERT(restartlab || (!restartlab && helper->canCauseGC()), "An exception snippet is marked as cannot cause GC"); // Set up appropriate GC Map if (!restartlab) gcMap().setGCRegisterMask((uint32_t)0x00000000); // everything gets clobbered if we're taking an exception. }
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; }
uint8_t *TR::PPCHelperCallSnippet::genHelperCall(uint8_t *buffer) { intptrj_t helperAddress = (intptrj_t)getDestination()->getSymbol()->castToMethodSymbol()->getMethodAddress(); if (cg()->directCallRequiresTrampoline(helperAddress, (intptrj_t)buffer)) { helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(getDestination()->getReferenceNumber(), (void *)buffer); TR_ASSERT_FATAL(TR::Compiler->target.cpu.isTargetWithinIFormBranchRange(helperAddress, (intptrj_t)buffer), "Helper address is out of range"); } intptrj_t distance = helperAddress - (intptrj_t)buffer; // b|bl distance *(int32_t *)buffer = 0x48000000 | (distance & 0x03fffffc); if (_restartLabel != NULL) { *(int32_t *)buffer |= 0x00000001; } cg()->addProjectSpecializedRelocation(buffer,(uint8_t *)getDestination(), NULL, TR_HelperAddress, __FILE__, __LINE__, getNode()); buffer += 4; gcMap().registerStackMap(buffer, cg()); if (_restartLabel != NULL) { int32_t returnDistance = _restartLabel->getCodeLocation() - buffer; *(int32_t *)buffer = 0x48000000 | (returnDistance & 0x03fffffc); buffer += 4; } return buffer; }
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; }