disppc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,470 行 · 第 1/3 页

C
1,470
字号

    code.full = ins->opcode;

    PPCFloatdb( h, d, ins );

    switch( ins->type ) {
    case DI_PPC_mffs:
        ins->num_ops = 1;
        break;
    case DI_PPC_mtfsf:
        ins->op[0].type = DO_IMMED;
        ins->op[0].base = DR_NONE;
        ins->op[0].value = code.hi.math.FM;
        break;
    default:
        break;
    }
    return( DHR_DONE );
}
dis_handler_return PPCMem1( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->num_ops = 2;
    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.general.second + DR_PPC_r0;
    ins->op[1].type = DO_MEMORY_ABS;
    ins->op[1].base = code.hi.general.first + DR_PPC_r0;
    ins->op[1].value = SEX( code.lo.immediate, 15 );

    if( code.hi.general.floating ) {
        if( code.hi.general.type & 0x2 ) {
            ins->op[1].ref_type = DRT_PPC_SFLOAT;
        } else {
            ins->op[1].ref_type = DRT_PPC_DFLOAT;
        }
    } else {
        switch( code.hi.general.type ) {
        case 0x1:
        case 0x3:
            ins->op[1].ref_type = DRT_PPC_BYTE;
            break;
        case 0x4:
        case 0x5:
        case 0x6:
            ins->op[1].ref_type = DRT_PPC_HWORD;
            break;
        case 0x7:
            ins->op[1].ref_type = DRT_PPC_MWORD;
            break;
        case 0x0:
        case 0x2:
            ins->op[1].ref_type = DRT_PPC_WORD;
            break;
        }
    }
    return( DHR_DONE );
}
dis_handler_return PPCMemD1( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->num_ops = 2;
    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.general.second + DR_PPC_r0;
    ins->op[1].type = DO_MEMORY_ABS;
    ins->op[1].base = code.hi.general.first + DR_PPC_r0;
    ins->op[1].value = SEX( code.lo.immediate & ~0x3, 15 );
    ins->op[1].ref_type = DRT_PPC_DWORD;
    return( DHR_DONE );
}
dis_handler_return PPCMem2( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->num_ops = 3;
    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.general.second + DR_PPC_r0;
    ins->op[1].type = DO_REG;
    ins->op[1].base = code.hi.general.first + DR_PPC_r0;
    ins->op[2].type = DO_REG;
    ins->op[2].base = code.lo.math.rB + DR_PPC_r0;
    ins->op[1].extra |= PE_XFORM;

    switch( code.lo.math.OE ) {
    case 0:
        switch( code.lo.math.type1 & 5 ) {
        case 0:
            ins->op[1].ref_type = DRT_PPC_WORD;
            break;
        case 1:
            ins->op[1].ref_type = DRT_PPC_BYTE;
            break;
        case 4:
            if( code.lo.math.type2 == 1 ) {
                ins->op[1].ref_type = DRT_PPC_SWORD;
                break;
            } // fall through
        case 5:
            ins->op[1].ref_type = DRT_PPC_HWORD;
            break;
        }
        break;
    case 1:
        switch( code.lo.math.type2 ) {
        case 1:
            ins->op[1].ref_type = DRT_PPC_SWORD;
            break;
        case 2:
            if( code.lo.math.type1 & (1<<2) ) {
                ins->op[1].ref_type = DRT_PPC_BRHWORD;
            } else {
                ins->op[1].ref_type = DRT_PPC_BRWORD;
            }
            break;
        case 3:
            if( code.lo.math.type1 & 1 ) {
                ins->op[1].ref_type = DRT_PPC_DFLOAT;
            } else {
                ins->op[1].ref_type = DRT_PPC_SFLOAT;
            }
            break;
        }
        break;
    }
    if( code.lo.math.Rc ) {
        ins->flags |= DIF_PPC_RC;
    }

    return( DHR_DONE );
}
dis_handler_return PPCMemD2( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->num_ops = 3;
    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.general.second + DR_PPC_r0;
    ins->op[1].type = DO_REG;
    ins->op[1].base = code.hi.general.first + DR_PPC_r0;
    ins->op[2].type = DO_REG;
    ins->op[2].base = code.lo.math.rB + DR_PPC_r0;
    ins->op[1].extra |= PE_XFORM;
    ins->op[1].ref_type = DRT_PPC_DWORD;
    return( DHR_DONE );
}
dis_handler_return PPCMem3( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->num_ops = 3;
    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.general.second + DR_PPC_r0;
    ins->op[1].type = DO_REG;
    ins->op[1].base = code.hi.general.first + DR_PPC_r0;
    ins->op[2].type = DO_IMMED;
    ins->op[2].value = code.lo.general.third;

    ins->op[1].ref_type = DRT_PPC_SWORD;

    return( DHR_DONE );
}
dis_handler_return PPCFloatMem1( dis_handle *h, void *d, dis_dec_ins *ins )
{
    PPCMem1( h, d, ins );
    ins->op[0].base += DR_PPC_f0 - DR_PPC_r0;

    return( DHR_DONE );
}
dis_handler_return PPCFloatMem2( dis_handle *h, void *d, dis_dec_ins *ins )
{
    PPCMem2( h, d, ins );
    ins->op[0].base += DR_PPC_f0 - DR_PPC_r0;

    return( DHR_DONE );
}
dis_handler_return PPCBranch( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;
    int         magic;

    code.full = ins->opcode;

    if( code.lo.branch.LK ) {
        ins->flags |= DIF_PPC_LK;
    }
    magic = 2;
    switch( ins->type ) {
    case DI_PPC_b:
        magic = 0; // fall through
    case DI_PPC_bc:
        magic++; // magic=1 for b, 3 for bc
        if( code.b.AA ) {
            ins->flags |= DIF_PPC_AA;
            ins->op[magic-1].type = DO_ABSOLUTE;
        } else {
            ins->op[magic-1].type = DO_RELATIVE;
        }
        // fall through
    case DI_PPC_bcctr:
    case DI_PPC_bclr:
        ins->num_ops = magic; // magic=2 for bcctr, bclr
        break;
    default:
        break;
    }
    switch( ins->type ) {
    case DI_PPC_b:
        ins->op[0].value = SEX( code.b.LI, 23 ) << 2;
        break;
    case DI_PPC_bc:
        ins->op[2].value = SEX( code.lo.branch.BD, 13 ) << 2;
        ins->op[2].op_position = 0;
        // fall through
    case DI_PPC_bcctr:
    case DI_PPC_bclr:
        ins->op[0].type = DO_IMMED;
        ins->op[0].value = code.hi.general.second;
        ins->op[0].op_position = 3;
        ins->op[1].type = DO_IMMED;
        ins->op[1].value = code.hi.general.first;
        ins->op[1].op_position = 2;
        break;
    default:
        break;
    }
    return( DHR_DONE );
}
dis_handler_return PPCCompare( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->num_ops = 4;
    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.compare.crfD + DR_PPC_cr0;
    ins->op[1].type = DO_IMMED;
    ins->op[1].value = code.hi.compare.L;
    ins->op[2].type = DO_REG;
    ins->op[2].base = code.hi.compare.rA + DR_PPC_r0;

    switch( ins->type ) {
    case DI_PPC_cmp:
    case DI_PPC_cmpl:
        ins->op[3].type = DO_REG;
        ins->op[3].base = code.lo.math.rB + DR_PPC_r0;
        break;
    case DI_PPC_cmpi:
        ins->op[3].type = DO_IMMED;
        ins->op[3].value = SEX( code.lo.immediate, 15 );
        break;
    case DI_PPC_cmpli:
        ins->op[3].type = DO_IMMED;
        ins->op[3].value = code.lo.immediate;
    default:
        break;
    }
    return( DHR_DONE );
}
dis_handler_return PPCCondition( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.general.second + DR_PPC_crb0;

    switch( ins->type ) {
    case DI_PPC_mtfsb0:
    case DI_PPC_mtfsb1:
        ins->num_ops = 1;
        break;
    default:
        ins->num_ops = 3;
        ins->op[1].type = DO_REG;
        ins->op[1].base = code.hi.general.first + DR_PPC_crb0;
        ins->op[2].type = DO_REG;
        ins->op[2].base = code.lo.math.rB + DR_PPC_crb0;
        break;
    }

    if( code.lo.general.Rc ) {
        ins->flags |= DIF_PPC_RC;
    }
    return( DHR_DONE );
}
dis_handler_return PPCConditionField( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->op[0].type = DO_REG;
    ins->op[0].base = code.hi.condition.crfD + DR_PPC_cr0;

    switch( ins->type ) {
    case DI_PPC_mcrf:
    case DI_PPC_mcrfs:
        ins->num_ops = 2;
        ins->op[1].type = DO_REG;
        ins->op[1].base = code.hi.condition.crfS + DR_PPC_cr0;
        break;
    case DI_PPC_mcrxr:
        ins->num_ops = 1;
        break;
    case DI_PPC_mtfsfi:
        ins->num_ops = 2;
        ins->op[1].type = DO_IMMED;
        ins->op[1].value = code.lo.condition.IMM;
        break;
    default:
        break;
    }

    return( DHR_DONE );
}
dis_handler_return PPCSpecial( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;
    int         magic = 0;

    code.full = ins->opcode;

    ins->num_ops = 2;
    switch( ins->type ) {
    case DI_PPC_mfspr:
    case DI_PPC_mfsr:
        magic = 0;
        break;
    case DI_PPC_mtspr:
    case DI_PPC_mtsr:
    case DI_PPC_mtcrf:
        magic = 1;
        break;
    default:
        break;
    }
    ins->op[magic].type = DO_REG;
    ins->op[magic].base = code.hi.general.second + DR_PPC_r0;
    magic = 1-magic;
    ins->op[magic].type = DO_IMMED;
    switch( ins->type ) {
    case DI_PPC_mfspr:
    case DI_PPC_mtspr:
        ins->op[magic].value = MK_SPR( code.lo.general.third, code.hi.general.first );
        break;
    case DI_PPC_mfsr:
    case DI_PPC_mtsr:
        ins->op[magic].value = code.hi.general.first;
        break;
    case DI_PPC_mtcrf:
        ins->op[magic].value = code.CRM.CRM;
        break;
    default:
        break;
    }

    return( DHR_DONE );
}
dis_handler_return PPCShiftImmed( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    PPCImmed2( h, d, ins );
    code.full = ins->opcode;

    ins->op[2].value = code.lo.general.third;

    if( code.lo.general.Rc ) {
        ins->flags |= DIF_PPC_RC;
    }
    return( DHR_DONE );
}
dis_handler_return PPCShiftImmedD( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    PPCImmed2( h, d, ins );
    code.full = ins->opcode;

    ins->op[2].value = code.lo.xs_form.sh | (code.lo.xs_form.sh_5 << 5);

    if( code.lo.general.Rc ) {
        ins->flags |= DIF_PPC_RC;
    }
    return( DHR_DONE );
}
dis_handler_return PPCRotate( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    PPCMath2( h, d, ins );
    code.full = ins->opcode;

    ins->num_ops = 5;

    switch( ins->type ) {
    case DI_PPC_rlwimi:
    case DI_PPC_rlwinm:
        ins->op[2].type = DO_IMMED;
        ins->op[2].base = DR_NONE;
        ins->op[2].value = code.lo.general.third;
        break;
    default:
        break;
    }

    ins->op[3].type = DO_IMMED;
    ins->op[3].value = code.lo.general.second;
    ins->op[4].type = DO_IMMED;
    ins->op[4].value = code.lo.general.first;

    if( code.lo.general.Rc ) {
        ins->flags |= DIF_PPC_RC;
    }
    return( DHR_DONE );
}
dis_handler_return PPCRotateD( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    PPCMath2( h, d, ins );
    code.full = ins->opcode;

    ins->num_ops = 4;

    ins->op[3].type = DO_IMMED;
    ins->op[3].value = code.lo.mds_form.mb;

    if( code.lo.general.Rc ) {
        ins->flags |= DIF_PPC_RC;
    }
    return( DHR_DONE );
}
dis_handler_return PPCRotateImmD( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    PPCMath2( h, d, ins );
    code.full = ins->opcode;

    ins->num_ops = 4;

    ins->op[2].type = DO_IMMED;
    ins->op[2].base = DR_NONE;
    ins->op[2].value = code.lo.md_form.sh | (code.lo.md_form.sh_5 << 5);

    ins->op[3].type = DO_IMMED;
    ins->op[3].value = code.lo.mds_form.mb;

    if( code.lo.general.Rc ) {
        ins->flags |= DIF_PPC_RC;
    }
    return( DHR_DONE );
}
dis_handler_return PPCTrap( dis_handle *h, void *d, dis_dec_ins *ins )
{
    ppc_ins     code;

    code.full = ins->opcode;

    ins->num_ops = 3;
    ins->op[0].type = DO_IMMED;
    ins->op[0].value = code.hi.general.second;
    ins->op[0].op_position = 3;
    ins->op[1].type = DO_REG;
    ins->op[1].base = code.hi.general.first + DR_PPC_r0;

    switch( ins->type ) {
    case DI_PPC_tw:
    case DI_PPC_td:
        ins->op[2].type = DO_REG;
        ins->op[2].base = code.lo.math.rB + DR_PPC_r0;
        break;
    case DI_PPC_twi:
    case DI_PPC_tdi:
        ins->op[2].type = DO_IMMED;
        ins->op[2].value = SEX( code.lo.immediate, 15 );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?