📄 peep68.c
字号:
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->noopt)
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;
else
{
if( isshort(ep) )
ip->length = 2;
}
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->noopt)
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;
else
{
if( isshort(ep) )
ip->length = 2;
}
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->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_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->noopt)
return;
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).
*/
{ int shcnt;
if (ip->noopt)
return;
if( ip->oper1->mode != am_immed )
return;
if(!isintconst( ip->oper1->offset->nodetype ))
return;
shcnt = ip->oper1->offset->v.i;
/* vax c doesn't do this type of switch well */
if( shcnt == 2) shcnt = 1;
else if( shcnt == 4) shcnt = 2;
else if( shcnt == 8) shcnt = 3;
else if( shcnt == 16) shcnt = 4;
else if( shcnt == 32) shcnt = 5;
else if( shcnt == 64) shcnt = 6;
else if( shcnt == 128) shcnt = 7;
else if( shcnt == 256) shcnt = 8;
else if( shcnt == 512) shcnt = 9;
else if( shcnt == 1024) shcnt = 10;
else if( shcnt == 2048) shcnt = 11;
else if( shcnt == 4096) shcnt = 12;
else if( shcnt == 8192) shcnt = 13;
else if( shcnt == 16384) shcnt = 14;
else return;
ip->oper1->offset->v.i = shcnt;
ip->opcode = op;
ip->length = 4;
}
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->opcode == op_label || curpos->opcode == op_line);
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 (ip->noopt)
return;
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;
while( ip != 0 )
{
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;
}
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_and:
if (ip->oper1->mode == am_immed)
ip->opcode = op_andi;
break;
case op_or:
if (ip->oper1->mode == am_immed)
ip->opcode = op_ori;
break;
case op_eor:
if (ip->oper1->mode == am_immed)
ip->opcode = op_eori;
break;
case op_muls:
peep_muldiv(ip,op_asl);
break;
case op_label:
peep_label(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 + -