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

📄 peepx86.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * C compiler * ========== * * Copyright 1989, 1990, 1991 Christoph van Wuellen. * Credits to Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. * * History: * * 1989   starting an 68000 C compiler, starting with material *		  originally by M. Brandt * 1990   68000 C compiler further bug fixes *		  started i386 port (December) * 1991   i386 port finished (January) *		  further corrections in the front end and in the 68000 *		  code generator. *		  The next port will be a SPARC port *//*****************************************************************************/#include "config.h"#ifdef INTEL#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "genx86.h"#include "outproto.h"/********************************************************* Macro Definitions */#define DEST_MODIFY ((unsigned char)1)#define DEST_OVERWRITE	((unsigned char)2)#define DEST_ALTERED	(DEST_MODIFY | DEST_OVERWRITE)/* *	  The next two #define statements are to make the *		code in the branch optimisation clearer.  Tests *		have shown that the in-line size cost is about *		the same as making them functions so we keep *		them in-line for speed. */#define is_same_instruction(ip1,ip2) \	((ip1 != NIL_CODE) && (ip2 != NIL_CODE) && \	(ip1->opcode == ip2->opcode) && \	(ip1->length == ip2->length) && \	(is_equal_oper (ip1->oper1, ip2->oper1)) && \	(is_equal_oper (ip1->oper2, ip2->oper2)))/* backup over any sequence of labels to previous instruction */#define previous_instruction(ip) \	do { \	ip = ip->back; \	} while (ip != NIL_CODE && ip->opcode == op_label)#define branch(ip)	(ip->opcode >= op_bra && ip->opcode <= op_jbe)/*********************************************** Static Function Definitions */static CODE *code P_ ((OPCODE, ILEN, ADDRESS *, ADDRESS *));static CODE *find_label P_ ((LABEL));static BOOL is_label_used P_ ((ADDRESS *, LABEL));static BOOL is_address_used P_ ((ADDRESS *, ADDRESS *));static BOOL is_dest_overwritten P_ ((ADDRESS *, CODE *));static void add_peep P_ ((CODE *));static void peep_delete P_ ((CODE *));static void peep_test P_ ((CODE *));static void peep_mov P_ ((CODE *));static void peep_cmp P_ ((CODE *));static void peep_lea P_ ((CODE *));static void peep_xtend P_ ((CODE *));static void peep_addsub P_ ((CODE *, IVAL));static void peep_uctran P_ ((CODE *));static void peep_bxx P_ ((CODE *));static void peep_label P_ ((CODE *));static void peep_line P_ ((CODE *));static void check_label P_ ((CODE *, CODE *));static void peep_bra P_ ((CODE *));static void opt3 P_ ((unsigned));static BOOL is_equal_oper P_ ((ADDRESS *, ADDRESS *));/********************************************************** Static Variables */static unsigned char op_flags[] = {    /* op_movsbl */ DEST_OVERWRITE,    /* op_movzbl */ DEST_OVERWRITE,    /* op_movswl */ DEST_OVERWRITE,    /* op_movzwl */ DEST_OVERWRITE,    /* op_movsbw */ DEST_OVERWRITE,    /* op_movzbw */ DEST_OVERWRITE,    /* op_cdq */ DEST_OVERWRITE,    /* op_cwd */ DEST_OVERWRITE,    /* op_cbw */ DEST_OVERWRITE,    /* op_mov */ DEST_OVERWRITE,    /* op_xchg */ DEST_OVERWRITE,    /* op_lea */ DEST_OVERWRITE,    /* op_not */ DEST_MODIFY,    /* op_neg */ DEST_MODIFY,    /* op_add */ DEST_MODIFY,    /* op_sub */ DEST_MODIFY,    /* op_adc */ DEST_MODIFY,    /* op_sbb */ DEST_MODIFY,    /* op_imul */ DEST_MODIFY,    /* op_idiv */ DEST_MODIFY,    /* op_div */ DEST_MODIFY,    /* op_and */ DEST_MODIFY,    /* op_or */ DEST_MODIFY,    /* op_xor */ DEST_MODIFY,    /* op_inc */ DEST_MODIFY,    /* op_dec */ DEST_MODIFY,    /* op_cmp */ 0,    /* op_push */ 0,    /* op_pop */ DEST_OVERWRITE,    /* op_jmp */ 0,    /* op_loop */ 0,    /* op_call */ 0,    /* op_leave */ DEST_OVERWRITE,    /* op_enter */ 0,    /* op_ret */ 0,    /* op_test */ 0,    /* op_bra */ 0,    /* op_je */ 0,    /* op_jne */ 0,    /* op_jl */ 0,    /* op_jle */ 0,    /* op_jg */ 0,    /* op_jge */ 0,    /* op_ja */ 0,    /* op_jae */ 0,    /* op_jb */ 0,    /* op_jbe */ 0,    /* op_rep */ 0,    /* op_smov */ DEST_OVERWRITE,    /* op_shl */ DEST_MODIFY,    /* op_shr */ DEST_MODIFY,    /* op_asl */ DEST_MODIFY,    /* op_asr */ DEST_MODIFY,    /* op_rol */ DEST_MODIFY,    /* op_ror */ DEST_MODIFY,    /* op_sahf */ DEST_MODIFY,    /* op_sete */ DEST_OVERWRITE,    /* op_setne */ DEST_OVERWRITE,    /* op_setb */ DEST_OVERWRITE,    /* op_setbe */ DEST_OVERWRITE,    /* op_seta */ DEST_OVERWRITE,    /* op_setae */ DEST_OVERWRITE,    /* op_setl */ DEST_OVERWRITE,    /* op_setle */ DEST_OVERWRITE,    /* op_setg */ DEST_OVERWRITE,    /* op_setge */ DEST_OVERWRITE,    /* op_nop */ 0,#ifdef FLOAT_IEEE    /* op_fadd */ 0,    /* op_faddp */ 0,    /* op_fsub */ 0,    /* op_fsubp */ 0,    /* op_fdiv */ 0,    /* op_fdivp */ 0,    /* op_fmul */ 0,    /* op_fmulp */ 0,    /* op_fsubr */ 0,    /* op_fsubrp */ 0,    /* op_fdivr */ 0,    /* op_fdivrp */ 0,    /* op_fld */ 0,    /* op_fldz */ 0,    /* op_fst */ 0,    /* op_fstp */ 0,    /* op_fpop */ 0,    /* op_fild */ 0,    /* op_fildl */ 0,    /* op_fistp */ 0,    /* op_fistpl */ 0,    /* op_ftst */ 0,    /* op_fchs */ 0,    /* op_fcomp */ 0,    /* op_fcompp */ 0,    /* op_fnstsw */ 0,    /* op_fwait */ 0,#endif				/* FLOAT_IEEE */    /* op_line */ 0,    /* op_label */ 0};static CODE *peep_head = NIL_CODE;static CODE *next_ip;static int changes;/*****************************************************************************//* * find the end of a block of code. */static CODE *block_end P1 (CODE *, ip){    int     count = 0;    while ((ip != NIL_CODE) && (ip->opcode != op_bra) &&	   (ip->opcode != op_jmp) && (ip->opcode != op_ret)) {	if (count == BRANCH_COUNT) {	    return NIL_CODE;	}	if (branch (ip)) {	    count++;	}	ip = ip->fwd;    }    return ip;}/* * find the node which contains the label 'lab' */static CODE *find_label P1 (LABEL, lab){    register CODE *ip;    for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) {	if (ip->opcode == op_label && ip->oper1->u.offset->v.l == lab) {	    return ip;	}    }    /* we should have found it */    return NIL_CODE;}/* * Returns false if the <ea> does is not a label or else isn't equal to label */static BOOL is_label_used P2 (ADDRESS *, ap, LABEL, label){    return (ap != NIL_ADDRESS &&	    ap->mode == am_direct &&	    ap->u.offset->nodetype == en_labcon &&	    ap->u.offset->v.l == label);}/* * Returns false if the <ea> of ap1 is not used in the <ea> of ap2, * otherwise it returns true.  If we arn't sure then returns true anyway. */static BOOL is_address_used P2 (ADDRESS *, ap1, ADDRESS *, ap2){    if (ap1 == NIL_ADDRESS || ap2 == NIL_ADDRESS) {	return FALSE;    }    switch (ap1->mode) {    case am_dreg:    case am_areg:	switch (ap2->mode) {	case am_dreg:	case am_areg:	case am_ind:	case am_indx:	case am_indx2:	    return ap2->preg == ap1->preg;	case am_direct:	case am_immed:	case am_line:	    return FALSE;	default:	    break;	}	break;    case am_immed:	return FALSE;    default:	break;    }    return TRUE;}/* * Checks to see if the addressing mode ap is overwritten with a new * value before the value is used. */static BOOL is_dest_overwritten P2 (ADDRESS *, ap, CODE *, ip){    CODE   *ip2, *ip3;    if (ap->mode != am_dreg && ap->mode != am_areg) {	return FALSE;    }    for (ip3 = NIL_CODE, ip2 = ip->fwd; ip2 != NIL_CODE;) {	switch (ip2->opcode) {	case op_leave:	    peep_delete (ip);	    return TRUE;	case op_lea:	    if (ip2->oper2->preg == STACKPTR) {		peep_delete (ip);		return TRUE;	    };	    goto def;	case op_ret:	case op_je:		/* use of SP unknown */	case op_jne:	case op_jl:	case op_jle:	case op_jg:	case op_jge:	case op_ja:	case op_jae:	case op_jb:	case op_jbe:	case op_jmp:	    return FALSE;	case op_call:		/* implicit use of SP */	case op_pop:	case op_push:	    if (ap->preg == STACKPTR) {		return FALSE;	    }	    /*FALLTHRU */	default:	  def:	    if (is_address_used (ap, ip2->oper1)		|| is_address_used (ap, ip2->oper2)) {		return FALSE;	    }	    /*FALLTHRU */	case op_label:	    ip2 = ip2->fwd;	    break;	case op_bra:	    if (ip2 == ip3)	/* check to see if we are looping */		return FALSE;	    ip3 = ip2;		/* remember that we have been here */	    ip2 = find_label (ip2->oper1->u.offset->v.l);	    break;	}    }    return FALSE;}/* * compare two address nodes and return true if they are equivalent. */BOOL is_equal_address P2 (ADDRESS *, ap1, ADDRESS *, ap2){    if (ap1 == NIL_ADDRESS && ap2 == NIL_ADDRESS) {	return TRUE;    }    if (ap1 == NIL_ADDRESS || ap2 == NIL_ADDRESS) {	return FALSE;    }    if (ap1->mode != ap2->mode) {	return FALSE;    }    switch (ap1->mode) {    case am_dreg:    case am_areg:    case am_freg:    case am_ind:	return (ap1->preg == ap2->preg);    case am_indx:	return (ap1->preg == ap2->preg &&		is_equalnode (ap1->u.offset, ap2->u.offset));    case am_indx2:	return (ap1->preg == ap2->preg &&		ap1->sreg == ap2->sreg &&		is_equalnode (ap1->u.offset, ap2->u.offset));    case am_mreg:	return (ap1->preg == ap2->preg && ap1->sreg == ap2->sreg);    case am_direct:	return is_equalnode (ap1->u.offset, ap2->u.offset);    default:	break;    }    return FALSE;}static BOOL is_equal_oper P2 (ADDRESS *, ap1, ADDRESS *, ap2){    if (ap1 == NIL_ADDRESS && ap2 == NIL_ADDRESS) {	return TRUE;    }    if (ap1 == NIL_ADDRESS || ap2 == NIL_ADDRESS) {	return FALSE;    }    if (ap1->mode != ap2->mode) {	return FALSE;    }    switch (ap1->mode) {    case am_dreg:    case am_areg:    case am_ind:	return ap1->preg == ap2->preg;    case am_freg:	return TRUE;    case am_indx:	return ap1->preg == ap2->preg	    && is_equalnode (ap1->u.offset, ap2->u.offset);    case am_direct:	return is_equalnode (ap1->u.offset, ap2->u.offset);    case am_immed:	return ap1->u.offset->v.i == ap2->u.offset->v.i;    default:	break;    }    return FALSE;}/* * Determine whether a move is redundant ... this is done by looking back * along the code list (following all branches to labels) to determine * whether the destination already contains the necessary result. */static BOOL was_move_redundant P3 (CODE *, ip, CODE *, ip2, BOOL, memory){    BOOL    altered, overwritten;    LABEL   label;    SWITCH *sw;    for (ip2 = ip2->back; ip2 != NIL_CODE; ip2 = ip2->back) {	switch (ip2->opcode) {	case op_label:	    label = ip2->oper1->u.offset->v.l;	    /* first check code before the label */	    if (!was_move_redundant (ip, ip2, memory)) {		return FALSE;	    }	    /* ... and then check all branches to this label */	    for (ip2 = peep_head; ip2 != NIL_CODE; ip2 = ip2->fwd) {		if (branch (ip2)) {		    if (is_label_used (ip2->oper1, label)) {			OPCODE  op = ip2->opcode;			ip2->opcode = op_nop;			if (!was_move_redundant (ip, ip2, memory)) {			    ip2->opcode = op;			    return FALSE;			}			ip2->opcode = op;		    }		}	    }	    /* but if it is via a jump table we cannot determine it */	    for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) {		LABEL   lab;		for (lab = (LABEL) 0; lab < sw->numlabs; lab++) {		    if (sw->labels[lab] == label) {			return FALSE;		    }		}	    }	    return TRUE;	case op_ret:	case op_jmp:	case op_bra:	    /* should have at least hit a label before here! */	case op_nop:	    return TRUE;	case op_call:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -