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    }