Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/p/codegen/InterfaceCastSnippet.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 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 "p/codegen/InterfaceCastSnippet.hpp"
24
25
#include "codegen/Machine.hpp"
26
#include "env/CompilerEnv.hpp"
27
#include "env/IO.hpp"
28
#include "env/jittypes.h"
29
#include "env/VMJ9.h"
30
#include "il/LabelSymbol.hpp"
31
#include "il/Node.hpp"
32
#include "il/Node_inlines.hpp"
33
#include "p/codegen/PPCTableOfConstants.hpp"
34
35
TR::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)
36
: 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)
37
{
38
}
39
40
uint8_t *
41
TR::PPCInterfaceCastSnippet::emitSnippetBody()
42
{
43
TR::Compilation *comp = cg()->comp();
44
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());
45
46
uint8_t * cursor = cg()->getBinaryBufferCursor();
47
48
TR::InstOpCode opcode;
49
int32_t branchDistance;
50
51
getSnippetLabel()->setCodeLocation(cursor);
52
53
if (_checkCast)
54
{
55
TR::RegisterDependencyConditions *deps = _doneLabel->getInstruction()->getDependencyConditions();
56
TR::RealRegister *objReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(0)->getRealRegister());
57
TR::RealRegister *castClassReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
58
TR::RealRegister *objClassReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
59
TR::RealRegister *cndReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());
60
TR::RealRegister *scratch1Reg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(4)->getRealRegister());
61
62
// checkcast
63
64
// TODO: at present _testCastClassIsSuper is always false
65
66
// lwz/ld scratch1Reg, objReg(_offsetClazz)
67
// lwz/ld scratch1Reg, scratch1Reg(_offsetCastClassCache)
68
// cmpl4/cmpl8 cr0, castClassReg, scratch1Reg
69
// if (_testCastClassIsSuper)
70
// beq cr0, 8 (_doneLabel)
71
// b restartLabel
72
// 8: b _doneLabel
73
// else
74
// bne cr0, 8 (_callLabel)
75
// b doneLabel
76
// 8: b _callLabel
77
78
if (comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())
79
opcode.setOpCodeValue(TR::InstOpCode::ld);
80
else
81
opcode.setOpCodeValue(TR::InstOpCode::lwz);
82
cursor = opcode.copyBinaryToBuffer(cursor);
83
scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);
84
objReg->setRegisterFieldRA((uint32_t *)cursor);
85
*(int32_t *)cursor |= _offsetClazz & 0xffff;
86
cursor += PPC_INSTRUCTION_LENGTH;
87
88
if (comp->target().is64Bit())
89
opcode.setOpCodeValue(TR::InstOpCode::ld);
90
else
91
opcode.setOpCodeValue(TR::InstOpCode::lwz);
92
cursor = opcode.copyBinaryToBuffer(cursor);
93
scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);
94
scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);
95
*(int32_t *)cursor |= _offsetCastClassCache & 0xffff;
96
cursor += PPC_INSTRUCTION_LENGTH;
97
98
if (comp->target().is64Bit())
99
opcode.setOpCodeValue(TR::InstOpCode::cmpl8);
100
else
101
opcode.setOpCodeValue(TR::InstOpCode::cmpl4);
102
cursor = opcode.copyBinaryToBuffer(cursor);
103
cndReg->setRegisterFieldRT((uint32_t *)cursor);
104
castClassReg->setRegisterFieldRA((uint32_t *)cursor);
105
scratch1Reg->setRegisterFieldRB((uint32_t *)cursor);
106
cursor += PPC_INSTRUCTION_LENGTH;
107
108
if (_testCastClassIsSuper)
109
{
110
opcode.setOpCodeValue(TR::InstOpCode::beq);
111
cursor = opcode.copyBinaryToBuffer(cursor);
112
cndReg->setRegisterFieldBI((uint32_t *)cursor);
113
branchDistance = (intptr_t) 8; // Jump two instructions below
114
*(int32_t *)cursor |= (branchDistance & 0x0fffc);
115
cursor += PPC_INSTRUCTION_LENGTH;
116
117
opcode.setOpCodeValue(TR::InstOpCode::b);
118
cursor = opcode.copyBinaryToBuffer(cursor);
119
branchDistance = (intptr_t)getReStartLabel()->getCodeLocation() - (intptr_t)cursor;
120
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)getReStartLabel()->getCodeLocation(), (intptr_t)cursor),
121
"backward jump in Interface Cache is too long\n");
122
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
123
cursor += PPC_INSTRUCTION_LENGTH;
124
125
opcode.setOpCodeValue(TR::InstOpCode::b);
126
cursor = opcode.copyBinaryToBuffer(cursor);
127
branchDistance = (intptr_t)_doneLabel->getCodeLocation() - (intptr_t)cursor;
128
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_doneLabel->getCodeLocation(), (intptr_t)cursor),
129
"backward jump in Interface Cache is too long\n");
130
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
131
cursor += PPC_INSTRUCTION_LENGTH;
132
}
133
else
134
{
135
opcode.setOpCodeValue(TR::InstOpCode::bne);
136
cursor = opcode.copyBinaryToBuffer(cursor);
137
cndReg->setRegisterFieldBI((uint32_t *)cursor);
138
branchDistance = (intptr_t) 8; // Jump two instructions below
139
*(int32_t *)cursor |= (branchDistance & 0x0fffc);
140
cursor += PPC_INSTRUCTION_LENGTH;
141
142
opcode.setOpCodeValue(TR::InstOpCode::b);
143
cursor = opcode.copyBinaryToBuffer(cursor);
144
branchDistance = (intptr_t)getDoneLabel()->getCodeLocation() - (intptr_t)cursor;
145
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)getDoneLabel()->getCodeLocation(), (intptr_t)cursor),
146
"backward jump in Interface Cache is too long\n");
147
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
148
cursor += PPC_INSTRUCTION_LENGTH;
149
150
opcode.setOpCodeValue(TR::InstOpCode::b);
151
cursor = opcode.copyBinaryToBuffer(cursor);
152
branchDistance = (intptr_t)_callLabel->getCodeLocation() - (intptr_t)cursor;
153
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_callLabel->getCodeLocation(), (intptr_t)cursor),
154
"backward jump in Interface Cache is too long\n");
155
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
156
cursor += PPC_INSTRUCTION_LENGTH;
157
}
158
}
159
else // if not _checkcast, then it is instanceof
160
{
161
auto firstArgReg = getNode()->getSymbol()->castToMethodSymbol()->getLinkageConvention() == TR_CHelper ? TR::RealRegister::gr4 : TR::RealRegister::gr3;
162
TR::RegisterDependencyConditions *deps = _doneLabel->getInstruction()->getDependencyConditions();
163
TR::RealRegister *castClassReg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg));
164
TR::RealRegister *objClassReg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 3));
165
TR::RealRegister *resultReg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 5));
166
TR::RealRegister *cndReg = cg()->machine()->getRealRegister(TR::RealRegister::cr0);
167
TR::RealRegister *scratch1Reg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 2));
168
TR::RealRegister *scratch2Reg = cg()->machine()->getRealRegister(static_cast<TR::RealRegister::RegNum>(firstArgReg + 4));
169
170
// instanceof
171
172
// lwz/ld scratch2Reg, objClassReg(_offsetCastClassCache)
173
// if (comp->target().is64Bit())
174
// sh=0
175
// me=62
176
// rldicr scratch1Reg, scratch2Reg, 0, 0x3d
177
// else
178
// rlwinm scratch1Reg, scratch2Reg, 0, 0xFFFF FFFE
179
// cmpl cr0, scratch1Reg, castClassReg
180
// if (_testCastClassIsSuper)
181
// beq cr0, 8 (continue)
182
// b restartLabel
183
// else
184
// beq cr0, 8 (continue)
185
// b callLabel
186
// 8:
187
// if (_needsResult)
188
// li scratch1Reg, 0x1
189
// or scratch1Reg, scratch1Reg, scratch2Reg
190
// xor. resultReg, scratch1Reg, scratch2Reg
191
// if (_falseLabel != _trueLabel)
192
// bne cr0, 8 (_falseLabel)
193
// b _trueLabel
194
// 8: b _falseLabel // branch if xor. does not set 0 on resultReg
195
// else
196
// b _doneLabel
197
// else
198
// if (_falseLabel != _trueLabel)
199
// li scratch1Reg, 0x1
200
// and. scratch1Reg, scratch1Reg, scratch2Reg
201
// bne cr0, 8 (_falseLabel)
202
// b _trueLabel
203
// 8: b _falseLabel // branch if and. does not set 0 on scratch1Reg
204
// else
205
// b _doneLabel
206
207
// TODO: this code is set on 390.
208
// int32_t offset = _offsetCastClassCache;
209
// if (comp->target().is64Bit())
210
// {
211
// offset += 4;
212
// }
213
214
if (comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())
215
opcode.setOpCodeValue(TR::InstOpCode::ld);
216
else
217
opcode.setOpCodeValue(TR::InstOpCode::lwz);
218
cursor = opcode.copyBinaryToBuffer(cursor);
219
scratch2Reg->setRegisterFieldRT((uint32_t *)cursor);
220
objClassReg->setRegisterFieldRA((uint32_t *)cursor);
221
*(int32_t *)cursor |= _offsetCastClassCache & 0xffff;
222
cursor += PPC_INSTRUCTION_LENGTH;
223
224
if (comp->target().is64Bit())
225
{
226
opcode.setOpCodeValue(TR::InstOpCode::rldicr);
227
cursor = opcode.copyBinaryToBuffer(cursor);
228
scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);
229
scratch2Reg->setRegisterFieldRS((uint32_t *)cursor);
230
*(int32_t *)cursor |= (0x3d << 5);
231
}
232
else
233
{
234
opcode.setOpCodeValue(TR::InstOpCode::rlwinm);
235
cursor = opcode.copyBinaryToBuffer(cursor);
236
scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);
237
scratch2Reg->setRegisterFieldRS((uint32_t *)cursor);
238
*(int32_t *)cursor |= (30 << 1);
239
}
240
cursor += PPC_INSTRUCTION_LENGTH;
241
242
if (comp->target().is64Bit())
243
opcode.setOpCodeValue(TR::InstOpCode::cmpl8);
244
else
245
opcode.setOpCodeValue(TR::InstOpCode::cmpl4);
246
cursor = opcode.copyBinaryToBuffer(cursor);
247
cndReg->setRegisterFieldRT((uint32_t *)cursor);
248
scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);
249
castClassReg->setRegisterFieldRB((uint32_t *)cursor);
250
cursor += PPC_INSTRUCTION_LENGTH;
251
252
if (_testCastClassIsSuper)
253
{
254
opcode.setOpCodeValue(TR::InstOpCode::beq);
255
cursor = opcode.copyBinaryToBuffer(cursor);
256
cndReg->setRegisterFieldBI((uint32_t *)cursor);
257
branchDistance = (intptr_t) 8; // Jump two instructions below
258
*(int32_t *)cursor |= (branchDistance & 0x0fffc);
259
cursor += PPC_INSTRUCTION_LENGTH;
260
261
opcode.setOpCodeValue(TR::InstOpCode::b);
262
cursor = opcode.copyBinaryToBuffer(cursor);
263
branchDistance = (intptr_t)getReStartLabel()->getCodeLocation() - (intptr_t)cursor;
264
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)getReStartLabel()->getCodeLocation(), (intptr_t)cursor),
265
"backward jump in Interface Cache is too long\n");
266
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
267
cursor += PPC_INSTRUCTION_LENGTH;
268
}
269
else
270
{
271
opcode.setOpCodeValue(TR::InstOpCode::beq);
272
cursor = opcode.copyBinaryToBuffer(cursor);
273
cndReg->setRegisterFieldBI((uint32_t *)cursor);
274
branchDistance = (intptr_t) 8; // Jump two instructions below
275
*(int32_t *)cursor |= (branchDistance & 0x0fffc);
276
cursor += PPC_INSTRUCTION_LENGTH;
277
278
opcode.setOpCodeValue(TR::InstOpCode::b);
279
cursor = opcode.copyBinaryToBuffer(cursor);
280
branchDistance = (intptr_t)_callLabel->getCodeLocation() - (intptr_t)cursor;
281
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_callLabel->getCodeLocation(), (intptr_t)cursor),
282
"backward jump in Interface Cache is too long\n");
283
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
284
cursor += PPC_INSTRUCTION_LENGTH;
285
}
286
287
if (_needsResult)
288
{
289
opcode.setOpCodeValue(TR::InstOpCode::addi);
290
cursor = opcode.copyBinaryToBuffer(cursor);
291
scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);
292
*(int32_t *)cursor |= 0x1;
293
cursor += PPC_INSTRUCTION_LENGTH;
294
295
opcode.setOpCodeValue(TR::InstOpCode::OR);
296
cursor = opcode.copyBinaryToBuffer(cursor);
297
scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);
298
scratch1Reg->setRegisterFieldRS((uint32_t *)cursor);
299
scratch2Reg->setRegisterFieldRB((uint32_t *)cursor);
300
cursor += PPC_INSTRUCTION_LENGTH;
301
302
opcode.setOpCodeValue(TR::InstOpCode::XOR);
303
cursor = opcode.copyBinaryToBuffer(cursor);
304
resultReg->setRegisterFieldRA((uint32_t *)cursor);
305
scratch1Reg->setRegisterFieldRS((uint32_t *)cursor);
306
scratch2Reg->setRegisterFieldRB((uint32_t *)cursor);
307
*(int32_t *)cursor |= 0x1; // Rc = 1
308
cursor += PPC_INSTRUCTION_LENGTH;
309
310
if (_falseLabel != _trueLabel)
311
{
312
opcode.setOpCodeValue(TR::InstOpCode::bne);
313
cursor = opcode.copyBinaryToBuffer(cursor);
314
cndReg->setRegisterFieldBI((uint32_t *)cursor);
315
branchDistance = (intptr_t) 8; // Jump two instructions below
316
*(int32_t *)cursor |= (branchDistance & 0x0fffc);
317
cursor += PPC_INSTRUCTION_LENGTH;
318
319
opcode.setOpCodeValue(TR::InstOpCode::b);
320
cursor = opcode.copyBinaryToBuffer(cursor);
321
branchDistance = (intptr_t)_trueLabel->getCodeLocation() - (intptr_t)cursor;
322
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_trueLabel->getCodeLocation(), (intptr_t)cursor),
323
"backward jump in Interface Cache is too long\n");
324
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
325
cursor += PPC_INSTRUCTION_LENGTH;
326
327
opcode.setOpCodeValue(TR::InstOpCode::b);
328
cursor = opcode.copyBinaryToBuffer(cursor);
329
branchDistance = (intptr_t)_falseLabel->getCodeLocation() - (intptr_t)cursor;
330
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_falseLabel->getCodeLocation(), (intptr_t)cursor),
331
"backward jump in Interface Cache is too long\n");
332
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
333
cursor += PPC_INSTRUCTION_LENGTH;
334
}
335
else
336
{
337
opcode.setOpCodeValue(TR::InstOpCode::b);
338
cursor = opcode.copyBinaryToBuffer(cursor);
339
branchDistance = (intptr_t)_doneLabel->getCodeLocation() - (intptr_t)cursor;
340
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_doneLabel->getCodeLocation(), (intptr_t)cursor),
341
"backward jump in Interface Cache is too long\n");
342
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
343
cursor += PPC_INSTRUCTION_LENGTH;
344
}
345
}
346
else
347
{
348
if (_falseLabel != _trueLabel)
349
{
350
opcode.setOpCodeValue(TR::InstOpCode::addi);
351
cursor = opcode.copyBinaryToBuffer(cursor);
352
scratch1Reg->setRegisterFieldRT((uint32_t *)cursor);
353
*(int32_t *)cursor |= 0x1;
354
cursor += PPC_INSTRUCTION_LENGTH;
355
356
opcode.setOpCodeValue(TR::InstOpCode::AND);
357
cursor = opcode.copyBinaryToBuffer(cursor);
358
scratch1Reg->setRegisterFieldRA((uint32_t *)cursor);
359
scratch1Reg->setRegisterFieldRS((uint32_t *)cursor);
360
scratch2Reg->setRegisterFieldRB((uint32_t *)cursor);
361
*(int32_t *)cursor |= 0x1; // Rc = 1
362
cursor += PPC_INSTRUCTION_LENGTH;
363
364
opcode.setOpCodeValue(TR::InstOpCode::bne);
365
cursor = opcode.copyBinaryToBuffer(cursor);
366
cndReg->setRegisterFieldBI((uint32_t *)cursor);
367
branchDistance = (intptr_t) 8; // Jump two instructions below
368
*(int32_t *)cursor |= (branchDistance & 0x0fffc);
369
cursor += PPC_INSTRUCTION_LENGTH;
370
371
opcode.setOpCodeValue(TR::InstOpCode::b);
372
cursor = opcode.copyBinaryToBuffer(cursor);
373
branchDistance = (intptr_t)_trueLabel->getCodeLocation() - (intptr_t)cursor;
374
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_trueLabel->getCodeLocation(), (intptr_t)cursor),
375
"backward jump in Interface Cache is too long\n");
376
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
377
cursor += PPC_INSTRUCTION_LENGTH;
378
379
opcode.setOpCodeValue(TR::InstOpCode::b);
380
cursor = opcode.copyBinaryToBuffer(cursor);
381
branchDistance = (intptr_t)_falseLabel->getCodeLocation() - (intptr_t)cursor;
382
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_falseLabel->getCodeLocation(), (intptr_t)cursor),
383
"backward jump in Interface Cache is too long\n");
384
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
385
cursor += PPC_INSTRUCTION_LENGTH;
386
}
387
else
388
{
389
opcode.setOpCodeValue(TR::InstOpCode::b);
390
cursor = opcode.copyBinaryToBuffer(cursor);
391
branchDistance = (intptr_t)_doneLabel->getCodeLocation() - (intptr_t)cursor;
392
TR_ASSERT(comp->target().cpu.isTargetWithinIFormBranchRange((intptr_t)_doneLabel->getCodeLocation(), (intptr_t)cursor),
393
"backward jump in Interface Cache is too long\n");
394
*(int32_t *)cursor |= (branchDistance & 0x03fffffc);
395
cursor += PPC_INSTRUCTION_LENGTH;
396
}
397
}
398
}
399
return cursor;
400
}
401
402
403
void
404
TR_Debug::print(TR::FILE *pOutFile, TR::PPCInterfaceCastSnippet * snippet)
405
{
406
TR_J9VMBase *fej9 = (TR_J9VMBase *)(_cg->fe());
407
uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation();
408
bool checkcast = snippet->isCheckCast();
409
410
if (checkcast)
411
{
412
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Interface Cast Snippet for Checkcast");
413
414
TR::RegisterDependencyConditions *deps = snippet->getDoneLabel()->getInstruction()->getDependencyConditions();
415
TR::RealRegister *objReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(0)->getRealRegister());
416
TR::RealRegister *castClassReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
417
TR::RealRegister *objClassReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
418
TR::RealRegister *cndReg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());
419
TR::RealRegister *scratch1Reg = _cg->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(4)->getRealRegister());
420
421
int32_t value;
422
423
printPrefix(pOutFile, NULL, cursor, 4);
424
value = *((int32_t *) cursor) & 0x0ffff;
425
if (_comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())
426
trfprintf(pOutFile, "ld \t%s, [%s, %d]\t; Load object class", getName(scratch1Reg), getName(objReg), value );
427
else
428
trfprintf(pOutFile, "lwz \t%s, [%s, %d]\t; Load object class", getName(scratch1Reg), getName(objReg), value );
429
cursor+=4;
430
431
printPrefix(pOutFile, NULL, cursor, 4);
432
value = *((int32_t *) cursor) & 0x0ffff;
433
if (_comp->target().is64Bit())
434
trfprintf(pOutFile, "ld \t%s, [%s, %d]\t; Load castClassCache", getName(scratch1Reg), getName(scratch1Reg), value );
435
else
436
trfprintf(pOutFile, "lwz \t%s, [%s, %d]\t; Load castClassCache", getName(scratch1Reg), getName(scratch1Reg), value );
437
cursor+=4;
438
439
printPrefix(pOutFile, NULL, cursor, 4);
440
trfprintf(pOutFile, "cmpl \t%s, %s, %s\t; Compare with type to cast", getName(cndReg), getName(castClassReg), getName(scratch1Reg) );
441
cursor+=4;
442
443
if (snippet->getTestCastClassIsSuper())
444
{
445
printPrefix(pOutFile, NULL, cursor, 4);
446
value = *((int32_t *) cursor) & 0xfffc;
447
value = (value << 16) >> 16; // sign extend
448
trfprintf(pOutFile, "beq \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);
449
cursor += 4;
450
451
printPrefix(pOutFile, NULL, cursor, 4);
452
value = *((int32_t *) cursor) & 0x03fffffc;
453
value = (value << 6) >> 6; // sign extend
454
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
455
cursor += 4;
456
457
printPrefix(pOutFile, NULL, cursor, 4);
458
value = *((int32_t *) cursor) & 0x03fffffc;
459
value = (value << 6) >> 6; // sign extend
460
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
461
cursor += 4;
462
}
463
else
464
{
465
printPrefix(pOutFile, NULL, cursor, 4);
466
value = *((int32_t *) cursor) & 0xfffc;
467
value = (value << 16) >> 16; // sign extend
468
trfprintf(pOutFile, "bne \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);
469
cursor += 4;
470
471
printPrefix(pOutFile, NULL, cursor, 4);
472
value = *((int32_t *) cursor) & 0x03fffffc;
473
value = (value << 6) >> 6; // sign extend
474
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
475
cursor += 4;
476
477
printPrefix(pOutFile, NULL, cursor, 4);
478
value = *((int32_t *) cursor) & 0x03fffffc;
479
value = (value << 6) >> 6; // sign extend
480
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
481
cursor += 4;
482
}
483
}
484
else
485
{
486
// InstanceOf has trueLabel = falseLabel
487
// in ifInstanceOf, trueLabel != falseLabel
488
489
if (snippet->getTrueLabel() == snippet->getFalseLabel())
490
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Interface Cast Snippet for instanceOf");
491
else
492
printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Interface Cast Snippet for ifInstanceOf");
493
494
TR::RegisterDependencyConditions *deps = snippet->getDoneLabel()->getInstruction()->getDependencyConditions();
495
TR::RealRegister *castClassReg = _cg->machine()->getRealRegister(TR::RealRegister::gr3);
496
TR::RealRegister *objClassReg = _cg->machine()->getRealRegister(TR::RealRegister::gr6);
497
TR::RealRegister *resultReg = _cg->machine()->getRealRegister(TR::RealRegister::gr8);
498
TR::RealRegister *cndReg = _cg->machine()->getRealRegister(TR::RealRegister::cr0);
499
TR::RealRegister *scratch1Reg = _cg->machine()->getRealRegister(TR::RealRegister::gr5);
500
TR::RealRegister *scratch2Reg = _cg->machine()->getRealRegister(TR::RealRegister::gr7);
501
502
int32_t value;
503
504
printPrefix(pOutFile, NULL, cursor, 4);
505
value = *((int32_t *) cursor) & 0x0ffff;
506
if (_comp->target().is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders())
507
trfprintf(pOutFile, "ld \t%s, [%s, %d]\t; Load castClassCache", getName(scratch2Reg), getName(objClassReg), value );
508
else
509
trfprintf(pOutFile, "lwz \t%s, [%s, %d]\t; Load castClassCache", getName(scratch2Reg), getName(objClassReg), value );
510
cursor+=4;
511
512
printPrefix(pOutFile, NULL, cursor, 4);
513
if (_comp->target().is64Bit())
514
trfprintf(pOutFile, "rldicr \t%s, %s, 0, 0x3D; Clean last bit (cached result)", getName(scratch1Reg), getName(scratch2Reg));
515
else
516
trfprintf(pOutFile, "rlwinm \t%s, %s, 0, 0xFFFFFFFE; Clean last bit (cached result)", getName(scratch1Reg), getName(scratch2Reg));
517
cursor+= 4;
518
519
printPrefix(pOutFile, NULL, cursor, 4);
520
trfprintf(pOutFile, "cmpl \t%s, %s, %s\t; Compare with type to cast", getName(cndReg), getName(scratch1Reg), getName(castClassReg) );
521
cursor+=4;
522
523
if (snippet->getTestCastClassIsSuper())
524
{
525
printPrefix(pOutFile, NULL, cursor, 4);
526
value = *((int32_t *) cursor) & 0xfffc;
527
value = (value << 16) >> 16; // sign extend
528
trfprintf(pOutFile, "beq \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);
529
cursor += 4;
530
531
printPrefix(pOutFile, NULL, cursor, 4);
532
value = *((int32_t *) cursor) & 0x03fffffc;
533
value = (value << 6) >> 6; // sign extend
534
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
535
cursor += 4;
536
}
537
else
538
{
539
printPrefix(pOutFile, NULL, cursor, 4);
540
value = *((int32_t *) cursor) & 0xfffc;
541
value = (value << 16) >> 16; // sign extend
542
trfprintf(pOutFile, "beq \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);
543
cursor += 4;
544
545
printPrefix(pOutFile, NULL, cursor, 4);
546
value = *((int32_t *) cursor) & 0x03fffffc;
547
value = (value << 6) >> 6; // sign extend
548
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
549
cursor += 4;
550
}
551
552
if (snippet->getNeedsResult())
553
{
554
printPrefix(pOutFile, NULL, cursor, 4);
555
trfprintf(pOutFile, "li \t%s, %d", getName(scratch1Reg), *((int32_t *) cursor) & 0x0000ffff);
556
cursor += 4;
557
558
printPrefix(pOutFile, NULL, cursor, 4);
559
trfprintf(pOutFile, "or \t%s, %s, %s; Set the last bit", getName(scratch1Reg), getName(scratch1Reg), getName(scratch2Reg));
560
cursor+= 4;
561
562
printPrefix(pOutFile, NULL, cursor, 4);
563
trfprintf(pOutFile, "xor. \t%s, %s, %s; Check if last bit is set in the cache", getName(resultReg), getName(scratch1Reg), getName(scratch2Reg));
564
cursor+= 4;
565
566
if (snippet->getFalseLabel() != snippet->getTrueLabel())
567
{
568
printPrefix(pOutFile, NULL, cursor, 4);
569
value = *((int32_t *) cursor) & 0xfffc;
570
value = (value << 16) >> 16; // sign extend
571
trfprintf(pOutFile, "bne \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);
572
cursor += 4;
573
574
printPrefix(pOutFile, NULL, cursor, 4);
575
value = *((int32_t *) cursor) & 0x03fffffc;
576
value = (value << 6) >> 6; // sign extend
577
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
578
cursor += 4;
579
580
printPrefix(pOutFile, NULL, cursor, 4);
581
value = *((int32_t *) cursor) & 0x03fffffc;
582
value = (value << 6) >> 6; // sign extend
583
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
584
cursor += 4;
585
}
586
else
587
{
588
printPrefix(pOutFile, NULL, cursor, 4);
589
value = *((int32_t *) cursor) & 0x03fffffc;
590
value = (value << 6) >> 6; // sign extend
591
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
592
cursor += 4;
593
}
594
}
595
else
596
{
597
if (snippet->getFalseLabel() != snippet->getTrueLabel())
598
{
599
printPrefix(pOutFile, NULL, cursor, 4);
600
trfprintf(pOutFile, "li \t%s, %d", getName(scratch1Reg), *((int32_t *) cursor) & 0x0000ffff);
601
cursor += 4;
602
603
printPrefix(pOutFile, NULL, cursor, 4);
604
trfprintf(pOutFile, "and. \t%s, %s, %s; Check if last bit is set in the cache", getName(scratch1Reg), getName(scratch1Reg), getName(scratch2Reg));
605
cursor+= 4;
606
607
printPrefix(pOutFile, NULL, cursor, 4);
608
value = *((int32_t *) cursor) & 0xfffc;
609
value = (value << 16) >> 16; // sign extend
610
trfprintf(pOutFile, "bne \t%s, 0x%p\t;", getName(cndReg), (intptr_t)cursor + value);
611
cursor += 4;
612
613
printPrefix(pOutFile, NULL, cursor, 4);
614
value = *((int32_t *) cursor) & 0x03fffffc;
615
value = (value << 6) >> 6; // sign extend
616
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
617
cursor += 4;
618
619
printPrefix(pOutFile, NULL, cursor, 4);
620
value = *((int32_t *) cursor) & 0x03fffffc;
621
value = (value << 6) >> 6; // sign extend
622
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
623
cursor += 4;
624
}
625
else
626
{
627
printPrefix(pOutFile, NULL, cursor, 4);
628
value = *((int32_t *) cursor) & 0x03fffffc;
629
value = (value << 6) >> 6; // sign extend
630
trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t;", (intptr_t)cursor + value);
631
cursor += 4;
632
}
633
}
634
}
635
}
636
637
638
uint32_t
639
TR::PPCInterfaceCastSnippet::getLength(int32_t estimatedSnippetStart)
640
{
641
uint32_t size;
642
643
if (_checkCast)
644
{
645
size = 6;
646
}
647
else // interfaceof
648
{
649
size = 5;
650
651
if (_needsResult)
652
{
653
size += 4;
654
if (_falseLabel != _trueLabel)
655
{
656
size += 3;
657
}
658
else
659
{
660
size += 1;
661
}
662
}
663
else
664
{
665
if (_falseLabel != _trueLabel)
666
{
667
size += 5;
668
}
669
else
670
{
671
size += 1;
672
}
673
}
674
}
675
676
return size * PPC_INSTRUCTION_LENGTH;
677
}
678
679
680