Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/aarch64/codegen/J9MemoryReference.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2019, 2020 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
#include "codegen/ARM64Instruction.hpp"
24
#include "codegen/CodeGenerator.hpp"
25
#include "codegen/MemoryReference.hpp"
26
#include "codegen/Machine.hpp"
27
#include "codegen/Relocation.hpp"
28
#include "codegen/UnresolvedDataSnippet.hpp"
29
30
J9::ARM64::MemoryReference::MemoryReference(
31
TR::Node *node,
32
TR::CodeGenerator *cg)
33
: OMR::MemoryReferenceConnector(node, cg), _j9Flags(0)
34
{
35
self()->setupCausesImplicitNullPointerException(cg);
36
if (self()->getUnresolvedSnippet())
37
self()->adjustForResolution(cg);
38
}
39
40
J9::ARM64::MemoryReference::MemoryReference(
41
TR::Node *node,
42
TR::SymbolReference *symRef,
43
TR::CodeGenerator *cg)
44
: OMR::MemoryReferenceConnector(node, symRef, cg), _j9Flags(0)
45
{
46
self()->setupCausesImplicitNullPointerException(cg);
47
if (self()->getUnresolvedSnippet())
48
self()->adjustForResolution(cg);
49
}
50
51
void J9::ARM64::MemoryReference::setupCausesImplicitNullPointerException(TR::CodeGenerator *cg)
52
{
53
auto topNode = cg->getCurrentEvaluationTreeTop()->getNode();
54
if (cg->getHasResumableTrapHandler() &&
55
(topNode->getOpCode().isNullCheck() || topNode->chkFoldedImplicitNULLCHK()))
56
{
57
self()->setCausesImplicitNullPointerException();
58
}
59
}
60
61
void
62
J9::ARM64::MemoryReference::adjustForResolution(TR::CodeGenerator *cg)
63
{
64
self()->setExtraRegister(cg->allocateRegister());
65
}
66
67
void
68
J9::ARM64::MemoryReference::assignRegisters(TR::Instruction *currentInstruction, TR::CodeGenerator *cg)
69
{
70
TR::Machine *machine = cg->machine();
71
TR::Register *baseRegister = self()->getBaseRegister();
72
TR::Register *indexRegister = self()->getIndexRegister();
73
TR::Register *extraRegister = self()->getExtraRegister();
74
TR::RealRegister *assignedBaseRegister;
75
TR::RealRegister *assignedIndexRegister;
76
TR::RealRegister *assignedExtraRegister;
77
78
if (baseRegister != NULL)
79
{
80
assignedBaseRegister = baseRegister->getAssignedRealRegister();
81
if (indexRegister != NULL)
82
{
83
indexRegister->block();
84
}
85
if (extraRegister != NULL)
86
{
87
extraRegister->block();
88
}
89
90
if (assignedBaseRegister == NULL)
91
{
92
if (baseRegister->getTotalUseCount() == baseRegister->getFutureUseCount())
93
{
94
if ((assignedBaseRegister = machine->findBestFreeRegister(currentInstruction, TR_GPR, true, baseRegister)) == NULL)
95
{
96
assignedBaseRegister = machine->freeBestRegister(currentInstruction, baseRegister);
97
}
98
}
99
else
100
{
101
assignedBaseRegister = machine->reverseSpillState(currentInstruction, baseRegister);
102
}
103
baseRegister->setAssignedRegister(assignedBaseRegister);
104
assignedBaseRegister->setAssignedRegister(baseRegister);
105
assignedBaseRegister->setState(TR::RealRegister::Assigned);
106
}
107
108
if (indexRegister != NULL)
109
{
110
indexRegister->unblock();
111
}
112
if (extraRegister != NULL)
113
{
114
extraRegister->unblock();
115
}
116
}
117
118
if (indexRegister != NULL)
119
{
120
if (baseRegister != NULL)
121
{
122
baseRegister->block();
123
}
124
if (extraRegister != NULL)
125
{
126
extraRegister->block();
127
}
128
129
assignedIndexRegister = indexRegister->getAssignedRealRegister();
130
if (assignedIndexRegister == NULL)
131
{
132
if (indexRegister->getTotalUseCount() == indexRegister->getFutureUseCount())
133
{
134
if ((assignedIndexRegister = machine->findBestFreeRegister(currentInstruction, TR_GPR, false, indexRegister)) == NULL)
135
{
136
assignedIndexRegister = machine->freeBestRegister(currentInstruction, indexRegister);
137
}
138
}
139
else
140
{
141
assignedIndexRegister = machine->reverseSpillState(currentInstruction, indexRegister);
142
}
143
indexRegister->setAssignedRegister(assignedIndexRegister);
144
assignedIndexRegister->setAssignedRegister(indexRegister);
145
assignedIndexRegister->setState(TR::RealRegister::Assigned);
146
}
147
148
if (baseRegister != NULL)
149
{
150
baseRegister->unblock();
151
}
152
if (extraRegister != NULL)
153
{
154
extraRegister->unblock();
155
}
156
}
157
158
if (extraRegister != NULL)
159
{
160
if (baseRegister != NULL)
161
{
162
baseRegister->block();
163
}
164
if (indexRegister != NULL)
165
{
166
indexRegister->block();
167
}
168
169
assignedExtraRegister = extraRegister->getAssignedRealRegister();
170
if (assignedExtraRegister == NULL)
171
{
172
if (extraRegister->getTotalUseCount() == extraRegister->getFutureUseCount())
173
{
174
if ((assignedExtraRegister = machine->findBestFreeRegister(currentInstruction, TR_GPR, false, extraRegister)) == NULL)
175
{
176
assignedExtraRegister = machine->freeBestRegister(currentInstruction, extraRegister);
177
}
178
}
179
else
180
{
181
assignedExtraRegister = machine->reverseSpillState(currentInstruction, extraRegister);
182
}
183
extraRegister->setAssignedRegister(assignedExtraRegister);
184
assignedExtraRegister->setAssignedRegister(extraRegister);
185
assignedExtraRegister->setState(TR::RealRegister::Assigned);
186
}
187
188
if (baseRegister != NULL)
189
{
190
baseRegister->unblock();
191
}
192
if (indexRegister != NULL)
193
{
194
indexRegister->unblock();
195
}
196
}
197
198
if (baseRegister != NULL)
199
{
200
machine->decFutureUseCountAndUnlatch(currentInstruction, baseRegister);
201
self()->setBaseRegister(assignedBaseRegister);
202
}
203
204
if (indexRegister != NULL)
205
{
206
machine->decFutureUseCountAndUnlatch(currentInstruction, indexRegister);
207
self()->setIndexRegister(assignedIndexRegister);
208
}
209
210
if (extraRegister != NULL)
211
{
212
machine->decFutureUseCountAndUnlatch(currentInstruction, extraRegister);
213
TR_ASSERT(extraRegister->getFutureUseCount() == 0, "Unexpected future use count for extraReg");
214
self()->setExtraRegister(assignedExtraRegister);
215
}
216
217
if (self()->getUnresolvedSnippet() != NULL)
218
{
219
currentInstruction->ARM64NeedsGCMap(cg, 0xFFFFFFFF);
220
}
221
}
222
223
uint8_t *
224
J9::ARM64::MemoryReference::generateBinaryEncoding(TR::Instruction *currentInstruction, uint8_t *cursor, TR::CodeGenerator *cg)
225
{
226
TR::UnresolvedDataSnippet *snippet = self()->getUnresolvedSnippet();
227
228
if (snippet)
229
{
230
if (self()->getIndexRegister())
231
{
232
TR_ASSERT(false, "Unresolved indexed snippet is not supported");
233
return NULL;
234
}
235
else
236
{
237
uint32_t *wcursor = (uint32_t *)cursor;
238
uint32_t preserve = *wcursor; // original instruction
239
snippet->setAddressOfDataReference(cursor);
240
snippet->setMemoryReference(self());
241
cg->addRelocation(new (cg->trHeapMemory()) TR::LabelRelative32BitRelocation(cursor, snippet->getSnippetLabel()));
242
*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b); // b snippetLabel
243
wcursor++;
244
cursor += ARM64_INSTRUCTION_LENGTH;
245
246
TR_ASSERT(self()->getExtraRegister(), "extraReg must have been allocated");
247
TR::RealRegister *extraReg = toRealRegister(self()->getExtraRegister());
248
249
// insert instructions for computing the address of the resolved field;
250
// the actual immediate operands are patched in by L_mergedDataResolve
251
// in PicBuilder.spp
252
253
// movk extraReg, #0, LSL #16
254
*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::movkx) | (TR::MOV_LSL16 << 5);
255
extraReg->setRegisterFieldRD(wcursor);
256
wcursor++;
257
cursor += ARM64_INSTRUCTION_LENGTH;
258
259
// movk extraReg, #0, LSL #32
260
*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::movkx) | (TR::MOV_LSL32 << 5);
261
extraReg->setRegisterFieldRD(wcursor);
262
wcursor++;
263
cursor += ARM64_INSTRUCTION_LENGTH;
264
265
// movk extraReg, #0, LSL #48
266
*wcursor = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::movkx) | (TR::MOV_LSL48 << 5);
267
extraReg->setRegisterFieldRD(wcursor);
268
wcursor++;
269
cursor += ARM64_INSTRUCTION_LENGTH;
270
271
// finally, encode the original instruction
272
*wcursor = preserve;
273
TR::RealRegister *base = self()->getBaseRegister() ? toRealRegister(self()->getBaseRegister()) : NULL;
274
TR::InstOpCode::Mnemonic op = currentInstruction->getOpCodeValue();
275
if (op != TR::InstOpCode::addx)
276
{
277
// load/store instruction
278
if (op == TR::InstOpCode::ldrimmx || op == TR::InstOpCode::strimmx
279
|| op == TR::InstOpCode::ldrimmw || op == TR::InstOpCode::strimmw
280
|| op == TR::InstOpCode::ldrhimm || op == TR::InstOpCode::strhimm
281
|| op == TR::InstOpCode::ldrshimmx || op == TR::InstOpCode::ldrshimmw
282
|| op == TR::InstOpCode::ldrbimm || op == TR::InstOpCode::strbimm
283
|| op == TR::InstOpCode::ldrsbimmx || op == TR::InstOpCode::ldrsbimmw
284
|| op == TR::InstOpCode::vldrimmd || op == TR::InstOpCode::vstrimmd
285
|| op == TR::InstOpCode::vldrimms || op == TR::InstOpCode::vstrimms)
286
{
287
if (base)
288
{
289
// if the load or store had a base, add it in as an index.
290
base->setRegisterFieldRN(wcursor);
291
extraReg->setRegisterFieldRM(wcursor);
292
// Rewrite the instruction from "ldr Rt, [Rn, #imm]" to "ldr Rt, [Rn, Rm]"
293
cursor[1] |= 0x68; // Set bits 11, 13, 14
294
cursor[2] |= 0x20; // Set bit 21
295
cursor[3] &= 0xFE; // Clear bit 24
296
}
297
else
298
{
299
// ldr Rt, [Rn]
300
extraReg->setRegisterFieldRN(wcursor);
301
}
302
}
303
else
304
{
305
TR_ASSERT_FATAL(false, "Unsupported load/store instruction for unresolved data snippet");
306
}
307
}
308
else
309
{
310
// loadaddrEvaluator() uses addx in generateTrgMemInstruction
311
if (base)
312
{
313
// addx Rt, Rn, Rm
314
base->setRegisterFieldRN(wcursor);
315
extraReg->setRegisterFieldRM(wcursor);
316
}
317
else
318
{
319
extraReg->setRegisterFieldRN(wcursor);
320
// Rewrite the instruction from "addx Rd, Rn, Rm" to "addimmx Rd, Rn, #0"
321
cursor[3] = (uint8_t)0x91;
322
}
323
}
324
cursor += ARM64_INSTRUCTION_LENGTH;
325
326
return cursor;
327
}
328
}
329
else
330
{
331
return OMR::MemoryReferenceConnector::generateBinaryEncoding(currentInstruction, cursor, cg);
332
}
333
}
334
335
uint32_t
336
J9::ARM64::MemoryReference::estimateBinaryLength(TR::InstOpCode op)
337
{
338
if (self()->getUnresolvedSnippet())
339
{
340
if (self()->getIndexRegister())
341
{
342
TR_ASSERT(false, "Unresolved indexed snippet is not supported");
343
return 0;
344
}
345
else
346
{
347
return 5 * ARM64_INSTRUCTION_LENGTH;
348
}
349
}
350
else
351
{
352
return OMR::MemoryReferenceConnector::estimateBinaryLength(op);
353
}
354
}
355
356