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

📄 inasm68.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 5 页
字号:

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

static AMODE *asm_movemarg(AMODE *rv)
{
    AMODE old =  *rv;
    int start, val = 0, i;
    if (rv->mode == am_freg)
    {
        rv->mode = am_fmask;
        while (TRUE)
        {
            if (lastst != minus)
            {
                val |= 1 << old.preg;
                if (lastst != divide)
                    break;
                getsym();
                if (lastst != kw_asmreg)
                {
                    asm_err(ERR_ANEEDFP);
                    return 0;
                }
                regimage = keyimage;
                old.preg = regimage->regnum;
                old.mode = regimage->regtype;
                getsym();
            }
            else
            {
                getsym();
                start = old.preg;
                if (lastst != kw_asmreg)
                {
                    asm_err(ERR_ANEEDFP);
                    return 0;
                }
                regimage = keyimage;
                old.preg = regimage->regnum;
                old.mode = regimage->regtype;
                getsym();
                if (old.mode != am_freg)
                {
                    asm_err(ERR_ANEEDFP);
                    return 0;
                }
                if (start <= old.preg)
                    for (i = start; i <= old.preg; i++)
                        val |= 1 << i;
            }
        }
    }
    else
    {
        rv->mode = am_mask;
        rv->offset = 0;
        while (TRUE)
        {
            if (lastst != minus)
            {
                if (old.mode == am_areg)
                    val |= 0x100 << old.preg;
                else
                    val |= 1 << old.preg;
                if (lastst != divide)
                    break;
                getsym();
                if (lastst != kw_asmreg)
                {
                    asm_err(ERR_ANEEDAD);
                    return 0;
                }
                regimage = keyimage;
                old.preg = regimage->regnum;
                old.mode = regimage->regtype;
                getsym();
                if (old.mode != am_dreg && old.mode != am_areg)
                {
                    asm_err(ERR_ANEEDAD);
                    return 0;
                }
            }
            else
            {
                int modetype = old.mode;
                getsym();
                start = old.preg;
                if (lastst != kw_asmreg)
                {
                    asm_err(ERR_ANEEDAD);
                    return 0;
                }
                regimage = keyimage;
                old.preg = regimage->regnum;
                old.mode = regimage->regtype;
                getsym();
                if (old.mode != am_dreg && old.mode != am_areg)
                {
                    asm_err(ERR_ANEEDAD);
                    return 0;
                }
                if (modetype != old.mode)
                {
                    asm_err(ERR_AREGMISMATCH);
                    return 0;
                }
                if (start <= old.preg)
                    for (i = start; i <= old.preg; i++)
                        if (old.mode == am_areg)
                            val |= 0x100 << i;
                        else
                            val |= 1 << i;
            }
        }
    }
    rv->offset = (void*)val;
    return rv;

}

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

static AMODE *asm_amode(void)
{
    AMODE *rv = xalloc(sizeof(AMODE));
    int sz = 0, seg = 0;
    lastsym = 0;
    switch (lastst)
    {
        case kw_asmreg:
            regimage = keyimage;
            rv->preg = regimage->regnum;
            rv->mode = regimage->regtype;
            sz = regimage->size;
            getsym();
            if (lastst == divide || lastst == minus)
            {
                if (!asm_movemarg(rv))
                {
                    asm_err(ERR_AILLADDRESS);
                    return 0;
                }
            }
            else if (lastst == colon)
            {
                AMODE *temp;
                getsym();
                if (rv->mode != am_dreg)
                {
                    asm_err(ERR_AILLADDRESS);
                    return 0;
                }
                if (!need_dreg(&temp))
                    return 0;
                rv->mode = am_divsl;
                rv->sreg = temp->preg;
            }
            break;
        case openpa:
        case minus:
            rv = asm_mem();
            break;
        case id:
            doid: rv->mode = am_immed;
            rv->offset = asm_ident();
            if (rv->offset->nodetype == en_autocon || rv->offset->nodetype ==
                en_autoreg)
            {
                asm_err(ERR_AUSELEA);
                return 0;
            }
            break;
        case hash:
            getsym();
            if (lastst == id)
                goto doid;
            if (lastst != minus && lastst != iconst && lastst != lconst &&
                lastst != luconst && lastst != cconst)
            {
                asm_err(ERR_AMODEEXPECT);
                return 0;
            }
            // FALL THROUGH
        case iconst:
        case iuconst:
        case lconst:
        case luconst:
        case cconst:
            rv->mode = am_immed;
            rv->offset = makeintnode(en_icon, intexpr(0));
            ;
            break;
        default:
            asm_err(ERR_AMODEEXPECT);
            return 0;
    }
    if (rv)
        rv->length = theSize;
    return rv;
}

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

static AMODE *getbf(void)
{
    AMODE *rv = xalloc(sizeof(AMODE));
    if (lastst != begin)
        return 0;
    getsym();
    if (lastst == kw_asmreg)
    {
        rv->mode = am_bfreg;
        if (keyimage->regtype != am_dreg)
            return 0;
        rv->preg = keyimage->regnum;
        getsym();
        if (lastst != colon)
            return 0;
        getsym();
        if (lastst != kw_asmreg)
            return 0;
        if (keyimage->regtype != am_dreg)
            return 0;
        rv->sreg = keyimage->regnum;
        getsym();
        if (lastst != end)
            return 0;
        getsym();
    }
    else
    {
        rv->mode = am_bf;
        rv->preg = intexpr(0);
        if (lastst != colon)
            return 0;
        getsym();
        rv->sreg = intexpr(0);
        if (lastst != end)
            return 0;
        getsym();
    }
    return rv;
}

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

enum e_op asm_op(void)
{
    int op;
    if (lastst != kw_asminst)
    {
        asm_err(ERR_AINVOP);
        return  - 1;
    } op = keyimage->regtype;
    getsym();
    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 int noincdec(AMODE *ap)
{
    if (ap->mode == am_ainc || ap->mode == am_adec)
    {
        asm_err(ERR_AILLADDRESS);
        return 0;
    }
    return 1;
}

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

static int dreg(AMODE *ap)
{
    if (ap->mode != am_dreg)
    {
        asm_err(ERR_AILLADDRESS);
        return 0;
    }
    return 1;
}

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

static int vermode(AMODE *ap, int dok, int aok, int pcok, int immok)
{
    switch (ap->mode)
    {
        case am_dreg:
            if (dok)
                return 1;
            break;
        case am_areg:
            if (aok)
                return 1;
            break;
        case am_pcindx:
        case am_pcindxaddr:
        case am_pcindxdata:
        case am_iiprepca:
        case am_iiprepcd:
        case am_iipostpca:
        case am_iipostpcd:
            if (pcok)
                return 1;
            break;
        case am_immed:
            if (immok)
                return 1;
            break;
        case am_baseindxaddr:
        case am_baseindxdata:
        case am_iimem:
        case am_iiprea:
        case am_iipred:
        case am_iiposta:
        case am_iipostd:
        case am_indx:
        case am_ainc:
        case am_adec:
        case am_direct:
        case am_adirect:
        case am_ind:
            return 1;
        default:
            break;
    }
    asm_err(ERR_AILLADDRESS);
    return 0;
}

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

static OCODE *ope_negbcd(void)
{
    AMODE *ap1,  *ap2;
    if (theSize && theSize != 1)
    {
        asm_err(ERR_AINVSIZE);
        return 0;
    }
    ap1 = asm_amode();
    if (!ap1)
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode();
    if (!ap2)
        return (OCODE*) - 1;
    if (ap1->mode != ap2->mode || (ap1->mode != am_dreg && ap1->mode != am_adec)
        )
        return (OCODE*) - 1;
    return make_ocode(ap1, ap2, 0);
}

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

static OCODE *ope_addx(void)
{
    AMODE *ap1,  *ap2;
    if (!intsize())
    {
        return 0;
    }
    if (!theSize)
        theSize = 2;
    ap1 = asm_amode();
    if (!ap1)
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode();
    if (!ap2)
        return (OCODE*) - 1;
    if (ap1->mode != ap2->mode || (ap1->mode != am_dreg && ap1->mode != am_adec)
        )
        return (OCODE*) - 1;
    return make_ocode(ap1, ap2, 0);
}

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

static OCODE *ope_math(void)
{
    AMODE *ap1,  *ap2;
    if (!intsize())
        return 0;
    if (!theSize)
        theSize = 2;
    ap1 = asm_amode();
    if (!ap1)
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode();
    if (!ap2)
        return (OCODE*) - 1;
    if (ap2->mode == am_areg)
        if (!wordsize())
            return ;
    if (ap2->mode == am_dreg || ap2->mode == am_areg)
    {
        if (!vermode(ap1, TRUE, TRUE, TRUE, TRUE))
            return 0;
    }
    else if (ap1->mode == am_dreg || ap1->mode == am_immed)
    {
        if (!vermode(ap2, TRUE, TRUE, FALSE, FALSE))
            return 0;
    }
    else
    {
        return (OCODE*) - 1;
    }
    return make_ocode(ap1, ap2, 0);

}

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

static OCODE *ope_amath(void)
{
    AMODE *ap1,  *ap2;
    if (!wordsize())
        return 0;
    ap1 = asm_amode();
    if (!ap1)
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode();
    if (!ap2)
        return (OCODE*) - 1;
    if (ap2->mode != am_areg)
    {
        asm_err(ERR_AAREGEXPECT);
        return 0;
    }
    if (!vermode(ap1, TRUE, TRUE, TRUE, TRUE))
        return 0;
    return make_ocode(ap1, ap2, 0);
}

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

static OCODE *ope_imath(void)
{
    AMODE *ap1,  *ap2;
    if (!intsize())
        return 0;
    if (!theSize)
        theSize = 2;
    ap1 = asm_amode();
    if (!ap1)
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode();
    if (!ap2)
        return (OCODE*) - 1;
    if (ap1->mode != am_immed)
    {
        return (OCODE*) - 1;
    }
    if (!vermode(ap2, TRUE, FALSE, FALSE, FALSE))
        return 0;
    return make_ocode(ap1, ap2, 0);
}

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

static OCODE *ope_qmath(void)
{
    OCODE *oc = ope_imath();
    if (!oc)
        return (OCODE*) - 1;
    if (!intsize())
        return 0;
    if (oc->oper1->offset->v.i < 1 || oc->oper1->offset->v.i > 8)
    {
        return (OCODE*) - 1;
    }
    return oc;
}

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

static OCODE *ope_log(void)
{
    AMODE *ap1,  *ap2;
    if (!intsize())
        return 0;
    if (!theSize)
        theSize = 2;
    ap1 = asm_amode();
    if (!ap1)
        return (OCODE*) - 1;
    needpunc(comma, 0);
    ap2 = asm_amode();
    if (!ap2)
        return (OCODE*) - 1;
    if (ap2->mode == am_dreg)
    {
        if (!vermode(ap1, TRUE, FALSE, TRUE, TRUE))
            return 0;
    }
    else if (ap1->mode == am_dreg || ap1->mode == am_immed)
    {
        if (!vermode(ap2, FALSE, FALSE, FALSE, FALSE))
            return 0;
    }
    else
    {
        return (OCODE*) - 1;
    }
    return make_ocode(ap1, ap2, 0);
}

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

static OCODE *ope_ilog(void)
{
    AMODE *ap1,  *ap2;
    if (!intsize())
        return 0;
    if (!theSize)
        theSize = 2;
    ap1 = asm_amode();
    if (!ap1)
        return (OCODE*) - 1;

⌨️ 快捷键说明

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