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

📄 inasm386.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 4 页
字号:
        asm_err(ERR_AMODEEXPECT);
        return 0;
    }
    regimage = keyimage;
    return sz;
}

//-------------------------------------------------------------------------

static int getscale(int *scale)
{
    if (lastst == star)
    {
        getsym();
        if (lastst == iconst && ! *scale)
        if (ival == 1 || ival == 2 || ival == 4 || ival == 8)
        {
            if (ival < 3)
                ival--;
            else
                ival = ival / 4+1;
            *scale = ival;
            getsym();
            return 1;
        }
        asm_err(ERR_ASCALE);
        *scale =  - 1;
        return 1;
    }
    return 0;
}

//-------------------------------------------------------------------------

int asm_enterauto(ENODE *node, int *reg1, int *reg2)
{
    if (node && (node->nodetype == en_autocon || node->nodetype == en_autoreg))
    {
        int *vreg;
        if (*reg1 >= 0 &&  *reg2 >= 0)
        {
            asm_err(ERR_AINVINDXMODE);
            return 0;
        }
        if (*reg1 < 0)
            vreg = reg1;
        else
            vreg = reg2;
        *vreg = EBP;
        return 1;
    }
    return 2;
}

//-------------------------------------------------------------------------

static int asm_structsize(void)
{
    if (lastsym->tp->type == bt_struct)
    {
        if (lastsym->tp->size == 6)
            return 7;
        if (lastsym->tp->size == 4)
            return 4;
        if (lastsym->tp->size == 1)
            return 1;
        if (lastsym->tp->size == 2)
            return 2;
        return 1000;
    }
    else
        return lastsym->tp->size;
}

//-------------------------------------------------------------------------

static AMODE *asm_mem(void)
{
    int reg1 =  - 1, reg2 =  - 1, scale = 0, temp, sz = 0, seg = 0;
    ENODE *node = 0;
    AMODE *rv;
    int first = TRUE;
    int gotident = FALSE, autonode = FALSE;
    while (TRUE)
    {
        int rg;
        cont: getsym();
        regimage = keyimage;
        if (regimage)
            rg = regimage->regnum;
        switch (lastst)
        {
            case kw_asmreg:
                regimage = keyimage;
                if (regimage->regtype == am_seg)
                {
                    if (seg)
                    {
                        asm_err(ERR_AINVINDXMODE);
                        return 0;
                    }
                    seg = rg;
                    getsym();
                    if (lastst != colon)
                    {
                        asm_err(ERR_AINVINDXMODE);
                        return 0;
                    }
                    goto cont;
                }
                if (regimage->regtype != am_dreg || regimage->size != 4)
                {
                    asm_err(ERR_AINVINDXMODE);
                    return 0;
                }
                if (reg1 >= 0)
                {
                    if (reg2 >= 0)
                    {
                        asm_err(ERR_AINVINDXMODE);
                        return 0;
                    }
                    reg2 = rg;
                    getsym();
                    getscale(&scale);
                    if (scale ==  - 1)
                        return 0;
                }
                else
                {
                    getsym();
                    if (getscale(&scale))
                    {
                        if (scale ==  - 1)
                            return 0;
                        if (reg2 >= 0)
                        {
                            reg1 = reg2;
                        }
                        reg2 = rg;
                    }
                    else
                    {
                        reg1 = rg;
                    }
                }
                break;
            case minus:
            case plus:
            case iuconst:
            case lconst:
            case luconst:
            case cconst:
            case iconst:
                if (node)
                    node = makenode(en_add, node, makeintnode(en_icon, intexpr
                        (0)));
                else
                    node = makeintnode(en_icon, intexpr(0));
                break;
            case id:
                if (gotident)
                {
                    asm_err(ERR_AINVINDXMODE);
                    return 0;
                }
                node = asm_ident();
                gotident = TRUE;
                sz = asm_structsize();
                switch (asm_enterauto(node, &reg1, &reg2))
                {
                case 0:
                    return 0;
                case 1:
                    autonode = TRUE;
                    break;
                case 2:
                    autonode = FALSE;
                    break;
                }
                break;
            default:
                asm_err(ERR_AILLADDRESS);
                return 0;
        }
        if (lastst == closebr)
        {
            getsym();
            break;
        }
        first = FALSE;
        if (lastst != plus && lastst != minus)
        {
            asm_err(ERR_AINVINDXMODE);
            return 0;
        }
        backup(lastst);
    }
    if ((reg2 == 4 || reg2 == 5) && scale > 1)
    {
        asm_err(ERR_AINVINDXMODE);
        return 0;
    }
    rv = xalloc(sizeof(AMODE));
    if (node)
    {
        rv->offset = node;
    }
    if (reg1 >= 0)
    {
        rv->preg = reg1;
        if (reg2 >= 0)
        {
            rv->sreg = reg2;
            rv->scale = scale;
            rv->mode = am_indispscale;
        }
        else
        {
            rv->mode = am_indisp;
        }
    }
    else
    if (reg2 >= 0)
    {
        rv->preg =  - 1;
        rv->sreg = reg2;
        rv->scale = scale;
        rv->mode = am_indispscale;
    }
    else
        rv->mode = am_direct;
    rv->seg = seg;
    return rv;
}

//-------------------------------------------------------------------------

static AMODE *asm_amode(int nosegreg)
{
    AMODE *rv = xalloc(sizeof(AMODE));
    int sz = 0, seg = 0;
    lastsym = 0;
    switch (lastst)
    {
        case iconst:
        case iuconst:
        case lconst:
        case luconst:
        case cconst:
        case minus:
        case plus:
        case kw_asmreg:
        case openbr:
        case id:
            break;
        default:
            asm_err(ERR_AMODEEXPECT);
            return 0;
    }
    if (lastst == kw_asmreg)
    {
        regimage = keyimage;
        if (regimage->regtype == am_ext)
        {
            sz = asm_getsize();
            regimage = keyimage;
        }
    }
    loop: switch (lastst)
    {
        case kw_asmreg:
            if (regimage->regtype == am_ext)
            {
                asm_err(ERR_ATOOMANYSPECS);
                return 0;
            }
            if (regimage->regtype == am_freg)
            {
                getsym();
                if (lastst == openpa)
                {
                    getsym();
                    if (lastst != iconst || ival < 0 || ival > 7)
                    {
                        asm_err(ERR_ANEEDFP);
                        return 0;
                    }
                    getsym();
                    needpunc(closepa, 0);
                }
                else
                    ival = 0;
                rv->preg = ival;
                rv->mode = am_freg;
                sz = 10;
            }
            else if (regimage->regtype == am_seg)
            {
                if (rv->seg)
                {
                    asm_err(ERR_ATOOMANYSEGS);
                    return 0;
                }
                rv->seg = seg = regimage->regnum;
                getsym();
                if (lastst == colon)
                {
                    getsym();
                    goto loop;
                }
                rv->mode = am_seg;
                sz = regimage->size;
            }
            else
            {
                rv->preg = regimage->regnum;
                rv->mode = regimage->regtype;
                sz = rv->length = regimage->size;
                getsym();
            }
            break;
        case openbr:
            rv = asm_mem();
            if (rv && rv->seg)
                seg = rv->seg;
            break;
        case id:
            rv->mode = am_immed;
            rv->offset = asm_ident();
            rv->length = 4;
            if (rv->offset->nodetype == en_autocon || rv->offset->nodetype ==
                en_autoreg)
            {
                asm_err(ERR_AUSELEA);
                return 0;
            }
            break;
        case minus:
        case plus:
        case iconst:
        case iuconst:
        case lconst:
        case luconst:
        case cconst:
            rv = make_immed(intexpr(0));
            break;
        default:
            asm_err(ERR_AILLADDRESS);
            return 0;
    }
    if (rv)
    {
        if (rv->seg)
            if (nosegreg || rv->mode != am_dreg)
        if (rv->mode != am_direct && rv->mode != am_indisp && rv->mode !=
            am_indispscale && rv->mode != am_seg)
        {
            asm_err(ERR_ATOOMANYSEGS);
            return 0;
        }
        if (!rv->length)
            if (sz)
                rv->length = sz;
            else if (lastsym)
                rv->length = asm_structsize();
        if (rv->length < 0)
            rv->length =  - rv->length;
        rv->seg = seg;
    }
    return rv;
}

//-------------------------------------------------------------------------

static AMODE *asm_immed(void)
{
    AMODE *rv;
    switch (lastst)
    {
        case iconst:
        case iuconst:
        case lconst:
        case luconst:
        case cconst:
            rv = make_immed(ival);
            rv->length = 4;
            getsym();
            return rv;
    }
    return 0;
}

//-------------------------------------------------------------------------

int isrm(AMODE *ap, int dreg_allowed)
{
    switch (ap->mode)
    {
        case am_dreg:
            return dreg_allowed;
        case am_indisp:
        case am_direct:
        case am_indispscale:
            return 1;
        default:
            return 0;
    }
}

//-------------------------------------------------------------------------

AMODE *getimmed(void)
{
    AMODE *rv;
    switch (lastst)
    {
        case iconst:
        case iuconst:
        case lconst:
        case luconst:
        case cconst:
            rv = make_immed(ival);
            getsym();
            return rv;
        default:
            return 0;
    }
}

//-------------------------------------------------------------------------

enum e_op asm_op(void)
{
    int op;
    if (lastst != kw_asminst)
    {
        asm_err(ERR_AINVOP);
        return  - 1;
    } op = keyimage->atype;
    getsym();
    floating = op >= op_f2xm1;
    return op;
}

//-------------------------------------------------------------------------

static OCODE *make_ocode(AMODE *ap1, AMODE *ap2, AMODE *ap3)
{
    OCODE *o = xalloc(sizeof(OCODE));
    o->oper1 = ap1;
    o->oper2 = ap2;
    o->oper3 = ap3;
    return o;
}

//-------------------------------------------------------------------------

static OCODE *ope_math(void)
{
    AMODE *ap1,  *ap2;
    ap1 = asm_amode(TRUE);
    if (!ap1)
        return 0;
    if (!isrm(ap1, TRUE))
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode(TRUE);
    if (!ap2)
        return 0;
    if (ap1->mode != am_dreg)
    {
        if (ap2->mode != am_immed && ap2->mode != am_dreg)
            return (OCODE*) - 1;
    }
    else
        if (!isrm(ap2, TRUE) && ap2->mode != am_immed)
            return (OCODE*) - 1;
    if (ap2->mode != am_immed)
        if (ap1->length && ap2->length && ap1->length != ap2->length)
            return (OCODE*) - 2;

    return make_ocode(ap1, ap2, 0);
}

//-------------------------------------------------------------------------

static OCODE *ope_arpl(void)
{
    AMODE *ap1,  *ap2;
    ap1 = asm_amode(TRUE);
    if (!ap1)
        return 0;
    if (!isrm(ap1, TRUE))
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode(TRUE);
    if (!ap2)
        return 0;
    if (ap2->mode != am_dreg)
        return (OCODE*) - 1;
    if (!ap1->length || !ap2->length || ap1->length != ap2->length || ap1
        ->length != 2)
        return (OCODE*) - 2;

    return make_ocode(ap1, ap2, 0);
}

//-------------------------------------------------------------------------

static OCODE *ope_bound(void)
{
    AMODE *ap1,  *ap2;
    ap1 = asm_amode(TRUE);
    if (!ap1)
        return 0;
    if (ap1->mode != am_dreg)
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode(TRUE);
    if (!ap2)
        return 0;
    if (!isrm(ap2, FALSE))
        return (OCODE*) - 1;
    if (ap2->length)
        return (OCODE*) - 2;
    #ifdef XXXXX
        switch (ap1->length)
        {
            case 1:
                return (OCODE*) - 1;
            case 2:
                if (ap2->length != 4)
                {
                    return (OCODE*) - 2;
                }
                break;

⌨️ 快捷键说明

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