예제 #1
0
//
// Decode the OR1K instruction at the passed address. If the decode succeeds,
// dispatch it to the corresponding function in the dispatch table and return
// True; otherwise, dispatch using the defaultCB and return False.
//
Bool or1kDecode(
    or1kP               or1k,
    Uns32               thisPC,
    or1kDispatchTableCP table,
    or1kDispatchFn      defaultCB,
    void               *userData,
    Bool                inDelaySlot
) {
    // get the instruction at the passed address - always 4 bytes on OR1K
    vmiProcessorP       processor   = (vmiProcessorP)or1k;
    Uns32               instruction = vmicxtFetch4Byte(processor, thisPC);
    or1kInstructionType type        = decode(instruction);

    // apply the callback, or the default if no match
    if(type!=OR1K_IT_LAST) {
        ((*table)[type])(or1k, thisPC, instruction, userData, inDelaySlot);
        return True;
    } else {
        defaultCB(or1k, thisPC, instruction, userData, inDelaySlot);
        return False;
    }
}
//
// Return the size of the instruction at the passed address in bytes
//
Uns32 microblazeGetInstructionBytes(
        microblazeP microblaze,
        microblazeAddr thisPC
) {
    vmiProcessorP processor = (vmiProcessorP)microblaze;

    //
    // Initialize the 32 bit decoder table
    //
    static vmidDecodeTableP decodeTable32;
    if(!decodeTable32) {
        decodeTable32 = microblazeCreateDecodeTable32();
    }

    Uns64 instr4 = vmicxtFetch4Byte(processor, thisPC);
    Uns32 type = MICROBLAZE_IT_LAST;
    type = vmidDecode(decodeTable32, instr4);

    if (type == MICROBLAZE_IT_IMM_TYPEI1) {
        return 8;
    } else {
        return 4;
    }
}
//
// Decoder function for a given address
//
void ppc32Decode(
    ppc32P ppc32,
    ppc32Addr thisPC,
    ppc32InstructionInfoP info
) {
    //
    // Initialize the following info fields before table creation
    //
    info->thisPC = thisPC;
    info->arch = ppc32->configInfo.arch;
    vmiProcessorP processor = (vmiProcessorP)ppc32;

    //
    // Initialize the UISA decoder table
    //
    static vmidDecodeTableP decodeTable_UISA_16Bit;
    if(!decodeTable_UISA_16Bit) {
        if(ppc32->params.UISA_I_VLE) {
            decodeTable_UISA_16Bit = ppc32CreateDecodeTable_I_VLE_16Bit(decodeTable_UISA_16Bit, False);
        }
    }
    static vmidDecodeTableP decodeTable_UISA_32Bit;
    if(!decodeTable_UISA_32Bit) {
        if(ppc32->params.UISA_I_B) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_B_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_BCDA) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_BCDA_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_S) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_S_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_E) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_E_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_E_PC) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_E_PC_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_E_PD) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_E_PD_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_FP) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_FP_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_DFP) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_DFP_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_MA) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_MA_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_SP) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_SP_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_V) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_V_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_LMA) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_LMA_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_WT) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_WT_32Bit(decodeTable_UISA_32Bit, False);
        }
        if(ppc32->params.UISA_I_VLE) {
            decodeTable_UISA_32Bit = ppc32CreateDecodeTable_I_VLE_32Bit(decodeTable_UISA_32Bit, False);
        }
    }

    //
    // Initialize the mpc82x_32Bit decoder table
    //
    static vmidDecodeTableP decodeTable_mpc82x_32Bit;
    if(!decodeTable_mpc82x_32Bit && (info->arch == VARIANT_MPC82X)) {
        decodeTable_mpc82x_32Bit = ppc32CreateDecodeTable_I_B_32Bit(decodeTable_mpc82x_32Bit, False);
        decodeTable_mpc82x_32Bit = ppc32CreateDecodeTable_I_E_32Bit(decodeTable_mpc82x_32Bit, False);
        decodeTable_mpc82x_32Bit = ppc32CreateDecodeTable_I_MA_32Bit(decodeTable_mpc82x_32Bit, False);
    }

    //
    // Initialize the following info fields before lookup
    //

    info->instrsize = 0;
    info->type = PPC32_IT_LAST;
    Uns64 instruction = 0;

    if (info->arch == VARIANT_UISA) {
        if (info->type == PPC32_IT_LAST) info->type = PPC32_IT_INSTR16;
        //
        // Attempt to match a UISA 16 Bit instruction
        //
        if (info->type == PPC32_IT_INSTR16) {
            instruction  = (Uns64)vmicxtFetch2Byte(processor, thisPC+0) | (instruction << 0);
            info->type = PPC32_IT_LAST;
            if (decodeTable_UISA_16Bit) {
                info->type = vmidDecode(decodeTable_UISA_16Bit, instruction);
            } else {
                info->type = PPC32_IT_INSTR32;
            }
            info->nextPC = info->thisPC + 2;
            info->instrsize = 2;
            info->instruction = instruction;
        }
        //
        // Attempt to match a UISA 32 Bit instruction
        //
        if (info->type == PPC32_IT_INSTR32) {
            instruction  = (Uns64)vmicxtFetch2Byte(processor, thisPC+2) | (instruction << 16);
            info->type = PPC32_IT_LAST;
            if (decodeTable_UISA_32Bit) {
                info->type = vmidDecode(decodeTable_UISA_32Bit, instruction);
            }
            info->nextPC = info->thisPC + 4;
            info->instrsize = 4;
            info->instruction = instruction;
        }
    }

    if (info->arch == VARIANT_MPC82X) {
        if (info->type == PPC32_IT_LAST) info->type = PPC32_IT_INSTR32;
        //
        // Attempt to match a mpc82x 32 Bit instruction
        //
        if (info->type == PPC32_IT_INSTR32) {
            instruction  = (Uns64)vmicxtFetch4Byte(processor, thisPC+0) | (instruction << 0);
            info->type = PPC32_IT_LAST;
            info->type = vmidDecode(decodeTable_mpc82x_32Bit, instruction);
            info->nextPC = info->thisPC + 4;
            info->instrsize = 4;
            info->instruction = instruction;
        }
    }

    ppc32GenInstructionInfo(info);
}
//
// Decoder function for a given address
//
void microblazeDecode(
    microblazeP microblaze,
    microblazeAddr thisPC,
    microblazeInstructionInfoP info
) {
    //
    // Initialize the 32 bit decoder table
    //
    static vmidDecodeTableP decodeTable32;
    if(!decodeTable32) {
        decodeTable32 = microblazeCreateDecodeTable32();
    }

    vmiProcessorP processor = (vmiProcessorP)microblaze;

    //
    // Initialize the following info fields before lookup
    //
    info->type = MICROBLAZE_IT_INSTR32;
    info->thisPC = thisPC;
    info->arch = microblaze->configInfo.arch;

    Uns64 instruction = 0;
    info->instrsize = 0;
    //
    // Attempt to match a 32 bit instruction
    //
    if (info->type == MICROBLAZE_IT_INSTR32) {
        Uns64 instr4 = vmicxtFetch4Byte(processor, thisPC);
        info->type = MICROBLAZE_IT_LAST;
        info->type = vmidDecode(decodeTable32, instr4);
        info->nextPC = info->thisPC + 4;
        instruction = instr4;
        info->instrsize = 4;
        info->instruction = instr4;
    }

    //
    // Fatal if there was a match failure
    //
    if (info->type == MICROBLAZE_IT_LAST && MICROBLAZE_DISASSEMBLE(microblaze)) {
        vmiMessage("F", "DECODE_FAIL", "Address=0x" FMT_640Nx " Instruction = 0x" FMT_640Nx, (Uns64)thisPC, instruction);
    }

    microblazeGenInstructionInfo(info, instruction);

    //
    // If this is a decode of an IMM instruction, we decode the next instruction
    //
    if (info->type == MICROBLAZE_IT_IMM_TYPEI1) {
        Uns64 instr4 = vmicxtFetch4Byte(processor, info->nextPC);
        info->type = MICROBLAZE_IT_LAST;
        info->type = vmidDecode(decodeTable32, instr4);
        info->thisPC = info->nextPC;
        info->nextPC = info->thisPC + 4;
        instruction = instr4;
        info->instrsize = 8;
        info->instruction = instr4;

        //
        // Fatal if there was a match failure
        //
        if (info->type == MICROBLAZE_IT_LAST && MICROBLAZE_DISASSEMBLE(microblaze)) {
            vmiMessage("F", "DECODE_FAIL", "Address=0x" FMT_640Nx " Instruction = 0x" FMT_640Nx, (Uns64)info->nextPC, instruction);
        }

        //
        // get the fields for the TYPEB instruction
        //
        microblazeGenInstructionInfo(info, instruction);
    } else {
        // Indicate that the simmhi is unset
        info->simmhi = 0x0000ffff;
    }
}