⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disasm.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * File:        src/cpu/coldfire/mcf5xxx/disasm.c
 * Purpose:     MCF5206 definitions
 *
 * Notes:       This file contains the routines necessary to disassemble
 *              MC680x0 and MCF52xx compatible instructions.  This file 
 *              is a standalone, and the main entry point is cpu_disasm().
 */

/********************************************************************/

#include "src/include/dbug.h"
#include "src/uif/uif.h"
#include "src/cpu/coldfire/mcf5xxx/ea.h"

/********************************************************************/

#define SYMBOL_TABLE

#define SIZE_BYTE   SIZE_8
#define SIZE_WORD   SIZE_16
#define SIZE_LONG   SIZE_32 

#define ADDRESS_REGISTER -2
#define DATA_REGISTER    -3

/********************************************************************/


/********************************************************************/

static char
dstr[80];

static ADDRESS
disasm_pc;

static int
disasm_op_size;

static int
valid_instruction;

/********************************************************************/
static void
inc_disasm_pc (unsigned int num)
{
    disasm_pc = (ADDRESS)((unsigned int)disasm_pc +
        (unsigned int)num);
}

/********************************************************************/
static void
append_instruction (char *buf, char *instruction)
{
    sprintf(buf,"%-10s",instruction);
}

/********************************************************************/

#define append_string(a,b)  strcat(a,b)

/********************************************************/
static void
append_value (char *buf, int value, int size)
{
    /*
     * This routine appends a value in hex notation.
     */
    char buffer[11];

    buffer[0] = '\0';
    switch (size)
    {
        case SIZE_BYTE:
            sprintf(buffer,"0x%02X",value & 0x000000FF);
            break;
        case SIZE_WORD:
            sprintf(buffer,"0x%04X",value & 0x0000FFFF);
            break;
        case SIZE_LONG:
            sprintf(buffer,"0x%08X",value);
            break;
    }
    strcat(buf,buffer);
}

/********************************************************************/
static int
append_size2 (char *buf, int opword, int size_offset, int instr_size)
{
    /*
     * This field accepts `opword' and then determines according
     * to the offset which size is specified.
     *
     * The `offset' are given by the bit number as listed in the
     * M68000 Family Programmer's Reference, Chapter 8. [15 .. 0]
     */
    int i, j, mask;

    mask = 0x3; /* 2 bits */
    for (i = 1; i < size_offset; i++)
        mask = mask << 1;
    i = (opword & mask) >> (size_offset - 1);

    if (instr_size)
    {
        for (j = 0; *(char *)((int)buf +j) != ' '; ++j)
            ;
        buf[j] = '.';
        switch (i)
        {
            case 1:
                buf[++j] = 'B';
                disasm_op_size = SIZE_BYTE;
                break;
            case 2:
                buf[++j] = 'L';
                disasm_op_size = SIZE_LONG;
                break;
            case 3:
                buf[++j] = 'W';
                disasm_op_size = SIZE_WORD;
                break;
            default:
                valid_instruction = FALSE;
                break;
        }
    }
    else
    {
        switch (i)
        {
            case 1:
                strcat(buf,".B");
                break;
            case 2:
                strcat(buf,".L");
                break;
            case 3:
                strcat(buf,".W");
                break;
            default:
                valid_instruction = FALSE;
                break;
        }
    }
    return i;
}

/********************************************************************/
static int
append_size (char *buf, int opword, int size_offset, int instr_size)
{
    /*
     * This field accepts `opword' and then determines according
     * to the offset which size is specified.
     *
     * The `offset' are given by the bit number as listed in the
     * M68000 Family Programmer's Reference, Chapter 8. [15 .. 0]
     */
    int i, j, mask;

    mask = 0x3; /* 2 bits */
    for (i = 1; i < size_offset; i++)
        mask = mask << 1;
    i = (opword & mask) >> (size_offset - 1);

    disasm_op_size = -1;
    if (instr_size)
    {
        for (j = 0; *(char *)((int)buf +j) != ' '; ++j)
            ;
        buf[j] = '.';
        switch (i)
        {
            case 0:
                buf[++j] = 'B';
                disasm_op_size = SIZE_BYTE;
                break;
            case 1:
                buf[++j] = 'W';
                disasm_op_size = SIZE_WORD;
                break;
            case 2:
                buf[++j] = 'L';
                disasm_op_size = SIZE_LONG;
                break;
            default:
                valid_instruction = FALSE;
                break;
        }
    }
    else
    {
        switch (i)
        {
            case 0:
                strcat(buf,".B");
                break;
            case 1:
                strcat(buf,".W");
                break;
            case 2:
                strcat(buf,".L");
                break;
            default:
                valid_instruction = FALSE;
                break;
        }
    }
    return i;
}

/********************************************************************/
static void
append_register (char *buf, int opword, int reg_offset, int reg_num_offset)
{
    /*
     * This field accepts `opword' and then determines according
     * to the offsets which register (A0..A7,D0..D7) is specified.
     * The register name is then concatenated to the end of the
     * disasm_stmt.
     *
     * The `offsets' are given by the bit number as listed in the
     * M68000 Family Programmer's Reference, Chapter 8. [15 .. 0]
     */
    int i, mask;
    char regnum[3];

    /* Determine what kind of register */
    if (reg_offset == ADDRESS_REGISTER)
    {
        strcat(buf,"A");
    }
    else
    {
        if (reg_offset == DATA_REGISTER)
        {
        strcat(buf,"D");
        }
        else
        {
            mask = 1;
            for (i = 0; i < reg_offset; i++)
                mask = mask << 1;
            if (opword & mask)
                strcat(buf,"A");
            else
                strcat(buf,"D");
        }
    }

    /* determine register number */
    /* The offset given is the msb of the 3 bit field containing */
    /* the register number. */
    mask = 0x7; /* 3 bits */
    for (i = 2; i < reg_num_offset; i++)
        mask = mask << 1;
    i = (opword & mask) >> (reg_num_offset - 2);
    sprintf(regnum,"%d",i);
    strcat(buf,regnum);
}

/********************************************************************/
static void
append_displacement (char *buf, int extension, int disp_offset)
{
    /*
     * This function determines and appends a 16 or 32 bit disp.
     * The `offsets' are given by the bit number as listed in the
     * M68000 Family Programmer's Reference, Chapter 2. [15 .. 0]
     */
    int i, mask, disp;

    mask = 0x3; /* 2 bits */
    for (i = 1; i < disp_offset; i++)
        mask = mask << 1;
    i = (extension & mask) >> (disp_offset - 1);

    switch (i)
    {
        case 0:
        case 1:
            break;
        case 2:
            disp = (int)((int16)cpu_read_data(disasm_pc, SIZE_16));
            inc_disasm_pc(2);
            append_value(buf, disp, SIZE_16);
            break;
        case 3:
            disp = (int)((int32)cpu_read_data(disasm_pc, SIZE_32));
            inc_disasm_pc(4);
            append_value(buf, disp, SIZE_32);
            break;
    }
}

/********************************************************************/
static void
append_size_scale (char *buf, int extension, int size_offset, int scale_offset)
{
    /*
     * This function determines the size and scale information
     * for addressing modes that require it.
     * 
     * The `offsets' are given by the bit number as listed in the
     * M68000 Family Programmer's Reference, Chapter 2. [15 .. 0]
     */
    int i, mask, size, scale;

    mask = 0x1; /* 1 bits */
    for (i = 0; i < size_offset; i++)
        mask = mask << 1;
    size = (extension & mask) >> size_offset;

    mask = 0x3; /* 2 bits */
    for (i = 1; i < scale_offset; i++)
        mask = mask << 1;
    scale = (extension & mask) >> (scale_offset - 1);

    if (size)
        append_string(buf,".L");
    else
        append_string(buf,".W");

    switch (scale)
    {
        case 0:
            append_string(buf,"*1");
            break;
        case 1:
            append_string(buf,"*2");
            break;
        case 2:
            append_string(buf,"*4");
            break;
        case 3:
            /* valid_instruction = FALSE; */
            append_string(buf,"*8");
            break;
    }
}

/********************************************************************/
static int
append_ea (char *buf, int opword, int offset, int ea_mask)
{
    /*
     * This routine creates the addressing mode.  The
     * extensions for the addressing mode, if necessary,
     * start at disasm_pc
     */
    int i, mask, mode, reg, ea;
    char buffer[9];
#if (defined(SYMBOL_TABLE))
    char tstr[100];
#endif

    ea = EA_NONE;

    /* get addressing mode */
    mask = 0x7; /* 3 bits */
    for (i = 2; i < offset; i++)
        mask = mask << 1;
    mode = (opword & mask) >> (offset - 2);

    /* get register */
    mask = 0x7; /* 3 bits */
    for (i = 2; i < (offset - 3); i++)
        mask = mask << 1;
    reg = (opword & mask) >> (offset -3 - 2);

    switch (mode)
    {
        case 0: /* data register direct mode */
            append_register(buf,reg,DATA_REGISTER,2);
            ea = DRD;
            break;
        case 1: /* address register direct mode */
            append_register(buf,reg,ADDRESS_REGISTER,2);
            ea = ARD;
            break;
        case 2: /* address register indirect mode (ARI) */
            append_string(buf,"(");
            append_register(buf,reg,ADDRESS_REGISTER,2);
            append_string(buf,")");
            ea = ARI;
            break;
        case 3: /* ARI with postincrement mode */
            append_string(buf,"(");
            append_register(buf,reg,ADDRESS_REGISTER,2);
            append_string(buf,")+");
            ea = ARIPO;
            break;
        case 4: /* ARI with predecrement mode */
            append_string(buf,"-(");
            append_register(buf,reg,ADDRESS_REGISTER,2);
            append_string(buf,")");
            ea = ARIPR;
            break;
        case 5: /* ARI with displacement mode */
            {
                int disp;
                disp = (int)((int16)cpu_read_data((ADDRESS)disasm_pc,16));
                inc_disasm_pc(2);
                sprintf(buffer,"%d",disp);
                append_string(buf,buffer);
                append_string(buf,"(");
                append_register(buf,reg,ADDRESS_REGISTER,2);
                append_string(buf,")");
                ea = ARID;
            }
            break;
        case 6:
            {
                /* this mode is overloaded.  the encoding in the */
                /* extension byte indicate which of the 4 modes  */
                /*                                               */
                /* [xxxxxxx0xxxx0000] ARI 8bit displacement      */
                /* [xxxxxxx1xxxx0000] ARI base displacement      */
                /* [xxxxxxx1xxxx00xx] memory indirect pre index  */
                /* [xxxxxxx1xxxx01xx] memory indirect post index */
                /*                                               */

                int extension;

                extension = (int)*(uint16 *)disasm_pc;
                inc_disasm_pc(2);

                if (extension & 0x0100)
                {
                    /* ARI base or memory indirects */
                    if (extension & 0x0007)
                    {
                        /* memory indirects */
                        if (extension & 0x0004)
                        {
                            /* memory indirect post index */
                            append_string(buf,"(");
                            append_string(buf,"[");
                            append_displacement(buf,extension,5);
                            append_string(buf,",");
                            append_register(buf,reg,ADDRESS_REGISTER,2);
                            append_string(buf,"]");
                            append_string(buf,",");
                            append_register(buf,extension,15,14);
                            append_size_scale(buf,extension,11,10);
                            append_string(buf,",");
                            append_displacement(buf,extension,1);
                            ea = MIPO;
                        }
                        else
                        {
                            /* memory indirect pre index */
                            append_string(buf,"(");
                            append_string(buf,"[");
                            append_displacement(buf,extension,5);
                            append_string(buf,",");
                            append_register(buf,reg,ADDRESS_REGISTER,2);
                            append_string(buf,",");
                            append_register(buf,extension,15,14);
                            append_size_scale(buf,extension,11,10);
                            append_string(buf,"]");
                            append_string(buf,",");
                            append_displacement(buf,extension,1);
                            ea = MIPR;
                        }
                    }
                    else

⌨️ 快捷键说明

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