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