Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/x/i386/codegen/IA32J9SystemLinkage.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#if defined(TR_TARGET_32BIT)
24
25
#include "codegen/IA32J9SystemLinkage.hpp"
26
#include "codegen/Linkage_inlines.hpp"
27
#include "codegen/RegisterDependency.hpp"
28
#include "codegen/X86Instruction.hpp"
29
#include "x/codegen/IA32LinkageUtils.hpp"
30
#include "codegen/LiveRegister.hpp"
31
#include "x/codegen/J9LinkageUtils.hpp"
32
#include "codegen/CodeGenerator.hpp"
33
#include "il/Node.hpp"
34
#include "il/Node_inlines.hpp"
35
36
TR::IA32J9SystemLinkage::IA32J9SystemLinkage(TR::CodeGenerator *cg) : TR::IA32SystemLinkage(cg)
37
{
38
_properties._framePointerRegister = TR::RealRegister::ebx;
39
_properties._methodMetaDataRegister = TR::RealRegister::ebp;
40
}
41
42
43
TR::Register*
44
TR::IA32J9SystemLinkage::buildVolatileAndReturnDependencies(TR::Node *callNode, TR::RegisterDependencyConditions *deps)
45
{
46
TR::Register* returnReg = TR::IA32SystemLinkage::buildVolatileAndReturnDependencies(callNode, deps);
47
48
deps->addPostCondition(cg()->getMethodMetaDataRegister(), TR::RealRegister::ebp, cg());
49
50
uint8_t numXmmRegs = 0;
51
TR_LiveRegisters *lr = cg()->getLiveRegisters(TR_FPR);
52
if (!lr || lr->getNumberOfLiveRegisters() > 0)
53
numXmmRegs = (uint8_t)(TR::RealRegister::LastXMMR - TR::RealRegister::FirstXMMR+1);
54
55
if (numXmmRegs > 0)
56
{
57
for (int regIndex = TR::RealRegister::FirstXMMR; regIndex <= TR::RealRegister::LastXMMR; regIndex++)
58
{
59
TR::Register *dummy = cg()->allocateRegister(TR_FPR);
60
dummy->setPlaceholderReg();
61
deps->addPostCondition(dummy, (TR::RealRegister::RegNum)regIndex, cg());
62
cg()->stopUsingRegister(dummy);
63
}
64
}
65
66
deps->stopAddingConditions();
67
return returnReg;
68
}
69
70
71
72
TR::Register*
73
TR::IA32J9SystemLinkage::buildDirectDispatch(TR::Node *callNode, bool spillFPRegs)
74
{
75
#ifdef DEBUG
76
if (debug("reportSysDispatch"))
77
{
78
printf("System Linkage Dispatch: %s calling %s\n", comp()->signature(), comp()->getDebug()->getName(callNode->getSymbolReference()));
79
}
80
#endif
81
82
TR::RealRegister *espReal = machine()->getRealRegister(TR::RealRegister::esp);
83
TR::SymbolReference *methodSymRef = callNode->getSymbolReference();
84
TR::MethodSymbol *methodSymbol = callNode->getSymbol()->castToMethodSymbol();
85
uint8_t numXmmRegs = 0;
86
87
if (!methodSymbol->isHelper())
88
diagnostic("Building call site for %s\n", methodSymbol->getMethod()->signature(trMemory()));
89
90
int32_t argSize = buildParametersOnCStack(callNode, 0);
91
92
TR::LabelSymbol* begLabel = generateLabelSymbol(cg());
93
TR::LabelSymbol* endLabel = generateLabelSymbol(cg());
94
begLabel->setStartInternalControlFlow();
95
endLabel->setEndInternalControlFlow();
96
97
generateLabelInstruction(TR::InstOpCode::label, callNode, begLabel, cg());
98
99
// Save VFP
100
TR::X86VFPSaveInstruction* vfpSave = generateVFPSaveInstruction(callNode, cg());
101
102
TR::J9LinkageUtils::switchToMachineCStack(callNode, cg());
103
104
// check to see if we need to set XMM register dependencies
105
TR_LiveRegisters *lr = cg()->getLiveRegisters(TR_FPR);
106
if (!lr || lr->getNumberOfLiveRegisters() > 0)
107
numXmmRegs = (uint8_t)(TR::RealRegister::LastXMMR - TR::RealRegister::FirstXMMR+1);
108
109
TR::RegisterDependencyConditions *deps;
110
deps = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)6 + numXmmRegs, cg());
111
TR::Register *returnReg = buildVolatileAndReturnDependencies(callNode, deps);
112
113
TR::RegisterDependencyConditions *dummy = generateRegisterDependencyConditions((uint8_t)0, (uint8_t)0, cg());
114
115
// Call-out
116
generateRegImmInstruction(argSize >= -128 && argSize <= 127 ? TR::InstOpCode::SUB4RegImms : TR::InstOpCode::SUB4RegImm4, callNode, espReal, argSize, cg());
117
generateImmSymInstruction(TR::InstOpCode::CALLImm4, callNode, (uintptr_t)methodSymbol->getMethodAddress(), methodSymRef, cg());
118
119
if (returnReg && !(methodSymbol->isHelper()))
120
TR::J9LinkageUtils::cleanupReturnValue(callNode, returnReg, returnReg, cg());
121
122
TR::J9LinkageUtils::switchToJavaStack(callNode, cg());
123
124
// Restore VFP
125
generateVFPRestoreInstruction(vfpSave, callNode, cg());
126
generateLabelInstruction(TR::InstOpCode::label, callNode, endLabel, deps, cg());
127
128
// Stop using the killed registers that are not going to persist
129
//
130
if (deps)
131
stopUsingKilledRegisters(deps, returnReg);
132
133
if (callNode->getOpCode().isFloat())
134
{
135
TR::MemoryReference *tempMR = machine()->getDummyLocalMR(TR::Float);
136
generateFPMemRegInstruction(TR::InstOpCode::FSTPMemReg, callNode, tempMR, returnReg, cg());
137
cg()->stopUsingRegister(returnReg); // zhxingl: this is added by me
138
returnReg = cg()->allocateSinglePrecisionRegister(TR_FPR);
139
generateRegMemInstruction(TR::InstOpCode::MOVSSRegMem, callNode, returnReg, generateX86MemoryReference(*tempMR, 0, cg()), cg());
140
}
141
else if (callNode->getOpCode().isDouble())
142
{
143
TR::MemoryReference *tempMR = machine()->getDummyLocalMR(TR::Double);
144
generateFPMemRegInstruction(TR::InstOpCode::DSTPMemReg, callNode, tempMR, returnReg, cg());
145
cg()->stopUsingRegister(returnReg); // zhxingl: this is added by me
146
returnReg = cg()->allocateRegister(TR_FPR);
147
generateRegMemInstruction(cg()->getXMMDoubleLoadOpCode(), callNode, returnReg, generateX86MemoryReference(*tempMR, 0, cg()), cg());
148
}
149
150
if (cg()->enableRegisterAssociations())
151
associatePreservedRegisters(deps, returnReg);
152
153
return returnReg;
154
}
155
156
int32_t TR::IA32J9SystemLinkage::buildParametersOnCStack(TR::Node *callNode, int firstParamIndex, bool passVMThread, bool wrapAddress)
157
{
158
TR_J9VMBase *fej9 = (TR_J9VMBase *)(fe());
159
TR_Stack<TR::MemoryReference*> paramsSlotsOnStack(trMemory(), callNode->getNumChildren()*2, false, stackAlloc);
160
// Evaluate children that are not part of parameters
161
for (size_t i = 0; i < firstParamIndex; i++)
162
{
163
auto child = callNode->getChild(i);
164
cg()->evaluate(child);
165
cg()->decReferenceCount(child);
166
}
167
// Load C Stack Pointer
168
auto cSP = cg()->allocateRegister();
169
generateRegMemInstruction(TR::InstOpCode::L4RegMem, callNode, cSP, generateX86MemoryReference(cg()->getVMThreadRegister(), fej9->thisThreadGetMachineSPOffset(), cg()), cg());
170
// Pass in the env to the jni method as the lexically first arg.
171
if (passVMThread)
172
{
173
auto slot = generateX86MemoryReference(cSP, 0, cg());
174
generateMemRegInstruction(TR::InstOpCode::S4MemReg, callNode, slot, cg()->getVMThreadRegister(), cg());
175
paramsSlotsOnStack.push(slot);
176
}
177
// Evaluate params
178
for (size_t i = firstParamIndex; i < callNode->getNumChildren(); i++)
179
{
180
auto child = callNode->getChild(i);
181
auto param = cg()->evaluate(child);
182
auto slot = generateX86MemoryReference(cSP, 0, cg());
183
paramsSlotsOnStack.push(slot);
184
switch (child->getDataType())
185
{
186
case TR::Int8:
187
case TR::Int16:
188
case TR::Int32:
189
generateMemRegInstruction(TR::InstOpCode::S4MemReg, callNode, slot, param, cg());
190
break;
191
case TR::Address:
192
if (wrapAddress && child->getOpCodeValue() == TR::loadaddr)
193
{
194
TR::StaticSymbol* sym = child->getSymbolReference()->getSymbol()->getStaticSymbol();
195
if (sym && sym->isAddressOfClassObject())
196
{
197
generateMemRegInstruction(TR::InstOpCode::S4MemReg, callNode, slot, param, cg());
198
}
199
else // must be loadaddr of parm or local
200
{
201
TR::Register *tmp = cg()->allocateRegister();
202
generateRegRegInstruction(TR::InstOpCode::XOR4RegReg, child, tmp, tmp, cg());
203
generateMemImmInstruction(TR::InstOpCode::CMP4MemImms, child, generateX86MemoryReference(child->getRegister(), 0, cg()), 0, cg());
204
generateRegRegInstruction(TR::InstOpCode::CMOVNE4RegReg, child, tmp, child->getRegister(), cg());
205
generateMemRegInstruction(TR::InstOpCode::S4MemReg, callNode, slot, tmp, cg());
206
cg()->stopUsingRegister(tmp);
207
}
208
}
209
else
210
{
211
generateMemRegInstruction(TR::InstOpCode::S4MemReg, callNode, slot, param, cg());
212
}
213
break;
214
case TR::Int64:
215
generateMemRegInstruction(TR::InstOpCode::S4MemReg, callNode, slot, param->getLowOrder(), cg());
216
{
217
auto highslot = generateX86MemoryReference(cSP, 0, cg());
218
paramsSlotsOnStack.push(highslot);
219
generateMemRegInstruction(TR::InstOpCode::S4MemReg, callNode, highslot, param->getHighOrder(), cg());
220
}
221
break;
222
case TR::Float:
223
generateMemRegInstruction(TR::InstOpCode::MOVSSMemReg, callNode, slot, param, cg());
224
break;
225
case TR::Double:
226
paramsSlotsOnStack.push(NULL);
227
generateMemRegInstruction(TR::InstOpCode::MOVSDMemReg, callNode, slot, param, cg());
228
break;
229
}
230
cg()->decReferenceCount(child);
231
}
232
cg()->stopUsingRegister(cSP);
233
int32_t argSize = paramsSlotsOnStack.size() * 4;
234
int32_t adjustedArgSize = 0;
235
if (argSize % 16 != 0)
236
{
237
adjustedArgSize = 16 - (argSize % 16);
238
argSize = argSize + adjustedArgSize;
239
if (comp()->getOption(TR_TraceCG))
240
traceMsg(comp(), "adjust arguments size by %d to make arguments 16 byte aligned \n", adjustedArgSize);
241
}
242
for(int offset = adjustedArgSize; !paramsSlotsOnStack.isEmpty(); offset += TR::Compiler->om.sizeofReferenceAddress())
243
{
244
auto param = paramsSlotsOnStack.pop();
245
if (param)
246
{
247
param->getSymbolReference().setOffset(-offset-4);
248
}
249
}
250
return argSize;
251
}
252
253
#endif
254
255