001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.ia32;
014    
015    import org.jikesrvm.ArchitectureSpecific;
016    import org.jikesrvm.VM;
017    import org.jikesrvm.MachineSpecific;
018    import org.jikesrvm.SizeConstants;
019    import org.jikesrvm.runtime.Magic;
020    import org.vmmagic.pragma.Interruptible;
021    import org.vmmagic.pragma.Uninterruptible;
022    import org.vmmagic.unboxed.Address;
023    import org.vmmagic.unboxed.Offset;
024    import org.vmmagic.unboxed.Word;
025    
026    /**
027     * Wrappers around IA32-specific code common to both 32 & 64 bit
028     */
029    public abstract class MachineSpecificIA extends MachineSpecific implements ArchConstants {
030    
031      /**
032       * A well-known memory location used to manipulate the FPU control word.
033       */
034      static int FPUControlWord;
035    
036      /**
037       * Wrappers around IA32-specific code (32-bit specific)
038       */
039      public static final class IA32 extends MachineSpecificIA {
040        public static final IA32 singleton = new IA32();
041      }
042    
043      /**
044       * Wrappers around EMT64-specific code (64-bit specific)
045       */
046      public static final class EM64T extends MachineSpecificIA {
047        public static final EM64T singleton = new EM64T();
048      }
049    
050      /*
051      * Generic (32/64 neutral) IA support
052      */
053    
054      /* common to all ISAs */
055    
056      /**
057       * The following method will emit code that moves a reference to an
058       * object's TIB into a destination register.
059       *
060       * @param asm the assembler object to emit code with
061       * @param dest the number of the destination register
062       * @param object the number of the register holding the object reference
063       * @param tibOffset the offset of the tib from the object header
064       */
065      @Interruptible
066      public final void baselineEmitLoadTIB(ArchitectureSpecific.Assembler asm, int dest, int object, Offset tibOffset) {
067        if (VM.BuildFor32Addr) {
068          asm.emitMOV_Reg_RegDisp(GPR.lookup(dest), GPR.lookup(object), tibOffset);
069        } else {
070          asm.emitMOV_Reg_RegDisp_Quad(GPR.lookup(dest), GPR.lookup(object), tibOffset);
071        }
072      }
073    
074      /**
075       * The following method initializes a thread stack as if
076       * "startoff" method had been called by an empty baseline-compiled
077       *  "sentinel" frame with one local variable
078       *
079       * @param contextRegisters The context registers for this thread
080       * @param ip The instruction pointer for the "startoff" method
081       * @param sp The base of the stack
082       */
083      @Uninterruptible
084      public final void initializeStack(ArchitectureSpecific.Registers contextRegisters, Address ip, Address sp) {
085        Address fp;
086        sp = sp.minus(STACKFRAME_HEADER_SIZE);                   // last word of header
087        fp = sp.minus(SizeConstants.BYTES_IN_ADDRESS + STACKFRAME_BODY_OFFSET);
088        Magic.setCallerFramePointer(fp, STACKFRAME_SENTINEL_FP);
089        Magic.setCompiledMethodID(fp, INVISIBLE_METHOD_ID);
090    
091        sp = sp.minus(SizeConstants.BYTES_IN_ADDRESS);                                 // allow for one local
092        contextRegisters.gprs.set(ESP.value(), sp.toWord());
093        contextRegisters.fp = fp;
094        contextRegisters.ip = ip;
095      }
096    
097      /* unique to IA */
098    
099      /**
100       * A thread's stack has been moved or resized.
101       * Adjust the ESP register to reflect new position.
102       *
103       * @param registers The registers for this thread
104       * @param delta The displacement to be applied
105       * @param traceAdjustments Log all adjustments to stderr if true
106       */
107      @Uninterruptible
108      @Override
109      public final void adjustESP(ArchitectureSpecific.Registers registers, Offset delta, boolean traceAdjustments) {
110        Word old = registers.gprs.get(ESP.value());
111        registers.gprs.set(ESP.value(), old.plus(delta));
112        if (traceAdjustments) {
113          VM.sysWrite(" esp =");
114          VM.sysWrite(registers.gprs.get(ESP.value()));
115        }
116      }
117    }