OpenCores
URL https://opencores.org/ocsvn/raptor64/raptor64/trunk

Subversion Repositories raptor64

[/] [raptor64/] [trunk/] [software/] [c64/] [source/] [Optimize.c] - Rev 37

Compare with Previous | Blame | View Log

#include        <stdio.h>
#include        "c.h"
#include        "expr.h"
#include        "gen.h"
#include        "cglbdec.h"
 
/*
 *	68000 C compiler
 *
 *	Copyright 1984, 1985, 1986 Matthew Brandt.
 *  all commercial rights reserved.
 *
 *	This compiler is intended as an instructive tool for personal use. Any
 *	use for profit without the written consent of the author is prohibited.
 *
 *	This compiler may be distributed freely for non-commercial use as long
 *	as this notice stays intact. Please forward any enhancements or questions
 *	to:
 *
 *		Matthew Brandt
 *		Box 920337
 *		Norcross, Ga 30092
 */
 
/*	Modified to support 64 bit Raptor64 by
	Robert Finch	robfinch<remove>@opencores.org
*/
 
void fold_const(struct enode **node);
 
/*
 *      dooper will execute a constant operation in a node and
 *      modify the node to be the result of the operation.
 */
void dooper(ENODE **node)
{
	ENODE *ep;
 
        ep = *node;
        switch( ep->nodetype ) {
                case en_add:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i + ep->p[1]->i;
                        break;
                case en_sub:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i - ep->p[1]->i;
                        break;
                case en_mul:
				case en_mulu:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i * ep->p[1]->i;
                        break;
                case en_div:
				case en_udiv:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i / ep->p[1]->i;
                        break;
                case en_shl:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i << ep->p[1]->i;
                        break;
                case en_shr:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i >> ep->p[1]->i;
                        break;
                case en_shru:
                        ep->nodetype = en_icon;
                        ep->i = (unsigned)ep->p[0]->i >> ep->p[1]->i;
                        break;
                case en_and:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i & ep->p[1]->i;
                        break;
                case en_or:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i | ep->p[1]->i;
                        break;
                case en_xor:
                        ep->nodetype = en_icon;
                        ep->i = ep->p[0]->i ^ ep->p[1]->i;
                        break;
                }
}
 
/*
 *      return which power of two i is or -1.
 */
int pwrof2(__int64 i)
{       
	int p;
	__int64 q;
 
    q = 2;
    p = 1;
    while( q > 0 )
    {
		if( q == i )
			return p;
		q <<= 1;
		++p;
    }
    return -1;
}
 
/*
 *      make a mod mask for a power of two.
 */
__int64 mod_mask(int i)
{   
	__int64 m;
    m = 0;
    while( i-- )
        m = (m << 1) | 1;
    return m;
}
 
/*
 *      opt0 - delete useless expressions and combine constants.
 *
 *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
 *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
 *      by node and combine obvious constant operations. It cannot
 *      combine name and label constants but will combine icon type
 *      nodes.
 */
void opt0(ENODE **node)
{
	ENODE *ep;
    __int64 val, sc;
 
    ep = *node;
    if( ep == NULL )
        return;
    switch( (*node)->nodetype ) {
            case en_b_ref:
			case en_c_ref:
			case en_h_ref:
            case en_w_ref:          /* optimize unary node */
            case en_ub_ref:
			case en_uc_ref:
			case en_uh_ref:
            case en_uw_ref:          /* optimize unary node */
			case en_cbc:
			case en_cbh:
			case en_cbw:
			case en_cch:
			case en_ccw:
			case en_chw:
			case en_ainc:
			case en_adec:
			case en_not:
			case en_compl:
                    opt0( &((*node)->p[0]));
                    return;
            case en_uminus:
                    opt0( &(ep->p[0]));
                    if( ep->p[0]->nodetype == en_icon )
                    {
                        ep->nodetype = en_icon;
                        ep->i = -ep->p[0]->i;
                    }
                    return;
            case en_add:
            case en_sub:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                        if( ep->p[1]->nodetype == en_icon ) {
                            dooper(node);
                            return;
                        }
                        if( ep->p[0]->i == 0 ) {
							if( ep->nodetype == en_sub )
							{
								ep->p[0] = ep->p[1];
                                ep->nodetype = en_uminus;
							}
							else
								*node = ep->p[1];
								return;
                        }
                    }
                    else if( ep->p[1]->nodetype == en_icon ) {
                        if( ep->p[1]->i == 0 ) {
                            *node = ep->p[0];
                            return;
                        }
                    }
                    return;
            case en_mul:
			case en_mulu:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                        if( ep->p[1]->nodetype == en_icon ) {
                            dooper(node);
                            return;
                        }
                        val = ep->p[0]->i;
                        if( val == 0 ) {
                            *node = ep->p[0];
                            return;
                        }
                        if( val == 1 ) {
                            *node = ep->p[1];
                            return;
                        }
                        sc = pwrof2(val);
                        if( sc != -1 )
                        {
                            swap_nodes(ep);
                            ep->p[1]->i = sc;
                            ep->nodetype = en_shl;
                        }
                    }
                    else if( ep->p[1]->nodetype == en_icon ) {
                        val = ep->p[1]->i;
                        if( val == 0 ) {
                            *node = ep->p[1];
                            return;
                        }
                        if( val == 1 ) {
                            *node = ep->p[0];
                            return;
                        }
                        sc = pwrof2(val);
                        if( sc != -1 )
                        {
							ep->p[1]->i = sc;
							ep->nodetype = en_shl;
                        }
                    }
                    break;
            case en_div:
			case en_udiv:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon ) {
                            if( ep->p[1]->nodetype == en_icon ) {
                                    dooper(node);
                                    return;
                                    }
                            if( ep->p[0]->i == 0 ) {    /* 0/x */
                                    *node = ep->p[0];
                                    return;
                                    }
                            }
                    else if( ep->p[1]->nodetype == en_icon ) {
                            val = ep->p[1]->i;
                            if( val == 1 ) {        /* x/1 */
                                    *node = ep->p[0];
                                    return;
                                    }
                            sc = pwrof2(val);
                            if( sc != -1 )
                                    {
                                    ep->p[1]->i = sc;
                                    ep->nodetype = en_shr;
                                    }
                            }
                    break;
            case en_mod:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[1]->nodetype == en_icon )
                            {
                            if( ep->p[0]->nodetype == en_icon )
                                    {
                                    dooper(node);
                                    return;
                                    }
                            sc = pwrof2(ep->p[1]->i);
                            if( sc != -1 )
                                    {
                                    ep->p[1]->i = mod_mask(sc);
                                    ep->nodetype = en_and;
                                    }
                            }
                    break;
            case en_and:    case en_or:
			case en_xor:    case en_shr:	case en_shru:
            case en_shl:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    if( ep->p[0]->nodetype == en_icon &&
                            ep->p[1]->nodetype == en_icon )
                            dooper(node);
                    break;
            case en_land:   case en_lor:
			case en_ult:	case en_ule:
			case en_ugt:	case en_uge:
			case en_lt:		case en_le:
			case en_gt:		case en_ge:
			case en_eq:		case en_ne:
            case en_asand:  case en_asor:
            case en_asadd:  case en_assub:
            case en_asmul:  case en_asdiv:
            case en_asmod:  case en_asrsh:
            case en_aslsh:  case en_cond:
            case en_fcall:  case en_void:
            case en_assign:
                    opt0(&(ep->p[0]));
                    opt0(&(ep->p[1]));
                    break;
            }
}
 
/*
 *      xfold will remove constant nodes and return the values to
 *      the calling routines.
 */
__int64 xfold(ENODE *node)
{
	__int64 i;
 
        if( node == NULL )
                return 0;
        switch( node->nodetype )
                {
                case en_icon:
                        i = node->i;
                        node->i = 0;
                        return i;
                case en_add:
                        return xfold(node->p[0]) + xfold(node->p[1]);
                case en_sub:
                        return xfold(node->p[0]) - xfold(node->p[1]);
                case en_mul:
				case en_mulu:
                        if( node->p[0]->nodetype == en_icon )
                                return xfold(node->p[1]) * node->p[0]->i;
                        else if( node->p[1]->nodetype == en_icon )
                                return xfold(node->p[0]) * node->p[1]->i;
                        else return 0;
                case en_shl:
                        if( node->p[0]->nodetype == en_icon )
                                return xfold(node->p[1]) << node->p[0]->i;
                        else if( node->p[1]->nodetype == en_icon )
                                return xfold(node->p[0]) << node->p[1]->i;
                        else return 0;
                case en_uminus:
                        return - xfold(node->p[0]);
				case en_shr:    case en_div:	case en_udiv:	case en_shru:
                case en_mod:    case en_asadd:
                case en_assub:  case en_asmul:
                case en_asdiv:  case en_asmod:
                case en_and:    case en_land:
                case en_or:     case en_lor:
                case en_xor:    case en_asand:
                case en_asor:   case en_void:
                case en_fcall:  case en_assign:
                        fold_const(&node->p[0]);
                        fold_const(&node->p[1]);
                        return 0;
				case en_ub_ref: case en_uw_ref:
				case en_uc_ref: case en_uh_ref:
                case en_b_ref:  case en_w_ref:
				case en_c_ref:  case en_h_ref:
                case en_compl:
                case en_not:
                        fold_const(&node->p[0]);
                        return 0;
                }
        return 0;
}
 
/*
 *      reorganize an expression for optimal constant grouping.
 */
void fold_const(ENODE **node)
{       ENODE *ep;
        __int64 i;
        ep = *node;
        if( ep == 0 )
                return;
        if( ep->nodetype == en_add )
                {
                if( ep->p[0]->nodetype == en_icon )
                        {
                        ep->p[0]->i += xfold(ep->p[1]);
                        return;
                        }
                else if( ep->p[1]->nodetype == en_icon )
                        {
                        ep->p[1]->i += xfold(ep->p[0]);
                        return;
                        }
                }
        else if( ep->nodetype == en_sub )
                {
                if( ep->p[0]->nodetype == en_icon )
                        {
                        ep->p[0]->i -= xfold(ep->p[1]);
                        return;
                        }
                else if( ep->p[1]->nodetype == en_icon )
                        {
                        ep->p[1]->i -= xfold(ep->p[0]);
                        return;
                        }
                }
        i = xfold(ep);
        if( i != 0 )
                {
                ep = makeinode(en_icon,i);
                ep = makenode(en_add,ep,*node);
                *node = ep;
                }
}
 
/*
 *      apply all constant optimizations.
 */
void opt4(struct enode **node)
{
	opt0(node);
	fold_const(node);
	opt0(node);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.