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);
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