📄 peep68.c
字号:
/*
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 + -