/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*
*/
// basic instruction decoder class
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;
this.operandType1 = INVALID_OPERANDTYPE;
this.operandType2 = INVALID_OPERANDTYPE;
this.operandType3 = INVALID_OPERANDTYPE;
this.addrMode1 = INVALID_ADDRMODE;
this.addrMode2 = INVALID_ADDRMODE;
this.addrMode3 = INVALID_ADDRMODE;
}
this(name);
this.operandType1 = operandType1;
}
public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2) {
this.operandType2 = operandType2;
}
public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2,
int addrMode3, int operandType3) {
this.operandType3 = operandType3;
}
// "operand1"
else
return null;
}
// "operand2"
else
return null;
}
// "operand3"
else
return null;
}
int ret = 0;
return ret;
}
int ret = 0;
return ret;
}
int ret = 0;
}
return ret;
}
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.instrStartIndex = instrStartIndex;
boolean operandSize; //operand-size prefix
boolean addrSize; //address-size prefix
operandSize = true;
else
operandSize = false;
addrSize = true;
else
addrSize = false;
byteIndex++;
}
}
protected Instruction decodeInstruction(byte[] bytesArray, boolean operandSize, boolean addrSize, X86InstructionFactory factory) {
}
// capital letters in template are macros
private String getCorrectOpcodeName(String oldName, int prefixes, boolean operandSize, boolean addrSize) {
int index = 0;
if (addrSize)
index++;
break;
case 'N':
index++;
break;
case 'S':
/* operand size flag */
if (operandSize == true)
else
index++;
break;
default:
break;
}
}
}
//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) {
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
switch (operandType) {
case b_mode:
break;
case w_mode:
break;
case v_mode:
if (operandSize == true) //Operand size prefix is present
else
break;
case p_mode:
if (operandSize == true) //Operand size prefix is present
else
break;
default:
break;
}
}
} 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) {
byteIndex++;
}
switch (mod) {
case 0:
switch(rm) {
case 4:
if(base == 5) {
byteIndex += 4;
if (index != 4) {
} else {
}
}
else {
if (index != 4) {
op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), 0, scale);
} else {
}
}
break;
case 5:
byteIndex += 4;
//Create an Address object only with displacement
break;
default:
//Create an Address object only with base
break;
}
break;
case 1:
byteIndex++;
if (rm !=4) {
//Address with base and disp only
} else {
if (index != 4) {
op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale);
} else {
}
}
break;
case 2:
byteIndex += 4;
if (rm !=4) {
//Address with base and disp
} else if (index != 4) {
op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale);
} else {
}
break;
}
}
break;
case ADDR_I:
switch (operandType) {
case b_mode:
byteIndex++;
break;
case w_mode:
byteIndex += 2;
break;
case v_mode:
if (operandSize == true) { //Operand size prefix is present
byteIndex += 4;
} else {
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) {
}
else {
}
break;
case AX:
case CX:
case DX:
case BX:
case SP:
case BP:
case SI:
case DI:
break;
case AL:
case CL:
case DL:
case BL:
case AH:
case CH:
case DH:
case BH:
break;
case ES: //ES, CS, SS, DS, FS, GS
case CS:
case SS:
case DS:
case FS:
case GS:
break;
}
break;
case ADDR_DIR: //segment and offset
long segment = 0;
long offset = 0;
switch (operandType) {
case p_mode:
if (addrSize == true) {
byteIndex += 4;
byteIndex += 2;
} else {
byteIndex += 2;
byteIndex += 2;
}
break;
case v_mode:
if (addrSize == true) {
byteIndex += 4;
} else {
byteIndex += 2;
}
break;
default:
break;
}
break;
case ADDR_G:
switch (operandType) {
case b_mode:
break;
case w_mode:
break;
case d_mode:
break;
case v_mode:
if (operandSize == true)
else
break;
default:
break;
}
break;
case ADDR_SEG:
break;
case ADDR_OFF:
int off = 0;
if (addrSize == true) {
byteIndex += 4;
}
else {
byteIndex += 2;
}
break;
case ADDR_J:
long disp = 0;
//The effective address is Instruction pointer + relative offset
switch(operandType) {
case b_mode:
byteIndex++;
break;
case v_mode:
if (operandSize == true) {
byteIndex += 4;
}
else {
byteIndex += 2;
}
//disp = disp + (byteIndex-instrStartIndex);
break;
}
break;
case ADDR_ESDI:
break;
case ADDR_DSSI:
break;
case ADDR_R:
switch (operandType) {
case b_mode:
break;
case w_mode:
break;
case d_mode:
break;
case v_mode:
if (operandSize == true)
else
break;
default:
break;
}
break;
case ADDR_FPREG:
switch (operandType) {
case 0:
break;
case 1:
break;
}
break;
//SSE: reg field of ModR/M byte selects a 128-bit XMM register
case ADDR_V:
break;
//SSE: reg field of ModR/M byte selects a 64-bit MMX register
case ADDR_P:
break;
}
return op;
}
return segRegister;
}
}