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 }