/******************************************************************************* * Copyright IBM Corp. and others 2000 * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ * or the Apache License, Version 2.0 which accompanies this distribution * and is available at https://www.apache.org/licenses/LICENSE-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the * Eclipse Public License, v. 2.0 are satisfied: GNU General Public License, * version 2 with the GNU Classpath Exception [1] and GNU General Public * License, version 2 with the OpenJDK Assembly Exception [2]. * * [1] https://www.gnu.org/software/classpath/license.html * [2] https://openjdk.org/legal/assembly-exception.html * * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0 *******************************************************************************/ #include "p/codegen/PPCHelperCallSnippet.hpp" #include <stddef.h> #include <stdint.h> #include "codegen/CodeGenerator.hpp" #include "env/FrontEnd.hpp" #include "codegen/InstOpCode.hpp" #include "codegen/Machine.hpp" #include "codegen/RealRegister.hpp" #include "codegen/SnippetGCMap.hpp" #include "compile/Compilation.hpp" #include "env/CompilerEnv.hpp" #include "env/IO.hpp" #include "env/jittypes.h" #include "il/DataTypes.hpp" #include "il/ILOpCodes.hpp" #include "il/ILOps.hpp" #include "il/LabelSymbol.hpp" #include "il/MethodSymbol.hpp" #include "il/Node.hpp" #include "il/Node_inlines.hpp" #include "il/Symbol.hpp" #include "il/SymbolReference.hpp" #include "infra/Assert.hpp" #include "ras/Debug.hpp" #include "runtime/CodeCacheManager.hpp" #include "runtime/Runtime.hpp" uint8_t *TR::PPCHelperCallSnippet::emitSnippetBody() { uint8_t *buffer = cg()->getBinaryBufferCursor(); uint8_t *gtrmpln, *trmpln; getSnippetLabel()->setCodeLocation(buffer); return genHelperCall(buffer); } void TR_Debug::print(TR::FILE *pOutFile, TR::PPCHelperCallSnippet * snippet) { uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation(); TR::LabelSymbol *restartLabel = snippet->getRestartLabel(); if (snippet->getKind() == TR::Snippet::IsArrayCopyCall) { cursor = print(pOutFile, (TR::PPCArrayCopyCallSnippet *)snippet, cursor); } else { printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Helper Call Snippet"); } const char *info = ""; int32_t distance; if (isBranchToTrampoline(snippet->getDestination(), cursor, distance)) info = " Through trampoline"; printPrefix(pOutFile, NULL, cursor, 4); distance = *((int32_t *) cursor) & 0x03fffffc; distance = (distance << 6) >> 6; // sign extend trfprintf(pOutFile, "%s \t" POINTER_PRINTF_FORMAT "\t\t; %s %s", restartLabel ? "bl" : "b", (intptr_t)cursor + distance, getName(snippet->getDestination()), info); if (restartLabel) { cursor += 4; printPrefix(pOutFile, NULL, cursor, 4); distance = *((int32_t *) cursor) & 0x03fffffc; distance = (distance << 6) >> 6; // sign extend trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t; Restart", (intptr_t)cursor + distance); } } uint32_t TR::PPCHelperCallSnippet::getLength(int32_t estimatedSnippetStart) { return getHelperCallLength(); } uint8_t *TR::PPCHelperCallSnippet::genHelperCall(uint8_t *buffer) { intptr_t helperAddress = (intptr_t)getDestination()->getSymbol()->castToMethodSymbol()->getMethodAddress(); if (cg()->directCallRequiresTrampoline(helperAddress, (intptr_t)buffer)) { helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(getDestination()->getReferenceNumber(), (void *)buffer); TR_ASSERT_FATAL(cg()->comp()->target().cpu.isTargetWithinIFormBranchRange(helperAddress, (intptr_t)buffer), "Helper address is out of range"); } intptr_t distance = helperAddress - (intptr_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; } uint32_t TR::PPCHelperCallSnippet::getHelperCallLength() { return ((_restartLabel==NULL)?4:8); } uint8_t *TR::PPCArrayCopyCallSnippet::emitSnippetBody() { TR::Node *node = getNode(); TR_ASSERT(node->getOpCodeValue() == TR::arraycopy && node->getChild(2)->getOpCode().isLoadConst(), "only valid for arraycopies with a constant length\n"); uint8_t *buffer = cg()->getBinaryBufferCursor(); getSnippetLabel()->setCodeLocation(buffer); TR::RealRegister *lengthReg = cg()->machine()->getRealRegister(_lengthRegNum); TR::Node *lengthNode = node->getChild(2); int64_t byteLen = (lengthNode->getType().isInt32() ? lengthNode->getInt() : lengthNode->getLongInt()); TR::InstOpCode opcode; // li lengthReg, #byteLen opcode.setOpCodeValue(TR::InstOpCode::li); buffer = opcode.copyBinaryToBuffer(buffer); lengthReg->setRegisterFieldRT((uint32_t *)buffer); TR_ASSERT(byteLen <= UPPER_IMMED,"byteLen too big to encode\n"); *(int32_t *)buffer |= byteLen; buffer += 4; return TR::PPCHelperCallSnippet::genHelperCall(buffer); } uint8_t* TR_Debug::print(TR::FILE *pOutFile, TR::PPCArrayCopyCallSnippet *snippet, uint8_t *cursor) { printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "ArrayCopy Helper Call Snippet"); TR::RealRegister *lengthReg = _cg->machine()->getRealRegister(snippet->getLengthRegNum()); printPrefix(pOutFile, NULL, cursor, 4); trfprintf(pOutFile, "li \t%s, %d", getName(lengthReg), *((int32_t *) cursor) & 0x0000ffff); cursor += 4; return cursor; } uint32_t TR::PPCArrayCopyCallSnippet::getLength(int32_t estimatedSnippetStart) { return TR::PPCHelperCallSnippet::getHelperCallLength() + 4; }