--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/asm/x86/InstructionDecoder.java Thu Sep 27 11:25:01 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,554 +0,0 @@
-/*
- * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.asm.x86;
-
-import sun.jvm.hotspot.asm.*;
-
-// basic instruction decoder class
-public class InstructionDecoder implements /* imports */ X86Opcodes , RTLDataTypes, RTLOperations {
-
- protected String name;
- protected int addrMode1;
- protected int operandType1;
- protected int addrMode2;
- protected int operandType2;
- protected int addrMode3;
- protected int operandType3;
-
- private int mod;
- private int regOrOpcode;
- private int rm;
- protected int prefixes;
-
- protected int byteIndex;
- protected int instrStartIndex;
-
- public InstructionDecoder(String name) {
- this.name = name;
- this.operandType1 = INVALID_OPERANDTYPE;
- this.operandType2 = INVALID_OPERANDTYPE;
- this.operandType3 = INVALID_OPERANDTYPE;
- this.addrMode1 = INVALID_ADDRMODE;
- this.addrMode2 = INVALID_ADDRMODE;
- this.addrMode3 = INVALID_ADDRMODE;
- }
- public InstructionDecoder(String name, int addrMode1, int operandType1) {
- this(name);
- this.addrMode1 = addrMode1;
- this.operandType1 = operandType1;
- }
- public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2) {
- this(name, addrMode1, operandType1);
- this.addrMode2 = addrMode2;
- this.operandType2 = operandType2;
- }
- public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2,
- int addrMode3, int operandType3) {
- this(name, addrMode1, operandType1, addrMode2, operandType2);
- this.addrMode3 = addrMode3;
- this.operandType3 = operandType3;
- }
- // "operand1"
- protected Operand getOperand1(byte[] bytesArray, boolean operandSize, boolean addrSize) {
- if( (addrMode1 != INVALID_ADDRMODE) && (operandType1 != INVALID_OPERANDTYPE) )
- return getOperand(bytesArray, addrMode1, operandType1, operandSize, addrSize);
- else
- return null;
- }
-
- // "operand2"
- protected Operand getOperand2(byte[] bytesArray, boolean operandSize, boolean addrSize) {
- if( (addrMode2 != INVALID_ADDRMODE) && (operandType2 != INVALID_OPERANDTYPE) )
- return getOperand(bytesArray, addrMode2, operandType2, operandSize, addrSize);
- else
- return null;
- }
-
- // "operand3"
- protected Operand getOperand3(byte[] bytesArray, boolean operandSize, boolean addrSize) {
- if( (addrMode3 != INVALID_ADDRMODE) && (operandType3 != INVALID_OPERANDTYPE) )
- return getOperand(bytesArray, addrMode3, operandType3, operandSize, addrSize);
- else
- return null;
- }
-
- static int readInt32(byte[] bytesArray, int index) {
- int ret = 0;
- ret = readByte(bytesArray, index);
- ret |= readByte(bytesArray, index+1) << 8;
- ret |= readByte(bytesArray, index+2) << 16;
- ret |= readByte(bytesArray, index+3) << 24;
- return ret;
- }
- static int readInt16(byte[] bytesArray, int index) {
- int ret = 0;
- ret = readByte(bytesArray, index);
- ret |= readByte(bytesArray, index+1) << 8;
- return ret;
- }
- static int readByte(byte[] bytesArray, int index) {
- int ret = 0;
- if (index < bytesArray.length) {
- ret = (int)bytesArray[index];
- ret = ret & 0xff;
- }
- return ret;
- }
- private boolean isModRMPresent(int addrMode) {
- if( (addrMode == ADDR_E) || (addrMode == ADDR_G) || (addrMode == ADDR_FPREG) || (addrMode == ADDR_Q) || (addrMode == ADDR_W) )
- return true;
- else
- return false;
- }
- public int getCurrentIndex() {
- return byteIndex;
- }
-
- public Instruction decode(byte[] bytesArray, int index, int instrStartIndex, int segmentOverride, int prefixes, X86InstructionFactory factory) {
- this.byteIndex = index;
- this.instrStartIndex = instrStartIndex;
- this.prefixes = prefixes;
- boolean operandSize; //operand-size prefix
- boolean addrSize; //address-size prefix
- if ( ( (prefixes & PREFIX_DATA) ^ segmentOverride ) == 1)
- operandSize = true;
- else
- operandSize = false;
- if ( ((prefixes & PREFIX_ADR) ^ segmentOverride) == 1)
- addrSize = true;
- else
- addrSize = false;
- this.name = getCorrectOpcodeName(name, prefixes, operandSize, addrSize);
-
- //Fetch the mod/reg/rm byte only if it is present.
- if( isModRMPresent(addrMode1) || isModRMPresent(addrMode2) || isModRMPresent(addrMode3) ) {
-
- int ModRM = readByte(bytesArray, byteIndex);
- byteIndex++;
- mod = (ModRM >> 6) & 3;
- regOrOpcode = (ModRM >> 3) & 7;
- rm = ModRM & 7;
- }
- return decodeInstruction(bytesArray, operandSize, addrSize, factory);
- }
-
- protected Instruction decodeInstruction(byte[] bytesArray, boolean operandSize, boolean addrSize, X86InstructionFactory factory) {
- Operand op1 = getOperand1(bytesArray, operandSize, addrSize);
- Operand op2 = getOperand2(bytesArray, operandSize, addrSize);
- Operand op3 = getOperand3(bytesArray, operandSize, addrSize);
- int size = byteIndex - instrStartIndex;
- return factory.newGeneralInstruction(name, op1, op2, op3, size, prefixes);
- }
-
- // capital letters in template are macros
- private String getCorrectOpcodeName(String oldName, int prefixes, boolean operandSize, boolean addrSize) {
- StringBuffer newName = new StringBuffer(oldName);
- int index = 0;
- for(index=0; index<oldName.length(); index++) {
- switch (oldName.charAt(index)) {
- case 'C': /* For jcxz/jecxz */
- if (addrSize)
- newName.setCharAt(index, 'e');
- index++;
- break;
- case 'N':
- if ((prefixes & PREFIX_FWAIT) == 0)
- newName.setCharAt(index, 'n');
- index++;
- break;
- case 'S':
- /* operand size flag */
- if (operandSize == true)
- newName.setCharAt(index, 'l');
- else
- newName.setCharAt(index, 'w');
- index++;
- break;
- default:
- break;
- }
- }
- return newName.toString();
- }
-
- //IA-32 Intel Architecture Software Developer's Manual Volume 2
- //Refer to Chapter 2 - Instruction Format
-
- //Get the Operand object from the address type and the operand type
- private Operand getOperand(byte[] bytesArray, int addrMode, int operandType, boolean operandSize, boolean addrSize) {
- Operand op = null;
- switch(addrMode) {
- case ADDR_E:
- case ADDR_W: //SSE: ModR/M byte specifies either 128 bit XMM register or memory
- case ADDR_Q: //SSE: ModR/M byte specifies either 128 bit MMX register or memory
- X86SegmentRegister segReg = getSegmentRegisterFromPrefix(prefixes);
-
- if (mod == 3) { //Register operand, no SIB follows
- if (addrMode == ADDR_E) {
- switch (operandType) {
- case b_mode:
- op = X86Registers.getRegister8(rm);
- break;
- case w_mode:
- op = X86Registers.getRegister16(rm);
- break;
- case v_mode:
- if (operandSize == true) //Operand size prefix is present
- op = X86Registers.getRegister32(rm);
- else
- op = X86Registers.getRegister16(rm);
- break;
- case p_mode:
- X86Register reg;
- if (operandSize == true) //Operand size prefix is present
- reg = X86Registers.getRegister32(rm);
- else
- reg = X86Registers.getRegister16(rm);
-
- op = new X86RegisterIndirectAddress(segReg, reg, null, 0);
- break;
- default:
- break;
- }
- } else if (addrMode == ADDR_W) {
- op = X86XMMRegisters.getRegister(rm);
- } else if (addrMode == ADDR_Q) {
- op = X86MMXRegisters.getRegister(rm);
- }
-
- } else { //mod != 3
- //SIB follows for (rm==4), SIB gives scale, index and base in this case
- //disp32 is present for (mod==0 && rm==5) || (mod==2)
- //disp8 is present for (mod==1)
- //for (rm!=4) base is register at rm.
- int scale = 0;
- int index = 0;
- int base = 0;
- long disp = 0;
- if(rm == 4) {
- int sib = readByte(bytesArray, byteIndex);
- byteIndex++;
- scale = (sib >> 6) & 3;
- index = (sib >> 3) & 7;
- base = sib & 7;
- }
-
- switch (mod) {
- case 0:
- switch(rm) {
- case 4:
- if(base == 5) {
- disp = readInt32(bytesArray, byteIndex);
- byteIndex += 4;
- if (index != 4) {
- op = new X86RegisterIndirectAddress(segReg, null, X86Registers.getRegister32(index), disp, scale);
- } else {
- op = new X86RegisterIndirectAddress(segReg, null, null, disp, scale);
- }
- }
- else {
- if (index != 4) {
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), 0, scale);
- } else {
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, 0, scale);
- }
- }
- break;
- case 5:
- disp = readInt32(bytesArray, byteIndex);
- byteIndex += 4;
- //Create an Address object only with displacement
- op = new X86RegisterIndirectAddress(segReg, null, null, disp);
- break;
- default:
- base = rm;
- //Create an Address object only with base
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, 0);
- break;
- }
- break;
- case 1:
- disp = (byte)readByte(bytesArray, byteIndex);
- byteIndex++;
- if (rm !=4) {
- base = rm;
- //Address with base and disp only
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp);
- } else {
- if (index != 4) {
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale);
- } else {
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp, scale);
- }
- }
- break;
- case 2:
- disp = readInt32(bytesArray, byteIndex);
- byteIndex += 4;
- if (rm !=4) {
- base = rm;
- //Address with base and disp
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp);
- } else if (index != 4) {
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale);
- } else {
- op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp, scale);
- }
- break;
- }
- }
- break;
-
- case ADDR_I:
- switch (operandType) {
- case b_mode:
- op = new Immediate(new Integer(readByte(bytesArray, byteIndex)));
- byteIndex++;
- break;
- case w_mode:
- op = new Immediate(new Integer(readInt16(bytesArray, byteIndex)));
- byteIndex += 2;
- break;
- case v_mode:
- if (operandSize == true) { //Operand size prefix is present
- op = new Immediate(new Integer(readInt32(bytesArray, byteIndex)));
- byteIndex += 4;
- } else {
- op = new Immediate(new Integer(readInt16(bytesArray, byteIndex)));
- byteIndex += 2;
- }
- break;
- default:
- break;
- }
- break;
- case ADDR_REG: //registers
- switch(operandType) {
- case EAX:
- case ECX:
- case EDX:
- case EBX:
- case ESP:
- case EBP:
- case ESI:
- case EDI:
- if(operandSize == true) {
- op = X86Registers.getRegister32(operandType - EAX);
- }
- else {
- op = X86Registers.getRegister16(operandType - EAX);
- }
- break;
- case AX:
- case CX:
- case DX:
- case BX:
- case SP:
- case BP:
- case SI:
- case DI:
- op = X86Registers.getRegister16(operandType - AX);
- break;
- case AL:
- case CL:
- case DL:
- case BL:
- case AH:
- case CH:
- case DH:
- case BH:
- op = X86Registers.getRegister8(operandType - AL);
- break;
- case ES: //ES, CS, SS, DS, FS, GS
- case CS:
- case SS:
- case DS:
- case FS:
- case GS:
- op = X86SegmentRegisters.getSegmentRegister(operandType - ES);
- break;
- }
- break;
- case ADDR_DIR: //segment and offset
- long segment = 0;
- long offset = 0;
- switch (operandType) {
- case p_mode:
- if (addrSize == true) {
- offset = readInt32(bytesArray, byteIndex);
- byteIndex += 4;
- segment = readInt16(bytesArray, byteIndex);
- byteIndex += 2;
- } else {
- offset = readInt16(bytesArray, byteIndex);
- byteIndex += 2;
- segment = readInt16(bytesArray, byteIndex);
- byteIndex += 2;
- }
- op = new X86DirectAddress(segment, offset); //with offset
- break;
- case v_mode:
- if (addrSize == true) {
- offset = readInt32(bytesArray, byteIndex);
- byteIndex += 4;
- } else {
- offset = readInt16(bytesArray, byteIndex);
- byteIndex += 2;
- }
- op = new X86DirectAddress(offset); //with offset
- break;
- default:
- break;
- }
- break;
- case ADDR_G:
- switch (operandType) {
- case b_mode:
- op = X86Registers.getRegister8(regOrOpcode);
- break;
- case w_mode:
- op = X86Registers.getRegister16(regOrOpcode);
- break;
- case d_mode:
- op = X86Registers.getRegister32(regOrOpcode);
- break;
- case v_mode:
- if (operandSize == true)
- op = X86Registers.getRegister32(regOrOpcode);
- else
- op = X86Registers.getRegister16(regOrOpcode);
- break;
- default:
- break;
- }
- break;
- case ADDR_SEG:
- op = X86SegmentRegisters.getSegmentRegister(regOrOpcode);
- break;
- case ADDR_OFF:
- int off = 0;
- if (addrSize == true) {
- off = readInt32(bytesArray, byteIndex);
- byteIndex += 4;
- }
- else {
- off = readInt16(bytesArray, byteIndex);
- byteIndex += 2;
- }
- op = new X86DirectAddress((long)off);
- break;
- case ADDR_J:
- long disp = 0;
- //The effective address is Instruction pointer + relative offset
- switch(operandType) {
- case b_mode:
- disp = (byte)readByte(bytesArray, byteIndex);
- byteIndex++;
- break;
- case v_mode:
- if (operandSize == true) {
- disp = readInt32(bytesArray, byteIndex);
- byteIndex += 4;
- }
- else {
- disp = readInt16(bytesArray, byteIndex);
- byteIndex += 2;
- }
- //disp = disp + (byteIndex-instrStartIndex);
- break;
- }
- op = new X86PCRelativeAddress(disp);
- break;
- case ADDR_ESDI:
- op = new X86SegmentRegisterAddress(X86SegmentRegisters.ES, X86Registers.DI);
- break;
- case ADDR_DSSI:
- op = new X86SegmentRegisterAddress(X86SegmentRegisters.DS, X86Registers.SI);
- break;
- case ADDR_R:
- switch (operandType) {
- case b_mode:
- op = X86Registers.getRegister8(mod);
- break;
- case w_mode:
- op = X86Registers.getRegister16(mod);
- break;
- case d_mode:
- op = X86Registers.getRegister32(mod);
- break;
- case v_mode:
- if (operandSize == true)
- op = X86Registers.getRegister32(mod);
- else
- op = X86Registers.getRegister16(mod);
- break;
- default:
- break;
- }
- break;
- case ADDR_FPREG:
- switch (operandType) {
- case 0:
- op = X86FloatRegisters.getRegister(0);
- break;
- case 1:
- op = X86FloatRegisters.getRegister(rm);
- break;
- }
- break;
-
- //SSE: reg field of ModR/M byte selects a 128-bit XMM register
- case ADDR_V:
- op = X86XMMRegisters.getRegister(regOrOpcode);
- break;
-
- //SSE: reg field of ModR/M byte selects a 64-bit MMX register
- case ADDR_P:
- op = X86MMXRegisters.getRegister(regOrOpcode);
- break;
- }
- return op;
- }
-
- private X86SegmentRegister getSegmentRegisterFromPrefix(int prefixes) {
- X86SegmentRegister segRegister = null;
-
- if ( (prefixes & PREFIX_CS) != 0)
- segRegister = X86SegmentRegisters.CS;
- if ( (prefixes & PREFIX_DS) != 0)
- segRegister = X86SegmentRegisters.DS;
- if ( (prefixes & PREFIX_ES) != 0)
- segRegister = X86SegmentRegisters.ES;
- if ( (prefixes & PREFIX_FS) != 0)
- segRegister = X86SegmentRegisters.FS;
- if ( (prefixes & PREFIX_SS) != 0)
- segRegister = X86SegmentRegisters.SS;
- if ( (prefixes & PREFIX_GS) != 0)
- segRegister = X86SegmentRegisters.GS;
-
- return segRegister;
- }
-
-}