x86stackmanager.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 209 行

JAVA
209
字号
/*
 * $Id: X86StackManager.java,v 1.9 2004/02/15 11:07:18 epr Exp $
 */
package org.jnode.vm.x86.compiler;

import org.jnode.assembler.x86.AbstractX86Stream;
import org.jnode.assembler.x86.Register;
import org.jnode.assembler.x86.X86Constants;

/**
 * @author Ewout Prangsma (epr@users.sourceforge.net)
 */
public class X86StackManager {

	/** PUSH reg */
	private static final int MODE_REG = 1;
	/** PUSH imm32 */
	private static final int MODE_IMM32 = 2;
	/** PUSH msbReg ; PUSH lsbReg */
	private static final int MODE_REG64 = 3;

	private static int pushCount;
	private static int popCount;
	private static int pushTrimCount;
	private static int popWarnCount;

	protected final AbstractX86Stream os;
	private Register lastPushReg = null;
	private Register lastPushRegMSB = null;
	private int lastPushStart = -1;
	private int lastPushEnd = -1;
	private int lastPushMode;
	private int lastPushImm32;

	/** Set to 0 to enable the push-pop removal, set to >0 to disable */
	private final int DISABLED = 0;

	/**
	 * Initialize this instance
	 * 
	 * @param os
	 */
	public X86StackManager(AbstractX86Stream os) {
		this.os = os;
	}

	/**
	 * Write code to push the imm32 value on the stack
	 * 
	 * @param imm32
	 */
	public void writePUSH(int imm32) {
		lastPushStart = os.writePUSH(imm32);
		lastPushEnd = os.getLength();
		lastPushReg = null;
		lastPushImm32 = imm32;
		lastPushMode = MODE_IMM32;
		pushCount++;
	}

	/**
	 * Write code to push the contents of the given register on the stack
	 * 
	 * @param reg
	 */
	public void writePUSH(Register reg) {
		lastPushStart = os.writePUSH(reg);
		lastPushEnd = os.getLength();
		lastPushReg = reg;
		lastPushMode = MODE_REG;
		pushCount++;
	}

	/**
	 * Write code to push a 64-bit word on the stack
	 * 
	 * @param lsbReg
	 * @param msbReg
	 */
	public void writePUSH64(Register lsbReg, Register msbReg) {
		lastPushStart = os.writePUSH(msbReg);
		os.writePUSH(lsbReg);
		lastPushEnd = os.getLength();
		lastPushReg = lsbReg;
		lastPushRegMSB = msbReg;
		lastPushMode = MODE_REG64;
		pushCount++;
	}

	/**
	 * Write code to pop the contents of the top of the stack into the given register. If the last instruction was a push, this push is removed.
	 * 
	 * @param reg
	 */
	public void writePOP(Register reg) {
		popCount++;
		//final int len = os.getLength()+1; // +1 -> Force an !=
		final int len = os.getLength() + DISABLED;
		if ((len == lastPushEnd) && (lastPushMode != MODE_REG64)) {
			// We can undo the last push
			pushTrimCount++;
			os.trim(lastPushEnd - lastPushStart);
			/*
			 * if (os.isLogEnabled()) { os.log("rewrite pop " + reg);
			 */
			switch (lastPushMode) {
				case MODE_REG :
					if (reg != lastPushReg) {
						os.writeMOV(X86Constants.BITS32, reg, lastPushReg);
					}
					break;
				case MODE_IMM32 :
					os.writeMOV_Const(reg, lastPushImm32);
					break;
				default :
					throw new IllegalArgumentException("Unknown lastPushMode");
			}
			lastPushEnd = -1;
		} else {
			os.writePOP(reg);
		}
	}

	/**
	 * Write code to pop the contents of the top of the stack into [reg+disp]. If the last instruction was a push, this push is removed.
	 * 
	 * @param reg
	 * @param disp
	 */
	public void writePOP(Register reg, int disp) {
		popCount++;
		//final int len = os.getLength();
		final int len = os.getLength() + DISABLED;
		if ((len == lastPushEnd) && (lastPushMode != MODE_REG64)) {
			// We can undo the last push
			pushTrimCount++;
			os.trim(lastPushEnd - lastPushStart);
			if (os.isLogEnabled()) {
				os.log("rewrite pop [" + reg + "+" + disp + "]");
			}
			switch (lastPushMode) {
				case MODE_REG :
					os.writeMOV(X86Constants.BITS32, reg, disp, lastPushReg);
					break;
				case MODE_IMM32 :
					os.writeMOV_Const(reg, disp, lastPushImm32);
					break;
				default :
					throw new IllegalArgumentException("Unknown lastPushMode");
			}
			lastPushEnd = -1;
		} else {
			os.writePOP(reg, disp);
		}
	}

	/**
	 * Write code to pop a 64-bit word from the stack
	 * 
	 * @param lsbReg
	 * @param msbReg
	 */
	public void writePOP64(Register lsbReg, Register msbReg) {
		popCount++;
		//final int len = os.getLength();
		final int len = os.getLength() + DISABLED;
		if ((len == lastPushEnd) && (lastPushMode == MODE_REG64)) {
			if (lsbReg != lastPushRegMSB) {
				// We can undo the last push
				pushTrimCount++;
				os.trim(lastPushEnd - lastPushStart);
				/*
				 * if (os.isLogEnabled()) { os.log("rewrite pop64 [" + lsbReg + "+" + msbReg + "]");
				 */
				if (lsbReg != lastPushReg) {
					os.writeMOV(X86Constants.BITS32, lsbReg, lastPushReg);
				}
				if (msbReg != lastPushRegMSB) {
					os.writeMOV(X86Constants.BITS32, msbReg, lastPushRegMSB);
				}
				lastPushEnd = -1;
			} else {
			    //BootLog.debug("lsbReg == lastPushRegMSB (" + lsbReg + ")", new Exception("Stacktrace"));
				popWarnCount++;
				os.writePOP(lsbReg);
				os.writePOP(msbReg);
			}
		} else {
			os.writePOP(lsbReg);
			os.writePOP(msbReg);
		}
	}

	/**
	 * Reset the contents of this object to its default state.
	 */
	public void reset() {
		lastPushReg = null;
		lastPushStart = -1;
		lastPushEnd = -1;
		lastPushMode = -1;
	}

	public static void dumpStatistics() {
		final int p = pushTrimCount * 100 / popCount;
		System.out.println("Removed " + pushTrimCount + " push-pop's which is " + p + "% of all pop's; #warnings " + popWarnCount);
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?