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

📄 intr386.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 2 页
字号:
    gen_pop(EDI, am_dreg, 0);
    if (ap1 == 0)
        ap1 = clreg;
    return ap1;
}

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

static AMODE *popSIDI(AMODE *ap, int tocx)
{
    AMODE *ap1 = popDI(ap, tocx);
    gen_pop(ESI, am_dreg, 0);
    return ap1;
}

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

static void skipdi(void)
{
    gen_code(op_sub, makedreg(EAX), makedreg(EAX));
    gen_code(op_mov, makedreg(ECX), make_immed( - 1));
    gen_code(op_repnz, 0, 0);
    gen_code(op_scasb, 0, 0);
    gen_code(op_dec, makedreg(EDI), 0);
}

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

static AMODE *xstrlen(int todec)
{
    AMODE *ap1;
    gen_code(op_sub, makedreg(EAX), makedreg(EAX));
    gen_code(op_mov, makedreg(ECX), make_immed( - 1));
    gen_code(op_repnz, 0, 0);
    gen_code(op_scasb, 0, 0);
    gen_code(op_not, makedreg(ECX), 0);
    if (todec)
        gen_code(op_dec, makedreg(ECX), 0);
    ap1 = temp_data();
    if (ap1->preg != ECX)
        gen_code(op_mov, ap1, makedreg(ECX));
    return ap1;
}

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

static void xmove(void)
{
    gen_code3(op_shrd, makedreg(EAX), makedreg(ECX), make_immed(2));
    gen_code(op_shr, makedreg(ECX), make_immed(2));
    gen_code(op_repnz, 0, 0);
    gen_code(op_movsd, 0, 0);
    gen_code3(op_shld, makedreg(ECX), makedreg(EAX), make_immed(2));
    gen_code(op_repnz, 0, 0);
    gen_code(op_movsb, 0, 0);
}

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

static void xset(void)
{
    gen_codes(op_mov, 1, makedreg(4), makedreg(0));
    gen_code2(op_movzx, 4, 2, makedreg(EDX), makedreg(EAX));
    gen_code(op_shl, makedreg(EAX), make_immed(16));
    gen_code(op_or, makedreg(EAX), makedreg(EDX));
    gen_code3(op_shrd, makedreg(EDX), makedreg(ECX), make_immed(2));
    gen_code(op_shr, makedreg(ECX), make_immed(2));
    gen_code(op_repnz, 0, 0);
    gen_code(op_stosd, 0, 0);
    gen_code3(op_shld, makedreg(ECX), makedreg(EDX), make_immed(2));
    gen_code(op_repnz, 0, 0);
    gen_code(op_stosb, 0, 0);
}

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

static AMODE *xstrcmp(void)
{
    int neg = nextlabel++, exit = nextlabel++;
    AMODE *ap1 = temp_data();
    gen_code(op_repz, 0, 0);
    gen_code(op_cmpsb, 0, 0);
    gen_code(op_mov, ap1, make_immed(0));
    gen_code(op_je, make_label(exit), 0);
    gen_code(op_js, make_label(neg), 0);
    gen_code(op_inc, ap1, 0);
    gen_comment("; TEST EAX,IMMED (branches around next four bytes of code)\n");
    gen_codes(op_genword, 0, make_immed(0xa9), 0);
    gen_codes(op_nop, 0, 0, 0);
    gen_codes(op_nop, 0, 0, 0);
    gen_codes(op_nop, 0, 0, 0);
    gen_label(neg);
    gen_code(op_dec, ap1, 0);
    gen_label(exit);
    return ap1;
}

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

AMODE *inport(ENODE *parms, int size)
{
    AMODE *ap1;
    int pushed = FALSE, pushedax = FALSE;
    if (!oneparm(parms))
        return 0;
    ap1 = gen_expr(parms->v.p[0], 0, 0, 2);
    if (ap1->mode != am_dreg || ap1->preg != EDX)
    {
        freeop(ap1);
        if (regs[2])
        {
            pushed = TRUE;
            gen_push(EDX, am_dreg, 0);
        }
        gen_codes(op_mov, 2, makedreg(EDX), ap1);
    }
    if (regs[0])
    {
        pushedax = TRUE;
        gen_push(EAX, am_dreg, 0);
    }
    switch (size)
    {
        case 1:
            gen_code(op_in, alreg, dxreg);
            gen_code(op_movzx, makedreg(EAX), alreg);
            break;
        case 2:
            gen_code(op_in, axreg, dxreg);
            gen_code(op_movzx, makedreg(EAX), axreg);
            break;
    }
    if (pushedax)
    {
        ap1 = temp_data();
        gen_code(op_mov, ap1, makedreg(EAX));
        gen_pop(EAX, am_dreg, 0);
    }
    else
    {
        regs[0]++;
        ap1 = makedreg(EAX);
    }
    if (pushed)
        gen_pop(EDX, am_dreg, 0);
    return ap1;
}

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

AMODE *outport(ENODE *parms, int size)
{
    AMODE *ap1,  *ap2;
    int pushed = FALSE, pushedax = FALSE;
    if (!twoparms(parms))
        return 0;
    ap2 = gen_expr(parms->v.p[0], FALSE, FALSE, size);
    if (regs[0] && (ap2->mode != am_dreg || ap2->preg != EAX))
    {
        pushedax = TRUE;
        gen_push(EAX, am_dreg, 0);
        regs[0]--;
    }
    else
        do_extend(ap2, size, F_DREG | F_VOL);
    ap1 = gen_expr(parms->v.p[1]->v.p[0], FALSE, FALSE, 2);
    if (ap1->mode != am_dreg || ap1->preg != EDX)
    {
        freeop(ap1);
        if (regs[2])
        {
            pushed = TRUE;
            gen_push(EDX, am_dreg, 0);
        }
        gen_codes(op_mov, 2, makedreg(EDX), ap1);
    }
    switch (size)
    {
        case 1:
            gen_code(op_out, dxreg, alreg);
            break;
        case 2:
            gen_code(op_out, dxreg, axreg);
            break;
    }
    if (pushed)
        gen_pop(EDX, am_dreg, 0);
    if (pushedax)
    {
        gen_pop(EAX, am_dreg, 0);
        regs[0]++;
    }
    return ap1;
}

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

AMODE *HandleIntrins(ENODE *node, int novalue)
{
    ENODE *parms = node->v.p[1]->v.p[1]->v.p[0];
    AMODE *ap1,  *ap2,  *ap3;
    SYM *sp;
    int xchg = FALSE;
    if (prm_intrinsic && (node->v.p[1]->v.p[0]->nodetype == en_nacon || node
        ->v.p[1]->v.p[0]->nodetype == en_napccon) && ((sp = node->v.p[1]
        ->v.p[0]->v.sp)->tp->cflags &DF_INTRINS))
    {
        switch (sp->value.i)
        {
            case 1:
                 /* abs */
                if (!oneparm(parms))
                    return 0;
                ap1 = gen_expr(parms->v.p[0], 0, 0, 4);
                do_extend(ap1, ap1->length, F_DREG | F_VOL);
                if (ap1->preg != EAX)
                {
                    gen_code(op_xchg, ap1, makedreg(EAX));
                    xchg = TRUE;
                }
                if (regs[2])
                    gen_push(EDX, am_dreg, 0);
                gen_code(op_cdq, 0, 0);
                gen_code(op_xor, makedreg(EAX), edxreg);
                gen_code(op_sub, makedreg(EAX), edxreg);
                if (regs[2])
                    gen_pop(EDX, am_dreg, 0);
                if (xchg)
                    gen_code(op_xchg, ap1, makedreg(EAX));
                return ap1;
            case 2:
                 /* div */
            case 3:
                 /* ldiv */
                break;
            case 4:
                 /* _rotl */
                return roll(parms, 4, op_rol);
            case 5:
                 /* _rotr */
                return roll(parms, 4, op_ror);
            case 6:
                 /* memcmp */
                if (!threeparms(parms))
                    return 0;
                gen_push(ESI, am_dreg, 0);
                gen_push(EDI, am_dreg, 0);
                LoadCX(parms->v.p[0]);
                LoadSIDI(parms->v.p[1], TRUE, FALSE);
                ap1 = xstrcmp();

                return popSIDI(ap1, 0);
            case 7:
                 /* memcpy */
                if (!threeparms(parms))
                    return 0;
                gen_push(ESI, am_dreg, 0);
                gen_push(EDI, am_dreg, 0);
                LoadCX(parms->v.p[0]);
                LoadSIDI(parms->v.p[1], FALSE, FALSE);
                xmove();

                return popSIDI(0, 0);
            case 8:
                 /* memmove */
                break;
            case 9:
                 /* memset */
                if (!threeparms(parms))
                    return 0;
                gen_push(EDI, am_dreg, 0);
                LoadDI(parms->v.p[1]->v.p[1], FALSE);
                ap2 = gen_expr(parms->v.p[1]->v.p[0], FALSE, FALSE, 4);
                do_extend(ap2, 4, F_DREG | F_VOL);
                if (ap2->preg != EAX)
                    gen_code(op_mov, makedreg(EAX), ap2);
                regs[0]++;
                ap1 = gen_expr(parms->v.p[0], FALSE, FALSE, 4);
                do_extend(ap1, 4, F_DREG | F_VOL);
                if (ap1->preg != ECX)
                    gen_code(op_mov, makedreg(ECX), ap1);
                regs[0]--;
                freeop(ap1);
                freeop(ap2);
                xset();
                return popDI(0, 0);
            case 10:
                 /* strcat */
                if (!twoparms(parms))
                    return 0;
                gen_push(ESI, am_dreg, 0);
                gen_push(EDI, am_dreg, 0);
                LoadSIDI(parms, FALSE, TRUE);
                skipdi();
                gen_code(op_xchg, makedreg(ESI), makedreg(EDI));
                gen_push(EDI, am_dreg, 0);
                xstrlen(FALSE);
                gen_pop(EDI, am_dreg, 0);
                gen_code(op_xchg, makedreg(ESI), makedreg(EDI));
                xmove();
                popSIDI(0, 0);
                ap1 = gen_expr(parms->v.p[1]->v.p[0], FALSE, FALSE, 0);
                return ap1;
            case 11:
                 /* strcmp */
                if (!twoparms(parms))
                    return 0;
                gen_push(ESI, am_dreg, 0);
                gen_push(EDI, am_dreg, 0);
                LoadSIDI(parms, TRUE, TRUE);
                gen_push(EDI, am_dreg, 0);
                xstrlen(FALSE);
                gen_pop(EDI, am_dreg, 0);
                ap1 = xstrcmp();
                return popSIDI(ap1, FALSE);
            case 12:
                 /* strcpy */
                if (!twoparms(parms))
                    return 0;
                gen_push(ESI, am_dreg, 0);
                gen_push(EDI, am_dreg, 0);
                LoadSIDI(parms, TRUE, TRUE);
                gen_push(EDI, am_dreg, 0);
                xstrlen(FALSE);
                gen_pop(EDI, am_dreg, 0);
                gen_code(op_xchg, makedreg(ESI), makedreg(EDI));
                xmove();
                popSIDI(0, 0);
                ap1 = gen_expr(parms->v.p[1]->v.p[0], FALSE, FALSE, 0);
                return ap1;
            case 13:
                 /* strlen */
                if (!oneparm(parms))
                    return 0;
                gen_push(EDI, am_dreg, 0);
                LoadDI(parms, FALSE);
                ap1 = xstrlen(TRUE);
                return popDI(ap1, TRUE);
            case 14:
                 /* strncat */
            case 15:
                 /* strncmp */
            case 16:
                 /* strncpy */
            case 17:
                 /* memchr */
            case 18:
                 /* strchr */
            case 19:
                 /* strrchr */
                break;
            case 20:
                 /* inportb */
                return inport(parms, 1);
            case 21:
                 /* inport */
                return inport(parms, 2);
            case 22:
                 /* inp */
                return inport(parms, 1);
            case 23:
                 /* inpw */
                return inport(parms, 2);
            case 24:
                 /* outportb */
                return outport(parms, 1);
            case 25:
                 /* outport */
                return outport(parms, 2);
            case 26:
                 /* outp */
                return outport(parms, 1);
            case 27:
                 /* outpw */
                return outport(parms, 2);
            case 28:
                 /* _crotl */
                return roll(parms, 1, op_rol);
            case 29:
                 /* _crotr */
                return roll(parms, 1, op_ror);
            case 30:
                 /* _disable */
                if (parms)
                    return 0;
                gen_code(op_cli, 0, 0);
                return 1;
            case 31:
                 /* __enable */
                if (parms)
                    return 0;
                gen_code(op_sti, 0, 0);
                return 1;
            case 32:
                 /* inportd */
                return inport(parms, 4);
            case 33:
                 /* outportd */
                return outport(parms, 4);
        }
    }
    if (node->v.p[1]->v.p[0]->nodetype == en_nacon || node->v.p[1]->v.p[0]
        ->nodetype == en_napccon)
        node->v.p[1]->v.p[0]->v.sp->tp->cflags &= ~DF_INTRINS;
    return 0;
}

⌨️ 快捷键说明

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