001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.compilers.baseline.ia32;
014
015 import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.FIVE_SLOTS;
016 import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.FOUR_SLOTS;
017 import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.NO_SLOT;
018 import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.ONE_SLOT;
019 import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.THREE_SLOTS;
020 import static org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.TWO_SLOTS;
021 import static org.jikesrvm.ia32.ArchConstants.SSE2_BASE;
022 import static org.jikesrvm.ia32.ArchConstants.SSE2_FULL;
023 import static org.jikesrvm.ia32.BaselineConstants.EBX_SAVE_OFFSET;
024 import static org.jikesrvm.ia32.BaselineConstants.EDI_SAVE_OFFSET;
025 import static org.jikesrvm.ia32.BaselineConstants.FPU_SAVE_OFFSET;
026 import static org.jikesrvm.ia32.BaselineConstants.LG_WORDSIZE;
027 import static org.jikesrvm.ia32.BaselineConstants.TR;
028 import static org.jikesrvm.ia32.BaselineConstants.S0;
029 import static org.jikesrvm.ia32.BaselineConstants.SP;
030 import static org.jikesrvm.ia32.BaselineConstants.T0;
031 import static org.jikesrvm.ia32.BaselineConstants.T0_SAVE_OFFSET;
032 import static org.jikesrvm.ia32.BaselineConstants.T1;
033 import static org.jikesrvm.ia32.BaselineConstants.T1_SAVE_OFFSET;
034 import static org.jikesrvm.ia32.BaselineConstants.WORDSIZE;
035 import static org.jikesrvm.ia32.BaselineConstants.XMM_SAVE_OFFSET;
036 import static org.jikesrvm.ia32.RegisterConstants.EAX;
037 import static org.jikesrvm.ia32.RegisterConstants.EBX;
038 import static org.jikesrvm.ia32.RegisterConstants.ECX;
039 import static org.jikesrvm.ia32.RegisterConstants.EDI;
040 import static org.jikesrvm.ia32.RegisterConstants.EDX;
041 import static org.jikesrvm.ia32.RegisterConstants.ESI;
042 import static org.jikesrvm.ia32.RegisterConstants.FP0;
043 import static org.jikesrvm.ia32.RegisterConstants.XMM0;
044 import static org.jikesrvm.ia32.RegisterConstants.XMM1;
045 import static org.jikesrvm.ia32.RegisterConstants.XMM2;
046 import static org.jikesrvm.ia32.RegisterConstants.XMM3;
047 import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_FRAME_POINTER_OFFSET;
048 import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_METHOD_ID_OFFSET;
049 import static org.jikesrvm.ia32.StackframeLayoutConstants.STACKFRAME_RETURN_ADDRESS_OFFSET;
050 import static org.jikesrvm.objectmodel.TIBLayoutConstants.TIB_TYPE_INDEX;
051 import static org.jikesrvm.runtime.EntrypointHelper.getMethodReference;
052
053 import org.jikesrvm.VM;
054 import org.jikesrvm.ArchitectureSpecific.Assembler;
055 import org.jikesrvm.ArchitectureSpecific.CodeArray;
056 import org.jikesrvm.ArchitectureSpecific.Registers;
057 import org.jikesrvm.classloader.Atom;
058 import org.jikesrvm.classloader.MethodReference;
059 import org.jikesrvm.classloader.RVMArray;
060 import org.jikesrvm.classloader.RVMMethod;
061 import org.jikesrvm.classloader.RVMType;
062 import org.jikesrvm.classloader.TypeReference;
063 import org.jikesrvm.compilers.common.assembler.ForwardReference;
064 import org.jikesrvm.ia32.RegisterConstants.GPR;
065 import org.jikesrvm.jni.FunctionTable;
066 import org.jikesrvm.mm.mminterface.MemoryManager;
067 import org.jikesrvm.objectmodel.IMT;
068 import org.jikesrvm.objectmodel.JavaHeader;
069 import org.jikesrvm.objectmodel.ObjectModel;
070 import org.jikesrvm.objectmodel.TIB;
071 import org.jikesrvm.runtime.ArchEntrypoints;
072 import org.jikesrvm.runtime.EntrypointHelper;
073 import org.jikesrvm.runtime.Entrypoints;
074 import org.jikesrvm.runtime.Magic;
075 import org.jikesrvm.runtime.MagicNames;
076 import org.jikesrvm.scheduler.RVMThread;
077 import org.jikesrvm.util.ImmutableEntryHashMapRVM;
078 import org.vmmagic.pragma.Uninterruptible;
079 import org.vmmagic.unboxed.Address;
080 import org.vmmagic.unboxed.AddressArray;
081 import org.vmmagic.unboxed.Extent;
082 import org.vmmagic.unboxed.ExtentArray;
083 import org.vmmagic.unboxed.ObjectReference;
084 import org.vmmagic.unboxed.ObjectReferenceArray;
085 import org.vmmagic.unboxed.Offset;
086 import org.vmmagic.unboxed.OffsetArray;
087 import org.vmmagic.unboxed.Word;
088 import org.vmmagic.unboxed.WordArray;
089
090 /**
091 * Create magic code
092 */
093 final class BaselineMagic {
094 /**
095 * Map of method references to objects that will generate the necessary magic
096 */
097 private static final ImmutableEntryHashMapRVM<MethodReference,MagicGenerator> generators =
098 new ImmutableEntryHashMapRVM<MethodReference,MagicGenerator>();
099
100 /**
101 * When casting or loading object references should the reference be checked
102 * to see if it is an object reference first?
103 */
104 private static final boolean VALIDATE_OBJECT_REFERENCES = false;
105
106 /**
107 * If a bad reference is encountered should we halt the VM?
108 */
109 private static final boolean FAIL_ON_BAD_REFERENCES = true;
110
111 /**
112 * Entry point to generating magic
113 * @param asm assembler to generate magic code into
114 * @param m method reference
115 * @param cm the method being compiled
116 * @param sd the depth of the stack
117 * @return {@code true} if magic was generated
118 */
119 static boolean generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
120 MagicGenerator g = generators.get(m);
121 if (g != null) {
122 g.generateMagic(asm, m, cm, sd);
123 return true;
124 } else {
125 return false;
126 }
127 }
128
129 /**
130 * Flag to avoid recursive calls to check
131 */
132 private static volatile boolean inCheck = false;
133 /**
134 * Method called to check an object reference is valid
135 * @param value
136 */
137 @SuppressWarnings("unused")
138 @Uninterruptible
139 private static void check(ObjectReference value) {
140 if (!inCheck) {
141 inCheck = true;
142 if (!MemoryManager.validRef(value) && FAIL_ON_BAD_REFERENCES) {
143 VM.sysFail("Bad object reference encountered");
144 }
145 inCheck = false;
146 }
147 }
148
149 /**
150 * Reference of method that checks a reference
151 */
152 private static final MethodReference checkMR =
153 EntrypointHelper.getMethodReference(BaselineMagic.class,
154 Atom.findOrCreateUnicodeAtom("check"), ObjectReference.class, void.class);
155
156 /**
157 * Parent of all magic generating classes
158 */
159 private abstract static class MagicGenerator {
160 abstract void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd);
161 }
162
163 /**
164 * Add a reference check to a magic generator
165 */
166 private static final class EarlyReferenceCheckDecorator extends MagicGenerator {
167 private final Offset offset;
168 private final MagicGenerator generator;
169 /**
170 * Construct decorator that will add reference checks
171 * @param offset on stack of reference to check
172 * @param generator the magic generator being decorated
173 */
174 EarlyReferenceCheckDecorator(Offset offset, MagicGenerator generator) {
175 this.offset = offset;
176 this.generator = generator;
177 }
178 @Override
179 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
180 Class<?> dc = cm.getDeclaringClass().getClassForType();
181 if ((dc != JavaHeader.class) &&
182 (dc != ObjectModel.class)
183 ){
184 if (checkMR.needsDynamicLink(cm)) {
185 BaselineCompilerImpl.emitDynamicLinkingSequence(asm, S0, checkMR, true);
186 if (offset.NE(NO_SLOT)) {
187 asm.emitMOV_Reg_RegDisp(T0, SP, offset);
188 } else {
189 asm.emitMOV_Reg_RegInd(T0, SP);
190 }
191 asm.emitPUSH_Reg(T0);
192 asm.emitCALL_RegDisp(S0, Magic.getTocPointer().toWord().toOffset());
193 } else {
194 if (offset.NE(NO_SLOT)) {
195 asm.emitMOV_Reg_RegDisp(T0, SP, offset);
196 } else {
197 asm.emitMOV_Reg_RegInd(T0, SP);
198 }
199 asm.emitPUSH_Reg(T0);
200 asm.emitCALL_Abs(Magic.getTocPointer().plus(checkMR.peekResolvedMethod().getOffset()));
201 }
202 }
203 generator.generateMagic(asm, m, cm, sd);
204 }
205 }
206
207 /**
208 * Add a reference check to a magic generator
209 */
210 private static final class LateReferenceCheckDecorator extends MagicGenerator {
211 private final Offset offset;
212 private final MagicGenerator generator;
213 /**
214 * Construct decorator that will add reference checks
215 * @param offset on stack of reference to check
216 * @param generator the magic generator being decorated
217 */
218 LateReferenceCheckDecorator(Offset offset, MagicGenerator generator) {
219 this.offset = offset;
220 this.generator = generator;
221 }
222 @Override
223 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
224 generator.generateMagic(asm, m, cm, sd);
225 Class<?> dc = cm.getDeclaringClass().getClassForType();
226 if ((dc != JavaHeader.class) &&
227 (dc != ObjectModel.class)
228 ){
229 if (checkMR.needsDynamicLink(cm)) {
230 BaselineCompilerImpl.emitDynamicLinkingSequence(asm, S0, checkMR, true);
231 if (offset.NE(NO_SLOT)) {
232 asm.emitMOV_Reg_RegDisp(T0, SP, offset);
233 } else {
234 asm.emitMOV_Reg_RegInd(T0, SP);
235 }
236 asm.emitPUSH_Reg(T0);
237 asm.emitCALL_RegDisp(S0, Magic.getTocPointer().toWord().toOffset());
238 } else {
239 if (offset.NE(NO_SLOT)) {
240 asm.emitMOV_Reg_RegDisp(T0, SP, offset);
241 } else {
242 asm.emitMOV_Reg_RegInd(T0, SP);
243 }
244 asm.emitPUSH_Reg(T0);
245 asm.emitCALL_Abs(Magic.getTocPointer().plus(checkMR.peekResolvedMethod().getOffset()));
246 }
247 }
248 }
249 }
250
251 /**
252 * Load a 32bit quantity from an address
253 */
254 private static final class Load32 extends MagicGenerator {
255 @Override
256 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
257 // No offset
258 asm.emitPOP_Reg(T0); // address
259 asm.emitPUSH_RegInd(T0); // pushes [T0+0]
260 }
261 }
262 static {
263 MagicGenerator g = new Load32();
264 generators.put(getMethodReference(Address.class, MagicNames.loadAddress, Address.class), g);
265 generators.put(getMethodReference(Address.class, MagicNames.prepareAddress, Address.class), g);
266 generators.put(getMethodReference(Address.class, MagicNames.loadWord, Word.class), g);
267 generators.put(getMethodReference(Address.class, MagicNames.prepareWord, Word.class), g);
268 generators.put(getMethodReference(Address.class, MagicNames.loadInt, int.class), g);
269 generators.put(getMethodReference(Address.class, MagicNames.prepareInt, int.class), g);
270 generators.put(getMethodReference(Address.class, MagicNames.loadFloat, float.class), g);
271 if (VALIDATE_OBJECT_REFERENCES) {
272 g = new LateReferenceCheckDecorator(NO_SLOT, g);
273 }
274 generators.put(getMethodReference(Address.class, MagicNames.prepareObjectReference, ObjectReference.class), g);
275 generators.put(getMethodReference(Address.class, MagicNames.loadObjectReference, ObjectReference.class), g);
276 }
277
278 /**
279 * Load a 32bit quantity from an address and offset parameter
280 */
281 private static final class Load32_Offset extends MagicGenerator {
282 @Override
283 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
284 // Load at offset
285 asm.emitPOP_Reg(S0); // offset
286 asm.emitPOP_Reg(T0); // object ref
287 asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0]
288 }
289 }
290 static {
291 MagicGenerator g = new Load32_Offset();
292 generators.put(getMethodReference(Address.class, MagicNames.loadAddress, Offset.class, Address.class), g);
293 generators.put(getMethodReference(Address.class, MagicNames.prepareAddress, Offset.class, Address.class), g);
294 generators.put(getMethodReference(Address.class, MagicNames.loadWord, Offset.class, Word.class), g);
295 generators.put(getMethodReference(Address.class, MagicNames.prepareWord, Offset.class, Word.class), g);
296 generators.put(getMethodReference(Address.class, MagicNames.loadInt, Offset.class, int.class), g);
297 generators.put(getMethodReference(Address.class, MagicNames.prepareInt, Offset.class, int.class), g);
298 generators.put(getMethodReference(Address.class, MagicNames.loadFloat, Offset.class, float.class), g);
299 generators.put(getMethodReference(Magic.class, MagicNames.getIntAtOffset, Object.class, Offset.class, int.class), g);
300 generators.put(getMethodReference(Magic.class, MagicNames.getFloatAtOffset, Object.class, Offset.class, float.class), g);
301 generators.put(getMethodReference(Magic.class, MagicNames.getWordAtOffset, Object.class, Offset.class, Word.class), g);
302 generators.put(getMethodReference(Magic.class, MagicNames.getAddressAtOffset, Object.class, Offset.class, Address.class), g);
303 generators.put(getMethodReference(Magic.class, MagicNames.getExtentAtOffset, Object.class, Offset.class, Extent.class), g);
304 generators.put(getMethodReference(Magic.class, MagicNames.getOffsetAtOffset, Object.class, Offset.class, Offset.class), g);
305 generators.put(getMethodReference(Magic.class, MagicNames.prepareInt, Object.class, Offset.class, int.class), g);
306 generators.put(getMethodReference(Magic.class, MagicNames.prepareAddress, Object.class, Offset.class, Address.class), g);
307 generators.put(getMethodReference(Magic.class, MagicNames.prepareWord, Object.class, Offset.class, Word.class), g);
308 if (VALIDATE_OBJECT_REFERENCES) {
309 g = new LateReferenceCheckDecorator(NO_SLOT, g);
310 }
311 generators.put(getMethodReference(Address.class, MagicNames.prepareObjectReference, Offset.class, ObjectReference.class), g);
312 generators.put(getMethodReference(Address.class, MagicNames.loadObjectReference, Offset.class, ObjectReference.class), g);
313 generators.put(getMethodReference(Magic.class, MagicNames.getObjectAtOffset, Object.class, Offset.class, Object.class), g);
314 generators.put(getMethodReference(Magic.class, MagicNames.getTIBAtOffset, Object.class, Offset.class, TIB.class), g);
315 generators.put(getMethodReference(Magic.class, MagicNames.prepareObject, Object.class, Offset.class, Object.class), g);
316 }
317
318 /**
319 * Load a 32bit quantity from an address and offset parameter
320 */
321 private static final class Magic_Load32_MD extends MagicGenerator {
322 @Override
323 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
324 asm.emitPOP_Reg(S0); // discard meta-data
325 // Load at offset
326 asm.emitPOP_Reg(S0); // offset
327 asm.emitPOP_Reg(T0); // object ref
328 asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0]
329 }
330 }
331 static {
332 MagicGenerator g = new Magic_Load32_MD();
333 generators.put(getMethodReference(Magic.class, MagicNames.getWordAtOffset, Object.class, Offset.class, int.class, Word.class), g);
334 generators.put(getMethodReference(Magic.class, MagicNames.getAddressAtOffset, Object.class, Offset.class, int.class, Address.class), g);
335 generators.put(getMethodReference(Magic.class, MagicNames.getExtentAtOffset, Object.class, Offset.class, int.class, Extent.class), g);
336 generators.put(getMethodReference(Magic.class, MagicNames.getOffsetAtOffset, Object.class, Offset.class, int.class, Offset.class), g);
337 if (VALIDATE_OBJECT_REFERENCES) {
338 g = new LateReferenceCheckDecorator(NO_SLOT, g);
339 }
340 generators.put(getMethodReference(Magic.class, MagicNames.getObjectAtOffset, Object.class, Offset.class, int.class, Object.class), g);
341 }
342
343 /**
344 * Load a byte from an address
345 */
346 private static final class LoadByte extends MagicGenerator {
347 @Override
348 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
349 // No offset
350 asm.emitPOP_Reg(T0); // base
351 asm.emitMOVSX_Reg_RegInd_Byte(T0, T0);
352 asm.emitPUSH_Reg(T0);
353 }
354 }
355 static {
356 // Load a byte
357 MagicGenerator g = new LoadByte();
358 generators.put(getMethodReference(Address.class, MagicNames.loadByte, byte.class), g);
359 }
360
361 /**
362 * Load a byte from an address and offset parameter
363 */
364 private static final class LoadByte_Offset extends MagicGenerator {
365 @Override
366 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
367 // Load at offset
368 asm.emitPOP_Reg(S0); // offset
369 asm.emitPOP_Reg(T0); // base
370 asm.emitMOVSX_Reg_RegIdx_Byte(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and sign extend byte [T0+S0]
371 asm.emitPUSH_Reg(T0);
372 }
373 }
374 static {
375 MagicGenerator g = new LoadByte_Offset();
376 generators.put(getMethodReference(Address.class, MagicNames.loadByte, Offset.class, byte.class), g);
377 generators.put(getMethodReference(Magic.class, MagicNames.getByteAtOffset, Object.class, Offset.class, byte.class), g);
378 }
379
380 /**
381 * Load an unsigned byte from an address and offset parameter
382 */
383 private static final class LoadUnsignedByte_Offset extends MagicGenerator {
384 @Override
385 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
386 // Load at offset
387 asm.emitPOP_Reg(S0); // offset
388 asm.emitPOP_Reg(T0); // base
389 asm.emitMOVZX_Reg_RegIdx_Byte(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and sign extend byte [T0+S0]
390 asm.emitPUSH_Reg(T0);
391 }
392 }
393 static {
394 MagicGenerator g = new LoadUnsignedByte_Offset();
395 generators.put(getMethodReference(Magic.class, MagicNames.getUnsignedByteAtOffset, Object.class, Offset.class, byte.class), g);
396 }
397
398 /**
399 * Load a short quantity from an address
400 */
401 private static final class LoadShort extends MagicGenerator {
402 @Override
403 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
404 // No offset
405 asm.emitPOP_Reg(T0); // base
406 asm.emitMOVSX_Reg_RegInd_Word(T0, T0);
407 asm.emitPUSH_Reg(T0);
408 }
409 }
410 static {
411 MagicGenerator g = new LoadShort();
412 generators.put(getMethodReference(Address.class, MagicNames.loadShort, short.class), g);
413 }
414
415 /**
416 * Load a short quantity from an address plus offset
417 */
418 private static final class LoadShort_Offset extends MagicGenerator {
419 @Override
420 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
421 // Load at offset
422 asm.emitPOP_Reg(S0); // offset
423 asm.emitPOP_Reg(T0); // base
424 asm.emitMOVSX_Reg_RegIdx_Word(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and sign extend word [T0+S0]
425 asm.emitPUSH_Reg(T0);
426 }
427 }
428 static {
429 MagicGenerator g = new LoadShort_Offset();
430 generators.put(getMethodReference(Address.class, MagicNames.loadShort, Offset.class, short.class), g);
431 generators.put(getMethodReference(Magic.class, MagicNames.getShortAtOffset, Object.class, Offset.class, short.class), g);
432 }
433
434 /**
435 * Load a char from an address
436 */
437 private static final class LoadChar extends MagicGenerator {
438 @Override
439 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
440 // No offset
441 asm.emitPOP_Reg(T0); // base
442 asm.emitMOVZX_Reg_RegInd_Word(T0, T0);
443 asm.emitPUSH_Reg(T0);
444 }
445 }
446 static {
447 MagicGenerator g = new LoadChar();
448 generators.put(getMethodReference(Address.class, MagicNames.loadChar, char.class), g);
449 }
450
451 /**
452 * Load a char from an address plus offset
453 */
454 private static final class LoadChar_Offset extends MagicGenerator {
455 @Override
456 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
457 // Load at offset
458 asm.emitPOP_Reg(S0); // offset
459 asm.emitPOP_Reg(T0); // base
460 asm.emitMOVZX_Reg_RegIdx_Word(T0, T0, S0, Assembler.BYTE, NO_SLOT); // load and sign extend word [T0+S0]
461 asm.emitPUSH_Reg(T0);
462 }
463 }
464 static {
465 MagicGenerator g = new LoadChar_Offset();
466 generators.put(getMethodReference(Address.class, MagicNames.loadChar, Offset.class, char.class), g);
467 generators.put(getMethodReference(Magic.class, MagicNames.getCharAtOffset, Object.class, Offset.class, char.class), g);
468 }
469
470 /**
471 * Load a 64bit quantity from an address
472 */
473 private static final class Load64 extends MagicGenerator {
474 @Override
475 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
476 // No offset
477 asm.emitPOP_Reg(T0); // base
478 if (VM.BuildFor32Addr) {
479 asm.emitPUSH_RegDisp(T0, ONE_SLOT); // pushes [T0+4]
480 asm.emitPUSH_RegInd(T0); // pushes [T0]
481 } else {
482 asm.emitPUSH_Reg(T0); // create space
483 asm.emitPUSH_RegInd(T0); // pushes [T0]
484 }
485 }
486 }
487 static {
488 MagicGenerator g = new Load64();
489 generators.put(getMethodReference(Address.class, MagicNames.loadDouble, double.class), g);
490 generators.put(getMethodReference(Address.class, MagicNames.loadLong, long.class), g);
491 generators.put(getMethodReference(Address.class, MagicNames.prepareLong, long.class), g);
492 }
493
494 /**
495 * Load a 32bit quantity from an address plus offset
496 */
497 private static final class Load64_Offset extends MagicGenerator {
498 @Override
499 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
500 // Load at offset
501 asm.emitPOP_Reg(S0); // offset
502 asm.emitPOP_Reg(T0); // base
503 if (VM.BuildFor32Addr) {
504 asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, ONE_SLOT); // pushes [T0+S0+4]
505 asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0]
506 } else {
507 asm.emitPUSH_Reg(T0); // create space
508 asm.emitPUSH_RegIdx(T0, S0, Assembler.BYTE, NO_SLOT); // pushes [T0+S0]
509 }
510 }
511 }
512 static {
513 MagicGenerator g = new Load64_Offset();
514 generators.put(getMethodReference(Address.class, MagicNames.loadDouble, Offset.class, double.class), g);
515 generators.put(getMethodReference(Address.class, MagicNames.loadLong, Offset.class, long.class), g);
516 generators.put(getMethodReference(Address.class, MagicNames.prepareLong, Offset.class, long.class), g);
517 generators.put(getMethodReference(Magic.class, MagicNames.getDoubleAtOffset, Object.class, Offset.class, double.class), g);
518 generators.put(getMethodReference(Magic.class, MagicNames.getLongAtOffset, Object.class, Offset.class, long.class), g);
519 generators.put(getMethodReference(Magic.class, MagicNames.prepareLong, Object.class, Offset.class, long.class), g);
520 }
521
522 /**
523 * Store a 32bit quantity to an address
524 */
525 private static final class Store32 extends MagicGenerator {
526 @Override
527 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
528 // No offset
529 asm.emitPOP_Reg(T0); // value
530 asm.emitPOP_Reg(S0); // address
531 asm.emitMOV_RegInd_Reg(S0, T0); // [S0+0] <- T0
532 }
533 }
534 static {
535 MagicGenerator g = new Store32();
536 generators.put(getMethodReference(Address.class, MagicNames.store, Address.class, void.class), g);
537 generators.put(getMethodReference(Address.class, MagicNames.store, Word.class, void.class), g);
538 generators.put(getMethodReference(Address.class, MagicNames.store, int.class, void.class), g);
539 generators.put(getMethodReference(Address.class, MagicNames.store, float.class, void.class), g);
540 if (VALIDATE_OBJECT_REFERENCES) {
541 g = new EarlyReferenceCheckDecorator(NO_SLOT, g);
542 }
543 generators.put(getMethodReference(Address.class, MagicNames.store, ObjectReference.class, void.class), g);
544 }
545
546 /**
547 * Store a 32bit quantity to an address plus offset
548 */
549 private static final class Store32_Offset extends MagicGenerator {
550 @Override
551 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
552 // Store at offset
553 asm.emitPOP_Reg(S0); // offset
554 asm.emitPOP_Reg(T0); // value
555 asm.emitPOP_Reg(T1); // address
556 asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- T0
557 }
558 }
559 static {
560 MagicGenerator g = new Store32_Offset();
561 generators.put(getMethodReference(Address.class, MagicNames.store, Address.class, Offset.class, void.class), g);
562 generators.put(getMethodReference(Address.class, MagicNames.store, Word.class, Offset.class, void.class), g);
563 generators.put(getMethodReference(Address.class, MagicNames.store, int.class, Offset.class, void.class), g);
564 generators.put(getMethodReference(Address.class, MagicNames.store, float.class, Offset.class, void.class), g);
565 if (VALIDATE_OBJECT_REFERENCES) {
566 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g);
567 }
568 generators.put(getMethodReference(Address.class, MagicNames.store, ObjectReference.class, Offset.class, void.class), g);
569 }
570
571 /**
572 * Store a 32bit quantity to an address plus offset in the format used in
573 * {@link Magic}
574 */
575 private static final class Magic_Store32 extends MagicGenerator {
576 @Override
577 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
578 asm.emitPOP_Reg(T0); // value
579 asm.emitPOP_Reg(S0); // offset
580 asm.emitPOP_Reg(T1); // obj ref
581 asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- T0
582 }
583 }
584 static {
585 MagicGenerator g = new Magic_Store32();
586 generators.put(getMethodReference(Magic.class, MagicNames.setIntAtOffset, Object.class, Offset.class, int.class, void.class), g);
587 generators.put(getMethodReference(Magic.class, MagicNames.setFloatAtOffset, Object.class, Offset.class, float.class, void.class), g);
588 generators.put(getMethodReference(Magic.class, MagicNames.setWordAtOffset, Object.class, Offset.class, Word.class, void.class), g);
589 generators.put(getMethodReference(Magic.class, MagicNames.setAddressAtOffset, Object.class, Offset.class, Address.class, void.class), g);
590 generators.put(getMethodReference(Magic.class, MagicNames.setExtentAtOffset, Object.class, Offset.class, Extent.class, void.class), g);
591 generators.put(getMethodReference(Magic.class, MagicNames.setOffsetAtOffset, Object.class, Offset.class, Offset.class, void.class), g);
592 if (VALIDATE_OBJECT_REFERENCES) {
593 g = new EarlyReferenceCheckDecorator(NO_SLOT, g);
594 }
595 generators.put(getMethodReference(Magic.class, MagicNames.setObjectAtOffset, Object.class, Offset.class, Object.class, void.class), g);
596 }
597
598 /**
599 * Store a 32bit quantity to an address plus offset in the format used in
600 * {@link Magic} with an additional meta-data argument
601 */
602 private static final class Magic_Store32_MD extends MagicGenerator {
603 @Override
604 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
605 asm.emitPOP_Reg(T0); // discard meta-data
606 asm.emitPOP_Reg(T0); // value
607 asm.emitPOP_Reg(S0); // offset
608 asm.emitPOP_Reg(T1); // obj ref
609 asm.emitMOV_RegIdx_Reg(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- T0
610 }
611 }
612 static {
613 MagicGenerator g = new Magic_Store32_MD();
614 generators.put(getMethodReference(Magic.class, MagicNames.setIntAtOffset, Object.class, Offset.class, int.class, int.class, void.class), g);
615 generators.put(getMethodReference(Magic.class, MagicNames.setWordAtOffset, Object.class, Offset.class, Word.class, int.class, void.class), g);
616 generators.put(getMethodReference(Magic.class, MagicNames.setAddressAtOffset, Object.class, Offset.class, Address.class, int.class, void.class), g);
617 generators.put(getMethodReference(Magic.class, MagicNames.setOffsetAtOffset, Object.class, Offset.class, Offset.class, int.class, void.class), g);
618 generators.put(getMethodReference(Magic.class, MagicNames.setExtentAtOffset, Object.class, Offset.class, Extent.class, int.class, void.class), g);
619 generators.put(getMethodReference(Magic.class, MagicNames.setFloatAtOffset, Object.class, Offset.class, float.class, int.class, void.class), g);
620 if (VALIDATE_OBJECT_REFERENCES) {
621 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g);
622 }
623 generators.put(getMethodReference(Magic.class, MagicNames.setObjectAtOffset, Object.class, Offset.class, Object.class, int.class, void.class), g);
624 }
625
626 /**
627 * Store a 8bit quantity to an address plus offset
628 */
629 private static final class Store8 extends MagicGenerator {
630 @Override
631 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
632 // No offset
633 asm.emitPOP_Reg(T0); // value
634 asm.emitPOP_Reg(T1); // base
635 asm.emitMOV_RegInd_Reg_Byte(T1, T0);
636 }
637 }
638 static {
639 MagicGenerator g = new Store8();
640 generators.put(getMethodReference(Address.class, MagicNames.store, byte.class, void.class), g);
641 generators.put(getMethodReference(Address.class, MagicNames.store, boolean.class, void.class), g);
642 }
643
644 /**
645 * Store a 8bit quantity to an address plus offset
646 */
647 private static final class Store8_Offset extends MagicGenerator {
648 @Override
649 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
650 // Store at offset
651 asm.emitPOP_Reg(S0); // offset
652 asm.emitPOP_Reg(T0); // value
653 asm.emitPOP_Reg(T1); // base
654 asm.emitMOV_RegIdx_Reg_Byte(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0
655 }
656 }
657 static {
658 MagicGenerator g = new Store8_Offset();
659 generators.put(getMethodReference(Address.class, MagicNames.store, byte.class, Offset.class, void.class), g);
660 generators.put(getMethodReference(Address.class, MagicNames.store, boolean.class, Offset.class, void.class), g);
661 }
662
663 /**
664 * Store a 8bit quantity to an address plus offset in the format used in {@link Magic}
665 */
666 private static final class Magic_Store8 extends MagicGenerator {
667 @Override
668 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
669 asm.emitPOP_Reg(T0); // value
670 asm.emitPOP_Reg(S0); // offset
671 asm.emitPOP_Reg(T1); // obj ref
672 asm.emitMOV_RegIdx_Reg_Byte(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0
673 }
674 }
675 static {
676 MagicGenerator g = new Magic_Store8();
677 generators.put(getMethodReference(Magic.class, MagicNames.setBooleanAtOffset, Object.class, Offset.class, boolean.class, void.class), g);
678 generators.put(getMethodReference(Magic.class, MagicNames.setByteAtOffset, Object.class, Offset.class, byte.class, void.class), g);
679 }
680
681 /**
682 * Store a 8bit quantity to an address plus offset in the format used in
683 * {@link Magic} with an additional meta-data argument
684 */
685 private static final class Magic_Store8_MD extends MagicGenerator {
686 @Override
687 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
688 asm.emitPOP_Reg(T0); // discard meta-data
689 asm.emitPOP_Reg(T0); // value
690 asm.emitPOP_Reg(S0); // offset
691 asm.emitPOP_Reg(T1); // obj ref
692 asm.emitMOV_RegIdx_Reg_Byte(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (byte) T0
693 }
694 }
695 static {
696 MagicGenerator g = new Magic_Store8_MD();
697 generators.put(getMethodReference(Magic.class, MagicNames.setBooleanAtOffset, Object.class, Offset.class, boolean.class, int.class, void.class), g);
698 generators.put(getMethodReference(Magic.class, MagicNames.setByteAtOffset, Object.class, Offset.class, byte.class, int.class, void.class), g);
699 }
700
701 /**
702 * Store a 16bit quantity to an address
703 */
704 private static final class Store16 extends MagicGenerator {
705 @Override
706 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
707 // No offset
708 asm.emitPOP_Reg(T0); // value
709 asm.emitPOP_Reg(T1); // base
710 asm.emitMOV_RegInd_Reg_Word(T1, T0);
711 }
712 }
713 static {
714 MagicGenerator g = new Store16();
715 generators.put(getMethodReference(Address.class, MagicNames.store, short.class, void.class), g);
716 generators.put(getMethodReference(Address.class, MagicNames.store, char.class, void.class), g);
717 }
718
719 /**
720 * Store a 16bit quantity to an address plus offset
721 */
722 private static final class Store16_Offset extends MagicGenerator {
723 @Override
724 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
725 // Store at offset
726 asm.emitPOP_Reg(S0); // offset
727 asm.emitPOP_Reg(T0); // value
728 asm.emitPOP_Reg(T1); // base
729 asm.emitMOV_RegIdx_Reg_Word(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (word) T0
730 }
731 }
732 static {
733 MagicGenerator g = new Store16_Offset();
734 generators.put(getMethodReference(Address.class, MagicNames.store, short.class, Offset.class, void.class), g);
735 generators.put(getMethodReference(Address.class, MagicNames.store, char.class, Offset.class, void.class), g);
736 }
737
738 /**
739 * Store a 16 bit quantity to an address plus offset in the format used in {@link Magic}
740 */
741 private static final class Magic_Store16 extends MagicGenerator {
742 @Override
743 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
744 asm.emitPOP_Reg(T0); // value
745 asm.emitPOP_Reg(S0); // offset
746 asm.emitPOP_Reg(T1); // obj ref
747 asm.emitMOV_RegIdx_Reg_Word(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (word) T0
748 }
749 }
750 static {
751 MagicGenerator g = new Magic_Store16();
752 generators.put(getMethodReference(Magic.class, MagicNames.setCharAtOffset, Object.class, Offset.class, char.class, void.class), g);
753 generators.put(getMethodReference(Magic.class, MagicNames.setShortAtOffset, Object.class, Offset.class, short.class, void.class), g);
754 }
755
756 /**
757 * Store a 16bit quantity to an address plus offset in the format used in
758 * {@link Magic} with an additional meta-data argument
759 */
760 private static final class Magic_Store16_MD extends MagicGenerator {
761 @Override
762 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
763 asm.emitPOP_Reg(T0); // discard meta-data
764 asm.emitPOP_Reg(T0); // value
765 asm.emitPOP_Reg(S0); // offset
766 asm.emitPOP_Reg(T1); // obj ref
767 asm.emitMOV_RegIdx_Reg_Word(T1, S0, Assembler.BYTE, NO_SLOT, T0); // [T1+S0] <- (word) T0
768 }
769 }
770 static {
771 MagicGenerator g = new Magic_Store16_MD();
772 generators.put(getMethodReference(Magic.class, MagicNames.setCharAtOffset, Object.class, Offset.class, char.class, int.class, void.class), g);
773 generators.put(getMethodReference(Magic.class, MagicNames.setShortAtOffset, Object.class, Offset.class, short.class, int.class, void.class), g);
774 }
775
776 /**
777 * Store a 64bit quantity to an address
778 */
779 private static final class Store64 extends MagicGenerator {
780 @Override
781 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
782 // No offset
783 if (VM.BuildFor32Addr) {
784 asm.emitPOP_Reg(T0); // value low
785 asm.emitPOP_Reg(T1); // value high
786 asm.emitPOP_Reg(S0); // base
787 asm.emitMOV_RegInd_Reg(S0, T0); // value low
788 asm.emitMOV_RegDisp_Reg(S0, ONE_SLOT, T1); // value high
789 } else {
790 asm.emitPOP_Reg(T0); // value
791 asm.emitPOP_Reg(T1); // throw away slot
792 asm.emitPOP_Reg(T1); // base
793 asm.emitMOV_RegInd_Reg_Quad(T1, T0);
794 }
795 }
796 }
797 static {
798 MagicGenerator g = new Store64();
799 generators.put(getMethodReference(Address.class, MagicNames.store, long.class, void.class), g);
800 generators.put(getMethodReference(Address.class, MagicNames.store, double.class, void.class), g);
801 }
802
803 /**
804 * Store a 64bit quantity to an address plus offset
805 */
806 private static final class Store64_Offset extends MagicGenerator {
807 @Override
808 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
809 // Store at offset
810 if (VM.BuildFor32Addr) {
811 asm.emitPOP_Reg(T0); // T0 = offset
812 asm.emitADD_Reg_RegDisp(T0, SP, TWO_SLOTS); // T0 = base+offset
813 asm.emitPOP_RegInd(T0); // [T0] <- value low
814 asm.emitPOP_RegDisp(T0, ONE_SLOT); // [T0+4] <- value high
815 asm.emitPOP_Reg(T0); // throw away slot
816 } else {
817 asm.emitPOP_Reg(T0); // offset
818 asm.emitADD_Reg_RegDisp_Quad(T0, SP, TWO_SLOTS); // T0 = base+offset
819 asm.emitPOP_RegInd(T0); // T0 <- value
820 asm.emitPOP_Reg(T0); // throw away slot
821 asm.emitPOP_Reg(T0); // throw away slot
822 }
823 }
824 }
825 static {
826 MagicGenerator g = new Store64_Offset();
827 generators.put(getMethodReference(Address.class, MagicNames.store, long.class, Offset.class, void.class), g);
828 generators.put(getMethodReference(Address.class, MagicNames.store, double.class, Offset.class, void.class), g);
829 }
830
831 /**
832 * Store a 64bit quantity to an address plus offset in the format used in
833 * {@link Magic}
834 */
835 private static final class Magic_Store64 extends MagicGenerator {
836 @Override
837 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
838 if (VM.BuildFor32Addr) {
839 asm.emitPOP_Reg(T0); // value low
840 asm.emitPOP_Reg(T1); // value high
841 asm.emitPOP_Reg(S0); // S0 = offset
842 asm.emitADD_Reg_RegInd(S0, SP); // S0 = base+offset
843 asm.emitMOV_RegInd_Reg(S0, T0); // [S0] <- value low
844 asm.emitPOP_Reg(T0); // throw away slot
845 asm.emitMOV_RegDisp_Reg(S0, ONE_SLOT, T1); // [S0+4] <- value high
846 } else {
847 asm.emitPOP_Reg(T0); // value
848 asm.emitPOP_Reg(T1); // throw away slot
849 asm.emitPOP_Reg(T1); // T1 = offset
850 asm.emitPOP_Reg(S0); // S0 = base
851 asm.emitMOV_RegIdx_Reg_Quad(S0, T1, Assembler.BYTE, NO_SLOT, T0); // [base+offset] <- T0
852 }
853 }
854 }
855 static {
856 MagicGenerator g = new Magic_Store64();
857 generators.put(getMethodReference(Magic.class, MagicNames.setLongAtOffset, Object.class, Offset.class, long.class, void.class), g);
858 generators.put(getMethodReference(Magic.class, MagicNames.setDoubleAtOffset, Object.class, Offset.class, double.class, void.class), g);
859 }
860
861 /**
862 * Store a 64bit quantity to an address plus offset in the format used in
863 * {@link Magic} with an additional meta-data argument
864 */
865 private static final class Magic_Store64_MD extends MagicGenerator {
866 @Override
867 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
868 asm.emitPOP_Reg(T0); // discard meta-data
869 if (VM.BuildFor32Addr) {
870 asm.emitPOP_Reg(T0); // value low
871 asm.emitPOP_Reg(T1); // value high
872 asm.emitPOP_Reg(S0); // S0 = offset
873 asm.emitADD_Reg_RegInd(S0, SP); // S0 = base+offset
874 asm.emitMOV_RegInd_Reg(S0, T0); // [S0] <- value low
875 asm.emitPOP_Reg(T0); // throw away slot
876 asm.emitMOV_RegDisp_Reg(S0, ONE_SLOT, T1); // [S0+4] <- value high
877 } else {
878 asm.emitPOP_Reg(T0); // value
879 asm.emitPOP_Reg(T1); // throw away slot
880 asm.emitPOP_Reg(T1); // T1 = offset
881 asm.emitPOP_Reg(S0); // S0 = base
882 asm.emitMOV_RegIdx_Reg_Quad(S0, T1, Assembler.BYTE, NO_SLOT, T0); // [base+offset] <- T0
883 }
884 }
885 }
886 static {
887 MagicGenerator g = new Magic_Store64_MD();
888 generators.put(getMethodReference(Magic.class, MagicNames.setLongAtOffset, Object.class, Offset.class, long.class, int.class, void.class), g);
889 generators.put(getMethodReference(Magic.class, MagicNames.setDoubleAtOffset, Object.class, Offset.class, double.class, int.class, void.class), g);
890 }
891
892 /**
893 * Compare and swap a 32bit value
894 */
895 private static final class Attempt32 extends MagicGenerator {
896 @Override
897 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
898 asm.emitPOP_Reg(T1); // newVal
899 asm.emitPOP_Reg(EAX); // oldVal (EAX is implicit arg to LCMPX
900 // No offset
901 asm.emitMOV_Reg_RegInd(S0, SP); // S0 = base
902 asm.emitLockNextInstruction();
903 asm.emitCMPXCHG_RegInd_Reg(S0, T1); // atomic compare-and-exchange
904 asm.emitMOV_RegInd_Imm(SP, 1); // 'push' true (overwriting base)
905 asm.emitBranchLikelyNextInstruction();
906 ForwardReference fr = asm.forwardJcc(Assembler.EQ); // skip if compare fails
907 asm.emitMOV_RegInd_Imm(SP, 0); // 'push' false (overwriting base)
908 fr.resolve(asm);
909 }
910 }
911 static {
912 MagicGenerator g = new Attempt32();
913 generators.put(getMethodReference(Address.class, MagicNames.attempt, Address.class, Address.class, boolean.class), g);
914 generators.put(getMethodReference(Address.class, MagicNames.attempt, Word.class, Word.class, boolean.class), g);
915 generators.put(getMethodReference(Address.class, MagicNames.attempt, int.class, int.class, boolean.class), g);
916 if (VALIDATE_OBJECT_REFERENCES) {
917 g = new EarlyReferenceCheckDecorator(NO_SLOT, g);
918 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g);
919 }
920 generators.put(getMethodReference(Address.class, MagicNames.attempt, ObjectReference.class, ObjectReference.class, boolean.class), g);
921 }
922
923 /**
924 * Compare and swap a 32bit value at an address plus offset
925 */
926 private static final class Attempt32_Offset extends MagicGenerator {
927 @Override
928 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
929 // Offset passed
930 asm.emitPOP_Reg(S0); // S0 = offset
931 asm.emitPOP_Reg(T1); // newVal
932 asm.emitPOP_Reg(EAX); // oldVal (EAX is implicit arg to LCMPX
933 asm.emitADD_Reg_RegInd(S0, SP); // S0 += base
934 asm.emitLockNextInstruction();
935 asm.emitCMPXCHG_RegInd_Reg(S0, T1); // atomic compare-and-exchange
936 asm.emitMOV_RegInd_Imm(SP, 1); // 'push' true (overwriting base)
937 asm.emitBranchLikelyNextInstruction();
938 ForwardReference fr = asm.forwardJcc(Assembler.EQ); // skip if compare fails
939 asm.emitMOV_RegInd_Imm(SP, 0); // 'push' false (overwriting base)
940 fr.resolve(asm);
941 }
942 }
943 static {
944 MagicGenerator g = new Attempt32_Offset();
945 generators.put(getMethodReference(Address.class, MagicNames.attempt, Address.class, Address.class, Offset.class, boolean.class), g);
946 generators.put(getMethodReference(Address.class, MagicNames.attempt, Word.class, Word.class, Offset.class, boolean.class), g);
947 generators.put(getMethodReference(Address.class, MagicNames.attempt, int.class, int.class, Offset.class, boolean.class), g);
948 if (VALIDATE_OBJECT_REFERENCES) {
949 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g);
950 g = new EarlyReferenceCheckDecorator(TWO_SLOTS, g);
951 }
952 generators.put(getMethodReference(Address.class, MagicNames.attempt, ObjectReference.class, ObjectReference.class, Offset.class, boolean.class), g);
953 }
954
955 /**
956 * Compare and swap a 32bit value in the format used in {@link Magic}
957 */
958 private static final class Magic_Attempt32 extends MagicGenerator {
959 @Override
960 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
961 // attempt gets called with four arguments: base, offset, oldVal, newVal
962 // returns ([base+offset] == oldVal)
963 // if ([base+offset] == oldVal) [base+offset] := newVal
964 // (operation on memory is atomic)
965 asm.emitPOP_Reg(T1); // newVal
966 asm.emitPOP_Reg(EAX); // oldVal (EAX is implicit arg to LCMPXCNG
967 asm.emitPOP_Reg(S0); // S0 = offset
968 asm.emitADD_Reg_RegInd(S0, SP); // S0 += base
969 asm.emitLockNextInstruction();
970 asm.emitCMPXCHG_RegInd_Reg(S0, T1); // atomic compare-and-exchange
971 asm.emitMOV_RegInd_Imm(SP, 1); // 'push' true (overwriting base)
972 asm.emitBranchLikelyNextInstruction();
973 ForwardReference fr = asm.forwardJcc(Assembler.EQ); // skip if compare fails
974 asm.emitMOV_RegInd_Imm(SP, 0); // 'push' false (overwriting base)
975 fr.resolve(asm);
976 }
977 }
978 static {
979 MagicGenerator g = new Magic_Attempt32();
980 generators.put(getMethodReference(Magic.class, MagicNames.attemptInt, Object.class, Offset.class, int.class, int.class, boolean.class), g);
981 generators.put(getMethodReference(Magic.class, MagicNames.attemptAddress, Object.class, Offset.class, Address.class, Address.class, boolean.class), g);
982 generators.put(getMethodReference(Magic.class, MagicNames.attemptWord, Object.class, Offset.class, Word.class, Word.class, boolean.class), g);
983 if (VALIDATE_OBJECT_REFERENCES) {
984 g = new EarlyReferenceCheckDecorator(NO_SLOT, g);
985 g = new EarlyReferenceCheckDecorator(ONE_SLOT, g);
986 g = new EarlyReferenceCheckDecorator(THREE_SLOTS, g);
987 }
988 generators.put(getMethodReference(Magic.class, MagicNames.attemptObject, Object.class, Offset.class, Object.class, Object.class, boolean.class), g);
989 }
990
991 /**
992 * Compare and swap a 64bit value in the format used in {@link Magic}
993 */
994 private static final class Magic_Attempt64 extends MagicGenerator {
995 @Override
996 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
997 // attempt gets called with four arguments: base, offset, oldVal, newVal
998 // returns ([base+offset] == oldVal)
999 // if ([base+offset] == oldVal) [base+offset] := newVal
1000 // (operation on memory is atomic)
1001 //t1:t0 with s0:ebx
1002 asm.emitMOV_Reg_RegDisp(T1, SP, THREE_SLOTS);
1003 asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS); // T1:T0 (EDX:EAX) -> oldVal
1004 asm.emitMOV_RegDisp_Reg(SP, THREE_SLOTS, EBX); // Save EBX
1005 asm.emitMOV_RegDisp_Reg(SP, TWO_SLOTS, ESI); // Save ESI
1006 asm.emitMOV_Reg_RegInd(EBX, SP);
1007 asm.emitMOV_Reg_RegDisp(S0, SP, ONE_SLOT); // S0:EBX (ECX:EBX) -> newVal
1008 asm.emitMOV_Reg_RegDisp(ESI, SP, FIVE_SLOTS); // ESI := base
1009 asm.emitADD_Reg_RegDisp(ESI, SP, FOUR_SLOTS); // ESI += offset
1010 asm.emitLockNextInstruction();
1011 asm.emitCMPXCHG8B_RegInd(ESI); // atomic compare-and-exchange
1012 ForwardReference fr1 = asm.forwardJcc(Assembler.NE); // skip if compare fails
1013 asm.emitMOV_RegDisp_Imm(SP, FIVE_SLOTS, 1); // 'push' true (overwriting base)
1014 ForwardReference fr2 = asm.forwardJMP(); // skip if compare fails
1015 fr1.resolve(asm);
1016 asm.emitMOV_RegDisp_Imm(SP, FIVE_SLOTS, 0); // 'push' false (overwriting base)
1017 fr2.resolve(asm);
1018 asm.emitMOV_Reg_RegDisp(EBX, SP, THREE_SLOTS); // Restore EBX
1019 asm.emitMOV_Reg_RegDisp(ESI, SP, TWO_SLOTS); // Restore ESI
1020 asm.emitADD_Reg_Imm(SP, WORDSIZE*5); // adjust SP popping the 4 args (6 slots) and pushing the result
1021 }
1022 }
1023 static {
1024 MagicGenerator g = new Magic_Attempt64();
1025 generators.put(getMethodReference(Magic.class, MagicNames.attemptLong, Object.class, Offset.class, long.class, long.class, boolean.class), g);
1026 }
1027
1028 /**
1029 * Prefetch from an address
1030 */
1031 private static final class Prefetch extends MagicGenerator {
1032 @Override
1033 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1034 asm.emitPOP_Reg(EDI);
1035 asm.emitPREFETCHNTA_Reg(EDI);
1036 }
1037 }
1038 static {
1039 MagicGenerator g = new Prefetch();
1040 generators.put(getMethodReference(Address.class, MagicNames.prefetch, void.class), g);
1041 generators.put(getMethodReference(Address.class, MagicNames.prefetchNTA, void.class), g);
1042 }
1043
1044 /**
1045 * Get the type from an object
1046 */
1047 private static final class GetObjectType extends MagicGenerator {
1048 @Override
1049 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1050 asm.emitPOP_Reg(T0); // object ref
1051 BaselineCompilerImpl.baselineEmitLoadTIB(asm, S0, T0);
1052 asm.emitPUSH_RegDisp(S0, Offset.fromIntZeroExtend(TIB_TYPE_INDEX << LG_WORDSIZE)); // push RVMType slot of TIB
1053 }
1054 }
1055 static {
1056 MagicGenerator g = new GetObjectType();
1057 generators.put(getMethodReference(Magic.class, MagicNames.getObjectType, Object.class, RVMType.class), g);
1058 }
1059
1060 /**
1061 * Perform no-operation
1062 */
1063 private static final class Nop extends MagicGenerator {
1064 @Override
1065 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1066 }
1067 }
1068 static {
1069 MagicGenerator g = new Nop();
1070 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1071 for (Class<?> type : unboxedTypes) {
1072 generators.put(getMethodReference(type, MagicNames.wordFromInt, int.class, type), g);
1073 if (VM.BuildFor32Addr) {
1074 generators.put(getMethodReference(type, MagicNames.wordFromIntSignExtend, int.class, type), g);
1075 generators.put(getMethodReference(type, MagicNames.wordFromIntZeroExtend, int.class, type), g);
1076 }
1077 generators.put(getMethodReference(type, MagicNames.wordToInt, int.class), g);
1078 if (type != Address.class)
1079 generators.put(getMethodReference(type, MagicNames.wordToAddress, Address.class), g);
1080 if (type != Extent.class)
1081 generators.put(getMethodReference(type, MagicNames.wordToExtent, Extent.class), g);
1082 if (type != Offset.class)
1083 generators.put(getMethodReference(type, MagicNames.wordToOffset, Offset.class), g);
1084 if (type != Word.class)
1085 generators.put(getMethodReference(type, MagicNames.wordToWord, Word.class), g);
1086 }
1087 generators.put(getMethodReference(Magic.class, MagicNames.floatAsIntBits, float.class, int.class), g);
1088 generators.put(getMethodReference(Magic.class, MagicNames.intBitsAsFloat, int.class, float.class), g);
1089 generators.put(getMethodReference(Magic.class, MagicNames.doubleAsLongBits, double.class, long.class), g);
1090 generators.put(getMethodReference(Magic.class, MagicNames.longBitsAsDouble, long.class, double.class), g);
1091 generators.put(getMethodReference(Magic.class, MagicNames.sync, void.class), g);
1092 generators.put(getMethodReference(Magic.class, MagicNames.isync, void.class), g);
1093 generators.put(getMethodReference(Magic.class, MagicNames.readCeiling, void.class), g);
1094 generators.put(getMethodReference(Magic.class, MagicNames.writeFloor, void.class), g);
1095 if (VALIDATE_OBJECT_REFERENCES) {
1096 g = new EarlyReferenceCheckDecorator(NO_SLOT, g);
1097 }
1098 for (Class<?> type : unboxedTypes) {
1099 generators.put(getMethodReference(type, MagicNames.wordFromObject, Object.class, type), g);
1100 generators.put(getMethodReference(type, MagicNames.wordToObject, Object.class), g);
1101 generators.put(getMethodReference(type, MagicNames.wordToObjectReference, ObjectReference.class), g);
1102 }
1103 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordFromObject, Object.class, ObjectReference.class), g);
1104 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordToObject, Object.class), g);
1105 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordToAddress, Address.class), g);
1106 generators.put(getMethodReference(Magic.class, MagicNames.codeArrayAsObject, CodeArray.class, Object.class), g);
1107 generators.put(getMethodReference(Magic.class, MagicNames.tibAsObject, TIB.class, Object.class), g);
1108 generators.put(getMethodReference(Magic.class, MagicNames.objectAsAddress, Object.class, Address.class), g);
1109 generators.put(getMethodReference(Magic.class, MagicNames.addressAsByteArray, Address.class, byte[].class), g);
1110 generators.put(getMethodReference(Magic.class, MagicNames.addressAsObject, Address.class, Object.class), g);
1111 generators.put(getMethodReference(Magic.class, MagicNames.addressAsTIB, Address.class, TIB.class), g);
1112 generators.put(getMethodReference(Magic.class, MagicNames.objectAsType, Object.class, RVMType.class), g);
1113 generators.put(getMethodReference(Magic.class, MagicNames.objectAsShortArray, Object.class, short[].class), g);
1114 generators.put(getMethodReference(Magic.class, MagicNames.objectAsIntArray, Object.class, int[].class), g);
1115 generators.put(getMethodReference(Magic.class, MagicNames.objectAsThread, Object.class, RVMThread.class), g);
1116 }
1117
1118 /**
1119 * Generate the MFENCE instruction.
1120 */
1121 private static final class MFence extends MagicGenerator {
1122 @Override
1123 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1124 asm.emitMFENCE();
1125 }
1126 }
1127 static {
1128 generators.put(getMethodReference(Magic.class, MagicNames.fence, void.class), new MFence());
1129 }
1130
1131 /**
1132 * Perform an operation to release a stack slot
1133 */
1134 private static final class FreeStackSlot extends MagicGenerator {
1135 @Override
1136 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1137 asm.emitPOP_Reg(T0);
1138 asm.emitPOP_Reg(T1);
1139 asm.emitPUSH_Reg(T0);
1140 }
1141 }
1142 static {
1143 MagicGenerator g = new FreeStackSlot();
1144 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1145 for (Class<?> type : unboxedTypes) {
1146 generators.put(getMethodReference(type, MagicNames.wordFromLong, long.class, type), g);
1147 }
1148 }
1149
1150 /**
1151 * Perform an operation to duplicate a stack slot
1152 */
1153 private static final class DuplicateStackSlot extends MagicGenerator {
1154 @Override
1155 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1156 asm.emitPOP_Reg(T0);
1157 asm.emitPUSH_Reg(T0);
1158 asm.emitPUSH_Reg(T0);
1159 }
1160 }
1161 static {
1162 if (VM.BuildFor64Addr) {
1163 MagicGenerator g = new DuplicateStackSlot();
1164 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1165 for (Class<?> type : unboxedTypes) {
1166 generators.put(getMethodReference(type, MagicNames.wordToLong, type, long.class), g);
1167 }
1168 }
1169 }
1170
1171 /**
1172 * Zero high part of 64bits
1173 */
1174 private static final class QuadZeroExtend extends MagicGenerator {
1175 @Override
1176 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1177 asm.emitPOP_Reg(T0);
1178 asm.emitMOV_Reg_Reg(T0, T0);
1179 asm.emitPUSH_Reg(T0);
1180 }
1181 }
1182 static {
1183 if (VM.BuildFor64Addr) {
1184 MagicGenerator g = new QuadZeroExtend();
1185 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1186 for (Class<?> type : unboxedTypes) {
1187 generators.put(getMethodReference(type, MagicNames.wordFromIntZeroExtend, int.class, type), g);
1188 }
1189 }
1190 }
1191
1192 /**
1193 * Sign extend 32bit int to 64bits
1194 */
1195 private static final class QuadSignExtend extends MagicGenerator {
1196 @Override
1197 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1198 asm.emitPOP_Reg(EAX);
1199 asm.emitCDQE();
1200 asm.emitPUSH_Reg(EAX);
1201 }
1202 }
1203 static {
1204 if (VM.BuildFor64Addr) {
1205 MagicGenerator g = new QuadSignExtend();
1206 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1207 for (Class<?> type : unboxedTypes) {
1208 generators.put(getMethodReference(type, MagicNames.wordFromIntSignExtend, int.class, type), g);
1209 }
1210 }
1211 }
1212
1213 /**
1214 * Generate an address constant
1215 */
1216 private static final class AddressConstant extends MagicGenerator {
1217 final int value;
1218 AddressConstant(int value) {
1219 this.value = value;
1220 }
1221 @Override
1222 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1223 asm.emitPUSH_Imm(value);
1224 }
1225 }
1226 static {
1227 MagicGenerator zero = new AddressConstant(0);
1228 MagicGenerator one = new AddressConstant(1);
1229 MagicGenerator max = new AddressConstant(-1);
1230 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1231 for (Class<?> type : unboxedTypes) {
1232 generators.put(getMethodReference(type, MagicNames.wordZero, type), zero);
1233 generators.put(getMethodReference(type, MagicNames.wordOne, type), one);
1234 generators.put(getMethodReference(type, MagicNames.wordMax, type), max);
1235 }
1236 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordNull, ObjectReference.class), zero);
1237 MagicGenerator g = new AddressConstant(Magic.getTocPointer().toInt());
1238 generators.put(getMethodReference(Magic.class, MagicNames.getJTOC, Address.class), g);
1239 generators.put(getMethodReference(Magic.class, MagicNames.getTocPointer, Address.class), g);
1240 }
1241
1242 /**
1243 * Address comparison
1244 */
1245 private static final class AddressComparison extends MagicGenerator {
1246 final byte comparator;
1247 AddressComparison(byte comparator) {
1248 this.comparator = comparator;
1249 }
1250 @Override
1251 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1252 asm.emitPOP_Reg(S0);
1253 asm.emitPOP_Reg(T0);
1254 if (VM.BuildFor32Addr) {
1255 asm.emitCMP_Reg_Reg(T0, S0);
1256 } else {
1257 asm.emitCMP_Reg_Reg_Quad(T0, S0);
1258 }
1259 ForwardReference fr1 = asm.forwardJcc(comparator);
1260 asm.emitPUSH_Imm(0);
1261 ForwardReference fr2 = asm.forwardJMP();
1262 fr1.resolve(asm);
1263 asm.emitPUSH_Imm(1);
1264 fr2.resolve(asm);
1265 }
1266 }
1267 static {
1268 MagicGenerator llt = new AddressComparison(Assembler.LLT);
1269 MagicGenerator lle = new AddressComparison(Assembler.LLE);
1270 MagicGenerator lgt = new AddressComparison(Assembler.LGT);
1271 MagicGenerator lge = new AddressComparison(Assembler.LGE);
1272 MagicGenerator eq = new AddressComparison(Assembler.EQ);
1273 MagicGenerator ne = new AddressComparison(Assembler.NE);
1274 // Unsigned unboxed types
1275 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Word.class};
1276 for (Class<?> type : unboxedTypes) {
1277 generators.put(getMethodReference(type, MagicNames.wordLT, type, boolean.class), llt);
1278 generators.put(getMethodReference(type, MagicNames.wordLE, type, boolean.class), lle);
1279 generators.put(getMethodReference(type, MagicNames.wordGT, type, boolean.class), lgt);
1280 generators.put(getMethodReference(type, MagicNames.wordGE, type, boolean.class), lge);
1281 generators.put(getMethodReference(type, MagicNames.wordEQ, type, boolean.class), eq);
1282 generators.put(getMethodReference(type, MagicNames.wordNE, type, boolean.class), ne);
1283 }
1284 MagicGenerator lt = new AddressComparison(Assembler.LT);
1285 MagicGenerator le = new AddressComparison(Assembler.LE);
1286 MagicGenerator gt = new AddressComparison(Assembler.GT);
1287 MagicGenerator ge = new AddressComparison(Assembler.GE);
1288 // Signed unboxed types
1289 unboxedTypes = new Class<?>[]{Offset.class};
1290 for (Class<?> type : unboxedTypes) {
1291 generators.put(getMethodReference(type, MagicNames.wordsLT, type, boolean.class), lt);
1292 generators.put(getMethodReference(type, MagicNames.wordsLE, type, boolean.class), le);
1293 generators.put(getMethodReference(type, MagicNames.wordsGT, type, boolean.class), gt);
1294 generators.put(getMethodReference(type, MagicNames.wordsGE, type, boolean.class), ge);
1295 generators.put(getMethodReference(type, MagicNames.wordEQ, type, boolean.class), eq);
1296 generators.put(getMethodReference(type, MagicNames.wordNE, type, boolean.class), ne);
1297 }
1298 }
1299
1300 /**
1301 * Is an address zero?
1302 */
1303 private static final class AddressComparison_isZero extends MagicGenerator {
1304 @Override
1305 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1306 asm.emitPOP_Reg(T0);
1307 if (VM.BuildFor32Addr) {
1308 asm.emitTEST_Reg_Reg(T0, T0);
1309 } else {
1310 asm.emitTEST_Reg_Reg_Quad(T0, T0);
1311 }
1312 ForwardReference fr1 = asm.forwardJcc(Assembler.EQ);
1313 asm.emitPUSH_Imm(0);
1314 ForwardReference fr2 = asm.forwardJMP();
1315 fr1.resolve(asm);
1316 asm.emitPUSH_Imm(1);
1317 fr2.resolve(asm);
1318 }
1319 }
1320 static {
1321 MagicGenerator g = new AddressComparison_isZero();
1322 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1323 for (Class<?> type : unboxedTypes) {
1324 generators.put(getMethodReference(type, MagicNames.wordIsZero, boolean.class), g);
1325 }
1326 if (VALIDATE_OBJECT_REFERENCES) {
1327 g = new EarlyReferenceCheckDecorator(NO_SLOT, g);
1328 }
1329 generators.put(getMethodReference(ObjectReference.class, MagicNames.wordIsNull, boolean.class), g);
1330 }
1331
1332 /**
1333 * Is an address max?
1334 */
1335 private static final class AddressComparison_isMax extends MagicGenerator {
1336 @Override
1337 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1338 asm.emitPOP_Reg(T0);
1339 if (VM.BuildFor32Addr) {
1340 asm.emitCMP_Reg_Imm(T0, -1);
1341 } else {
1342 asm.emitCMP_Reg_Imm_Quad(T0, -1);
1343 }
1344 ForwardReference fr1 = asm.forwardJcc(Assembler.EQ);
1345 asm.emitPUSH_Imm(0);
1346 ForwardReference fr2 = asm.forwardJMP();
1347 fr1.resolve(asm);
1348 asm.emitPUSH_Imm(1);
1349 fr2.resolve(asm);
1350 }
1351 }
1352 static {
1353 MagicGenerator g = new AddressComparison_isMax();
1354 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1355 for (Class<?> type : unboxedTypes) {
1356 generators.put(getMethodReference(type, MagicNames.wordIsMax, boolean.class), g);
1357 }
1358 }
1359
1360 /**
1361 * Addition of words
1362 */
1363 private static final class WordPlus extends MagicGenerator {
1364 @Override
1365 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1366 asm.emitPOP_Reg(T0);
1367 if (VM.BuildFor32Addr) {
1368 asm.emitADD_RegInd_Reg(SP, T0);
1369 } else {
1370 asm.emitADD_RegInd_Reg_Quad(SP, T0);
1371 }
1372 }
1373 }
1374 /**
1375 * Special case of 64bit addition to 32bit value
1376 */
1377 private static final class WordPlus32 extends MagicGenerator {
1378 @Override
1379 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1380 asm.emitPOP_Reg(EAX);
1381 asm.emitCDQE();
1382 asm.emitADD_RegInd_Reg_Quad(SP, EAX);
1383 }
1384 }
1385 static {
1386 MagicGenerator g = new WordPlus();
1387 generators.put(getMethodReference(Address.class, MagicNames.wordPlus, Offset.class, Address.class), g);
1388 generators.put(getMethodReference(Address.class, MagicNames.wordPlus, Extent.class, Address.class), g);
1389 generators.put(getMethodReference(Extent.class, MagicNames.wordPlus, Extent.class, Extent.class), g);
1390 generators.put(getMethodReference(Word.class, MagicNames.wordPlus, Word.class, Word.class), g);
1391 generators.put(getMethodReference(Word.class, MagicNames.wordPlus, Offset.class, Word.class), g);
1392 generators.put(getMethodReference(Word.class, MagicNames.wordPlus, Extent.class, Word.class), g);
1393 if (VM.BuildFor64Addr) {
1394 g = new WordPlus32();
1395 }
1396 generators.put(getMethodReference(Address.class, MagicNames.wordPlus, int.class, Address.class), g);
1397 generators.put(getMethodReference(Extent.class, MagicNames.wordPlus, int.class, Extent.class), g);
1398 generators.put(getMethodReference(Offset.class, MagicNames.wordPlus, int.class, Offset.class), g);
1399 }
1400
1401 /**
1402 * Subtraction of words
1403 */
1404 private static final class WordMinus extends MagicGenerator {
1405 @Override
1406 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1407 asm.emitPOP_Reg(T0);
1408 if (VM.BuildFor32Addr) {
1409 asm.emitSUB_RegInd_Reg(SP, T0);
1410 } else {
1411 asm.emitSUB_RegInd_Reg_Quad(SP, T0);
1412 }
1413 }
1414 }
1415 /**
1416 * Special case of 64bit subtraction to 32bit value
1417 */
1418 private static final class WordMinus32 extends MagicGenerator {
1419 @Override
1420 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1421 asm.emitPOP_Reg(EAX);
1422 asm.emitCDQE();
1423 asm.emitSUB_RegInd_Reg_Quad(SP, EAX);
1424 }
1425 }
1426 static {
1427 MagicGenerator g = new WordMinus();
1428 generators.put(getMethodReference(Address.class, MagicNames.wordMinus, Offset.class, Address.class), g);
1429 generators.put(getMethodReference(Address.class, MagicNames.wordMinus, Extent.class, Address.class), g);
1430 generators.put(getMethodReference(Address.class, MagicNames.wordDiff, Address.class, Offset.class), g);
1431 generators.put(getMethodReference(Extent.class, MagicNames.wordMinus, Extent.class, Extent.class), g);
1432 generators.put(getMethodReference(Offset.class, MagicNames.wordMinus, Offset.class, Offset.class), g);
1433 generators.put(getMethodReference(Word.class, MagicNames.wordMinus, Word.class, Word.class), g);
1434 generators.put(getMethodReference(Word.class, MagicNames.wordMinus, Offset.class, Word.class), g);
1435 generators.put(getMethodReference(Word.class, MagicNames.wordMinus, Extent.class, Word.class), g);
1436 if (VM.BuildFor64Addr) {
1437 g = new WordMinus32();
1438 }
1439 generators.put(getMethodReference(Address.class, MagicNames.wordMinus, int.class, Address.class), g);
1440 generators.put(getMethodReference(Extent.class, MagicNames.wordMinus, int.class, Extent.class), g);
1441 generators.put(getMethodReference(Offset.class, MagicNames.wordMinus, int.class, Offset.class), g);
1442 }
1443
1444 /**
1445 * Logical and of words
1446 */
1447 private static final class WordAnd extends MagicGenerator {
1448 @Override
1449 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1450 asm.emitPOP_Reg(T0);
1451 if (VM.BuildFor32Addr) {
1452 asm.emitAND_RegInd_Reg(SP, T0);
1453 } else {
1454 asm.emitAND_RegInd_Reg_Quad(SP, T0);
1455 }
1456 }
1457 }
1458 static {
1459 MagicGenerator g = new WordAnd();
1460 generators.put(getMethodReference(Word.class, MagicNames.wordAnd, Word.class, Word.class), g);
1461 }
1462
1463 /**
1464 * Logical or of words
1465 */
1466 private static final class WordOr extends MagicGenerator {
1467 @Override
1468 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1469 asm.emitPOP_Reg(T0);
1470 if (VM.BuildFor32Addr) {
1471 asm.emitOR_RegInd_Reg(SP, T0);
1472 } else {
1473 asm.emitOR_RegInd_Reg_Quad(SP, T0);
1474 }
1475 }
1476 }
1477 static {
1478 MagicGenerator g = new WordOr();
1479 generators.put(getMethodReference(Word.class, MagicNames.wordOr, Word.class, Word.class), g);
1480 }
1481
1482 /**
1483 * Logical xor of words
1484 */
1485 private static final class WordXor extends MagicGenerator {
1486 @Override
1487 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1488 asm.emitPOP_Reg(T0);
1489 if (VM.BuildFor32Addr) {
1490 asm.emitXOR_RegInd_Reg(SP, T0);
1491 } else {
1492 asm.emitXOR_RegInd_Reg_Quad(SP, T0);
1493 }
1494 }
1495 }
1496 static {
1497 MagicGenerator g = new WordXor();
1498 generators.put(getMethodReference(Word.class, MagicNames.wordXor, Word.class, Word.class), g);
1499 }
1500
1501 /**
1502 * Logical left shift of words
1503 */
1504 private static final class WordLsh extends MagicGenerator {
1505 @Override
1506 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1507 asm.emitPOP_Reg(ECX);
1508 if (VM.BuildFor32Addr) {
1509 asm.emitSHL_RegInd_Reg(SP, ECX);
1510 } else {
1511 asm.emitSHL_RegInd_Reg_Quad(SP, ECX);
1512 }
1513 }
1514 }
1515 static {
1516 MagicGenerator g = new WordLsh();
1517 generators.put(getMethodReference(Word.class, MagicNames.wordLsh, int.class, Word.class), g);
1518 }
1519
1520 /**
1521 * Logical right shift of words
1522 */
1523 private static final class WordRshl extends MagicGenerator {
1524 @Override
1525 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1526 asm.emitPOP_Reg(ECX);
1527 if (VM.BuildFor32Addr) {
1528 asm.emitSHR_RegInd_Reg(SP, ECX);
1529 } else {
1530 asm.emitSHR_RegInd_Reg_Quad(SP, ECX);
1531 }
1532 }
1533 }
1534 static {
1535 MagicGenerator g = new WordRshl();
1536 generators.put(getMethodReference(Word.class, MagicNames.wordRshl, int.class, Word.class), g);
1537 }
1538
1539 /**
1540 * Arithmetic right shift of words
1541 */
1542 private static final class WordRsha extends MagicGenerator {
1543 @Override
1544 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1545 asm.emitPOP_Reg(ECX);
1546 if (VM.BuildFor32Addr) {
1547 asm.emitSAR_RegInd_Reg(SP, ECX);
1548 } else {
1549 asm.emitSAR_RegInd_Reg_Quad(SP, ECX);
1550 }
1551 }
1552 }
1553 static {
1554 MagicGenerator g = new WordRsha();
1555 generators.put(getMethodReference(Word.class, MagicNames.wordRsha, int.class, Word.class), g);
1556 }
1557
1558 /**
1559 * Logical not of word
1560 */
1561 private static final class WordNot extends MagicGenerator {
1562 @Override
1563 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1564 if (VM.BuildFor32Addr) {
1565 asm.emitNOT_RegInd(SP);
1566 } else {
1567 asm.emitNOT_RegInd_Quad(SP);
1568 }
1569 }
1570 }
1571 static {
1572 MagicGenerator g = new WordNot();
1573 generators.put(getMethodReference(Word.class, MagicNames.wordNot, Word.class), g);
1574 }
1575
1576 /**
1577 * Convert word to long
1578 */
1579 private static final class WordToLong extends MagicGenerator {
1580 @Override
1581 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1582 asm.emitPOP_Reg(T0);
1583 if (VM.BuildFor32Addr) {
1584 asm.emitPUSH_Imm(0); // upper 32 bits
1585 asm.emitPUSH_Reg(T0); // lower 32 bits
1586 } else {
1587 asm.emitPUSH_Reg(T0); // adjust stack
1588 asm.emitPUSH_Reg(T0); // long value
1589 }
1590 }
1591 }
1592 static {
1593 MagicGenerator g = new WordToLong();
1594 Class<?>[] unboxedTypes = new Class<?>[]{Address.class, Extent.class, Offset.class, Word.class};
1595 for (Class<?> type : unboxedTypes) {
1596 generators.put(getMethodReference(type, MagicNames.wordToLong, long.class), g);
1597 }
1598 }
1599
1600 /**
1601 * Set a register to a value from the stack
1602 */
1603 private static final class SetRegister extends MagicGenerator {
1604 private final GPR reg;
1605 SetRegister(GPR reg) {
1606 this.reg = reg;
1607 }
1608 @Override
1609 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1610 asm.emitPOP_Reg(reg);
1611 }
1612 }
1613 static {
1614 generators.put(getMethodReference(Magic.class, MagicNames.setESIAsThread, RVMThread.class, void.class),
1615 new SetRegister(ESI));
1616 generators.put(getMethodReference(Magic.class, MagicNames.setThreadRegister, RVMThread.class, void.class),
1617 new SetRegister(TR));
1618 }
1619
1620 /**
1621 * Put a register on to the stack
1622 */
1623 private static final class GetRegister extends MagicGenerator {
1624 private final GPR reg;
1625 GetRegister(GPR reg) {
1626 this.reg = reg;
1627 }
1628 @Override
1629 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1630 asm.emitPUSH_Reg(reg);
1631 }
1632 }
1633 static {
1634 generators.put(getMethodReference(Magic.class, MagicNames.getESIAsThread, RVMThread.class),
1635 new GetRegister(ESI));
1636 generators.put(getMethodReference(Magic.class, MagicNames.getThreadRegister, RVMThread.class),
1637 new GetRegister(TR));
1638 }
1639
1640 /**
1641 * Reflective method dispatch
1642 */
1643 private static final class InvokeMethodReturningObject extends MagicGenerator {
1644 @Override
1645 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1646 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset();
1647 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words
1648 asm.emitCALL_Abs(Magic.getTocPointer().plus(offset));
1649 asm.emitPUSH_Reg(T0);
1650 }
1651 }
1652 static {
1653 MagicGenerator g = new InvokeMethodReturningObject();
1654 if (VALIDATE_OBJECT_REFERENCES) {
1655 g = new LateReferenceCheckDecorator(NO_SLOT, g);
1656 }
1657 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningObject, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, Object.class), g);
1658 }
1659
1660 /**
1661 * Reflective method dispatch
1662 */
1663 private static final class InvokeMethodReturningVoid extends MagicGenerator {
1664 @Override
1665 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1666 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset();
1667 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words
1668 asm.emitCALL_Abs(Magic.getTocPointer().plus(offset));
1669 }
1670 }
1671 static {
1672 MagicGenerator g = new InvokeMethodReturningVoid();
1673 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningVoid, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, void.class), g);
1674 }
1675
1676 /**
1677 * Reflective method dispatch
1678 */
1679 private static final class InvokeMethodReturningInt extends MagicGenerator {
1680 @Override
1681 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1682 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset();
1683 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words
1684 asm.emitCALL_Abs(Magic.getTocPointer().plus(offset));
1685 asm.emitPUSH_Reg(T0);
1686 }
1687 }
1688 static {
1689 MagicGenerator g = new InvokeMethodReturningInt();
1690 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningInt, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, int.class), g);
1691 }
1692
1693 /**
1694 * Reflective method dispatch
1695 */
1696 private static final class InvokeMethodReturningLong extends MagicGenerator {
1697 @Override
1698 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1699 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset();
1700 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words
1701 asm.emitCALL_Abs(Magic.getTocPointer().plus(offset));
1702 asm.emitPUSH_Reg(T0); // high half
1703 asm.emitPUSH_Reg(T1); // low half
1704 }
1705 }
1706 static {
1707 MagicGenerator g = new InvokeMethodReturningLong();
1708 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningLong, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, long.class), g);
1709 }
1710
1711 /**
1712 * Reflective method dispatch
1713 */
1714 private static final class InvokeMethodReturningFloat extends MagicGenerator {
1715 @Override
1716 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1717 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset();
1718 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words
1719 asm.emitCALL_Abs(Magic.getTocPointer().plus(offset));
1720 asm.emitPUSH_Reg(T0); // create space
1721 if (SSE2_FULL) {
1722 asm.emitMOVSS_RegInd_Reg(SP, XMM0);
1723 } else {
1724 asm.emitFSTP_RegInd_Reg(SP, FP0);
1725 }
1726 }
1727 }
1728 static {
1729 MagicGenerator g = new InvokeMethodReturningFloat();
1730 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningFloat, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, float.class), g);
1731 }
1732
1733 /**
1734 * Reflective method dispatch
1735 */
1736 private static final class InvokeMethodReturningDouble extends MagicGenerator {
1737 @Override
1738 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1739 Offset offset = ArchEntrypoints.reflectiveMethodInvokerInstructionsField.getOffset();
1740 BaselineCompilerImpl.genParameterRegisterLoad(asm, 5); // pass 5 parameter words
1741 asm.emitCALL_Abs(Magic.getTocPointer().plus(offset));
1742 asm.emitPUSH_Reg(T0); // create space
1743 asm.emitPUSH_Reg(T0);
1744 if (SSE2_FULL) {
1745 asm.emitMOVLPD_RegInd_Reg(SP, XMM0);
1746 } else {
1747 asm.emitFSTP_RegInd_Reg_Quad(SP, FP0);
1748 }
1749 }
1750 }
1751 static {
1752 MagicGenerator g = new InvokeMethodReturningDouble();
1753 generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningDouble, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, double.class), g);
1754 }
1755
1756 /**
1757 * Invoke an entry point taking values off of the stack
1758 */
1759 private static final class InvokeEntryPoint extends MagicGenerator {
1760 private final Offset offset;
1761 private final int args;
1762 InvokeEntryPoint(Offset offset, int args) {
1763 this.offset = offset;
1764 this.args = args;
1765 }
1766 @Override
1767 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1768 BaselineCompilerImpl.genParameterRegisterLoad(asm, args);
1769 asm.emitCALL_Abs(Magic.getTocPointer().plus(offset));
1770 }
1771 }
1772 static {
1773 generators.put(getMethodReference(Magic.class, MagicNames.saveThreadState, Registers.class, void.class),
1774 new InvokeEntryPoint(ArchEntrypoints.saveThreadStateInstructionsField.getOffset(), 1));
1775 generators.put(getMethodReference(Magic.class, MagicNames.threadSwitch, RVMThread.class, Registers.class, void.class),
1776 new InvokeEntryPoint(ArchEntrypoints.threadSwitchInstructionsField.getOffset(), 2));
1777 generators.put(getMethodReference(Magic.class, MagicNames.restoreHardwareExceptionState, Registers.class, void.class),
1778 new InvokeEntryPoint(ArchEntrypoints.restoreHardwareExceptionStateInstructionsField.getOffset(), 1));
1779 }
1780
1781 /**
1782 * Perform dynamic bridge from linker to compiled code
1783 */
1784 private static final class DynamicBridgeTo extends MagicGenerator {
1785 @Override
1786 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1787 if (VM.VerifyAssertions) VM._assert(cm.getDeclaringClass().hasDynamicBridgeAnnotation());
1788
1789 // save the branch address for later
1790 asm.emitPOP_Reg(S0); // S0<-code address
1791
1792 if (VM.BuildFor32Addr) {
1793 asm.emitADD_Reg_Imm(SP, sd.toInt() - WORDSIZE); // just popped WORDSIZE bytes above.
1794 } else {
1795 asm.emitADD_Reg_Imm_Quad(SP, sd.toInt() - WORDSIZE); // just popped WORDSIZE bytes above.
1796 }
1797 if (SSE2_FULL) {
1798 // TODO: Restore SSE2 Control word?
1799 asm.emitMOVQ_Reg_RegDisp(XMM0, SP, XMM_SAVE_OFFSET.plus(0));
1800 asm.emitMOVQ_Reg_RegDisp(XMM1, SP, XMM_SAVE_OFFSET.plus(8));
1801 asm.emitMOVQ_Reg_RegDisp(XMM2, SP, XMM_SAVE_OFFSET.plus(16));
1802 asm.emitMOVQ_Reg_RegDisp(XMM3, SP, XMM_SAVE_OFFSET.plus(24));
1803 } else {
1804 // restore FPU state
1805 asm.emitFRSTOR_RegDisp(SP, FPU_SAVE_OFFSET);
1806 }
1807
1808 // restore GPRs
1809 if (VM.BuildFor32Addr) {
1810 asm.emitMOV_Reg_RegDisp(T0, SP, T0_SAVE_OFFSET);
1811 asm.emitMOV_Reg_RegDisp(T1, SP, T1_SAVE_OFFSET);
1812 asm.emitMOV_Reg_RegDisp(EBX, SP, EBX_SAVE_OFFSET);
1813 asm.emitMOV_Reg_RegDisp(EDI, SP, EDI_SAVE_OFFSET);
1814 } else {
1815 asm.emitMOV_Reg_RegDisp_Quad(T0, SP, T0_SAVE_OFFSET);
1816 asm.emitMOV_Reg_RegDisp_Quad(T1, SP, T1_SAVE_OFFSET);
1817 asm.emitMOV_Reg_RegDisp_Quad(EBX, SP, EBX_SAVE_OFFSET);
1818 asm.emitMOV_Reg_RegDisp_Quad(EDI, SP, EDI_SAVE_OFFSET);
1819 }
1820
1821 // pop frame
1822 asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset()); // FP<-previous FP
1823
1824 // branch
1825 asm.emitJMP_Reg(S0);
1826 }
1827 }
1828 static {
1829 MagicGenerator g = new DynamicBridgeTo();
1830 generators.put(getMethodReference(Magic.class, MagicNames.dynamicBridgeTo, CodeArray.class, void.class), g);
1831 }
1832
1833 /**
1834 * Exchange stacks
1835 */
1836 private static final class ReturnToNewStack extends MagicGenerator {
1837 @Override
1838 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1839 // SP gets frame pointer for new stack
1840 asm.emitPOP_Reg(SP);
1841
1842 // restore nonvolatile registers
1843 if (VM.BuildFor32Addr) {
1844 asm.emitMOV_Reg_RegDisp(EDI, SP, EDI_SAVE_OFFSET);
1845 asm.emitMOV_Reg_RegDisp(EBX, SP, EBX_SAVE_OFFSET);
1846 } else {
1847 asm.emitMOV_Reg_RegDisp_Quad(EDI, SP, EDI_SAVE_OFFSET);
1848 asm.emitMOV_Reg_RegDisp_Quad(EBX, SP, EBX_SAVE_OFFSET);
1849 }
1850 // discard current stack frame
1851 asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset());
1852
1853 // return to caller- pop parameters from stack
1854 int parameterWords = cm.getParameterWords() + (cm.isStatic() ? 0 : 1); // add 1 for this pointer
1855 asm.emitRET_Imm(parameterWords << LG_WORDSIZE);
1856 }
1857 }
1858 static {
1859 MagicGenerator g = new ReturnToNewStack();
1860 generators.put(getMethodReference(Magic.class, MagicNames.returnToNewStack, Address.class, void.class), g);
1861 }
1862
1863 /**
1864 * Boot up calling of class initializers
1865 */
1866 private static final class InvokeClassInitializer extends MagicGenerator {
1867 @Override
1868 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1869 asm.emitPOP_Reg(S0);
1870 asm.emitCALL_Reg(S0); // call address just popped
1871 }
1872 }
1873 static {
1874 MagicGenerator g = new InvokeClassInitializer();
1875 generators.put(getMethodReference(Magic.class, MagicNames.invokeClassInitializer, CodeArray.class, void.class), g);
1876 }
1877
1878 /**
1879 * Get frame pointer on entry to method
1880 */
1881 private static final class GetFramePointer extends MagicGenerator {
1882 @Override
1883 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1884 asm.emitLEA_Reg_RegDisp(S0, SP, sd);
1885 asm.emitPUSH_Reg(S0);
1886 }
1887 }
1888 static {
1889 MagicGenerator g = new GetFramePointer();
1890 generators.put(getMethodReference(Magic.class, MagicNames.getFramePointer, Address.class), g);
1891 }
1892
1893 /**
1894 * Load an address from the stack and load the value at it plus a displacement
1895 */
1896 private static final class GetValueAtDisplacement extends MagicGenerator {
1897 final Offset disp;
1898 GetValueAtDisplacement(Offset disp) {
1899 this.disp = disp;
1900 }
1901 @Override
1902 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1903 asm.emitPOP_Reg(T0);
1904 asm.emitPUSH_RegDisp(T0, disp);
1905 }
1906 }
1907 static {
1908 generators.put(getMethodReference(Magic.class, MagicNames.getCallerFramePointer, Address.class, Address.class),
1909 new GetValueAtDisplacement(Offset.fromIntSignExtend(STACKFRAME_FRAME_POINTER_OFFSET)));
1910 generators.put(getMethodReference(Magic.class, MagicNames.getCompiledMethodID, Address.class, int.class),
1911 new GetValueAtDisplacement(Offset.fromIntSignExtend(STACKFRAME_METHOD_ID_OFFSET)));
1912 MagicGenerator g = new GetValueAtDisplacement(ObjectModel.getArrayLengthOffset());
1913 generators.put(getMethodReference(Magic.class, MagicNames.getArrayLength, Object.class, int.class), g);
1914 Class<?>[] unboxedTypes = new Class<?>[]{AddressArray.class, CodeArray.class, ExtentArray.class, FunctionTable.class, IMT.class, ObjectReferenceArray.class, OffsetArray.class, TIB.class, WordArray.class};
1915 for (Class<?> type : unboxedTypes) {
1916 generators.put(getMethodReference(type, MagicNames.addressArrayLength, int.class), g);
1917 }
1918 }
1919
1920 /**
1921 * Store a value to an address from the stack plus a displacement
1922 */
1923 private static final class SetValueAtDisplacement extends MagicGenerator {
1924 final Offset disp;
1925 SetValueAtDisplacement(Offset disp) {
1926 this.disp = disp;
1927 }
1928 @Override
1929 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1930 asm.emitPOP_Reg(T0); // value
1931 asm.emitPOP_Reg(S0); // fp
1932 if (VM.BuildFor32Addr) {
1933 asm.emitMOV_RegDisp_Reg(S0, disp, T0); // [S0+disp] <- T0
1934 } else {
1935 asm.emitMOV_RegDisp_Reg_Quad(S0, disp, T0); // [S0+disp] <- T0
1936 }
1937 }
1938 }
1939 static {
1940 generators.put(getMethodReference(Magic.class, MagicNames.setCallerFramePointer, Address.class, Address.class, void.class),
1941 new SetValueAtDisplacement(Offset.fromIntSignExtend(STACKFRAME_FRAME_POINTER_OFFSET)));
1942 generators.put(getMethodReference(Magic.class, MagicNames.setCompiledMethodID, Address.class, int.class, void.class),
1943 new SetValueAtDisplacement(Offset.fromIntSignExtend(STACKFRAME_METHOD_ID_OFFSET)));
1944 }
1945
1946 /**
1947 * Create an array for a runtime table
1948 * @see org.jikesrvm.objectmodel.RuntimeTable
1949 */
1950 private static final class CreateArray extends MagicGenerator {
1951 private final RVMArray array;
1952 CreateArray(RVMArray array) {
1953 this.array = array;
1954 }
1955 @Override
1956 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1957 int width = array.getLogElementSize();
1958 Offset tibOffset = array.getTibOffset();
1959 int headerSize = ObjectModel.computeHeaderSize(array);
1960 int whichAllocator = MemoryManager.pickAllocator(array, cm);
1961 int site = MemoryManager.getAllocationSite(true);
1962 int align = ObjectModel.getAlignment(array);
1963 int offset = ObjectModel.getOffsetForAlignment(array, false);
1964 // count is already on stack- nothing required
1965 asm.emitPUSH_Imm(width); // logElementSize
1966 asm.emitPUSH_Imm(headerSize); // headerSize
1967 asm.emitPUSH_Abs(Magic.getTocPointer().plus(tibOffset)); // tib
1968 asm.emitPUSH_Imm(whichAllocator); // allocator
1969 asm.emitPUSH_Imm(align);
1970 asm.emitPUSH_Imm(offset);
1971 asm.emitPUSH_Imm(site);
1972 BaselineCompilerImpl.genParameterRegisterLoad(asm, 8); // pass 8 parameter words
1973 asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.resolvedNewArrayMethod.getOffset()));
1974 asm.emitPUSH_Reg(T0);
1975 }
1976 }
1977 static {
1978 Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class,
1979 CodeArray.class, ExtentArray.class, ObjectReferenceArray.class,
1980 OffsetArray.class, WordArray.class };
1981 for (Class<?> type : unboxedTypes) {
1982 MagicGenerator g = new CreateArray(TypeReference.findOrCreate(type).resolve().asArray());
1983 generators.put(getMethodReference(type, MagicNames.addressArrayCreate, int.class, type), g);
1984 }
1985 }
1986
1987 /**
1988 * Get a 32bit element from a runtime table
1989 * @see org.jikesrvm.objectmodel.RuntimeTable#get(int)
1990 */
1991 private static final class Load32_Array extends MagicGenerator {
1992 @Override
1993 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
1994 asm.emitPOP_Reg(T0); // T0 is array index
1995 asm.emitPOP_Reg(S0); // S0 is array ref
1996 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
1997 // push [S0+T0<<2]
1998 asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT);
1999 }
2000 }
2001 /**
2002 * Get a 64bit element from a runtime table
2003 * @see org.jikesrvm.objectmodel.RuntimeTable#get(int)
2004 */
2005 private static final class Load64_Array extends MagicGenerator {
2006 @Override
2007 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2008 asm.emitPOP_Reg(T0); // T0 is array index
2009 asm.emitPOP_Reg(S0); // S0 is array ref
2010 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
2011 // push [S0+T0<<3]
2012 asm.emitPUSH_RegIdx(S0, T0, Assembler.LONG, NO_SLOT);
2013 }
2014 }
2015 static {
2016 MagicGenerator g = VM.BuildFor32Addr ? new Load32_Array() : new Load64_Array();
2017 Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class,
2018 ExtentArray.class, FunctionTable.class, IMT.class,
2019 ObjectReferenceArray.class, OffsetArray.class,
2020 TIB.class, WordArray.class };
2021 Class<?>[] resultTypes = new Class<?>[] { Address.class, Extent.class,
2022 CodeArray.class, CodeArray.class, ObjectReference.class, Offset.class,
2023 Object.class, Word.class };
2024 for (int i=0; i < unboxedTypes.length; i++) {
2025 Class<?> type = unboxedTypes[i];
2026 Class<?> result = resultTypes[i];
2027 generators.put(getMethodReference(type, MagicNames.addressArrayGet, int.class, result), g);
2028 }
2029 }
2030
2031 /**
2032 * Get a byte element from a runtime table
2033 */
2034 private static final class LoadByte_Array extends MagicGenerator {
2035 @Override
2036 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2037 asm.emitPOP_Reg(T0); // T0 is array index
2038 asm.emitPOP_Reg(S0); // S0 is array ref
2039 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
2040 // T1 = (int)[S0+T0<<1]
2041 asm.emitMOVSX_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
2042 asm.emitPUSH_Reg(T1); // push byte onto stack
2043 }
2044 }
2045 static {
2046 MagicGenerator g = new LoadByte_Array();
2047 generators.put(getMethodReference(CodeArray.class, MagicNames.addressArrayGet, int.class, byte.class), g);
2048 }
2049
2050 /**
2051 * Store a 32bit element to a runtime table
2052 * @see org.jikesrvm.objectmodel.RuntimeTable#set(int, Object)
2053 */
2054 private static final class Store32_Array extends MagicGenerator {
2055 @Override
2056 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2057 Barriers.compileModifyCheck(asm, 8);
2058 asm.emitPOP_Reg(T1); // T1 is the value
2059 asm.emitPOP_Reg(T0); // T0 is array index
2060 asm.emitPOP_Reg(S0); // S0 is array ref
2061 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
2062 asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1
2063 }
2064 }
2065 /**
2066 * Store a 64bit element to a runtime table
2067 * @see org.jikesrvm.objectmodel.RuntimeTable#set(int, Object)
2068 */
2069 private static final class Store64_Array extends MagicGenerator {
2070 @Override
2071 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2072 Barriers.compileModifyCheck(asm, 8);
2073 asm.emitPOP_Reg(T1); // T1 is the value
2074 asm.emitPOP_Reg(T0); // T0 is array index
2075 asm.emitPOP_Reg(S0); // S0 is array ref
2076 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
2077 asm.emitMOV_RegIdx_Reg_Quad(S0, T0, Assembler.LONG, NO_SLOT, T1); // [S0 + T0<<2] <- T1
2078 }
2079 }
2080 static {
2081 MagicGenerator g = VM.BuildFor32Addr ? new Store32_Array() : new Store64_Array();
2082 Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class,
2083 ExtentArray.class, FunctionTable.class, IMT.class,
2084 ObjectReferenceArray.class, OffsetArray.class,
2085 TIB.class, WordArray.class };
2086 Class<?>[] operandTypes = new Class<?>[] { Address.class, Extent.class,
2087 CodeArray.class, CodeArray.class, ObjectReference.class, Offset.class,
2088 Object.class, Word.class };
2089 for (int i=0; i < unboxedTypes.length; i++) {
2090 Class<?> type = unboxedTypes[i];
2091 Class<?> operand = operandTypes[i];
2092 generators.put(getMethodReference(type, MagicNames.addressArraySet, int.class, operand, void.class), g);
2093 }
2094 }
2095
2096 /**
2097 * Set a 8bit in a runtime table
2098 */
2099 private static final class Store8_Array extends MagicGenerator {
2100 @Override
2101 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2102 Barriers.compileModifyCheck(asm, 8);
2103 asm.emitPOP_Reg(T1); // T1 is the value
2104 asm.emitPOP_Reg(T0); // T0 is array index
2105 asm.emitPOP_Reg(S0); // S0 is array ref
2106 BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
2107 asm.emitMOV_RegIdx_Reg_Byte(S0, T0, Assembler.BYTE, NO_SLOT, T1); // [S0 + T0<<2] <- T1
2108 }
2109 }
2110 static {
2111 MagicGenerator g = new Store8_Array();
2112 generators.put(getMethodReference(CodeArray.class, MagicNames.addressArraySet, int.class, byte.class, void.class), g);
2113 }
2114
2115 /**
2116 * Create address that holds return address
2117 */
2118 private static final class GetReturnAddressLocation extends MagicGenerator {
2119 @Override
2120 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2121 if (VM.BuildFor32Addr) {
2122 asm.emitADD_RegInd_Imm(SP, STACKFRAME_RETURN_ADDRESS_OFFSET);
2123 } else {
2124 asm.emitADD_RegInd_Imm_Quad(SP, STACKFRAME_RETURN_ADDRESS_OFFSET);
2125 }
2126 }
2127 }
2128 static {
2129 MagicGenerator g = new GetReturnAddressLocation();
2130 generators.put(getMethodReference(Magic.class, MagicNames.getReturnAddressLocation, Address.class, Address.class), g);
2131 }
2132
2133 /**
2134 * Get a 64bit time base value (not accurate on certain multi-cores)
2135 */
2136 private static final class GetTimeBase extends MagicGenerator {
2137 @Override
2138 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2139 asm.emitRDTSC(); // read timestamp counter instruction
2140 asm.emitPUSH_Reg(EDX); // upper 32 bits
2141 asm.emitPUSH_Reg(EAX); // lower 32 bits
2142 }
2143 }
2144 static {
2145 MagicGenerator g = new GetTimeBase();
2146 generators.put(getMethodReference(Magic.class, MagicNames.getTimeBase, long.class), g);
2147 }
2148
2149 /**
2150 * Pause hint that thread is contending for a lock
2151 */
2152 private static final class Pause extends MagicGenerator {
2153 @Override
2154 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2155 asm.emitPAUSE();
2156 }
2157 }
2158 static {
2159 MagicGenerator g = new Pause();
2160 generators.put(getMethodReference(Magic.class, MagicNames.pause, void.class), g);
2161 }
2162
2163 /**
2164 * Floating point square root
2165 */
2166 private static final class Fsqrt extends MagicGenerator {
2167 @Override
2168 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2169 if (SSE2_BASE) {
2170 asm.emitSQRTSS_Reg_RegInd(XMM0, SP); // XMM0 = sqrt(value)
2171 asm.emitMOVSS_RegInd_Reg(SP, XMM0); // set result on stack
2172 } else {
2173 VM.sysFail("Hardware sqrt only available for SSE");
2174 }
2175 }
2176 }
2177 static {
2178 MagicGenerator g = new Fsqrt();
2179 generators.put(getMethodReference(Magic.class, MagicNames.sqrt, float.class, float.class), g);
2180 }
2181
2182 /**
2183 * Double precision square root
2184 */
2185 private static final class Dsqrt extends MagicGenerator {
2186 @Override
2187 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2188 if (SSE2_BASE) {
2189 asm.emitSQRTSD_Reg_RegInd(XMM0, SP); // XMM0 = sqrt(value)
2190 asm.emitMOVLPD_RegInd_Reg(SP, XMM0); // set result on stack
2191 } else {
2192 VM.sysFail("Hardware sqrt only available for SSE");
2193 }
2194 }
2195 }
2196 static {
2197 MagicGenerator g = new Dsqrt();
2198 generators.put(getMethodReference(Magic.class, MagicNames.sqrt, double.class, double.class), g);
2199 }
2200
2201 /**
2202 * Return the current inlining depth (always 0 for baseline)
2203 */
2204 private static final class GetInlineDepth extends MagicGenerator {
2205 @Override
2206 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2207 asm.emitPUSH_Imm(0);
2208 }
2209 }
2210 static {
2211 MagicGenerator g = new GetInlineDepth();
2212 generators.put(getMethodReference(Magic.class, MagicNames.getInlineDepth, int.class), g);
2213 }
2214
2215 /**
2216 * Is the requested parameter a constant? Always {@code false} for baseline.
2217 */
2218 private static final class IsConstantParameter extends MagicGenerator {
2219 @Override
2220 void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
2221 asm.emitPOP_Reg(T0);
2222 asm.emitPUSH_Imm(0);
2223 }
2224 }
2225 static {
2226 MagicGenerator g = new IsConstantParameter();
2227 generators.put(getMethodReference(Magic.class, MagicNames.isConstantParameter, int.class, boolean.class), g);
2228 }
2229 }