static TR::Register *addOrSubInteger(TR::Node *node, TR::CodeGenerator *cg) { TR::Node *firstChild = node->getFirstChild(); TR::Register *src1Reg = cg->evaluate(firstChild); TR::Node *secondChild = node->getSecondChild(); TR::Register *trgReg = cg->allocateRegister(); bool isAdd = node->getOpCode().isAdd(); if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL) { int32_t value = secondChild->getInt(); if (constantIsUnsignedImm12(value)) { generateTrg1Src1ImmInstruction(cg, isAdd ? TR::InstOpCode::addimmw : TR::InstOpCode::subimmw, node, trgReg, src1Reg, value); } else { TR::Register *tmpReg = cg->allocateRegister(); loadConstant32(cg, node, value, tmpReg); generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, tmpReg); cg->stopUsingRegister(tmpReg); } } else { TR::Register *src2Reg = cg->evaluate(secondChild); generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, src2Reg); } node->setRegister(trgReg); firstChild->decReferenceCount(); secondChild->decReferenceCount(); return trgReg; }
void TR::ARM64SystemLinkage::createEpilogue(TR::Instruction *cursor) { TR::CodeGenerator *codeGen = cg(); const TR::ARM64LinkageProperties& properties = getProperties(); TR::Machine *machine = codeGen->machine(); TR::Node *lastNode = cursor->getNode(); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); TR::RealRegister *sp = machine->getRealRegister(properties.getStackPointerRegister()); // restore callee-saved registers uint32_t offset = bodySymbol->getLocalMappingCursor(); for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldrimmx, lastNode, rr, stackSlot, cursor); offset += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::vldrimmd, lastNode, rr, stackSlot, cursor); offset += 8; } } // restore link register (x30) TR::RealRegister *lr = machine->getRealRegister(TR::RealRegister::lr); if (machine->getLinkRegisterKilled()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, 0, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldrimmx, lastNode, lr, stackSlot, cursor); } // remove space for preserved registers uint32_t frameSize = codeGen->getFrameSizeInBytes(); if (constantIsUnsignedImm12(frameSize)) { cursor = generateTrg1Src1ImmInstruction(codeGen, TR::InstOpCode::addimmx, lastNode, sp, sp, frameSize, cursor); } else { TR_UNIMPLEMENTED(); } // return cursor = generateRegBranchInstruction(codeGen, TR::InstOpCode::ret, lastNode, lr, cursor); }
TR::Register *TR::ARM64SystemLinkage::buildDirectDispatch(TR::Node *callNode) { TR::SymbolReference *callSymRef = callNode->getSymbolReference(); const TR::ARM64LinkageProperties &pp = getProperties(); TR::RealRegister *sp = cg()->machine()->getRealRegister(pp.getStackPointerRegister()); TR::RegisterDependencyConditions *dependencies = new (trHeapMemory()) TR::RegisterDependencyConditions( pp.getNumberOfDependencyGPRegisters(), pp.getNumberOfDependencyGPRegisters(), trMemory()); int32_t totalSize = buildArgs(callNode, dependencies); if (totalSize > 0) { if (constantIsUnsignedImm12(totalSize)) { generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::subimmx, callNode, sp, sp, totalSize); } else { TR_ASSERT_FATAL(false, "Too many arguments."); } } TR::MethodSymbol *callSymbol = callSymRef->getSymbol()->castToMethodSymbol(); generateImmSymInstruction(cg(), TR::InstOpCode::bl, callNode, (uintptr_t)callSymbol->getMethodAddress(), dependencies, callSymRef ? callSymRef : callNode->getSymbolReference(), NULL); cg()->machine()->setLinkRegisterKilled(true); if (totalSize > 0) { if (constantIsUnsignedImm12(totalSize)) { generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::addimmx, callNode, sp, sp, totalSize); } else { TR_ASSERT_FATAL(false, "Too many arguments."); } } TR::Register *retReg; switch(callNode->getOpCodeValue()) { case TR::icall: case TR::iucall: retReg = dependencies->searchPostConditionRegister( pp.getIntegerReturnRegister()); break; case TR::lcall: case TR::lucall: case TR::acall: retReg = dependencies->searchPostConditionRegister( pp.getLongReturnRegister()); break; case TR::fcall: case TR::dcall: retReg = dependencies->searchPostConditionRegister( pp.getFloatReturnRegister()); break; case TR::call: retReg = NULL; break; default: retReg = NULL; TR_ASSERT(false, "Unsupported direct call Opcode."); } callNode->setRegister(retReg); return retReg; }
void TR::ARM64SystemLinkage::createPrologue(TR::Instruction *cursor, List<TR::ParameterSymbol> &parmList) { TR::CodeGenerator *codeGen = cg(); TR::Machine *machine = codeGen->machine(); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); const TR::ARM64LinkageProperties& properties = getProperties(); TR::RealRegister *sp = machine->getRealRegister(properties.getStackPointerRegister()); TR::Node *firstNode = comp()->getStartTree()->getNode(); // allocate stack space uint32_t frameSize = (uint32_t)codeGen->getFrameSizeInBytes(); if (constantIsUnsignedImm12(frameSize)) { cursor = generateTrg1Src1ImmInstruction(codeGen, TR::InstOpCode::subimmx, firstNode, sp, sp, frameSize, cursor); } else { TR_UNIMPLEMENTED(); } // save link register (x30) if (machine->getLinkRegisterKilled()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, 0, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, machine->getRealRegister(TR::RealRegister::x30), cursor); } // spill argument registers int32_t nextIntArgReg = 0; int32_t nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&parmList); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, parameter->getParameterOffset(), codeGen); TR::InstOpCode::Mnemonic op; switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::strimmx : TR::InstOpCode::strimmw; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::x0 + nextIntArgReg)), cursor); nextIntArgReg++; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::vstrimmd : TR::InstOpCode::vstrimms; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::v0 + nextFltArgReg)), cursor); nextFltArgReg++; } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on AArch64."); break; default: TR_ASSERT(false, "Unknown parameter type."); } } // save callee-saved registers uint32_t offset = bodySymbol->getLocalMappingCursor(); for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, rr, cursor); offset += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::vstrimmd, firstNode, stackSlot, rr, cursor); offset += 8; } } }