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

📄 peep68.c

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

/*
 * this returns the address of a single bit, or -1
 */
int single_bit(int val)
{
    unsigned long v = 1, t = val;
    int i;
    for (i = 0; i < 32; i++, v <<= 1)
    {
        if (v > t)
            return  - 1;
        if (v == t)
            return i;
    }
    return  - 1;

}

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

int equal_address(AMODE *ap1, AMODE *ap2)
/*
 *      compare two address nodes and return true if they are
 *      equivalent.
 */
{
    if (ap1 == 0 || ap2 == 0)
        return 0;
    if (ap1->mode != ap2->mode)
        return 0;
    switch (ap1->mode)
    {
        case am_areg:
        case am_dreg:
        case am_ainc:
        case am_adec:
            return ap1->preg == ap2->preg;
        case am_baseindxaddr:
        case am_baseindxdata:
        case am_indx:
            if (ap1->preg != ap2->preg)
                return FALSE;
            if (ap1->sreg != ap2->sreg)
                return FALSE;
            return equalnode(ap1->offset, ap2->offset);
        case am_immed:
        case am_direct:
        case am_adirect:
        case am_pcindx:
            return equalnode(ap1->offset, ap2->offset);
    }
    return 0;
}

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

void peep_add(OCODE *ip)
/*
 *      peephole optimization for add instructions.
 *      makes quick immediates out of small constants.
 */
{
    ENODE *ep;
    if (ip->oper1->mode == am_immed && ip->oper1->offset->v.i == 0)
    {
        ip->back->fwd = ip->fwd;
        ip->fwd->back = ip->back;
        return ;
    }
    if (ip->oper2->mode == am_areg)
        ip->opcode = op_adda;
    if (ip->oper1->mode != am_immed)
        return ;
    ep = ip->oper1->offset;
    if (ip->oper2->mode != am_areg)
        ip->opcode = op_addi;
    #ifdef XXXXX
        else
        {
            if (isshort(ep))
                ip->length = 2;
        }
    #endif 
    if (!(isintconst(ep->nodetype)))
        return ;
    if (1 <= ep->v.i && ep->v.i <= 8)
        ip->opcode = op_addq;
    else if ( - 8 <= ep->v.i && ep->v.i <=  - 1)
    {
        ip->opcode = op_subq;
        ep->v.i =  - ep->v.i;
    }
}

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

void peep_sub(OCODE *ip)
/*
 *      peephole optimization for subtract instructions.
 *      makes quick immediates out of small constants.
 */
{
    ENODE *ep;
    if (ip->oper1->mode == am_immed && ip->oper1->offset->v.i == 0)
    {
        ip->back->fwd = ip->fwd;
        ip->fwd->back = ip->back;
        return ;
    }
    if (ip->oper2->mode == am_areg)
        ip->opcode = op_suba;
    if (ip->oper1->mode != am_immed)
        return ;
    ep = ip->oper1->offset;
    if (ip->oper2->mode != am_areg)
        ip->opcode = op_subi;
    #ifdef XXXXX
        else
        {
            if (isshort(ep))
                ip->length = 2;
        }
    #endif 
    if (!isintconst(ep->nodetype))
        return ;
    if (1 <= ep->v.i && ep->v.i <= 8)
    {
        ip->opcode = op_subq;
        if (ip->oper2->mode == am_areg && ip->length <= 4 && ip->fwd->opcode !=
            op_line && ip->fwd->opcode != op_label && ip->fwd->oper1 && ip->fwd
            ->oper1->mode == am_ind && ip->oper2->preg == ip->fwd->oper1->preg)
        {
            int sz1 = ip->fwd->length;
            int sz2 = ep->v.i;
            if (sz1 < 0)
                sz1 =  - sz1;
            if (sz2 < 0)
                sz2 =  - sz2;
            if (sz2 == sz1)
            {
                ip->back->fwd = ip->fwd;
                ip->fwd->back = ip->back;
                ip->fwd->oper1->mode = am_adec;
            }
        }
    }
    else if ( - 8 <= ep->v.i && ep->v.i <=  - 1)
    {
        ip->opcode = op_addq;
        ep->v.i =  - ep->v.i;
    }
}

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

void peep_andi(OCODE *ip)
{
    OCODE *ipf = ip->fwd;
    if (ipf->opcode != op_andi)
        return ;
    if (ip->oper1->mode != am_immed || ipf->oper1->mode != am_immed)
        return ;
    if (!equal_address(ip->oper2, ipf->oper2))
        return ;
    ip->oper1->offset->v.i &= ipf->oper1->offset->v.i;
    ipf->back->fwd = ipf->fwd;
    ipf->fwd->back = ipf->back;
}

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

void peep_cmp(OCODE *ip)
/*
 *      peephole optimization for compare instructions.
 *      changes compare #0 to tst and if previous instruction
 *      should have set the condition codes properly delete.
 *      return value is true if instruction was deleted.
 */
{
    OCODE *prev = 0;
    ENODE *ep;
    if (ip->oper2->mode == am_areg)
        ip->opcode = op_cmpa;
    if (ip->oper1->mode == am_immed)
    {
        ep = ip->oper1->offset;
        if (ip->oper2->mode == am_areg)
        {
            if (isshort(ep))
                ip->length = 2;
            return ;
        }
        ip->opcode = op_cmpi;
        if (isintconst(ep->nodetype) && ep->v.i == 0)
        {
            if (ip->fwd->opcode == op_bne || ip->fwd->opcode == op_beq)
            {
                ip->oper1 = ip->oper2;
                ip->oper2 = 0;
                ip->opcode = op_tst;
                prev = ip->back;
            }
        }
    }
    if (prev == 0)
        return ;
    if ((((prev->opcode == op_move || prev->opcode == op_moveq || prev->opcode 
        == op_add || prev->opcode == op_addi || prev->opcode == op_sub || prev
        ->opcode == op_subi || prev->opcode == op_addq || prev->opcode ==
        op_subq) && equal_address(prev->oper1, ip->oper1)) && prev->oper2->mode
        != am_areg) || (prev->opcode != op_label && equal_address(prev->oper2,
        ip->oper1)))
    {
        prev->fwd = ip->fwd;
        if (prev->fwd != 0)
            prev->fwd->back = prev;
    }
}

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

void peep_muldiv(OCODE *ip, int op)
/*
 *      changes multiplies and divides by convienient values
 *      to shift operations. op should be either op_asl or
 *      op_asr (for divide).
 */
{
    long shcnt;
    if (ip->oper1->mode != am_immed)
        return ;
    if (!isintconst(ip->oper1->offset->nodetype))
        return ;
    shcnt = pwrof2(ip->oper1->offset->v.i);
    if (shcnt ==  - 1)
        return ;
    ip->oper1->offset->v.i = shcnt;
    ip->opcode = op;
    ip->length = 4;
}

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

void peep_lea(OCODE *ip)
{
    OCODE *ip1 = ip->fwd;
    if (ip1->opcode == op_move && ip1->oper1->mode == am_areg && ip1->oper1
        ->preg == ip->oper2->preg)
    if (ip1->oper2->mode == am_adec && ip1->oper2->preg == 7)
    {
        ip->opcode = op_pea;
        ip->oper2 = 0;
        ip->fwd = ip1->fwd;
        ip1->fwd->back = ip;
    }
}

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

void peep_uctran(OCODE *ip)
/*
 *      peephole optimization for unconditional transfers.
 *      deletes instructions which have no path.
 *      applies to bra, jmp, and rts instructions.
 */
{
    while (ip->fwd != 0 && ip->fwd->opcode != op_label)
    {
        ip->fwd = ip->fwd->fwd;
        if (ip->fwd != 0)
            ip->fwd->back = ip;
    }
}

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

void peep_label(OCODE *ip)
/*
 *		peephole optimization for labels
 *		deletes relbranches that jump to the next instruction
 */
{
    OCODE *curpos,  *index;
    curpos = ip;

    if (!curpos->back)
        return ;
    do
    {
        curpos = curpos->back;
    }
    while (curpos && (curpos->opcode == op_label || curpos->opcode == op_line));
    if (!curpos)
        return ;
    while ((curpos->opcode == op_bra) || curpos->opcode == op_cmp || curpos
        ->opcode == op_cmpi || curpos->opcode == op_tst || (curpos->opcode ==
        op_bne) || (curpos->opcode == op_beq) || (curpos->opcode == op_bge) || 
        (curpos->opcode == op_ble) || (curpos->opcode == op_bgt) || (curpos
        ->opcode == op_blt) || (curpos->opcode == op_bhs) || (curpos->opcode ==
        op_bls) || (curpos->opcode == op_bhi) || (curpos->opcode == op_blo))
    {
        index = curpos->fwd;
        if ((curpos->opcode == op_cmpi || curpos->opcode == op_cmp || curpos
            ->opcode == op_tst))
        {
            if (curpos->fwd->opcode == op_label)
            {
                curpos->back->fwd = curpos->fwd;
                curpos->fwd->back = curpos->back;
                curpos = curpos->back;
            }
            else
                break;
        }
        else
        {
            do
            {
                if ((index->opcode == op_label) && (curpos->oper1->mode ==
                    am_direct) && ((int)index->oper1 == curpos->oper1->offset
                    ->v.i))
                {
                    curpos->back->fwd = curpos->fwd;
                    curpos->fwd->back = curpos->back;
                    curpos = curpos->back;
                    break;
                }
                index = index->fwd;
            }
            while (index != ip->fwd);
            if (index == ip->fwd)
                break;
        }
        while (curpos->opcode == op_label || curpos->opcode == op_line)
            curpos = curpos->back;
    }
}

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

void opt3(void)
/*
 *      peephole optimizer. This routine calls the instruction
 *      specific optimization routines above for each instruction
 *      in the peep list.
 */
{
    OCODE *ip = peep_head;
    if (!prm_peepopt)
        return ;
    while (ip != 0)
    {
        if (!ip->noopt)
        {
            if (ip->opcode != op_line && ip->opcode != op_label && ip->opcode 
                != op_slit)
            {
                if (ip->oper1 && ip->oper1->mode == am_indx && ip->oper1
                    ->offset->v.i == 0)
                    ip->oper1->mode = am_ind;
                if (ip->oper2 && ip->oper2->mode == am_indx && ip->oper2
                    ->offset->v.i == 0)
                    ip->oper2->mode = am_ind;
            }
            // Fix references to FP regs to use size 'X'
            switch (ip->opcode)
            {
                case op_line:
                case op_label:
                case op_seqx:
                case op_slit:
                case op_funclabel:
                case op_genword:
                case op_void:
                case op_dcl:
                case op_dcr:
                case op_blockstart:
                case op_blockend:
                    break;
                default:
                    if (ip->oper1)
                        if (ip->oper1->mode == am_freg)
                            if (!ip->oper2 || ip->oper2->mode == am_freg)
                                ip->length = 10;
                    break;
            }
            switch (ip->opcode)
            {
                case op_move:
                    peep_move(ip);
                    break;
                case op_add:
                    peep_add(ip);
                    break;
                case op_sub:
                    peep_sub(ip);
                    break;
                case op_tst:
                    peep_tst(ip);
                    break;
                case op_cmp:
                    peep_cmp(ip);
                    break;
                case op_andi:
                    peep_andi(ip);
                    break;
                case op_and:
                    if (ip->oper1->mode == am_immed)
                    {
                        ip->opcode = op_andi;
                        if (ip->oper1->offset->v.i == 0)
                            ip->opcode = op_move;
                    }
                    break;
                case op_or:
                    if (ip->oper1->mode == am_immed)
                    {
                        ip->opcode = op_ori;
                        if (ip->oper1->offset->v.i == 0)
                        {
                            ip->back->fwd = ip->fwd;
                            ip->fwd->back = ip->back;
                        }
                    }
                    break;
                case op_eor:
                    if (ip->oper1->mode == am_immed)
                    {
                        ip->opcode = op_eori;
                        if (ip->oper1->offset->v.i == 0)
                        {
                            ip->back->fwd = ip->fwd;
                            ip->fwd->back = ip->back;
                        }
                    }
                    break;
                case op_muls:
                    peep_muldiv(ip, op_asl);
                    break;
                case op_label:
                    peep_label(ip);
                    break;
                case op_lea:
                    peep_lea(ip);
                    break;
                case op_bra:
                case op_jmp:
                case op_rts:
                    peep_uctran(ip);
            }
        }
        ip = ip->fwd;
    }
}

⌨️ 快捷键说明

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