/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.ppc;
import org.jikesrvm.mm.mminterface.MemoryManager;
import org.jikesrvm.runtime.ArchEntrypoints;
import org.jikesrvm.runtime.Magic;
import org.jikesrvm.scheduler.RVMThread;
import org.jikesrvm.VM;
import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.pragma.Untraced;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.Offset;
import org.vmmagic.unboxed.WordArray;
import org.vmmagic.unboxed.Word;
/**
* The machine state comprising a thread's execution context.
*/
@Uninterruptible
public abstract class Registers implements ArchConstants {
// The following are used both for thread context switching
// and for hardware exception reporting/delivery.
//
@Untraced
public final WordArray gprs; // word size general purpose registers (either 32 or 64 bit)
@Untraced
public final double[] fprs; // 64-bit floating point registers
public final WordArray gprsShadow;
public final double[] fprsShadow;
public Address ip; // instruction address register
// The following are used by exception delivery.
// They are set by either Runtime.athrow or the C hardware exception
// handler and restored by "Magic.restoreHardwareExceptionState".
// They are not used for context switching.
//
public Address lr; // link register
public boolean inuse; // do exception registers currently contain live values?
private static final Address invalidIP = Address.max();
public Registers() {
gprs = gprsShadow = MemoryManager.newNonMovingWordArray(NUM_GPRS);
fprs = fprsShadow = MemoryManager.newNonMovingDoubleArray(NUM_FPRS);
ip = invalidIP;
}
public final void clear() {
for (int i=0;i<NUM_GPRS;++i) {
gprs.set(i,Word.zero());
}
for (int i=0;i<NUM_FPRS;++i) {
fprs[i]=0.;
}
ip=Address.zero();
lr=Address.zero();
}
public final void copyFrom(Registers other) {
for (int i=0;i<NUM_GPRS;++i) {
gprs.set(i,other.gprs.get(i));
}
for (int i=0;i<NUM_FPRS;++i) {
fprs[i]=other.fprs[i];
}
ip=other.ip;
lr=other.lr;
}
public final void assertSame(Registers other) {
boolean fail=false;
for (int i=0;i<NUM_GPRS;++i) {
if (gprs.get(i).NE(other.gprs.get(i))) {
VM.sysWriteln("Registers not equal: GPR #",i);
fail=true;
}
}
for (int i=0;i<NUM_FPRS;++i) {
if (fprs[i]!=other.fprs[i]) {
VM.sysWriteln("Registers not equal: FPR #",i);
fail=true;
}
}
if (ip.NE(other.ip)) {
VM.sysWriteln("Registers not equal: IP");
fail=true;
}
if (lr.NE(other.lr)) {
VM.sysWriteln("Registers not equal: LR");
fail=true;
}
if (fail) {
RVMThread.dumpStack();
VM.sysFail("Registers.assertSame() failed");
}
}
/** @return framepointer for the deepest stackframe */
public final Address getInnermostFramePointer() {
return gprs.get(FRAME_POINTER).toAddress();
}
/** @return next instruction address for the deepest stackframe */
public final Address getInnermostInstructionAddress() {
if (ip.NE(invalidIP)) return ip; // ip set by hardware exception handler or Magic.threadSwitch
return Magic.getNextInstructionAddress(getInnermostFramePointer()); // ip set to -1 because we're unwinding
}
/** Update the machine state to unwind the deepest stackframe. */
public final void unwindStackFrame() {
ip = invalidIP; // if there was a valid value in ip, it ain't valid anymore
gprs.set(FRAME_POINTER, Magic.getCallerFramePointer(getInnermostFramePointer()).toWord());
}
/**
* Set ip & fp. used to control the stack frame at which a scan of
* the stack during GC will start, for ex., the top java frame for
* a thread that is blocked in native code during GC.
*/
public final void setInnermost(Address newip, Address newfp) {
ip = newip;
gprs.set(FRAME_POINTER, newfp.toWord());
}
/**
* Set ip and fp values to those of the caller. used just prior to entering
* sigwait to set fp & ip so that GC will scan the threads stack
* starting at the frame of the method that called sigwait.
*/
public final void setInnermost() {
Address fp = Magic.getFramePointer();
ip = Magic.getReturnAddress(fp);
gprs.set(FRAME_POINTER, Magic.getCallerFramePointer(fp).toWord());
}
public final Address getIPLocation() {
Offset ipOffset = ArchEntrypoints.registersIPField.getOffset();
return Magic.objectAsAddress(this).plus(ipOffset);
}
}