📄 protectedmodeudecoder.java
字号:
/* JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine Release Version 2.0 A project from the Physics Dept, The University of Oxford Copyright (C) 2007 Isis Innovation Limited This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Details (including contact information) can be found at: www.physics.ox.ac.uk/jpc*/package org.jpc.emulator.memory.codeblock.optimised;import org.jpc.emulator.memory.codeblock.*;public final class ProtectedModeUDecoder implements MicrocodeSet, Decoder, InstructionSource{ private static final boolean[] modrmArray = new boolean[] { // true for opcodes that require a modrm byte true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, true, true, true, true, false, false, false, false, false, false, false, false, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, true, true }; private static final boolean[] sibArray = new boolean[] { // true for modrm values that require a sib byte (32 bit addressing only) false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }; private static final boolean[] twoByte_0f_modrmArray = new boolean[] { // true for opcodes that require a modrm byte true, true, true, true, false, false, false, false, false, false, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, true, true, true, true, true, false, true, false, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, true, true, true, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true }; private static final boolean[] twoByte_0f_sibArray = new boolean[] { // true for modrm values that require a sib byte (32 bit addressing only) false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }; private static final int PREFICES_SG = 0x7; private static final int PREFICES_ES = 0x1; private static final int PREFICES_CS = 0x2; private static final int PREFICES_SS = 0x3; private static final int PREFICES_DS = 0x4; private static final int PREFICES_FS = 0x5; private static final int PREFICES_GS = 0x6; private static final int PREFICES_OPERAND = 0x8; private static final int PREFICES_ADDRESS = 0x10; private static final int PREFICES_REPNE = 0x20; private static final int PREFICES_REPE = 0x40; private static final int PREFICES_REP = PREFICES_REPNE | PREFICES_REPE; private static final int PREFICES_LOCK = 0x80; private ByteSource source; private Operation current; private Operation waiting; private Operation working; private boolean blockComplete; private boolean addressModeDecoded; private boolean operandSizeIs32Bit; public ProtectedModeUDecoder() { this.current = new Operation(); this.waiting = new Operation(); this.working = new Operation(); } public InstructionSource decodeReal(ByteSource source) { return null; } public InstructionSource decodeVirtual8086(ByteSource source) { return null; } public InstructionSource decodeProtected(ByteSource source, boolean operandSize) { reset(); operandSizeIs32Bit = operandSize; this.source = source; return this; } private void blockFinished() { blockComplete = true; } private void rotate() { Operation temp = current; current = waiting; waiting = working; working = temp; } public boolean getNext() { decode(); //will put new block in working rotate(); //moves buffer around if (current.decoded()) return true; else if (current.terminal()) { reset(); return false; } else return getNext(); } private void reset() { working.reset(); waiting.reset(); current.reset(); blockComplete = false; } public int getMicrocode() { return current.getMicrocode(); } public int getLength() { return current.getLength(); } public int getX86Length() { return current.getX86Length(); } private boolean decodingAddressMode() { if (addressModeDecoded) { return false; } else { return (addressModeDecoded = true); } } private void decodeComplete(int position) { if (addressModeDecoded) { working.write(MEM_RESET); addressModeDecoded = false; } working.finish(position); } private void decode() { working.reset(); if (blockComplete) { working.makeTerminal(); return; } int length = 0; try { length = decodeOpcode(operandSizeIs32Bit); } catch (NullPointerException npe) { //System.out.println("Got an IOException: " + npe.getMessage()); //npe.printStackTrace(); throw npe; } catch (RuntimeException e) { //System.out.println("Got an IOException: " + e.getMessage()); //e.printStackTrace(); if (!waiting.decoded()) throw e; waiting.write(EIP_UPDATE); working.makeTerminal(); blockFinished(); return; } if (length < 0) { decodeComplete(-length); blockFinished(); } else { decodeComplete(length); } } private int decodeOpcode(boolean operandSizeIs32Bit) { int opcode = 0; int opcodePrefix = 0; int prefices = operandSizeIs32Bit ? PREFICES_OPERAND | PREFICES_ADDRESS : 0x00; int bytesRead = 0; int modrm = -1; int sib = -1; while (true) { bytesRead += 1; switch (opcode = 0xff & source.getByte()) { case 0x0f: opcodePrefix = (opcodePrefix << 8) | opcode; opcode = 0xff & source.getByte(); bytesRead += 1; modrm = opcode; break; case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: opcodePrefix = (opcodePrefix << 8) | opcode; opcode = 0; modrm = 0xff & source.getByte(); bytesRead += 1; break; //Prefices case 0x2e: prefices &= ~PREFICES_SG; prefices |= PREFICES_CS; continue; case 0x3e: prefices &= ~PREFICES_SG; prefices |= PREFICES_DS; continue; case 0x26: prefices &= ~PREFICES_SG; prefices |= PREFICES_ES; continue; case 0x36: prefices &= ~PREFICES_SG; prefices |= PREFICES_SS; continue; case 0x64: prefices &= ~PREFICES_SG; prefices |= PREFICES_FS; continue; case 0x65: prefices &= ~PREFICES_SG; prefices |= PREFICES_GS; continue; case 0x66: prefices = prefices ^ PREFICES_OPERAND; continue; case 0x67: prefices = prefices ^ PREFICES_ADDRESS; continue; case 0xf2: prefices |= PREFICES_REPNE; continue; case 0xf3: prefices |= PREFICES_REPE; continue; case 0xf0: prefices |= PREFICES_LOCK; continue; default: break; } break; } opcode = (opcodePrefix << 8) | opcode; switch (opcodePrefix) { case 0x00: if (modrmArray[opcode]) { modrm = 0xff & source.getByte(); bytesRead += 1; } else { modrm = -1; } if ((modrm == -1) || ((prefices & PREFICES_ADDRESS) == 0)) { sib = -1; } else { if (sibArray[modrm]) { sib = 0xff & source.getByte(); bytesRead += 1; } else { sib = -1; } } break; case 0x0f: if (twoByte_0f_modrmArray[0xff & opcode]) { modrm = 0xff & source.getByte(); bytesRead += 1; } else { modrm = -1; } if ((modrm == -1) || ((prefices & PREFICES_ADDRESS) == 0)) { sib = -1; } else { if (twoByte_0f_sibArray[modrm]) { sib = 0xff & source.getByte(); bytesRead += 1; } else { sib = -1; } } //System.out.println("0x0F prefix "+Integer.toHexString(opcode)); break; case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: if (sibArray[modrm]) { sib = 0xff & source.getByte(); bytesRead += 1; } else { sib = -1; } break; default: modrm = -1; sib = -1; break; } if (isJump(opcode, modrm)) working.write(EIP_UPDATE); int displacement = 0; switch (operationHasDisplacement(prefices, opcode, modrm, sib)) { case 0: break; case 1: displacement = source.getByte(); bytesRead += 1; break; case 2: displacement = (source.getByte() & 0xff) | ((source.getByte() << 8) & 0xff00); bytesRead += 2; break; case 4: displacement = (source.getByte() & 0xff) | ((source.getByte() << 8) & 0xff00) | ((source.getByte() << 16) & 0xff0000) | ((source.getByte() << 24) & 0xff000000); bytesRead += 4; break; default: System.err.println("Displacement Longer Than 4-bytes"); break; } long immediate = 0; switch (operationHasImmediate(prefices, opcode, modrm)) { case 0: break; case 1: immediate = source.getByte(); bytesRead += 1; break; case 2: immediate = (source.getByte() & 0xff) | ((source.getByte() << 8) & 0xff00); bytesRead += 2; break; case 3: immediate = ((source.getByte() << 16) & 0xff0000) | ((source.getByte() << 24) & 0xff000000) | (source.getByte() & 0xff);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -