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.compilers.common.assembler.ia32.Assembler;
016    import org.jikesrvm.runtime.Magic;
017    import org.jikesrvm.scheduler.RVMThread;
018    import org.vmmagic.pragma.Uninterruptible;
019    import org.vmmagic.unboxed.Offset;
020    import org.jikesrvm.ia32.RegisterConstants.GPR;
021    
022    /**
023     * This class provides a layer of abstraction that the rest of the VM must
024     * use in order to access the current <code>RVMThread</code> object.
025     *
026     * @see RVMThread
027     */
028    public abstract class ThreadLocalState {
029    
030      protected static final GPR THREAD_REGISTER = RegisterConstants.ESI;
031    
032      /**
033       * The C bootstrap program has placed a pointer to the initial
034       * RVMThread in ESI.
035       */
036      @Uninterruptible
037      public
038      static void boot() {
039        // do nothing - everything is already set up.
040      }
041    
042      /**
043       * Return the current RVMThread object
044       */
045      @Uninterruptible
046      public static RVMThread getCurrentThread() {
047        return Magic.getESIAsThread();
048      }
049    
050      /**
051       * Set the current RVMThread object
052       */
053      @Uninterruptible
054      public static void setCurrentThread(RVMThread p) {
055        Magic.setESIAsThread(p);
056      }
057    
058      /**
059       * Emit an instruction sequence to move the value of a register into a field
060       * in the current thread offset
061       *
062       * @param asm assembler object
063       * @param offset of field in the <code>RVMThread</code> object
064       * @param reg number of the register supplying the new value
065       */
066      public static void emitMoveRegToField(Assembler asm, Offset offset, GPR reg) {
067        asm.emitMOV_RegDisp_Reg(THREAD_REGISTER, offset, reg);
068      }
069    
070      /**
071       * Emit an instruction sequence to move an immediate value into a field
072       * in the current thread offset
073       *
074       * @param asm assembler object
075       * @param offset of field in the <code>RVMThread</code> object
076       * @param imm immediate value
077       */
078      public static void emitMoveImmToField(Assembler asm, Offset offset, int imm) {
079        asm.emitMOV_RegDisp_Imm(THREAD_REGISTER, offset, imm);
080      }
081    
082      /**
083       * Emit an instruction sequence to move the value of a field in the
084       * current thread offset to a register
085       *
086       * @param asm assembler object
087       * @param dest number of destination register
088       * @param offset of field in the <code>RVMThread</code> object
089       */
090      public static void emitMoveFieldToReg(Assembler asm, GPR dest, Offset offset) {
091        asm.emitMOV_Reg_RegDisp(dest, THREAD_REGISTER, offset);
092      }
093    
094      /**
095       * Emit an instruction sequence to compare the value of a field in the
096       * current thread offset with an immediate value
097       *
098       * @param asm assembler object
099       * @param offset of field in the <code>RVMThread</code> object
100       * @param imm immediate value to compare with
101       */
102      public static void emitCompareFieldWithImm(Assembler asm, Offset offset, int imm) {
103        asm.emitCMP_RegDisp_Imm(THREAD_REGISTER, offset, imm);
104      }
105    
106      /**
107       * Emit an instruction sequence to to an atomic compare and exchange on a field in the
108       * current thread offset with an immediate value. Assumes EAX (T0) contains old value.
109       *
110       * @param asm assembler object
111       * @param offset of field in the <code>RVMThread</code> object
112       * @param srcReg register containing value to exchange
113       */
114      public static void emitCompareAndExchangeField(Assembler asm, Offset offset, GPR srcReg) {
115        asm.emitLockNextInstruction();
116        asm.emitCMPXCHG_RegDisp_Reg(THREAD_REGISTER, offset, srcReg);
117      }
118    
119      /**
120       * Emit an instruction sequence to decrement the value of a field in the
121       * current thread offset
122       *
123       * @param asm assembler object
124       * @param offset of field in the <code>RVMThread</code> object
125       */
126      public static void emitDecrementField(Assembler asm, Offset offset) {
127        asm.emitDEC_RegDisp(THREAD_REGISTER, offset);
128      }
129    
130      /**
131       * Emit an instruction sequence to PUSH the value of a field in the
132       * current thread offset
133       *
134       * @param asm assembler object
135       * @param offset of field in the <code>RVMThread</code> object
136       */
137      public static void emitPushField(Assembler asm, Offset offset) {
138        asm.emitPUSH_RegDisp(THREAD_REGISTER, offset);
139      }
140    
141      /**
142       * Emit an instruction sequence to POP a value into a field in the
143       * current thread offset
144       *
145       * @param asm assembler object
146       * @param offset of field in the <code>RVMThread</code> object
147       */
148      public static void emitPopField(Assembler asm, Offset offset) {
149        asm.emitPOP_RegDisp(THREAD_REGISTER, offset);
150      }
151    
152      /**
153       * Emit an instruction sequence to PUSH a pointer to the current RVMThread
154       * object on the stack.
155       *
156       * @param asm assembler object
157       */
158      public static void emitPushThread(Assembler asm) {
159        asm.emitPUSH_Reg(THREAD_REGISTER);
160      }
161    
162      /**
163       * Emit an instruction sequence to POP a value on the stack, and set the
164       * current thread reference to be this value.
165       *
166       * @param asm assembler object
167       */
168      public static void emitPopThread(Assembler asm) {
169        asm.emitPOP_Reg(THREAD_REGISTER);
170      }
171    
172      /**
173       * Emit an instruction sequence to store a pointer to the current RVMThread
174       * object at a location defined by [base]+offset
175       *
176       * @param asm assembler object
177       * @param base number of base register
178       * @param offset offset
179       */
180      public static void emitStoreThread(Assembler asm, GPR base, Offset offset) {
181        asm.emitMOV_RegDisp_Reg(base, offset, THREAD_REGISTER);
182      }
183    
184      /**
185       * Emit an instruction sequence to load current RVMThread
186       * object from a location defined by [base]+offset
187       *
188       * @param asm assembler object
189       * @param base number of base register
190       * @param offset offset
191       */
192      public static void emitLoadThread(Assembler asm, GPR base, Offset offset) {
193        asm.emitMOV_Reg_RegDisp(THREAD_REGISTER, base, offset);
194      }
195    }
196