📄 peep68.c
字号:
/*
* 68K/386 32-bit C compiler.
*
* copyright (c) 1997, David Lindauer
*
* This compiler is intended for educational use. It may not be used
* for profit without the express written consent of the author.
*
* It may be freely redistributed, as long as this notice remains intact
* and either the original sources or derived sources
* are distributed along with any executables derived from the originals.
*
* The author is not responsible for any damages that may arise from use
* of this software, either idirect or consequential.
*
* v1.35 March 1997
* David Lindauer, gclind01@starbase.spd.louisville.edu
*
* Credits to Mathew Brandt for original K&R C compiler
*
*/
/*
* peepcode optimizations
*/
#include <stdio.h>
#include "expr.h"
#include "c.h"
#include "gen68.h"
#include "diag.h"
extern SYM *currentfunc;
OCODE *peep_head = 0,
*peep_tail = 0,
*peep_insert;
extern int prm_buggyclr;
void peepini(void)
{
peep_head = peep_tail = 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->tempflag = ap->tempflag;
newap->offset = ap->offset;
return newap;
}
void gen_code(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;
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);
}
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_code(op_move,4,ap3,ap2);
if (om == am_ainc)
gen_code(op_add,4,ap4,ap3);
else
gen_code(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_code(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_code(op_add,4,ap3,ap2);
}
else
gen_code(op_lea,size,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_code(op_add,4,ap3,ap2);
}
else
gen_code(op_lea,0,ap1,ap2);
}
else
gen_code(op_lea,0,ap1,ap2);
}
else
gen_code(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->oper1 = (AMODE *)stmt->label;
new->oper2 = 0;
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_code(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 = 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 */
while( peep_head != 0 )
{
if( peep_head->opcode == op_label )
put_label(peep_head);
else
if (peep_head->opcode == op_funclabel)
gen_strlab(peep_head->oper1);
else
put_code(peep_head);
peep_head = peep_head->fwd;
}
/* oc_reorgfunc(); */
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;
if (ip->noopt)
return;
if (ip->oper2->mode == am_areg)
ip->opcode = op_movea;
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->noopt)
return;
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;
}
}
}
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -