Path: blob/master/runtime/compiler/p/codegen/InterfaceCastSnippet.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2000, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "p/codegen/InterfaceCastSnippet.hpp"2324#include "codegen/Machine.hpp"25#include "env/CompilerEnv.hpp"26#include "env/IO.hpp"27#include "env/jittypes.h"28#include "env/VMJ9.h"29#include "il/LabelSymbol.hpp"30#include "il/Node.hpp"31#include "il/Node_inlines.hpp"32#include "p/codegen/PPCTableOfConstants.hpp"3334TR::PPCInterfaceCastSnippet::PPCInterfaceCastSnippet(TR::CodeGenerator * cg, TR::Node * n, TR::LabelSymbol *restartLabel, TR::LabelSymbol *snippetLabel, TR::LabelSymbol *trueLabel, TR::LabelSymbol *falseLabel, TR::LabelSymbol *doneLabel, TR::LabelSymbol *callLabel, bool testCastClassIsSuper, bool checkCast, int32_t offsetClazz, int32_t offsetCastClassCache, bool needsResult)35: TR::Snippet(cg, n, snippetLabel, false), _restartLabel(restartLabel), _trueLabel(trueLabel), _falseLabel(falseLabel), _doneLabel(doneLabel), _callLabel(callLabel), _testCastClassIsSuper(testCastClassIsSuper), _checkCast(checkCast), _offsetClazz(offsetClazz), _offsetCastClassCache(offsetCastClassCache), _needsResult(needsResult)36{37}3839uint8_t *40TR::PPCInterfaceCastSnippet::emitSnippetBody()41{42TR::Compilation *comp = cg()->comp();43TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());4445uint8_t * cursor = cg()->getBinaryBufferCursor();4647TR::InstOpCode opcode;48int32_t branchDistance;4950getSnippetLabel()->setCodeLocation(cursor);5152if (_checkCast)53{54TR::RegisterDependencyConditions *deps = _doneLabel->getInstruction()->getDependencyConditions();55TR::RealRegister *objReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(0)->getRealRegister());56TR::RealRegister *castClassReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());57TR::RealRegister *objClassReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());58TR::RealRegister *cndReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());59TR::RealRegister *scratch1Reg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(4)->getRealRegister());6061// checkcast6263// TODO: at present _testCastClassIsSuper is always false6465// lwz/ld scratch1Reg, objReg(_offsetClazz)66// lwz/ld scratch1Reg, scratch1Reg(_offsetCastClassCache)67// cmpl4/cmpl8 cr0, castClassReg, scratch1Reg68// if (_testCastClassIsSuper)69// beq cr0, 8 (_doneLabel)70// b restartLabel71// 8: b _doneLabel72// else73// bne cr0, 8 (_callLabel)74// b doneLabel75// 8: b _callLabel7677if (comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())78opcode.setOpCodeValue(TR::InstOpCode::ld);79else80opcode.setOpCodeValue(TR::InstOpCode::lwz);81cursor = opcode.copyBinaryToBuffer(cursor);82scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);83objReg->setRegisterFieldRA((uint32_t *)cursor);84*(int32_t *)cursor |= _offsetClazz & 0xffff;85cursor += PPC_INSTRUCTION_LENGTH;8687if (comp->target().is64Bit())88opcode.setOpCodeValue(TR::InstOpCode::ld);89else90opcode.setOpCodeValue(TR::InstOpCode::lwz);91cursor = opcode.copyBinaryToBuffer(cursor);92scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);93scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);94*(int32_t *)cursor |= _offsetCastClassCache & 0xffff;95cursor += PPC_INSTRUCTION_LENGTH;9697if (comp->target().is64Bit())98opcode.setOpCodeValue(TR::InstOpCode::cmpl8);99else100opcode.setOpCodeValue(TR::InstOpCode::cmpl4);101cursor = opcode.copyBinaryToBuffer(cursor);102cndReg->setRegisterFieldRT((uint32_t *)cursor);103castClassReg->setRegisterFieldRA((uint32_t *)cursor);104scratch1Reg->setRegisterFieldRB((uint32_t *)cursor);105cursor += PPC_INSTRUCTION_LENGTH;106107if (_testCastClassIsSuper)108{109opcode.setOpCodeValue(TR::InstOpCode::beq);110cursor = opcode.copyBinaryToBuffer(cursor);111cndReg->setRegisterFieldBI((uint32_t *)cursor);112branchDistance = (intptr_t) 8; // Jump two instructions below113*(int32_t *)cursor |= (branchDistance & 0x0fffc);114cursor += PPC_INSTRUCTION_LENGTH;115116opcode.setOpCodeValue(TR::InstOpCode::b);117cursor = opcode.copyBinaryToBuffer(cursor);118branchDistance = (intptr_t)getReStartLabel()->getCodeLocation() - (intptr_t)cursor;119TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)getReStartLabel()->getCodeLocation(), (intptr_t)cursor),120"backward jump in Interface Cache is too long\n");121*(int32_t *)cursor |= (branchDistance & 0x03fffffc);122cursor += PPC_INSTRUCTION_LENGTH;123124opcode.setOpCodeValue(TR::InstOpCode::b);125cursor = opcode.copyBinaryToBuffer(cursor);126branchDistance = (intptr_t)_doneLabel->getCodeLocation() - (intptr_t)cursor;127TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_doneLabel->getCodeLocation(), (intptr_t)cursor),128"backward jump in Interface Cache is too long\n");129*(int32_t *)cursor |= (branchDistance & 0x03fffffc);130cursor += PPC_INSTRUCTION_LENGTH;131}132else133{134opcode.setOpCodeValue(TR::InstOpCode::bne);135cursor = opcode.copyBinaryToBuffer(cursor);136cndReg->setRegisterFieldBI((uint32_t *)cursor);137branchDistance = (intptr_t) 8; // Jump two instructions below138*(int32_t *)cursor |= (branchDistance & 0x0fffc);139cursor += PPC_INSTRUCTION_LENGTH;140141opcode.setOpCodeValue(TR::InstOpCode::b);142cursor = opcode.copyBinaryToBuffer(cursor);143branchDistance = (intptr_t)getDoneLabel()->getCodeLocation() - (intptr_t)cursor;144TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)getDoneLabel()->getCodeLocation(), (intptr_t)cursor),145"backward jump in Interface Cache is too long\n");146*(int32_t *)cursor |= (branchDistance & 0x03fffffc);147cursor += PPC_INSTRUCTION_LENGTH;148149opcode.setOpCodeValue(TR::InstOpCode::b);150cursor = opcode.copyBinaryToBuffer(cursor);151branchDistance = (intptr_t)_callLabel->getCodeLocation() - (intptr_t)cursor;152TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_callLabel->getCodeLocation(), (intptr_t)cursor),153"backward jump in Interface Cache is too long\n");154*(int32_t *)cursor |= (branchDistance & 0x03fffffc);155cursor += PPC_INSTRUCTION_LENGTH;156}157}158else // if not _checkcast, then it is instanceof159{160auto firstArgReg = getNode()->getSymbol()->castToMethodSymbol()->getLinkageConvention() == TR_CHelper ? TR::RealRegister::gr4 : TR::RealRegister::gr3;161TR::RegisterDependencyConditions *deps = _doneLabel->getInstruction()->getDependencyConditions();162TR::RealRegister *castClassReg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg));163TR::RealRegister *objClassReg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 3));164TR::RealRegister *resultReg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 5));165TR::RealRegister *cndReg = cg()->machine()->getRealRegister(TR::RealRegister::cr0);166TR::RealRegister *scratch1Reg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 2));167TR::RealRegister *scratch2Reg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 4));168169// instanceof170171// lwz/ld scratch2Reg, objClassReg(_offsetCastClassCache)172// if (comp->target().is64Bit())173// sh=0174// me=62175// rldicr scratch1Reg, scratch2Reg, 0, 0x3d176// else177// rlwinm scratch1Reg, scratch2Reg, 0, 0xFFFF FFFE178// cmpl cr0, scratch1Reg, castClassReg179// if (_testCastClassIsSuper)180// beq cr0, 8 (continue)181// b restartLabel182// else183// beq cr0, 8 (continue)184// b callLabel185// 8:186// if (_needsResult)187// li scratch1Reg, 0x1188// or scratch1Reg, scratch1Reg, scratch2Reg189// xor. resultReg, scratch1Reg, scratch2Reg190// if (_falseLabel != _trueLabel)191// bne cr0, 8 (_falseLabel)192// b _trueLabel193// 8: b _falseLabel // branch if xor. does not set 0 on resultReg194// else195// b _doneLabel196// else197// if (_falseLabel != _trueLabel)198// li scratch1Reg, 0x1199// and. scratch1Reg, scratch1Reg, scratch2Reg200// bne cr0, 8 (_falseLabel)201// b _trueLabel202// 8: b _falseLabel // branch if and. does not set 0 on scratch1Reg203// else204// b _doneLabel205206// TODO: this code is set on 390.207// int32_t offset = _offsetCastClassCache;208// if (comp->target().is64Bit())209// {210// offset += 4;211// }212213if (comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())214opcode.setOpCodeValue(TR::InstOpCode::ld);215else216opcode.setOpCodeValue(TR::InstOpCode::lwz);217cursor = opcode.copyBinaryToBuffer(cursor);218scratch2Reg->setRegisterFieldRT((uint32_t *)cursor);219objClassReg->setRegisterFieldRA((uint32_t *)cursor);220*(int32_t *)cursor |= _offsetCastClassCache & 0xffff;221cursor += PPC_INSTRUCTION_LENGTH;222223if (comp->target().is64Bit())224{225opcode.setOpCodeValue(TR::InstOpCode::rldicr);226cursor = opcode.copyBinaryToBuffer(cursor);227scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);228scratch2Reg->setRegisterFieldRS((uint32_t *)cursor);229*(int32_t *)cursor |= (0x3d << 5);230}231else232{233opcode.setOpCodeValue(TR::InstOpCode::rlwinm);234cursor = opcode.copyBinaryToBuffer(cursor);235scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);236scratch2Reg->setRegisterFieldRS((uint32_t *)cursor);237*(int32_t *)cursor |= (30 << 1);238}239cursor += PPC_INSTRUCTION_LENGTH;240241if (comp->target().is64Bit())242opcode.setOpCodeValue(TR::InstOpCode::cmpl8);243else244opcode.setOpCodeValue(TR::InstOpCode::cmpl4);245cursor = opcode.copyBinaryToBuffer(cursor);246cndReg->setRegisterFieldRT((uint32_t *)cursor);247scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);248castClassReg->setRegisterFieldRB((uint32_t *)cursor);249cursor += PPC_INSTRUCTION_LENGTH;250251if (_testCastClassIsSuper)252{253opcode.setOpCodeValue(TR::InstOpCode::beq);254cursor = opcode.copyBinaryToBuffer(cursor);255cndReg->setRegisterFieldBI((uint32_t *)cursor);256branchDistance = (intptr_t) 8; // Jump two instructions below257*(int32_t *)cursor |= (branchDistance & 0x0fffc);258cursor += PPC_INSTRUCTION_LENGTH;259260opcode.setOpCodeValue(TR::InstOpCode::b);261cursor = opcode.copyBinaryToBuffer(cursor);262branchDistance = (intptr_t)getReStartLabel()->getCodeLocation() - (intptr_t)cursor;263TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)getReStartLabel()->getCodeLocation(), (intptr_t)cursor),264"backward jump in Interface Cache is too long\n");265*(int32_t *)cursor |= (branchDistance & 0x03fffffc);266cursor += PPC_INSTRUCTION_LENGTH;267}268else269{270opcode.setOpCodeValue(TR::InstOpCode::beq);271cursor = opcode.copyBinaryToBuffer(cursor);272cndReg->setRegisterFieldBI((uint32_t *)cursor);273branchDistance = (intptr_t) 8; // Jump two instructions below274*(int32_t *)cursor |= (branchDistance & 0x0fffc);275cursor += PPC_INSTRUCTION_LENGTH;276277opcode.setOpCodeValue(TR::InstOpCode::b);278cursor = opcode.copyBinaryToBuffer(cursor);279branchDistance = (intptr_t)_callLabel->getCodeLocation() - (intptr_t)cursor;280TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_callLabel->getCodeLocation(), (intptr_t)cursor),281"backward jump in Interface Cache is too long\n");282*(int32_t *)cursor |= (branchDistance & 0x03fffffc);283cursor += PPC_INSTRUCTION_LENGTH;284}285286if (_needsResult)287{288opcode.setOpCodeValue(TR::InstOpCode::addi);289cursor = opcode.copyBinaryToBuffer(cursor);290scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);291*(int32_t *)cursor |= 0x1;292cursor += PPC_INSTRUCTION_LENGTH;293294opcode.setOpCodeValue(TR::InstOpCode::OR);295cursor = opcode.copyBinaryToBuffer(cursor);296scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);297scratch1Reg->setRegisterFieldRS((uint32_t *)cursor);298scratch2Reg->setRegisterFieldRB((uint32_t *)cursor);299cursor += PPC_INSTRUCTION_LENGTH;300301opcode.setOpCodeValue(TR::InstOpCode::XOR);302cursor = opcode.copyBinaryToBuffer(cursor);303resultReg->setRegisterFieldRA((uint32_t *)cursor);304scratch1Reg->setRegisterFieldRS((uint32_t *)cursor);305scratch2Reg->setRegisterFieldRB((uint32_t *)cursor);306*(int32_t *)cursor |= 0x1; // Rc = 1307cursor += PPC_INSTRUCTION_LENGTH;308309if (_falseLabel != _trueLabel)310{311opcode.setOpCodeValue(TR::InstOpCode::bne);312cursor = opcode.copyBinaryToBuffer(cursor);313cndReg->setRegisterFieldBI((uint32_t *)cursor);314branchDistance = (intptr_t) 8; // Jump two instructions below315*(int32_t *)cursor |= (branchDistance & 0x0fffc);316cursor += PPC_INSTRUCTION_LENGTH;317318opcode.setOpCodeValue(TR::InstOpCode::b);319cursor = opcode.copyBinaryToBuffer(cursor);320branchDistance = (intptr_t)_trueLabel->getCodeLocation() - (intptr_t)cursor;321TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_trueLabel->getCodeLocation(), (intptr_t)cursor),322"backward jump in Interface Cache is too long\n");323*(int32_t *)cursor |= (branchDistance & 0x03fffffc);324cursor += PPC_INSTRUCTION_LENGTH;325326opcode.setOpCodeValue(TR::InstOpCode::b);327cursor = opcode.copyBinaryToBuffer(cursor);328branchDistance = (intptr_t)_falseLabel->getCodeLocation() - (intptr_t)cursor;329TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_falseLabel->getCodeLocation(), (intptr_t)cursor),330"backward jump in Interface Cache is too long\n");331*(int32_t *)cursor |= (branchDistance & 0x03fffffc);332cursor += PPC_INSTRUCTION_LENGTH;333}334else335{336opcode.setOpCodeValue(TR::InstOpCode::b);337cursor = opcode.copyBinaryToBuffer(cursor);338branchDistance = (intptr_t)_doneLabel->getCodeLocation() - (intptr_t)cursor;339TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_doneLabel->getCodeLocation(), (intptr_t)cursor),340"backward jump in Interface Cache is too long\n");341*(int32_t *)cursor |= (branchDistance & 0x03fffffc);342cursor += PPC_INSTRUCTION_LENGTH;343}344}345else346{347if (_falseLabel != _trueLabel)348{349opcode.setOpCodeValue(TR::InstOpCode::addi);350cursor = opcode.copyBinaryToBuffer(cursor);351scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);352*(int32_t *)cursor |= 0x1;353cursor += PPC_INSTRUCTION_LENGTH;354355opcode.setOpCodeValue(TR::InstOpCode::AND);356cursor = opcode.copyBinaryToBuffer(cursor);357scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);358scratch1Reg->setRegisterFieldRS((uint32_t *)cursor);359scratch2Reg->setRegisterFieldRB((uint32_t *)cursor);360*(int32_t *)cursor |= 0x1; // Rc = 1361cursor += PPC_INSTRUCTION_LENGTH;362363opcode.setOpCodeValue(TR::InstOpCode::bne);364cursor = opcode.copyBinaryToBuffer(cursor);365cndReg->setRegisterFieldBI((uint32_t *)cursor);366branchDistance = (intptr_t) 8; // Jump two instructions below367*(int32_t *)cursor |= (branchDistance & 0x0fffc);368cursor += PPC_INSTRUCTION_LENGTH;369370opcode.setOpCodeValue(TR::InstOpCode::b);371cursor = opcode.copyBinaryToBuffer(cursor);372branchDistance = (intptr_t)_trueLabel->getCodeLocation() - (intptr_t)cursor;373TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_trueLabel->getCodeLocation(), (intptr_t)cursor),374"backward jump in Interface Cache is too long\n");375*(int32_t *)cursor |= (branchDistance & 0x03fffffc);376cursor += PPC_INSTRUCTION_LENGTH;377378opcode.setOpCodeValue(TR::InstOpCode::b);379cursor = opcode.copyBinaryToBuffer(cursor);380branchDistance = (intptr_t)_falseLabel->getCodeLocation() - (intptr_t)cursor;381TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_falseLabel->getCodeLocation(), (intptr_t)cursor),382"backward jump in Interface Cache is too long\n");383*(int32_t *)cursor |= (branchDistance & 0x03fffffc);384cursor += PPC_INSTRUCTION_LENGTH;385}386else387{388opcode.setOpCodeValue(TR::InstOpCode::b);389cursor = opcode.copyBinaryToBuffer(cursor);390branchDistance = (intptr_t)_doneLabel->getCodeLocation() - (intptr_t)cursor;391TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_doneLabel->getCodeLocation(), (intptr_t)cursor),392"backward jump in Interface Cache is too long\n");393*(int32_t *)cursor |= (branchDistance & 0x03fffffc);394cursor += PPC_INSTRUCTION_LENGTH;395}396}397}398return cursor;399}400401402void403TR_Debug::print(TR::FILE *pOutFile, TR::PPCInterfaceCastSnippet * snippet)404{405TR_J9VMBase *fej9 = (TR_J9VMBase *)(_cg->fe());406uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation();407bool checkcast = snippet->isCheckCast();408409if (checkcast)410{411printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Interface Cast Snippet for Checkcast");412413TR::RegisterDependencyConditions *deps = snippet->getDoneLabel()->getInstruction()->getDependencyConditions();414TR::RealRegister *objReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(0)->getRealRegister());415TR::RealRegister *castClassReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());416TR::RealRegister *objClassReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());417TR::RealRegister *cndReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());418TR::RealRegister *scratch1Reg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(4)->getRealRegister());419420int32_t value;421422printPrefix(pOutFile, NULL, cursor, 4);423value = *((int32_t *) cursor) & 0x0ffff;424if (_comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())425trfprintf(pOutFile, "ld \t%s, [%s, %d]\t; Load object class", getName(scratch1Reg), getName(objReg), value );426else427trfprintf(pOutFile, "lwz \t%s, [%s, %d]\t; Load object class", getName(scratch1Reg), getName(objReg), value );428cursor+=4;429430printPrefix(pOutFile, NULL, cursor, 4);431value = *((int32_t *) cursor) & 0x0ffff;432if (_comp->target().is64Bit())433trfprintf(pOutFile, "ld \t%s, [%s, %d]\t; Load castClassCache", getName(scratch1Reg), getName(scratch1Reg), value );434else435trfprintf(pOutFile, "lwz \t%s, [%s, %d]\t; Load castClassCache", getName(scratch1Reg), getName(scratch1Reg), value );436cursor+=4;437438printPrefix(pOutFile, NULL, cursor, 4);439trfprintf(pOutFile, "cmpl \t%s, %s, %s\t; Compare with type to cast", getName(cndReg), getName(castClassReg), getName(scratch1Reg) );440cursor+=4;441442if (snippet->getTestCastClassIsSuper())443{444printPrefix(pOutFile, NULL, cursor, 4);445value = *((int32_t *) cursor) & 0xfffc;446value = (value << 16) >> 16; // sign extend447trfprintf(pOutFile, "beq \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);448cursor += 4;449450printPrefix(pOutFile, NULL, cursor, 4);451value = *((int32_t *) cursor) & 0x03fffffc;452value = (value << 6) >> 6; // sign extend453trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);454cursor += 4;455456printPrefix(pOutFile, NULL, cursor, 4);457value = *((int32_t *) cursor) & 0x03fffffc;458value = (value << 6) >> 6; // sign extend459trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);460cursor += 4;461}462else463{464printPrefix(pOutFile, NULL, cursor, 4);465value = *((int32_t *) cursor) & 0xfffc;466value = (value << 16) >> 16; // sign extend467trfprintf(pOutFile, "bne \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);468cursor += 4;469470printPrefix(pOutFile, NULL, cursor, 4);471value = *((int32_t *) cursor) & 0x03fffffc;472value = (value << 6) >> 6; // sign extend473trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);474cursor += 4;475476printPrefix(pOutFile, NULL, cursor, 4);477value = *((int32_t *) cursor) & 0x03fffffc;478value = (value << 6) >> 6; // sign extend479trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);480cursor += 4;481}482}483else484{485// InstanceOf has trueLabel = falseLabel486// in ifInstanceOf, trueLabel != falseLabel487488if (snippet->getTrueLabel() == snippet->getFalseLabel())489printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Interface Cast Snippet for instanceOf");490else491printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Interface Cast Snippet for ifInstanceOf");492493TR::RegisterDependencyConditions *deps = snippet->getDoneLabel()->getInstruction()->getDependencyConditions();494TR::RealRegister *castClassReg = _cg->machine()->getRealRegister(TR::RealRegister::gr3);495TR::RealRegister *objClassReg = _cg->machine()->getRealRegister(TR::RealRegister::gr6);496TR::RealRegister *resultReg = _cg->machine()->getRealRegister(TR::RealRegister::gr8);497TR::RealRegister *cndReg = _cg->machine()->getRealRegister(TR::RealRegister::cr0);498TR::RealRegister *scratch1Reg = _cg->machine()->getRealRegister(TR::RealRegister::gr5);499TR::RealRegister *scratch2Reg = _cg->machine()->getRealRegister(TR::RealRegister::gr7);500501int32_t value;502503printPrefix(pOutFile, NULL, cursor, 4);504value = *((int32_t *) cursor) & 0x0ffff;505if (_comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())506trfprintf(pOutFile, "ld \t%s, [%s, %d]\t; Load castClassCache", getName(scratch2Reg), getName(objClassReg), value );507else508trfprintf(pOutFile, "lwz \t%s, [%s, %d]\t; Load castClassCache", getName(scratch2Reg), getName(objClassReg), value );509cursor+=4;510511printPrefix(pOutFile, NULL, cursor, 4);512if (_comp->target().is64Bit())513trfprintf(pOutFile, "rldicr \t%s, %s, 0, 0x3D; Clean last bit (cached result)", getName(scratch1Reg), getName(scratch2Reg));514else515trfprintf(pOutFile, "rlwinm \t%s, %s, 0, 0xFFFFFFFE; Clean last bit (cached result)", getName(scratch1Reg), getName(scratch2Reg));516cursor+= 4;517518printPrefix(pOutFile, NULL, cursor, 4);519trfprintf(pOutFile, "cmpl \t%s, %s, %s\t; Compare with type to cast", getName(cndReg), getName(scratch1Reg), getName(castClassReg) );520cursor+=4;521522if (snippet->getTestCastClassIsSuper())523{524printPrefix(pOutFile, NULL, cursor, 4);525value = *((int32_t *) cursor) & 0xfffc;526value = (value << 16) >> 16; // sign extend527trfprintf(pOutFile, "beq \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);528cursor += 4;529530printPrefix(pOutFile, NULL, cursor, 4);531value = *((int32_t *) cursor) & 0x03fffffc;532value = (value << 6) >> 6; // sign extend533trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);534cursor += 4;535}536else537{538printPrefix(pOutFile, NULL, cursor, 4);539value = *((int32_t *) cursor) & 0xfffc;540value = (value << 16) >> 16; // sign extend541trfprintf(pOutFile, "beq \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);542cursor += 4;543544printPrefix(pOutFile, NULL, cursor, 4);545value = *((int32_t *) cursor) & 0x03fffffc;546value = (value << 6) >> 6; // sign extend547trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);548cursor += 4;549}550551if (snippet->getNeedsResult())552{553printPrefix(pOutFile, NULL, cursor, 4);554trfprintf(pOutFile, "li \t%s, %d", getName(scratch1Reg), *((int32_t *) cursor) & 0x0000ffff);555cursor += 4;556557printPrefix(pOutFile, NULL, cursor, 4);558trfprintf(pOutFile, "or \t%s, %s, %s; Set the last bit", getName(scratch1Reg), getName(scratch1Reg), getName(scratch2Reg));559cursor+= 4;560561printPrefix(pOutFile, NULL, cursor, 4);562trfprintf(pOutFile, "xor. \t%s, %s, %s; Check if last bit is set in the cache", getName(resultReg), getName(scratch1Reg), getName(scratch2Reg));563cursor+= 4;564565if (snippet->getFalseLabel() != snippet->getTrueLabel())566{567printPrefix(pOutFile, NULL, cursor, 4);568value = *((int32_t *) cursor) & 0xfffc;569value = (value << 16) >> 16; // sign extend570trfprintf(pOutFile, "bne \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);571cursor += 4;572573printPrefix(pOutFile, NULL, cursor, 4);574value = *((int32_t *) cursor) & 0x03fffffc;575value = (value << 6) >> 6; // sign extend576trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);577cursor += 4;578579printPrefix(pOutFile, NULL, cursor, 4);580value = *((int32_t *) cursor) & 0x03fffffc;581value = (value << 6) >> 6; // sign extend582trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);583cursor += 4;584}585else586{587printPrefix(pOutFile, NULL, cursor, 4);588value = *((int32_t *) cursor) & 0x03fffffc;589value = (value << 6) >> 6; // sign extend590trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);591cursor += 4;592}593}594else595{596if (snippet->getFalseLabel() != snippet->getTrueLabel())597{598printPrefix(pOutFile, NULL, cursor, 4);599trfprintf(pOutFile, "li \t%s, %d", getName(scratch1Reg), *((int32_t *) cursor) & 0x0000ffff);600cursor += 4;601602printPrefix(pOutFile, NULL, cursor, 4);603trfprintf(pOutFile, "and. \t%s, %s, %s; Check if last bit is set in the cache", getName(scratch1Reg), getName(scratch1Reg), getName(scratch2Reg));604cursor+= 4;605606printPrefix(pOutFile, NULL, cursor, 4);607value = *((int32_t *) cursor) & 0xfffc;608value = (value << 16) >> 16; // sign extend609trfprintf(pOutFile, "bne \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);610cursor += 4;611612printPrefix(pOutFile, NULL, cursor, 4);613value = *((int32_t *) cursor) & 0x03fffffc;614value = (value << 6) >> 6; // sign extend615trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);616cursor += 4;617618printPrefix(pOutFile, NULL, cursor, 4);619value = *((int32_t *) cursor) & 0x03fffffc;620value = (value << 6) >> 6; // sign extend621trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);622cursor += 4;623}624else625{626printPrefix(pOutFile, NULL, cursor, 4);627value = *((int32_t *) cursor) & 0x03fffffc;628value = (value << 6) >> 6; // sign extend629trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);630cursor += 4;631}632}633}634}635636637uint32_t638TR::PPCInterfaceCastSnippet::getLength(int32_t estimatedSnippetStart)639{640uint32_t size;641642if (_checkCast)643{644size = 6;645}646else // interfaceof647{648size = 5;649650if (_needsResult)651{652size += 4;653if (_falseLabel != _trueLabel)654{655size += 3;656}657else658{659size += 1;660}661}662else663{664if (_falseLabel != _trueLabel)665{666size += 5;667}668else669{670size += 1;671}672}673}674675return size * PPC_INSTRUCTION_LENGTH;676}677678679680