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

📄 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 页
字号:
/* 
Copyright 1994-2003 Free Software Foundation, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  

This program is derived from the cc68k complier by 
Matthew Brandt (mattb@walkingdog.net) 

You may contact the author of this derivative at:

mailto::camille@bluegrass.net

or by snail mail at:

David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
 */
/*
 * peepcode optimizations
 * 26-Aug-1999 (SJS) Some changes for ColdFire instructions.
 * 28-Aug-1999 (SJS) 68020 compile now allowed with ColdFire restrictions on
 *	baseindex modes implemented in gen_code(). This is not the most elegant
 *	solution, but if someone wants to re-do gen_index() in gexpr68.c, please
 *	feel free...
 * 23-Oct-99 (SJS) Fixed enforcer hits with baseoffset checking in gen_code().
 * 07-jul-2001 (DAL) moved the 28 aug fixed to gen_index()
 */
#include <stdio.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "gen68.h"
#include "diag.h"

extern int prm_coldfire;
extern int prm_asmfile;
extern SYM *currentfunc;
extern int nextlabel;
extern int prm_peepopt;

OCODE *peep_head = 0, *peep_tail = 0, *peep_insert;

extern int prm_buggyclr;

void peepini(void)
{
    peep_head = peep_tail = peep_insert = 0;
}

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

AMODE *copy_addr(AMODE *ap)
/*
 *      copy an address mode structure (these things dont last).
 */
{
    AMODE *newap;
    if (ap == 0)
        return 0;
    newap = xalloc(sizeof(AMODE));
    newap->mode = ap->mode;
    newap->preg = ap->preg;
    newap->sreg = ap->sreg;
    newap->scale = ap->scale;
    newap->length = ap->length;
    newap->tempflag = ap->tempflag;
    newap->offset = ap->offset;
    return newap;
}

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

void gen_code(int op, AMODE *ap1, AMODE *ap2)
/*
 *      generate a code sequence into the peep list.
 */
{
    OCODE *new;
    new = xalloc(sizeof(OCODE));
    new->opcode = op;
    new->noopt = FALSE;
    if (ap1)
        if (ap1->length < 0)
            new->length =  - ap1->length;
        else
            new->length = ap1->length;
        else
            new->length = 0;
    new->oper1 = copy_addr(ap1);
    new->oper2 = copy_addr(ap2);
    new->oper3 = 0;
    add_peep(new);
}

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

AMODE *gen_codes(int op, int len, AMODE *ap1, AMODE *ap2)
/*
 *      generate a code sequence into the peep list.
 */
{
    OCODE *new;
    new = xalloc(sizeof(OCODE));
    new->opcode = op;
    new->noopt = FALSE;
    if (len < 0)
        new->length =  - len;
    else
        new->length = len;
    new->oper1 = copy_addr(ap1);
    new->oper2 = copy_addr(ap2);
    new->oper3 = 0;
    add_peep(new);
    return new;
}

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

void gen_coden(int op, int len, AMODE *ap1, AMODE *ap2)
{
    OCODE *new = gen_codes(op, len, ap1, ap2);
    new->noopt = TRUE;
}

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

void gen_branch(int op, AMODE *ap1)
{
    gen_code(op, ap1, 0);
}

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

void gen_1branch(int op, AMODE *ap1)
{
    gen_codes(op, 1, ap1, 0);
}

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

void gen_codeb(int op, int len, AMODE *ap1, AMODE *ap2)
/*
 *   		move ap1 to dreg if we don't have a valid pair for math functions
 */
{
    AMODE *ap = ap1;
    if (ap1->mode != am_dreg && (ap2->mode != am_dreg && ap2->mode != am_areg))
    {
        ap = temp_data();
        gen_codes(op_move, len, ap1, ap);
    }
    gen_codes(op, len, ap, ap2);
    if (ap != ap1)
        freeop(ap);
}

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

void gen_lea(int size, AMODE *ap1, AMODE *ap2)
{
    AMODE *ap3,  *ap4;
    if (ap1->mode == am_ainc || ap1->mode == am_adec)
    {
        enum e_am om = ap1->mode;
        if (!size)
        {
            size = 1;
            DIAG("Illegal len in autoinc lea");
        } if (size < 0)
            size =  - size;
        ap1->mode = am_ind;
        ap3 = copy_addr(ap1);
        ap3->mode = am_areg;
        ap4 = make_immed(size);
        gen_codes(op_move, 4, ap3, ap2);
        if (om == am_ainc)
            gen_codes(op_add, 4, ap4, ap3);
        else
            gen_codes(op_sub, 4, ap4, ap3);
        ap1->mode = om;
    }
    else
    if (ap2->mode == am_areg)
    {
        if (ap1->mode == am_baseindxaddr && !ap1->scale)
        {
            if (ap1->preg == ap2->preg && !ap1->offset->v.i)
            {
                ap3 = xalloc(sizeof(AMODE));
                ap3->mode = am_areg;
                ap3->preg = ap1->sreg;
                gen_codes(op_add, 4, ap3, ap2);
            }
            else if (ap1->sreg == ap2->preg && !ap1->offset->v.i)
            {
                ap3 = xalloc(sizeof(AMODE));
                ap3->mode = am_areg;
                ap3->preg = ap1->preg;
                gen_codes(op_add, 4, ap3, ap2);
            }
            else
                gen_codes(op_lea, 0, ap1, ap2);
        }
        else if (ap1->mode == am_baseindxdata && !ap1->offset->v.i && !ap1
            ->scale)
        {
            if (ap1->preg == ap2->preg)
            {
                ap3 = xalloc(sizeof(AMODE));
                ap3->mode = am_dreg;
                ap3->preg = ap1->sreg;
                gen_codes(op_add, 4, ap3, ap2);
            }
            else
                gen_codes(op_lea, 0, ap1, ap2);
        }
        else
            gen_codes(op_lea, 0, ap1, ap2);
    }
    else
        gen_codes(op_lea, 0, ap1, ap2);
}

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

void gen_codelab(SYM *lab)
/*
 *      generate a code sequence into the peep list.
 */
{
    OCODE *new;
    new = xalloc(sizeof(OCODE));
    new->opcode = op_funclabel;
    new->length = 0;
    new->oper1 = lab;
    new->oper2 = 0;
    new->oper3 = 0;
    add_peep(new);
}

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

void gen_line(SNODE *stmt)
{
    OCODE *new = xalloc(sizeof(OCODE));
    new->opcode = op_line;
    new->length = (int)stmt->exp;
    new->oper2 = (AMODE*)((int)stmt->s1);
    new->oper1 = (AMODE*)stmt->label;
    new->oper3 = 0;
    add_peep(new);
}

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

void gen_codef(int op, int len, AMODE *ap1, AMODE *ap2)
{
    if (ap1->mode == am_freg)
    {
        if (!ap2 || ap2->mode == am_freg)
            len = 10;
    }
    else if (ap2 && ap2->mode == am_freg)
    {
        if (ap1->mode == am_immed)
            len = 10;
    }
    gen_codes(op, len, ap1, ap2);
}

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

void gen_code3(int op, int len, AMODE *ap1, AMODE *ap2, AMODE *ap3)
{
    OCODE *new;
    new = xalloc(sizeof(OCODE));
    new->opcode = op;
    if (len < 0)
        new->length =  - len;
    else
        new->length = len;
    new->oper1 = copy_addr(ap1);
    new->oper2 = copy_addr(ap2);
    new->oper3 = copy_addr(ap3);
    add_peep(new);
}

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

void add_peep(OCODE *new)
/*
 *      add the ocoderuction pointed to by new to the peep list.
 */
{
    if (peep_head == 0)
    {
        peep_head = peep_tail = peep_insert = new;
        new->fwd = 0;
        new->back = 0;
    }
    else
    {
        new->fwd = 0;
        new->back = peep_tail;
        peep_tail->fwd = new;
        peep_tail = new;
    }
}

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

void gen_label(int labno)
/*
 *      add a compiler generated label to the peep list.
 */
{
    OCODE *new;
    new = xalloc(sizeof(OCODE));
    new->opcode = op_label;
    new->oper1 = (AMODE*)labno;
    add_peep(new);
}

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

void flush_peep(void)
/*
 *      output all code and labels in the peep list.
 */
{
    opt3(); /* do the peephole optimizations */
    opt3();

    if (peep_head)
        outcode_gen(peep_head);
    if (prm_asmfile)
    {
        while (peep_head != 0)
        {
            switch (peep_head->opcode)
            {
                case op_label:
                    put_label((int)peep_head->oper1);
                    break;
                case op_funclabel:
                    gen_strlab(peep_head->oper1);
                    break;
                default:
                    put_code(peep_head);
                    break;

            }
            peep_head = peep_head->fwd;
        }
    }
    peep_head = 0;
}

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

void peep_move(OCODE *ip)
/*
 *      peephole optimization for move instructions.
 *      makes quick immediates when possible.
 *      changes move #0,d to clr d.
 *      changes long moves to address registers to short when
 *              possible.
 *      changes move immediate to stack to pea.
 */
{
    ENODE *ep;
    /* SCREEN out moves to self */
    if (equal_address(ip->oper1, ip->oper2))
    {
        ip->fwd->back = ip->back;
        ip->back->fwd = ip->fwd;
        return ;
    }
    if (ip->oper2->mode == am_areg)
        ip->opcode = op_movea;
    /* get rid of extraneous temp regs */
    if (!prm_coldfire && ip->oper2->mode == am_dreg)
    if (ip->fwd && ip->fwd->opcode == op_move && ip->fwd->oper1->mode ==
        am_dreg && ip->fwd->oper1->preg == ip->oper2->preg && ip->length == ip
        ->fwd->length)
    {
        ip->oper2 = ip->fwd->oper2;
        ip->fwd->fwd->back = ip;
        ip->fwd = ip->fwd->fwd;
    }
    if (ip->oper1->mode != am_immed)
        return ;
    ep = ip->oper1->offset;
    if (!isintconst(ep->nodetype))
        return ;
    if (ip->oper2->mode == am_areg)
    {
        if ( - 32768L <= ep->v.i && ep->v.i <= 32768L)
            ip->length = 2;
    }
    else if (ip->oper2->mode == am_dreg)
    {
        if ( - 128 <= ep->v.i && ep->v.i <= 127)
        {
            ip->opcode = op_moveq;
            ip->length = 0;
        }
    }
    else
    {
        if (ep->v.i == 0 && !prm_buggyclr)
        {
            ip->opcode = op_clr;
            ip->oper1 = ip->oper2;
            ip->oper2 = 0;
        }
        else if (ip->oper2->mode == am_adec && ip->oper2->preg == 7)
        {
            ip->opcode = op_pea;
            ip->length = 0;
            ip->oper1->mode = am_direct;
            ip->oper2 = 0;
        }
    }
}

/*
 * get rid of a TST after any other instruction that sets flags if the
 * args match
 */
int peep_tst(OCODE *ip)
{
    if (ip->back->opcode == op_move || ip->back->opcode == op_and || ip->back
        ->opcode == op_or || ip->back->opcode == op_andi || ip->back->opcode ==
        op_ori || ip->back->opcode == op_add || ip->back->opcode == op_addi ||
        ip->back->opcode == op_addq || ip->back->opcode == op_sub || ip->back
        ->opcode == op_subi || ip->back->opcode == op_subq)
    {
        if (equal_address(ip->back->oper2, ip->oper1))
        {
            ip->back->fwd = ip->fwd;
            ip->fwd->back = ip->back;
        }

⌨️ 快捷键说明

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