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

📄 asm.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * File:        asm.c   
 * Purpose:     Assembly routines for ColdFire dBUG
 *
 * Notes:
 *
 */
#include "src/include/dbug.h"
#include "src/uif/sym.h"
#include "src/cpu/coldfire/mcf5xxx/ea.h"

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

#define MAX_OPERAND 10

/* Globals */
int8 size = 0;      /* written by check_size_and_label(), used by afun's    */
int8 word_sel =0;  /* written by getwordselect(), used by afun's */
uint8 error;            /* global error flag                    */
uint8 reg_error;        /* global error flag set in get_XXXX_register()     */
uint8 ext_word_flag;    /* used in handle_ext_words(), set if ext_word exists   */ 
uint8 ext_long_flag;    /* used in handle_ext_words(), set if ext_long exists   */ 
uint8 opword2_flag; /* used in handle_ext_words(), set if opword2 exists    */ 
uint32 addr_mode;   /* written by get_ea(), used by afun26 (MOVE)       */
uint16 opword2;     /* written by various afun's, used in handle_ext_words()*/
uint16 ext_word;    /* written in get_ea() and afun's, used by "        */
uint32 ext_long;        /*  "                           */
int success;        /* global error flag set by get_value()         */
char *instruct[UIF_MAX_ARGS];       /* parsed inputs            */
ADDRESS asm_pc;         /* address where opcode is written  */
static const char ERR_ADDR_REG[] = "Not a valid address register: %s\n";
static const char ERR_DATA_REG[] = "Not a valid data register: %s\n";
static const char ERR_REG[] = "Not a valid register: %s\n";
static const char ERR_OPER[]= "Not a valid operand: %s\n";

static const char data_register[8][3] = {"D0","D1","D2","D3","D4","D5","D6","D7"};
static const char addr_register[8][3] = {"A0","A1","A2","A3","A4","A5","A6","A7"};

/****************************************************************/
static void
get_word_select(int operand)
{ 
    int i,j;

    j=operand;
 
    for (i=2; (instruct[j][i] != ':') && (instruct[j][i] != '.')  && (instruct[j][i] != NULL) ; i++)
    {}
    
    if (instruct[j][i] == NULL)      /* No word select found !*/
    { 
        word_sel = 0;                /* default to "lower word" (L) */ 
    }
    else if((instruct[j][i] == '.') || (instruct[j][i] == ':'))
    {
        switch (instruct[j][i+1])
        {
            case 'l':
            case 'L':
                word_sel=0;
                break;
            case 'u':
            case 'U':
                word_sel=1;
                break;
            default:
                error = TRUE;
                printf("Not a valid attribute %s\n",instruct[j]);
                break;
        }

        instruct[j][i] = NULL;
    }
    else
    {
        word_sel = -1;              /* error */
    }

}

/****************************************************************/
static int
get_data_register (char *reg)
{
    int Dn, i;
    Dn = 8;     /* return value of 8 is error */  
    for (i=0; i<8; i++)
    {
        if (strncasecmp(reg,data_register[i],2) == 0)
        {
            Dn = i;
            reg_error = FALSE;
            break;
        }
    }
    if (Dn == 8)
        reg_error = TRUE;

    return Dn;
}   
/****************************************************************/
static int
get_addr_register (char *reg)
{
    int An, i;
    An = 8;     /* return value of 8 is error */  
    for (i=0; i<8; i++)
    {
        if (strncasecmp(reg,addr_register[i],2) == 0)
        {
            An = i;
            reg_error = FALSE;
            break;
        }
    }
    /* A7 is SP  */
    if (strncasecmp(reg,"sp",2) == 0)
    {
        An = 7;
        reg_error = FALSE;
    }
    if (An == 8)
        reg_error = TRUE;
    return An;
}   
/****************************************************************/
static void
check_base (char *data, int *temp_base)
{
    if (data[0] == '0' && (data[1] == 'x' || data[1] == 'X'))
        *temp_base = 16;
    else if (data[0] == '$')
        *temp_base = 16;
    else if (data[0] == '%')
        *temp_base = 2;
    else if (data[0] == '@')
        *temp_base = 8;
    else
        *temp_base = 10;
}
/****************************************************************/
static void 
write_data(int size, int data)
{
    switch (size)
    {
        case SIZE_16:
            *((uint16 *) asm_pc) = (uint16)data;
            asm_pc += 2;
            break;
        case SIZE_32:
            *((uint32 *) asm_pc) = (uint32)data;
            asm_pc += 4;
            break;
    }
}
/****************************************************************/
static void
handle_ext_words(void)
{
    if (opword2_flag)
        write_data (16,opword2);

    /* Extend uint16 operand to uint32 opcode */
    if (ext_word_flag && ext_long_flag)
    {
        ext_long = (uint32)ext_word;
        write_data (32,ext_long);
    }
    else if (ext_word_flag)
        write_data (16,ext_word);
    else if (ext_long_flag)
        write_data (32,ext_long);
}
/****************************************************************/
static uint32
get_imm_data (char *data_str,uint32 mask)
{
    int temp_base, offset;
    uint32 imm_data;


    if (data_str[0] != '#')
    {
        error = TRUE;
        printf("Not valid immediate data: %s\n", data_str);
        printf("It might help if you use '#'.\n");
        return 0;
    }
    check_base(&data_str[1],&temp_base);
    
    /* adjust string so call to stroul in get_value() doesn't 
     * choke on special base indication characters
     */
    if (data_str[1] == '$' || data_str[1] == '%' || data_str[1] == '@')
        offset = 2;
    else 
        offset = 1;

    imm_data = get_value(&data_str[offset],&success,temp_base);
    if (success == 0)
    {
        error = TRUE;
        printf(INVALUE,&data_str[1]);
        return 0;
    }
    else if (imm_data & mask)
    {
        error = TRUE;
        printf("Not valid immediate data: %s\n",&data_str[1]);
        printf("Value is larger than specified.\n");
        return 0;
    }
    else
        return imm_data;
}
/****************************************************************/
static int
size_is_long(void)
{
    switch (size)
    {
        case 0:
        case 1:
            printf("Invalid size: .L only\n");
            return 0;
        case 2:
        case -1:
            return 1;
    }
    return 0;
}
/****************************************************************/
static int
is_DRD (int* reg, int* mod, char* raw)
{
    if ((*reg = get_data_register(raw)) != 8)
    {   /* Dn */
        *mod = 0x0;
        addr_mode = DRD;
            return 1;
    }
    return 0;
}
static int
is_ARD (int* reg, int* mod, char* raw)
{
    if ((*reg = get_addr_register(raw)) != 8)
    {   /* An */
        *mod = 0x1;
                addr_mode = ARD;
            return 1;
    }
        return 0;
}
static int
is_ARI (int* reg, int* mod, char* raw)
{
    if (raw[0] == '(' && raw[3] == ')' && raw[4] == NULL)
    {
        if ((*reg = get_addr_register(&raw[1])) != 8)
        {
            *mod = 0x2;
            addr_mode = ARI;
            return 1;
                }
    }
    return 0;
}
static int
is_ARIPR (int* reg, int* mod, char* raw)
{
    if (raw[0] == '-' && raw[1] == '(' && raw[4] == ')' && raw[5] == NULL)
    {
        if ((*reg = get_addr_register(&raw[2])) != 8)
        {
            *mod = 0x4;
            addr_mode = ARIPR;
            return 1;
                }
    }
    return 0;
}
static int
is_ARIPO (int* reg, int* mod, char* raw)
{
    if (raw[0] == '(' && raw[3] == ')' && raw[4] == '+' && raw[5] == NULL)
    {
        if ((*reg = get_addr_register(&raw[1])) != 8)
        {
            *mod = 0x3;
            addr_mode = ARIPO;
            return 1;
                }
    }
    return 0;
}
static int
is_IM (int* reg, int* mod, char* raw)
{
    int32 temp;

    if (raw[0] == '#')
    {
        *reg = 0x4;
        *mod = 0x7;
        addr_mode = IM;
        temp = (uint32)get_imm_data(raw,0x0);   /* FIX !!! usage of temp */
        if (!error || symtab_convert_string(raw,(ADDRESS *)&temp))
        {
            if (temp & 0xFFFF0000)
            {
                ext_long = temp; 
                ext_long_flag = 1;
            }
            else  
            {
                ext_word = (uint16)temp; 
                ext_word_flag = 1;
            }
                    return 1;
        }
    }
        return 0;
}
static int
is_AS_AL (int* reg, int* mod, char* raw)
{   /* (xxx).W  or  (xxx).L */
    int i, force = 0, parens = 0;
    uint32 temp;
    char *tstr[1], copy[MAX_OPERAND];
    
    strcpy(copy,raw);
    tstr[0] = &copy[0];

    if (copy[0] == '(')
    {
        parens++;
        tstr[0] = &copy[1];
    }
    for (i=0; (tstr[0][i] != '.' && tstr[0][i] != NULL); i++) {}
    if (tstr[0][i] == '.')
    {
        tstr[0][i] = NULL;
        switch (tstr[0][i+1])
        {
            case 'w':
            case 'W':
                break;
            case 'l':
            case 'L':
                force = 1;
                break;
            default:
                return 0;
        }
        if (tstr[0][i+2] == ')')
            parens--;
    }
    for (i=1; (copy[i] != NULL && copy[i] != ')'); i++) {}
    if (copy[i] == ')')
    {
        parens--;
        copy[i] = NULL;
    }
    if (parens)
        return 0;

    if (((tstr[0][0] == '0' && (tstr[0][1] == 'x' || tstr[0][1] == 'X')) 
       || tstr[0][0] == '$') || (symtab_convert_string(raw,(ADDRESS *)&temp)))
    {       
            *mod = 0x7;
                temp = get_value(tstr[0],&success,16);
                if (success && ((temp & 0xffff0000) || force))
            {       /* Absolute Long */
            *reg = 0x1;
                    addr_mode = AL;
                    ext_long = temp;
            ext_long_flag = 1;
            return 1;
        }
                else if (success)
                {       /* Absolute Short */
                        *reg = 0x0;
                        addr_mode = AS;
                        ext_word = (uint16)temp;
            ext_word_flag = 1;
            return 1;
        }
                else
            return 0;
    }
        return 0;
}
static int
is_ARID_PCID (int* reg, int* mod, char **strg)
{
    int temp_base, go_ahead = 0;
    int32 temp;
    
    if (strg[0][0] != NULL && strg[1][0] != NULL && strg[2][0] == NULL)
    {
        if ((*reg = get_addr_register(strg[1])) != 8)
        {
            go_ahead = 1;
            addr_mode = ARID;
            *mod = 0x5;
        }
        else if (strncasecmp(strg[1],"pc",2) == 0)
        {
            go_ahead = 1;
            addr_mode = PCID;
            *mod = 0x7;
            *reg = 0x2;
        }
        if (go_ahead)
        {
            check_base(strg[0],&temp_base);
            temp = get_value(strg[0],&success,temp_base);
            /* 16-bit */
            if (success && temp >= -32768 && temp <= 32767)
            {
                ext_word_flag = 1;
                ext_word = (uint16)temp;
                return 1;
            }
        }   
    }
    return 0;
}
static int
is_ARII8_PCII8 (int* reg, int* reg2, int* mod, char **strg)
{
    int temp_base, go_ahead = 0;
    int32 temp;

    if (strg[0][0] != NULL && strg[1][0] != NULL && strg[2][0] != NULL)
    {
        if ((*reg = get_addr_register(strg[1])) != 8)
        {
            go_ahead = 1;
            addr_mode = ARII8;
            *mod = 0x6;
        }
        else if (strncasecmp(strg[1],"pc",2) == 0)
        {
            go_ahead = 1;
            addr_mode = PCII8;
            *mod = 0x7;
            *reg = 0x3;
        }
        if (go_ahead)
        {
            check_base(strg[0],&temp_base);

⌨️ 快捷键说明

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