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