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

📄 gexpr386.c

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

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

int isshort(ENODE *node)
/*
 *      return true if the node passed can be generated as a short
 *      offset.
 */
{
    return (isintconst(node->nodetype) && (node->v.i >=  - 32768L && node->v.i
        <= 32767L));
}

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

int isbyte(ENODE *node)
/*
 *      return true if the node passed can be evaluated as a byte
 *      offset.
 */
{
    return isintconst(node->nodetype) && ( - 128 <= node->v.i && node->v.i <=
        127);
}

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

static int depth(ENODE *node)
{
    int a, b;
    if (!node)
        return 0;
    switch (node->nodetype)
    {
        case en_structret:
            return 0;
        case en_cl_reg:
            return depth(node->v.p[0]);
        case en_cfi:
        case en_cfc:
        case en_cri:
        case en_crc:
        case en_clri:
        case en_clrc:
        case en_cl:
        case en_cul:
		case en_ci:
		case en_cui:
        case en_cp:
        case en_cfp:
        case en_csp:
        case en_cbool:
        case en_cub:
        case en_cb:
        case en_cuw:
        case en_cw:
        case en_cd:
        case en_cld:
        case en_cf:
        case en_cll:
        case en_cull:
        case en_bits:
        case en_ll_ref:
        case en_ull_ref:
        case en_l_ref:
        case en_ul_ref:
		case en_a_ref:
		case en_ua_ref:
		case en_i_ref:
		case en_ui_ref:
        case en_ub_ref:
        case en_bool_ref:
        case en_b_ref:
        case en_fp_ref:
        case en_uw_ref:
        case en_w_ref:
        case en_longdoubleref:
        case en_doubleref:
        case en_floatref:
        case en_fimaginaryref:
        case en_rimaginaryref:
        case en_lrimaginaryref:
        case en_fcomplexref:
        case en_rcomplexref:
        case en_lrcomplexref:
        case en_substack:
            return 1+depth(node->v.p[0]);
        case en_uminus:
        case en_moveblock:
        case en_stackblock:
        case en_clearblock:
            return 1+depth(node->v.p[0]);
        case en_fimaginarycon:
        case en_rimaginarycon:
        case en_lrimaginarycon:
        case en_fcomplexcon:
        case en_rcomplexcon:
        case en_lrcomplexcon:
        case en_llcon:
        case en_llucon:
        case en_icon:
        case en_lcon:
        case en_lucon:
        case en_iucon:
        case en_boolcon:
        case en_ccon:
        case en_cucon:
        case en_rcon:
        case en_lrcon:
        case en_fcon:
        case en_absacon:
        case en_trapcall:
        case en_labcon:
        case en_nacon:
        case en_autocon:
        case en_autoreg:
        case en_napccon:
        case en_nalabcon:
        case en_tempref:
        case en_regref:
            return 1;
        case en_not:
        case en_compl:
            return 1+depth(node->v.p[0]);
        case en_eq:
        case en_ne:
        case en_lt:
        case en_le:
        case en_gt:
        case en_ge:
        case en_ugt:
        case en_uge:
        case en_ult:
        case en_ule:
        case en_land:
        case en_lor:
        case en_div:
        case en_udiv:
        case en_pdiv:
        case en_mod:
        case en_umod:
        case en_assign:
        case en_refassign:
        case en_lassign:
        case en_asuminus:
        case en_ascompl:
        case en_add:
        case en_sub:
        case en_addstruc:
        case en_umul:
        case en_pmul:
		case en_arrayindex:
        case en_mul:
        case en_and:
        case en_or:
        case en_xor:
        case en_asalsh:
        case en_asarsh:
        case en_alsh:
        case en_arsh:
        case en_arshd:
        case en_asarshd:
        case en_lsh:
        case en_rsh:
        case en_asadd:
        case en_assub:
        case en_asmul:
        case en_asdiv:
        case en_asmod:
        case en_asand:
        case en_asumod:
        case en_asudiv:
        case en_asumul:
        case en_asor:
        case en_aslsh:
        case en_asxor:
        case en_asrsh:
        case en_repcons:
        case en_ainc:
        case en_adec:
		case en_array:
            a = depth(node->v.p[0]);
            b = depth(node->v.p[1]);
            if (a > b)
                return 1+a;
            return 1+b;
        case en_void:
        case en_cond:
        case en_voidnz:
        case en_dvoid:
            return 1+depth(node->v.p[1]);
        case en_conslabel:
        case en_destlabel:
        case en_movebyref:
        case en_addcast:
            return depth(node->v.p[0]);
        case en_sfcall:
        case en_sfcallb:
        case en_scallblock:
        case en_pfcall:
        case en_pfcallb:
        case en_fcall:
        case en_intcall:
        case en_callblock:
        case en_fcallb:
        case en_pcallblock:
        case en_thiscall:
            return 1;
        default:
            DIAG("error in depth routine.");
            return 1;
    }
}

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

void noids(AMODE *ap)
{
    if (ap->mode == am_indispscale)
        if (ap->length == BESZ_QWORD || ap->length ==  - BESZ_QWORD)
            do_extend(ap, ap->length, F_AXDX);
        else
            do_extend(ap, ap->length, F_DREG | F_VOL);
}

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

AMODE *indx_data(AMODE *ap)
{
    // we have to go to all this work to prevent accidental pops
    AMODE *ap3 = 0, ap4, ap5;
    int preg, sreg;
    memset(&ap4, 0, sizeof(ap4));
    ap4.mode = am_none;
    if (ap->mode != am_indispscale)
    {
        DIAG("indx_data: unscaled mode");
        freeop(ap);
        ap3 = temp_data();
    }
    else
    {
        if (ap->preg ==  - 1)
        {
            if (ap->sreg >= 3)
            {
                freeop(ap);
                ap3 = temp_data();
            }
            else
            {
                ap3 = xalloc(sizeof(AMODE));
                ap3->mode = am_dreg;
                ap3->preg = ap->sreg;
            }
        }
        else
        {
            if (ap->preg >= 3)
            {
                if (ap->sreg >= 3)
                {
                    freeop(ap);
                    ap3 = temp_data();
                }
                else
                {
                    ap3 = xalloc(sizeof(AMODE));
                    ap3->mode = am_dreg;
                    ap3->preg = ap->sreg;
                }
            }
            else
            {
                ap3 = xalloc(sizeof(AMODE));
                ap3->mode = am_dreg;
                ap3->preg = ap->preg;
                ap4.mode = am_dreg;
                ap4.preg = ap->sreg;
            }
        }
    }
    ap3->length = BESZ_DWORD ;
    gen_codes(op_lea, BESZ_DWORD , ap3, ap);
    ap3->seg = ap->seg;
    freeop(&ap4);
    ap3->mode = am_indisp;
    ap3->offset = makeintnode(en_icon, 0);
    return ap3;
}

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

AMODE *doindex(ENODE *node, enum e_node type)
{
    AMODE *ap,  *ap3;
    ENODE node2;
    int scale;
    switch (node->nodetype)
    {
        case en_icon:
            ap = gen_expr(node, FALSE, TRUE, BESZ_DWORD );
            break;
        case en_lsh:
            if ((scale = node->v.p[1]->v.i) < 4 && scale)
            {
                ap = gen_expr(node->v.p[0], FALSE, TRUE, BESZ_DWORD );
                if (node->v.p[0]->nodetype == en_bits)
                    ap = bit_load(ap, node->v.p[0]);
                if (ap->mode != am_immed)
                    do_extend(ap, BESZ_DWORD , F_DREG);
                if (ap->mode == am_immed)
                {
                    while (--scale)
                        ap->offset->v.i <<= 1;
                }
                else
                {
                    do_extend(ap, BESZ_DWORD , 0);
                    ap->mode = am_indispscale;
                    ap->sreg = ap->preg;
                    ap->preg =  - 1;
                    ap->scale = scale;
                    ap->offset = makeintnode(en_icon, 0);
                }
                break;
            }
        default:
            node2.v.p[0] = node;
            node2.nodetype = type;
            ap = gen_deref(&node2, BESZ_DWORD );
            switch (ap->mode)
            {
            default:
                break;
            case am_indispscale:
                if (ap->sreg >= 0 && ap->preg >= 0)
                {
                    ap = indx_data(ap);
                }
            }

            break;
    }
    return ap;
}

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

AMODE *gen_index(ENODE *node)
/*
 *      generate code to evaluate an index node (^+) and return
 *      the addressing mode of the result. This routine takes no
 *      flags since it always returns either am_ind or am_indx.
 */
{
    AMODE *ap1,  *ap2,  *ap,  *ap3;
    ENODE node2;

    int a = depth(node->v.p[1]) - depth(node->v.p[0]);
    int nsize;
    if (a <= 2)
    {
        ap1 = doindex(node->v.p[0], node->nodetype);
        nsize = natural_size(node->v.p[1]);
        if (nsize == BESZ_QWORD || nsize ==  - BESZ_QWORD)
            aprtocx(ap1);
        ap2 = doindex(node->v.p[1], node->nodetype);
    }
    else
    {
        ap2 = doindex(node->v.p[1], node->nodetype);
        nsize = natural_size(node->v.p[0]);
        if (nsize == BESZ_QWORD || nsize ==  - BESZ_QWORD)
            aprtocx(ap2);
        ap1 = doindex(node->v.p[0], node->nodetype);
    }
    switch (ap1->mode)
    {
        case am_dreg:
            switch (ap2->mode)
            {
            case am_dreg:
                do_extend(ap1, BESZ_DWORD , 0);
                ap1->sreg = ap2->preg;
                ap1->scale = 0;
                ap1->mode = am_indispscale;
                ap1->offset = makeintnode(en_icon, 0);
                if (!ap1->seg)
                    ap1->seg = ap2->seg;
                return ap1;
            case am_immed:
            case am_direct:
                ap2->preg = ap1->preg;
                ap2->mode = am_indisp;
                if (!ap2->seg)
                    ap2->seg = ap1->seg;
                return ap2;
            case am_indisp:
                ap2->sreg = ap2->preg;
                ap2->preg = ap1->preg;
                ap2->mode = am_indispscale;
                ap2->offset = ap1->offset;
                ap2->scale = 0;
                if (!ap2->seg)
                    ap2->seg = ap1->seg;
                return ap2;
            case am_indispscale:
                if (ap2->preg ==  - 1)
                {
                    ap2->preg = ap1->preg;
                    if (!ap2->seg)
                        ap2->seg = ap1->seg;
                    return ap2;
                }
                ap = indx_data(ap2);
                ap->sreg = ap1->preg;
                ap->mode = am_indispscale;

⌨️ 快捷键说明

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