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.runtime.ArchEntrypoints;
016    import org.jikesrvm.runtime.Magic;
017    import org.jikesrvm.scheduler.RVMThread;
018    import org.jikesrvm.VM;
019    import org.jikesrvm.mm.mminterface.MemoryManager;
020    import org.vmmagic.pragma.NonMoving;
021    import org.vmmagic.pragma.Uninterruptible;
022    import org.vmmagic.pragma.Untraced;
023    import org.vmmagic.unboxed.Address;
024    import org.vmmagic.unboxed.Word;
025    import org.vmmagic.unboxed.Offset;
026    import org.vmmagic.unboxed.WordArray;
027    
028    /**
029     * The machine state comprising a thread's execution context, used both for
030     * thread context switching and for software/hardware exception
031     * reporting/delivery.
032     */
033    @Uninterruptible
034    @NonMoving
035    public abstract class Registers implements RegisterConstants {
036    
037      /** General purpose registers */
038      @Untraced
039      public final WordArray gprs;
040      /** Floating point registers */
041      @Untraced
042      public final double[] fprs;
043      public final WordArray gprsShadow;
044      public final double[] fprsShadow;
045      /** Instruction address register */
046      public Address ip;
047      /** Frame pointer */
048      public Address fp;
049    
050      /**
051       * Do exception registers currently contain live values? Set by C hardware
052       * exception handler and RuntimeEntrypoints.athrow and reset by each
053       * implementation of ExceptionDeliverer.deliverException
054       */
055      public boolean inuse;
056    
057      public Registers() {
058        gprs = gprsShadow = MemoryManager.newNonMovingWordArray(NUM_GPRS);
059        fprs = fprsShadow = MemoryManager.newNonMovingDoubleArray(NUM_FPRS);
060      }
061      public final void copyFrom(Registers other) {
062        for (int i=0;i<NUM_GPRS;++i) {
063          gprs.set(i,other.gprs.get(i));
064        }
065        for (int i=0;i<NUM_FPRS;++i) {
066          fprs[i]=other.fprs[i];
067        }
068        ip=other.ip;
069        fp=other.fp;
070      }
071      public final void clear() {
072        for (int i=0;i<NUM_GPRS;++i) {
073          gprs.set(i,Word.zero());
074        }
075        for (int i=0;i<NUM_FPRS;++i) {
076          fprs[i]=0.;
077        }
078        ip=Address.zero();
079        fp=Address.zero();
080      }
081      public final void assertSame(Registers other) {
082        boolean fail=false;
083        for (int i=0;i<NUM_GPRS;++i) {
084          if (gprs.get(i).NE(other.gprs.get(i))) {
085            VM.sysWriteln("Registers not equal: GPR #",i);
086            fail=true;
087          }
088        }
089        for (int i=0;i<NUM_FPRS;++i) {
090          if (fprs[i]!=other.fprs[i]) {
091            VM.sysWriteln("Registers not equal: FPR #",i);
092            fail=true;
093          }
094        }
095        if (ip.NE(other.ip)) {
096          VM.sysWriteln("Registers not equal: IP");
097          fail=true;
098        }
099        if (fp.NE(other.fp)) {
100          VM.sysWriteln("Registers not equal: FP");
101          fail=true;
102        }
103        if (fail) {
104          RVMThread.dumpStack();
105          VM.sysFail("Registers.assertSame() failed");
106        }
107      }
108    
109      /**
110       * Return framepointer for the deepest stackframe
111       */
112      public final Address getInnermostFramePointer() {
113        return fp;
114      }
115    
116      /**
117       * Return next instruction address for the deepest stackframe
118       */
119      public final Address getInnermostInstructionAddress() {
120        return ip;
121      }
122    
123      /**
124       * update the machine state as if the stackframe were unwound.
125       */
126      public final void unwindStackFrame() {
127        ip = Magic.getReturnAddress(fp, RVMThread.getCurrentThread());
128        fp = Magic.getCallerFramePointer(fp);
129      }
130    
131      /**
132       * set ip & fp. used to control the stack frame at which a scan of
133       * the stack during GC will start, for ex., the top java frame for
134       * a thread that is blocked in native code during GC.
135       */
136      public final void setInnermost(Address newip, Address newfp) {
137        ip = newip;
138        fp = newfp;
139      }
140    
141      /**
142       * set ip and fp values to those of the caller. used just prior to entering
143       * sigwait to set fp & ip so that GC will scan the threads stack
144       * starting at the frame of the method that called sigwait.
145       */
146      public final void setInnermost() {
147        Address current_fp = Magic.getFramePointer();
148        ip = Magic.getReturnAddress(current_fp);
149        fp = Magic.getCallerFramePointer(current_fp);
150      }
151    
152      public final Address getIPLocation() {
153        Offset ipOffset = ArchEntrypoints.registersIPField.getOffset();
154        return Magic.objectAsAddress(this).plus(ipOffset);
155      }
156      public final void dump() {
157        for (int i=0;i<NUM_GPRS;++i) {
158          VM.sysWriteln("gprs[",i,"] = ",gprs.get(i));
159        }
160        for (int i=0;i<NUM_FPRS;++i) {
161          VM.sysWriteln("fprs[",i,"] = ",fprs[i]);
162        }
163        VM.sysWriteln("ip = ",ip);
164        VM.sysWriteln("fp = ",fp);
165      }
166    }
167