Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/arm/codegen/J9ARMSnippet.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
#include "j9.h"
24
25
#include "arm/codegen/J9ARMSnippet.hpp"
26
27
#include <stdint.h>
28
#include "arm/codegen/ARMInstruction.hpp"
29
#include "codegen/Machine.hpp"
30
#include "env/CompilerEnv.hpp"
31
#include "env/IO.hpp"
32
#include "env/jittypes.h"
33
#include "il/Node.hpp"
34
#include "il/Node_inlines.hpp"
35
#include "runtime/J9CodeCache.hpp"
36
37
TR::ARMMonitorEnterSnippet::ARMMonitorEnterSnippet(
38
TR::CodeGenerator *codeGen,
39
TR::Node *monitorNode,
40
int32_t lwOffset,
41
//bool isPreserving,
42
TR::LabelSymbol *incLabel,
43
TR::LabelSymbol *callLabel,
44
TR::LabelSymbol *restartLabel)
45
: _incLabel(incLabel),
46
_lwOffset(lwOffset),
47
// _isReservationPreserving(isPreserving),
48
TR::ARMHelperCallSnippet(codeGen, monitorNode, callLabel, monitorNode->getSymbolReference(), restartLabel)
49
{
50
// Helper call, preserves all registers
51
//
52
incLabel->setSnippet(this);
53
gcMap().setGCRegisterMask(0xFFFFFFFF);
54
}
55
56
uint8_t *TR::ARMMonitorEnterSnippet::emitSnippetBody()
57
{
58
59
// The 32-bit code for the snippet looks like:
60
// incLabel:
61
// mvn tempReg, (OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT) -> 0x7f
62
// and tempReg, dataReg, tempReg
63
// cmp metaReg, tempReg
64
// addeq dataReg, dataReg, LOCK_INC_DEC_VALUE
65
// streq dataReg, [addrReg]
66
// beq restartLabel
67
// callLabel:
68
// bl jitMonitorEntry <- HelperSnippet
69
// b restartLabel;
70
71
TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();
72
73
TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();
74
TR::RealRegister *dataReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
75
TR::RealRegister *addrReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
76
TR::RealRegister *tempReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());
77
78
TR::InstOpCode opcode;
79
TR::InstOpCode::Mnemonic opCodeValue;
80
81
uint8_t *buffer = cg()->getBinaryBufferCursor();
82
83
_incLabel->setCodeLocation(buffer);
84
85
opcode.setOpCodeValue(TR::InstOpCode::mvn);
86
buffer = opcode.copyBinaryToBuffer(buffer);
87
tempReg->setRegisterFieldRD((uint32_t *)buffer);
88
// OBJECT_HEADER_LOCK_BITS_MASK is 0xFF
89
// OBJECT_HEADER_LOCK_LAST_RECURSION_BIT is 0x80
90
// Taken out before complement 0x7F
91
// rotate_imm is 0 and immed_8 is 0x7F, I bit set to 1, result should be 0xFFFFFF80
92
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeAL) << 28 | 0x1 << 25 | (OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT));
93
buffer += ARM_INSTRUCTION_LENGTH;
94
95
opcode.setOpCodeValue(TR::InstOpCode::and_);
96
buffer = opcode.copyBinaryToBuffer(buffer);
97
tempReg->setRegisterFieldRD((uint32_t *)buffer);
98
dataReg->setRegisterFieldRN((uint32_t *)buffer);
99
tempReg->setRegisterFieldRM((uint32_t *)buffer);
100
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeAL) << 28);
101
buffer += ARM_INSTRUCTION_LENGTH;
102
103
opcode.setOpCodeValue(TR::InstOpCode::cmp);
104
buffer = opcode.copyBinaryToBuffer(buffer);
105
metaReg->setRegisterFieldRN((uint32_t *)buffer);
106
tempReg->setRegisterFieldRM((uint32_t *)buffer);
107
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeAL) << 28);
108
buffer += ARM_INSTRUCTION_LENGTH;
109
110
opcode.setOpCodeValue(TR::InstOpCode::add);
111
buffer = opcode.copyBinaryToBuffer(buffer);
112
dataReg->setRegisterFieldRD((uint32_t *)buffer);
113
dataReg->setRegisterFieldRN((uint32_t *)buffer);
114
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeEQ) << 28 | 0x1 << 25 | LOCK_INC_DEC_VALUE);
115
buffer += ARM_INSTRUCTION_LENGTH;
116
117
opcode.setOpCodeValue(TR::InstOpCode::str);
118
buffer = opcode.copyBinaryToBuffer(buffer);
119
dataReg->setRegisterFieldRD((uint32_t *)buffer);
120
addrReg->setRegisterFieldRN((uint32_t *)buffer); // offset_12 = 0, U = X, B = 0, L = 0
121
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeEQ) << 28);
122
// No modification needed
123
buffer += ARM_INSTRUCTION_LENGTH;
124
125
opcode.setOpCodeValue(TR::InstOpCode::b);
126
buffer = opcode.copyBinaryToBuffer(buffer);
127
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeEQ) << 28 | ((getRestartLabel()->getCodeLocation() - buffer - 8) >> 2) & 0x00FFFFFF);
128
buffer += ARM_INSTRUCTION_LENGTH;
129
130
cg()->setBinaryBufferCursor(buffer);
131
buffer = TR::ARMHelperCallSnippet::emitSnippetBody();
132
133
return buffer;
134
}
135
136
137
void
138
TR::ARMMonitorEnterSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)
139
{
140
uint8_t *bufferPos = getIncLabel()->getCodeLocation();
141
// debug->printSnippetLabel(pOutFile, getIncLabel(), bufferPos, debug->getName(snippet));
142
debug->printSnippetLabel(pOutFile, getIncLabel(), bufferPos, "Inc Monitor Counter");
143
144
TR::Machine *machine = cg()->machine();
145
TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();
146
TR::LabelSymbol *restartLabel = getRestartLabel();
147
TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();
148
TR::RealRegister *dataReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
149
TR::RealRegister *addrReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
150
TR::RealRegister *tempReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());
151
152
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
153
// mvn tempReg, (OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT) -> 0x7f
154
trfprintf(pOutFile, "mvn \t%s, #0x%08x; (OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT)", debug->getName(tempReg), (OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT));
155
bufferPos += 4;
156
157
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
158
// and tempReg, dataReg, tempReg
159
trfprintf(pOutFile, "and \t%s, %s, %s;", debug->getName(tempReg), debug->getName(dataReg), debug->getName(tempReg));
160
bufferPos += 4;
161
162
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
163
// cmp metaReg, tempReg
164
trfprintf(pOutFile, "cmp \t%s, %s; ", debug->getName(metaReg), debug->getName(tempReg));
165
bufferPos += 4;
166
167
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
168
// addeq dataReg, dataReg, LOCK_INC_DEC_VALUE
169
trfprintf(pOutFile, "addeq \t%s, %s, #0x%08x; Increment the count", debug->getName(dataReg), debug->getName(dataReg), LOCK_INC_DEC_VALUE);
170
bufferPos += 4;
171
172
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
173
// streq dataReg, [addrReg]
174
trfprintf(pOutFile, "streq \t%s, [%s]; Increment the count", debug->getName(dataReg), debug->getName(addrReg));
175
bufferPos += 4;
176
177
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
178
// beq restartLabel
179
trfprintf(pOutFile, "beq\t" POINTER_PRINTF_FORMAT "\t\t; Return to %s", (intptr_t)(restartLabel->getCodeLocation()), debug->getName(restartLabel));
180
debug->print(pOutFile, (TR::ARMHelperCallSnippet *)this);
181
}
182
uint32_t TR::ARMMonitorEnterSnippet::getLength(int32_t estimatedSnippetStart)
183
{
184
int32_t len = 28;
185
len += TR::ARMHelperCallSnippet::getLength(estimatedSnippetStart+len);
186
return len;
187
}
188
189
int32_t TR::ARMMonitorEnterSnippet::setEstimatedCodeLocation(int32_t estimatedSnippetStart)
190
{
191
_incLabel->setEstimatedCodeLocation(estimatedSnippetStart);
192
getSnippetLabel()->setEstimatedCodeLocation(estimatedSnippetStart+ 28);
193
return(estimatedSnippetStart);
194
}
195
196
197
TR::ARMMonitorExitSnippet::ARMMonitorExitSnippet(
198
TR::CodeGenerator *codeGen,
199
TR::Node *monitorNode,
200
int32_t lwOffset,
201
//bool flag,
202
//bool isPreserving,
203
TR::LabelSymbol *decLabel,
204
//TR::LabelSymbol *restoreAndCallLabel,
205
TR::LabelSymbol *callLabel,
206
TR::LabelSymbol *restartLabel)
207
: _decLabel(decLabel),
208
//_restoreAndCallLabel(restartLabel),
209
_lwOffset(lwOffset),
210
//_isReadOnly(flag),
211
//_isReservationPreserving(isPreserving),
212
TR::ARMHelperCallSnippet(codeGen, monitorNode, callLabel, monitorNode->getSymbolReference(), restartLabel)
213
{
214
// Helper call, preserves all registers
215
//
216
decLabel->setSnippet(this);
217
gcMap().setGCRegisterMask(0xFFFFFFFF);
218
}
219
220
uint8_t *TR::ARMMonitorExitSnippet::emitSnippetBody()
221
{
222
TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();
223
224
TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();
225
TR::RealRegister *objReg = cg()->machine()->getRealRegister(TR::RealRegister::gr0);
226
TR::RealRegister *monitorReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
227
TR::RealRegister *threadReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
228
229
TR::InstOpCode opcode;
230
TR::InstOpCode::Mnemonic opCodeValue;
231
232
uint8_t *buffer = cg()->getBinaryBufferCursor();
233
#if 0
234
if (0 /*_isReadOnly*/)
235
{
236
// THIS CODE IS CURRENTLY DISABLED
237
// BEFORE THIS CODE CAN BE ENABLED IT MUST BE UPDATED FOR THE NEW LOCK FIELDS
238
// decLabel (actual restoreAndCallLabel):
239
// andi threadReg, monitorReg, 0x3
240
// or threadReg, metaReg, threadReg
241
// stwcx. [objReg, offsetReg], threadReg
242
// beq callLabel
243
// b loopLabel
244
// callLabel:
245
// bl jitMonitorExit
246
// b doneLabel;
247
248
TR::RealRegister *offsetReg = cg()->machine()->getRealRegister(TR::RealRegister::gr4);
249
_decLabel->setCodeLocation(buffer);
250
251
opcode.setOpCodeValue(ARMOp_andi_r);
252
buffer = opcode.copyBinaryToBuffer(buffer);
253
monitorReg->setRegisterFieldRS((uint32_t *)buffer);
254
threadReg->setRegisterFieldRA((uint32_t *)buffer);
255
*(int32_t *)buffer |= (0x3);
256
buffer += ARM_INSTRUCTION_LENGTH;
257
258
opcode.setOpCodeValue(ARMOp_or);
259
buffer = opcode.copyBinaryToBuffer(buffer);
260
threadReg->setRegisterFieldRA((uint32_t *)buffer);
261
threadReg->setRegisterFieldRS((uint32_t *)buffer);
262
metaReg->setRegisterFieldRB((uint32_t *)buffer);
263
buffer += ARM_INSTRUCTION_LENGTH;
264
265
if (cg()->comp()->target().is64Bit() && !fej9->generateCompressedLockWord())
266
opCodeValue = ARMOp_stdcx_r;
267
else
268
opCodeValue = ARMOp_stwcx_r;
269
opcode.setOpCodeValue(opCodeValue);
270
buffer = opcode.copyBinaryToBuffer(buffer);
271
threadReg->setRegisterFieldRS((uint32_t *)buffer);
272
objReg->setRegisterFieldRA((uint32_t *)buffer);
273
offsetReg->setRegisterFieldRB((uint32_t *)buffer);
274
buffer += ARM_INSTRUCTION_LENGTH;
275
276
opcode.setOpCodeValue(ARMOp_beq);
277
buffer = opcode.copyBinaryToBuffer(buffer);
278
cndReg->setRegisterFieldBI((uint32_t *)buffer);
279
*(int32_t *)buffer |= 8;
280
buffer += ARM_INSTRUCTION_LENGTH;
281
282
opcode.setOpCodeValue(TR::InstOpCode::b);
283
buffer = opcode.copyBinaryToBuffer(buffer);
284
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeAL) << 28 | ((getRestoreAndCallLabel()->getCodeLocation()-buffer) >> 2) & 0x00FFFFFF);
285
buffer += ARM_INSTRUCTION_LENGTH;
286
287
cg()->setBinaryBufferCursor(buffer);
288
buffer = TR::ARMHelperCallSnippet::emitSnippetBody();
289
290
return buffer;
291
292
}
293
#endif
294
// The 32-bit code for the snippet looks like:
295
// decLabel:
296
// mvn threadReg, OBJECT_HEADER_LOCK_RECURSION_MASK // mask out count field
297
// and threadReg, monitorReg, threadReg
298
// cmp metaReg, threadReg
299
// subeq monitorReg, monitorReg, LOCK_INC_DEC_VALUE
300
// streq [objReg, monitor offset], monitorReg
301
// beq restartLabel
302
// callLabel:
303
// bl jitMonitorExit // inflated or flc bit set
304
// b restartLabel
305
306
// reservationPreserving exit snippet looks like: (Not for ARM)
307
// decLabel:
308
// li threadReg, OWING_NON_INFLATED_COMPLEMENT
309
// andc threadReg, monitorReg, threadReg
310
// cmpl cndReg, threadReg, metaReg
311
// bne callLabel
312
// andi_r threadReg, monitorReg, OBJECT_HEADER_LOCK_RECURSION_MASK
313
// beq callLabel
314
// andi_r threadReg, monitorReg, OWING_NON_INFLATED_COMPLEMENT
315
// cmpli cndReg, threadReg, LOCK_RES_CONTENDED_VALUE
316
// beq callLabel
317
// addi monitorReg, monitorReg, -INC
318
// st monitorReg, [objReg, lwOffset]
319
// b restartLabel
320
// callLabel:
321
// bl jitMonitorExit
322
// b restartLabel
323
324
_decLabel->setCodeLocation(buffer);
325
#if 0
326
if (0/*isReservationPreserving()*/)
327
{
328
opcode.setOpCodeValue(ARMOp_li);
329
buffer = opcode.copyBinaryToBuffer(buffer);
330
threadReg->setRegisterFieldRT((uint32_t *)buffer);
331
*(int32_t *)buffer |= LOCK_OWNING_NON_INFLATED_COMPLEMENT;
332
buffer += ARM_INSTRUCTION_LENGTH;
333
334
opcode.setOpCodeValue(ARMOp_andc);
335
buffer = opcode.copyBinaryToBuffer(buffer);
336
threadReg->setRegisterFieldRA((uint32_t *)buffer);
337
monitorReg->setRegisterFieldRS((uint32_t *)buffer);
338
threadReg->setRegisterFieldRB((uint32_t *)buffer);
339
buffer += ARM_INSTRUCTION_LENGTH;
340
341
opcode.setOpCodeValue(Op_cmpl);
342
buffer = opcode.copyBinaryToBuffer(buffer);
343
cndReg->setRegisterFieldRT((uint32_t *)buffer);
344
threadReg->setRegisterFieldRA((uint32_t *)buffer);
345
metaReg->setRegisterFieldRB((uint32_t *)buffer);
346
buffer += ARM_INSTRUCTION_LENGTH;
347
348
opcode.setOpCodeValue(ARMOp_bne);
349
buffer = opcode.copyBinaryToBuffer(buffer);
350
cndReg->setRegisterFieldBI((uint32_t *)buffer);
351
*(int32_t *)buffer |= 36;
352
buffer += ARM_INSTRUCTION_LENGTH;
353
354
opcode.setOpCodeValue(ARMOp_andi_r);
355
buffer = opcode.copyBinaryToBuffer(buffer);
356
threadReg->setRegisterFieldRA((uint32_t *)buffer);
357
monitorReg->setRegisterFieldRS((uint32_t *)buffer);
358
*(int32_t *)buffer |= OBJECT_HEADER_LOCK_RECURSION_MASK;
359
buffer += ARM_INSTRUCTION_LENGTH;
360
361
opcode.setOpCodeValue(ARMOp_beq);
362
buffer = opcode.copyBinaryToBuffer(buffer);
363
cndReg->setRegisterFieldBI((uint32_t *)buffer);
364
*(int32_t *)buffer |= 28;
365
buffer += ARM_INSTRUCTION_LENGTH;
366
367
opcode.setOpCodeValue(ARMOp_andi_r);
368
buffer = opcode.copyBinaryToBuffer(buffer);
369
threadReg->setRegisterFieldRA((uint32_t *)buffer);
370
monitorReg->setRegisterFieldRS((uint32_t *)buffer);
371
*(int32_t *)buffer |= LOCK_OWNING_NON_INFLATED_COMPLEMENT;
372
buffer += ARM_INSTRUCTION_LENGTH;
373
374
opcode.setOpCodeValue(Op_cmpli);
375
buffer = opcode.copyBinaryToBuffer(buffer);
376
cndReg->setRegisterFieldRT((uint32_t *)buffer);
377
threadReg->setRegisterFieldRA((uint32_t *)buffer);
378
*(int32_t *)buffer |= LOCK_RES_CONTENDED_VALUE;
379
buffer += ARM_INSTRUCTION_LENGTH;
380
381
opcode.setOpCodeValue(ARMOp_beq);
382
buffer = opcode.copyBinaryToBuffer(buffer);
383
cndReg->setRegisterFieldBI((uint32_t *)buffer);
384
*(int32_t *)buffer |= 16;
385
buffer += ARM_INSTRUCTION_LENGTH;
386
}
387
else
388
#endif
389
{
390
opcode.setOpCodeValue(TR::InstOpCode::mvn);
391
buffer = opcode.copyBinaryToBuffer(buffer);
392
threadReg->setRegisterFieldRD((uint32_t *)buffer);
393
// 32-bit immediate shifter_operand
394
// rotate_imm = 0
395
// immed_8 = OBJECT_HEADER_LOCK_RECURSION_MASK (0xF8)
396
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeAL) << 28 | 0x1 << 25 | OBJECT_HEADER_LOCK_RECURSION_MASK);
397
buffer += ARM_INSTRUCTION_LENGTH;
398
399
opcode.setOpCodeValue(TR::InstOpCode::and_);
400
buffer = opcode.copyBinaryToBuffer(buffer);
401
threadReg->setRegisterFieldRD((uint32_t *)buffer);
402
monitorReg->setRegisterFieldRN((uint32_t *)buffer);
403
threadReg->setRegisterFieldRM((uint32_t *)buffer);
404
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeAL) << 28);
405
buffer += ARM_INSTRUCTION_LENGTH;
406
407
opcode.setOpCodeValue(TR::InstOpCode::cmp);
408
buffer = opcode.copyBinaryToBuffer(buffer);
409
metaReg->setRegisterFieldRN((uint32_t *)buffer);
410
threadReg->setRegisterFieldRM((uint32_t *)buffer);
411
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeAL) << 28);
412
buffer += ARM_INSTRUCTION_LENGTH;
413
414
opcode.setOpCodeValue(TR::InstOpCode::sub);
415
buffer = opcode.copyBinaryToBuffer(buffer);
416
monitorReg->setRegisterFieldRD((uint32_t *)buffer);
417
monitorReg->setRegisterFieldRN((uint32_t *)buffer);
418
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeEQ) << 28 | 0x1 << 25 | (LOCK_INC_DEC_VALUE & 0xFFFF));
419
buffer += ARM_INSTRUCTION_LENGTH;
420
421
opcode.setOpCodeValue(TR::InstOpCode::str);
422
buffer = opcode.copyBinaryToBuffer(buffer);
423
monitorReg->setRegisterFieldRD((uint32_t *)buffer);
424
objReg->setRegisterFieldRN((uint32_t *)buffer);
425
// Store base register offset
426
// P(24)=1(offset addressing), U=1(23)(add offset), I=0(immed), B=0(word), L=0(store)
427
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeEQ) << 28 | 0x1 << 24 | 0x1 << 23 | _lwOffset & 0xFFF);
428
buffer += ARM_INSTRUCTION_LENGTH;
429
430
opcode.setOpCodeValue(TR::InstOpCode::b);
431
buffer = opcode.copyBinaryToBuffer(buffer);
432
// Back to restartLabel
433
*(int32_t *)buffer |= ((uint32_t)(ARMConditionCodeEQ) << 28 |((getRestartLabel()->getCodeLocation() - buffer - 8) >> 2) & 0x00FFFFFF);
434
buffer += ARM_INSTRUCTION_LENGTH;
435
}
436
437
cg()->setBinaryBufferCursor(buffer);
438
buffer = TR::ARMHelperCallSnippet::emitSnippetBody();
439
440
return buffer;
441
}
442
443
444
void
445
TR::ARMMonitorExitSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)
446
{
447
uint8_t *bufferPos = getDecLabel()->getCodeLocation();
448
// debug->printSnippetLabel(pOutFile, getDecLabel(), bufferPos, debug->getName(snippet));
449
debug->printSnippetLabel(pOutFile, getDecLabel(), bufferPos, "Dec Monitor Counter");
450
451
TR::Machine *machine = cg()->machine();
452
TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();
453
TR::LabelSymbol *restartLabel = getRestartLabel();
454
TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();
455
TR::RealRegister *objReg = machine->getRealRegister(TR::RealRegister::gr0);
456
TR::RealRegister *monitorReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
457
TR::RealRegister *threadReg = machine->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
458
459
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
460
// mvn threadReg, OBJECT_HEADER_LOCK_RECURSION_MASK // mask out count field
461
trfprintf(pOutFile, "mvn\t%s, #0x%08x; OBJECT_HEADER_LOCK_RECURSION_MASK", debug->getName(threadReg), OBJECT_HEADER_LOCK_RECURSION_MASK);
462
bufferPos += 4;
463
464
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
465
// and threadReg, monitorReg, threadReg
466
trfprintf(pOutFile, "and\t%s, %s, %s; ", debug->getName(threadReg), debug->getName(monitorReg), debug->getName(threadReg));
467
bufferPos += 4;
468
469
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
470
// cmp metaReg, threadReg
471
trfprintf(pOutFile, "cmp\t%s, %s; ", debug->getName(metaReg), debug->getName(threadReg));
472
bufferPos += 4;
473
474
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
475
// subeq monitorReg, monitorReg, LOCK_INC_DEC_VALUE
476
trfprintf(pOutFile, "subeq\t%s, %s, #0x%08x; Decrement the count", debug->getName(monitorReg), debug->getName(monitorReg), LOCK_INC_DEC_VALUE);
477
bufferPos += 4;
478
479
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
480
// streq monitorReg, [objReg, monitor offset]
481
trfprintf(pOutFile, "streq\t%s, [%s, %d]; ", debug->getName(monitorReg), debug->getName(objReg), getLockWordOffset());
482
bufferPos += 4;
483
484
debug->printPrefix(pOutFile, NULL, bufferPos, 4);
485
// beq restartLabel
486
trfprintf(pOutFile, "beq\t" POINTER_PRINTF_FORMAT "\t\t; Return to %s", (intptr_t)(restartLabel->getCodeLocation()), debug->getName(restartLabel));
487
488
debug->print(pOutFile, (TR::ARMHelperCallSnippet *)this);
489
}
490
491
492
493
uint32_t TR::ARMMonitorExitSnippet::getLength(int32_t estimatedSnippetStart)
494
{
495
496
int32_t len;
497
len = ARM_INSTRUCTION_LENGTH*6;
498
len += TR::ARMHelperCallSnippet::getLength(estimatedSnippetStart + len);
499
return len;
500
}
501
502
int32_t TR::ARMMonitorExitSnippet::setEstimatedCodeLocation(int32_t estimatedSnippetStart)
503
{
504
int32_t len;
505
_decLabel->setEstimatedCodeLocation(estimatedSnippetStart);
506
507
len = ARM_INSTRUCTION_LENGTH*6;
508
509
getSnippetLabel()->setEstimatedCodeLocation(estimatedSnippetStart+len);
510
return(estimatedSnippetStart);
511
}
512
513