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

📄 peep68.c

📁 一个c compiler的source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -