/*
    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.qanddcompiler;

import java.lang.reflect.*;
import java.util.*;

import org.jpc.emulator.memory.codeblock.optimised.*;
import org.jpc.emulator.memory.codeblock.*;

public class MicrocodeNode implements MicrocodeSet
{
    private boolean hasImmediate;
    private int microcode, x86Position, immediate, x86Index;
    
    public MicrocodeNode(int microcode, int x86Position, int x86Index)
    {
        this.x86Index = x86Index;
        this.x86Position = x86Position;
        this.microcode = microcode;
        hasImmediate = false;
    }
    
    public MicrocodeNode(int microcode, int x86Position, int x86Index, int immediate)
    {
        this.x86Index = x86Index;
        this.x86Position = x86Position;
        this.microcode = microcode;
        this.immediate = immediate;
        hasImmediate = true;
    }

    public int getMicrocode()
    {
        return microcode;
    }

    public int getX86Index()
    {
        return x86Index;
    }
    
    public int getX86Position()
    {
        return x86Position;
    }

    public boolean hasImmediate()
    {
        return hasImmediate;
    }

    public int getImmediate()
    {
        return immediate;
    }

    public String toString()
    {
        return getName(microcode);
    }

    public boolean hasExternalEffect()
    {
        return hasExternalEffect(microcode);
    }

    public static String getName(int microcode)
    {
	try 
        {
	    return microcodeNames[microcode];
	} 
        catch (Exception e) 
        {
	    return "Invalid["+microcode+"]";
	}
    }

    private static String[] microcodeNames;
    static 
    {
	Field[] fields = MicrocodeSet.class.getDeclaredFields();
	microcodeNames = new String[fields.length];
	for (int i = 0; i < fields.length; i++) 
        {
	    try 
            {
		microcodeNames[fields[i].getInt(null)] = fields[i].getName();
	    } 
            catch (IllegalAccessException e){}
	}
    }

    public static boolean hasVariableX86Count(int microcode)
    {
        switch (microcode)
        {
        case REP_MOVSB_A16:
        case REP_MOVSW_A16:
        case REPE_CMPSB_A16:
        case REPNE_SCASB_A16:
        case REP_STOSW_A16:
        case REPE_CMPSB_A32:
        case REPE_CMPSW_A16:
        case REPE_CMPSW_A32:
        case REPE_CMPSD_A16:
        case REPE_CMPSD_A32:
        case REPNE_CMPSB_A16:
        case REPNE_CMPSB_A32:
        case REPNE_CMPSW_A16:
        case REPNE_CMPSW_A32:
        case REPNE_CMPSD_A16:
        case REPNE_CMPSD_A32:
        case REP_INSB_A16:
        case REP_INSB_A32:
        case REP_INSW_A16:
        case REP_INSW_A32:
        case REP_INSD_A16:
        case REP_INSD_A32:
        case REP_LODSB_A16:
        case REP_LODSB_A32:
        case REP_LODSW_A16:
        case REP_LODSW_A32:
        case REP_LODSD_A16:
        case REP_LODSD_A32:
        case REP_MOVSB_A32:
        case REP_MOVSW_A32:
        case REP_MOVSD_A16:
        case REP_MOVSD_A32:
        case REP_OUTSB_A16:
        case REP_OUTSB_A32:
        case REP_OUTSW_A16:
        case REP_OUTSW_A32:
        case REP_OUTSD_A16:
        case REP_OUTSD_A32:
        case REPE_SCASB_A16:
        case REPE_SCASB_A32:
        case REPE_SCASW_A16:
        case REPE_SCASW_A32:
        case REPE_SCASD_A16:
        case REPE_SCASD_A32:
        case REPNE_SCASB_A32:
        case REPNE_SCASW_A16:
        case REPNE_SCASW_A32:
        case REPNE_SCASD_A16:
        case REPNE_SCASD_A32:
        case REP_STOSB_A16:
        case REP_STOSB_A32:
        case REP_STOSW_A32:
        case REP_STOSD_A16:
        case REP_STOSD_A32:
            return true;
        default:
            return false;
        }
    }

    public static boolean hasExternalEffect(int microcode)
    {
        switch (microcode)
        {
//         case ADC:
//         case ADC_O16_FLAGS:
//         case ADC_O8_FLAGS:
//         case ADD:
//         case ADDR_BP:
//         case ADDR_BX:
//         case ADDR_DI:
//         case ADDR_IB:
//         case ADDR_ID:
//         case ADDR_IW:
//         case ADDR_MASK16:
//         case ADDR_SI:
//         case ADD_O16_FLAGS:
//         case ADD_O32_FLAGS:
//         case ADD_O8_FLAGS:
//         case AND:
//         case BITWISE_FLAGS_O16:
//         case BITWISE_FLAGS_O32:
//         case BITWISE_FLAGS_O8:
        case CALL_ABS_O16_A16:
        case CALL_FAR_O16_A16:
        case CALL_O16_A16:
//         case CLC:
//         case CLD:
//         case CLI:
//         case CWD:
//         case DEC:
//         case DEC_O16_FLAGS:
//         case DEC_O8_FLAGS:
//         case DIV_O16:
//         case DIV_O8:
//         case EIP_UPDATE:
        case ENTER_O16_A16:
//         case IDIV_O16:
//         case IMULA_O16:
//         case INC:
//         case INC_O16_FLAGS:
//         case INC_O32_FLAGS:
//         case INC_O8_FLAGS:
        case INT_O16_A16:
        case IN_O8:
        case IRET_O16_A16:
//         case JA_O16:
//         case JA_O8:
//         case JCXZ:
//         case JC_O16:
//         case JC_O8:
//         case JG_O8:
//         case JL_O8:
//         case JNA_O8:
//         case JNC_O16:
//         case JNC_O8:
//         case JNG_O8:
//         case JNL_O8:
//         case JNS_O8:
//         case JNZ_O16:
//         case JNZ_O8:
//         case JUMP_ABS_O16:
//         case JUMP_FAR_O16:
//         case JUMP_O16:
//         case JUMP_O8:
//         case JZ_O16:
//         case JZ_O8:
//         case LAHF:
        case LEAVE_O16_A16:
//         case LGDT_O16:
//         case LOAD0_ADDR:
//         case LOAD0_AH:
//         case LOAD0_AL:
//         case LOAD0_AX:
//         case LOAD0_BH:
//         case LOAD0_BL:
//         case LOAD0_BP:
//         case LOAD0_BX:
//         case LOAD0_CH:
//         case LOAD0_CL:
//         case LOAD0_CR0:
//         case LOAD0_CR2:
//         case LOAD0_CR3:
//         case LOAD0_CR4:
//         case LOAD0_CS:
//         case LOAD0_CX:
//         case LOAD0_DH:
//         case LOAD0_DI:
//         case LOAD0_DL:
//         case LOAD0_DR0:
//         case LOAD0_DR1:
//         case LOAD0_DR2:
//         case LOAD0_DR3:
//         case LOAD0_DR6:
//         case LOAD0_DR7:
//         case LOAD0_DS:
//         case LOAD0_DX:
//         case LOAD0_EAX:
//         case LOAD0_EBP:
//         case LOAD0_EBX:
//         case LOAD0_ECX:
//         case LOAD0_EDI:
//         case LOAD0_EDX:
//         case LOAD0_ES:
//         case LOAD0_ESI:
//         case LOAD0_ESP:
//         case LOAD0_FS:
//         case LOAD0_GS:
//         case LOAD0_IB:
//         case LOAD0_ID:
//         case LOAD0_IW:
        case LOAD0_MEM_BYTE:
        case LOAD0_MEM_DWORD:
        case LOAD0_MEM_QWORD:
        case LOAD0_MEM_WORD:
//         case LOAD0_SI:
//         case LOAD0_SP:
//         case LOAD0_SS:
//         case LOAD1_AH:
//         case LOAD1_AL:
//         case LOAD1_AX:
//         case LOAD1_BH:
//         case LOAD1_BL:
//         case LOAD1_BP:
//         case LOAD1_BX:
//         case LOAD1_CH:
//         case LOAD1_CL:
//         case LOAD1_CX:
//         case LOAD1_DH:
//         case LOAD1_DI:
//         case LOAD1_DL:
//         case LOAD1_DX:
//         case LOAD1_EAX:
//         case LOAD1_EBX:
//         case LOAD1_ECX:
//         case LOAD1_EDI:
//         case LOAD1_EDX:
//         case LOAD1_IB:
//         case LOAD1_ID:
//         case LOAD1_IW:
        case LOAD1_MEM_BYTE:
        case LOAD1_MEM_DWORD:
        case LOAD1_MEM_WORD:
//         case LOAD1_SI:
//         case LOAD1_SP:
//         case LOAD_SEG_CS:
//         case LOAD_SEG_DS:
//         case LOAD_SEG_ES:
//         case LOAD_SEG_SS:
        case LODSB_A16:
        case LODSW_A16:
//         case LOOPZ_CX:
//         case LOOP_CX:
//         case MEM_RESET:
        case MOVSB_A16:
        case MOVSW_A16:
//         case MUL_O16:
//         case MUL_O32:
//         case MUL_O8:
//         case NEG:
//         case NEG_O16_FLAGS:
//         case NEG_O8_FLAGS:
//         case NOOP:
//         case NOT:
//         case OR:
        case OUT_O16:
        case OUT_O8:
        case POPAD_A16:
        case POPA_A16:
        case POPF_O16_A16:
        case POP_O16_A16:
        case POP_O32_A16:
        case PUSHAD_A16:
        case PUSHA_A16:
        case PUSHF_O16_A16:
        case PUSH_O16_A16:
        case PUSH_O32_A16:
//         case RCL_O16:
//         case RCL_O16_FLAGS:
        case REPE_CMPSB_A16:
        case REPNE_SCASB_A16:
        case REP_MOVSB_A16:
        case REP_MOVSW_A16:
        case REP_STOSW_A16:
        case RET_FAR_IW_O16_A16:
        case RET_FAR_O16_A16:
        case RET_IW_O16_A16:
        case RET_O16_A16:
//         case ROR_O8:
//         case ROR_O8_FLAGS:
//         case SAR_O16:
//         case SAR_O16_FLAGS:
//         case SBB:
//         case SBB_O16_FLAGS:
//         case SBB_O8_FLAGS:
//         case SETC:
//         case SHL:
//         case SHL_O16_FLAGS:
//         case SHL_O32_FLAGS:
//         case SHL_O8_FLAGS:
//         case SHR:
//         case SHR_O16_FLAGS:
//         case SHR_O32_FLAGS:
//         case SHR_O8_FLAGS:
//         case SIGN_EXTEND_8_16:
//         case SMSW:
//         case STC:
//         case STI:
//         case STORE0_AH:
//         case STORE0_AL:
//         case STORE0_AX:
//         case STORE0_BH:
//         case STORE0_BL:
//         case STORE0_BP:
//         case STORE0_BX:
//         case STORE0_CH:
//         case STORE0_CL:
//         case STORE0_CR0:
//         case STORE0_CR2:
//         case STORE0_CR3:
//         case STORE0_CR4:
//         case STORE0_CS:
//         case STORE0_CX:
//         case STORE0_DH:
//         case STORE0_DI:
//         case STORE0_DL:
//         case STORE0_DR0:
//         case STORE0_DR1:
//         case STORE0_DS:
//         case STORE0_DX:
//         case STORE0_EAX:
//         case STORE0_EBP:
//         case STORE0_EBX:
//         case STORE0_ECX:
//         case STORE0_EDI:
//         case STORE0_EDX:
//         case STORE0_ES:
//         case STORE0_ESI:
//         case STORE0_ESP:
//         case STORE0_FS:
//         case STORE0_GS:
        case STORE0_MEM_BYTE:
        case STORE0_MEM_DWORD:
        case STORE0_MEM_WORD:
//         case STORE0_SI:
//         case STORE0_SP:
//         case STORE0_SS:
//         case STORE1_AL:
//         case STORE1_AX:
//         case STORE1_CL:
//         case STORE1_DI:
//         case STORE1_DS:
//         case STORE1_ES:
//         case STORE1_ESP:
        case STORE1_MEM_BYTE:
        case STORE1_MEM_WORD:
//         case STORE1_SI:
        case STOSB_A16:
        case STOSW_A16:
//         case SUB:
//         case SUB_O16_FLAGS:
//         case SUB_O32_FLAGS:
//         case SUB_O8_FLAGS:
//         case XOR:
//     case AAA:
//     case AAD:
//     case AAM:
//     case AAS:
//     case ADC_O32_FLAGS:
//     case ADDR_2EAX:
//     case ADDR_2EBP:
//     case ADDR_2EBX:
//     case ADDR_2ECX:
//     case ADDR_2EDI:
//     case ADDR_2EDX:
//     case ADDR_2ESI:
//     case ADDR_2ESP:
//     case ADDR_2REG1:
//     case ADDR_4EAX:
//     case ADDR_4EBP:
//     case ADDR_4EBX:
//     case ADDR_4ECX:
//     case ADDR_4EDI:
//     case ADDR_4EDX:
//     case ADDR_4ESI:
//     case ADDR_4ESP:
//     case ADDR_4REG1:
//     case ADDR_8EAX:
//     case ADDR_8EBP:
//     case ADDR_8EBX:
//     case ADDR_8ECX:
//     case ADDR_8EDI:
//     case ADDR_8EDX:
//     case ADDR_8ESI:
//     case ADDR_8ESP:
//     case ADDR_8REG1:
//     case ADDR_AX:
//     case ADDR_CX:
//     case ADDR_DX:
//     case ADDR_EAX:
//     case ADDR_EBP:
//     case ADDR_EBX:
//     case ADDR_ECX:
//     case ADDR_EDI:
//     case ADDR_EDX:
//     case ADDR_ESI:
//     case ADDR_ESP:
//     case ADDR_REG1:
//     case ADDR_SP:
//     case ADDR_uAL:
        case BOUND_O16:
        case BOUND_O32:
        case BSF:
        case BSR:
//     case BSWAP:
        case BTC_MEM:
//     case BTC_O16:
//     case BTC_O32:
        case BTR_MEM:
//     case BTR_O16:
//     case BTR_O32:
    case BTS_MEM:
//     case BTS_O16:
//     case BTS_O32:
    case BT_MEM:
//     case BT_O16:
//     case BT_O32:
    case CALL_ABS_O16_A32:
    case CALL_ABS_O32_A16:
    case CALL_ABS_O32_A32:
    case CALL_FAR_O16_A32:
    case CALL_FAR_O32_A16:
    case CALL_FAR_O32_A32:
    case CALL_O16_A32:
    case CALL_O32_A16:
    case CALL_O32_A32:
//     case CDQ:
//     case CLTS:
//     case CMC:
//     case CMOVA:
//     case CMOVC:
//     case CMOVG:
//     case CMOVL:
//     case CMOVNA:
//     case CMOVNC:
//     case CMOVNG:
//     case CMOVNL:
//     case CMOVNO:
//     case CMOVNP:
//     case CMOVNS:
//     case CMOVNZ:
//     case CMOVO:
//     case CMOVP:
//     case CMOVS:
//     case CMOVZ:
    case CMPSB_A16:
    case CMPSB_A32:
    case CMPSD_A16:
    case CMPSD_A32:
    case CMPSW_A16:
    case CMPSW_A32:
//     case CMPXCHG:
//     case CMPXCHG_O16_FLAGS:
//     case CMPXCHG_O32_FLAGS:
//     case CMPXCHG_O8_FLAGS:
//     case CPUID:
//     case DAA:
//     case DAS:
//     case DEC_O32_FLAGS:
//     case DIV_O32:
    case ENTER_O16_A32:
    case ENTER_O32_A16:
    case ENTER_O32_A32:
    case HALT:
//     case IDIV_O32:
//     case IDIV_O8:
//     case IMULA_O32:
//     case IMULA_O8:
//     case IMUL_O16:
//     case IMUL_O32:
    case INSB_A16:
    case INSB_A32:
    case INSD_A16:
    case INSD_A32:
    case INSW_A16:
    case INSW_A32:
    case INT3_O16_A16:
    case INT3_O16_A32:
    case INT3_O32_A16:
    case INT3_O32_A32:
    case INTO_O16_A16:
    case INTO_O16_A32:
    case INTO_O32_A16:
    case INTO_O32_A32:
    case INT_O16_A32:
    case INT_O32_A16:
    case INT_O32_A32:
    case INVLPG:
    case IN_O16:
    case IN_O32:
    case IRET_O16_A32:
    case IRET_O32_A16:
    case IRET_O32_A32:
//     case JA_O32:
//     case JC_O32:
//     case JECXZ:
//     case JG_O16:
//     case JG_O32:
//     case JL_O16:
//     case JL_O32:
//     case JNA_O16:
//     case JNA_O32:
//     case JNC_O32:
//     case JNG_O16:
//     case JNG_O32:
//     case JNL_O16:
//     case JNL_O32:
//     case JNO_O16:
//     case JNO_O32:
//     case JNO_O8:
//     case JNP_O16:
//     case JNP_O32:
//     case JNP_O8:
//     case JNS_O16:
//     case JNS_O32:
//     case JNZ_O32:
//     case JO_O16:
//     case JO_O32:
//     case JO_O8:
//     case JP_O16:
//     case JP_O32:
//     case JP_O8:
//     case JS_O16:
//     case JS_O32:
//     case JS_O8:
//     case JUMP_ABS_O32:
//     case JUMP_FAR_O32:
//     case JUMP_O32:
//     case JZ_O32:
    case LEAVE_O16_A32:
    case LEAVE_O32_A16:
    case LEAVE_O32_A32:
//     case LGDT_O32:
//     case LIDT_O16:
//     case LIDT_O32:
//     case LLDT:
//     case LMSW:
//     case LOAD1_EBP:
//     case LOAD1_ESI:
//     case LOAD1_ESP:
//     case LOAD2_AL:
//     case LOAD2_AX:
//     case LOAD2_CL:
//     case LOAD2_EAX:
//     case LOAD2_IB:
//     case LOAD_SEG_FS:
//     case LOAD_SEG_GS:
    case LODSB_A32:
    case LODSD_A16:
    case LODSD_A32:
    case LODSW_A32:
//     case LOOPNZ_CX:
//     case LOOPNZ_ECX:
//     case LOOPZ_ECX:
//     case LOOP_ECX:
//     case LTR:
    case MOVSB_A32:
    case MOVSD_A16:
    case MOVSD_A32:
    case MOVSW_A32:
//     case NEG_O32_FLAGS:
    case OUTSB_A16:
    case OUTSB_A32:
    case OUTSD_A16:
    case OUTSD_A32:
    case OUTSW_A16:
    case OUTSW_A32:
    case OUT_O32:
    case POPAD_A32:
    case POPA_A32:
    case POPF_O16_A32:
    case POPF_O32_A16:
    case POPF_O32_A32:
    case POP_O16_A32:
    case POP_O32_A32:
    case PUSHAD_A32:
    case PUSHA_A32:
    case PUSHF_O16_A32:
    case PUSHF_O32_A16:
    case PUSHF_O32_A32:
    case PUSH_O16_A32:
    case PUSH_O32_A32:
//     case RCL_O32:
//     case RCL_O32_FLAGS:
//     case RCL_O8:
//     case RCL_O8_FLAGS:
//     case RCR_O16:
//     case RCR_O16_FLAGS:
//     case RCR_O32:
//     case RCR_O32_FLAGS:
//     case RCR_O8:
//     case RCR_O8_FLAGS:
    case RDMSR:
    case RDTSC:
    case REPE_CMPSB_A32:
    case REPE_CMPSD_A16:
    case REPE_CMPSD_A32:
    case REPE_CMPSW_A16:
    case REPE_CMPSW_A32:
    case REPE_SCASB_A16:
    case REPE_SCASB_A32:
    case REPE_SCASD_A16:
    case REPE_SCASD_A32:
    case REPE_SCASW_A16:
    case REPE_SCASW_A32:
    case REPNE_CMPSB_A16:
    case REPNE_CMPSB_A32:
    case REPNE_CMPSD_A16:
    case REPNE_CMPSD_A32:
    case REPNE_CMPSW_A16:
    case REPNE_CMPSW_A32:
    case REPNE_SCASB_A32:
    case REPNE_SCASD_A16:
    case REPNE_SCASD_A32:
    case REPNE_SCASW_A16:
    case REPNE_SCASW_A32:
    case REP_INSB_A16:
    case REP_INSB_A32:
    case REP_INSD_A16:
    case REP_INSD_A32:
    case REP_INSW_A16:
    case REP_INSW_A32:
    case REP_LODSB_A16:
    case REP_LODSB_A32:
    case REP_LODSD_A16:
    case REP_LODSD_A32:
    case REP_LODSW_A16:
    case REP_LODSW_A32:
    case REP_MOVSB_A32:
    case REP_MOVSD_A16:
    case REP_MOVSD_A32:
    case REP_MOVSW_A32:
    case REP_OUTSB_A16:
    case REP_OUTSB_A32:
    case REP_OUTSD_A16:
    case REP_OUTSD_A32:
    case REP_OUTSW_A16:
    case REP_OUTSW_A32:
    case REP_STOSB_A16:
    case REP_STOSB_A32:
    case REP_STOSD_A16:
    case REP_STOSD_A32:
    case REP_STOSW_A32:
    case RET_FAR_IW_O16_A32:
    case RET_FAR_IW_O32_A16:
    case RET_FAR_IW_O32_A32:
    case RET_FAR_O16_A32:
    case RET_FAR_O32_A16:
    case RET_FAR_O32_A32:
    case RET_IW_O16_A32:
    case RET_IW_O32_A16:
    case RET_IW_O32_A32:
    case RET_O16_A32:
    case RET_O32_A16:
    case RET_O32_A32:
//     case ROL_O16:
//     case ROL_O16_FLAGS:
//     case ROL_O32:
//     case ROL_O32_FLAGS:
//     case ROL_O8:
//     case ROL_O8_FLAGS:
//     case ROR_O16:
//     case ROR_O16_FLAGS:
//     case ROR_O32:
//     case ROR_O32_FLAGS:
//     case SAHF:
//     case SAR_O32:
//     case SAR_O32_FLAGS:
//     case SAR_O8:
//     case SAR_O8_FLAGS:
//     case SBB_O32_FLAGS:
    case SCASB_A16:
    case SCASB_A32:
    case SCASD_A16:
    case SCASD_A32:
    case SCASW_A16:
    case SCASW_A32:
//     case SETA:
//     case SETG:
//     case SETL:
//     case SETNA:
//     case SETNC:
//     case SETNG:
//     case SETNL:
//     case SETNO:
//     case SETNP:
//     case SETNS:
//     case SETNZ:
//     case SETO:
//     case SETP:
//     case SETS:
//     case SETZ:
//     case SGDT_O16:
//     case SGDT_O32:
//     case SHLD_O16:
//     case SHLD_O32:
//     case SHRD_O16:
//     case SHRD_O32:
//     case SIDT_O16:
//     case SIDT_O32:
//     case SIGN_EXTEND_16_32:
//     case SIGN_EXTEND_8_32:
//     case SLDT:
//     case STD:
//     case STORE0_DR2:
//     case STORE0_DR3:
//     case STORE0_DR6:
//     case STORE0_DR7:
//     case STORE1_AH:
//     case STORE1_BH:
//     case STORE1_BL:
//     case STORE1_BP:
//     case STORE1_BX:
//     case STORE1_CH:
//     case STORE1_CS:
//     case STORE1_CX:
//     case STORE1_DH:
//     case STORE1_DL:
//     case STORE1_DX:
//     case STORE1_EAX:
//     case STORE1_EBP:
//     case STORE1_EBX:
//     case STORE1_ECX:
//     case STORE1_EDI:
//     case STORE1_EDX:
//     case STORE1_ESI:
//     case STORE1_FS:
//     case STORE1_GS:
    case STORE1_MEM_DWORD:
//     case STORE1_SP:
//     case STORE1_SS:
    case STOSB_A32:
    case STOSD_A16:
    case STOSD_A32:
    case STOSW_A32:
    case STR:
    case SYSENTER:
    case SYSEXIT:
    case UNDEFINED:
    case VERR:
    case VERW:
    case WAIT:
    case WRMSR:
            return true;
        default:
            return false;
        }
    }

    private static boolean hasImmediate(int microcode)
    {
	switch (microcode) 
        {
	case LOAD0_IB:
	case LOAD0_IW:
	case LOAD0_ID:
	    
	case LOAD1_IB:
	case LOAD1_IW:
	case LOAD1_ID:
	    
	case LOAD2_IB:
	    
	case ADDR_IB:
	case ADDR_IW:
	case ADDR_ID:
	    return true;
	    
	default:
	    return false;
	}
    }

    public static MicrocodeNode[] getMicrocodes(InstructionSource source)
    {
      	int x86Length = 0, x86Count = 0;
        Vector buffer = new Vector();

	while (source.getNext()) 
        {
	    x86Length += source.getX86Length();
	    x86Count++;
	    int length = source.getLength();
	    for (int i = 0; i < length; i++) 
            {
		int microcode = source.getMicrocode();	
		MicrocodeNode node = null;
                
		if (hasImmediate(microcode)) 
                {
		    node = new MicrocodeNode(microcode, x86Length, x86Count, source.getMicrocode());
		    i++;
		} 
                else 
		    node = new MicrocodeNode(microcode, x86Length, x86Count);
		
                buffer.add(node);
            }
        }
        
        MicrocodeNode[] result = new MicrocodeNode[buffer.size()];
        buffer.toArray(result);
        return result;
    }
}
