summaryrefslogblamecommitdiff
path: root/misc/pascal/insn16/popt/polocal.c
blob: c2b2a5b679934490c2768bbb7c83cb6fd83585ca (plain) (tree)











































































































































































































































































































                                                                               
/**********************************************************************
 * polocal.c
 * P-Code Local Optimizer
 *
 *   Copyright (C) 2008 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name NuttX nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 **********************************************************************/

/**********************************************************************
 * Included Files
 **********************************************************************/

#include <stdio.h>

#include "keywords.h"
#include "podefs.h"
#include "pinsn16.h"

#include "pofflib.h"
#include "paslib.h"
#include "pinsn.h"
#include "pcopt.h"
#include "plopt.h"
#include "pjopt.h"
#include "polocal.h"

/**********************************************************************
 * Private Function Prototypes
 **********************************************************************/

static void initPTable        (void);
static void putPCodeFromTable (void);
static void setupPointer      (void);

/**********************************************************************
 * Global Variables
 **********************************************************************/

OPTYPE  ptable [WINDOW];                /* Pcode Table */
OPTYPE *pptr   [WINDOW];                /* Valid Pcode Pointers */

sint16  nops    = 0;                    /* No. Valid Pcode Pointers */
sint16  end_out = 0;                    /* 1 = oEND pcode has been output */

/**********************************************************************
 * Private Variables
 **********************************************************************/

static poffHandle_t     myPoffHandle;         /* Handle to POFF object */
static poffProgHandle_t myPoffProgHandle;/* Handle to temporary POFF object */

/**********************************************************************
 * Global Functions
 **********************************************************************/

/***********************************************************************/

void localOptimization(poffHandle_t poffHandle,
		       poffProgHandle_t poffProgHandle)
{
  sint16 nchanges;

  TRACE(stderr, "[pass2]");

  /* Save the handles for use by other, private functions */

  myPoffHandle     = poffHandle;
  myPoffProgHandle = poffProgHandle;

  /* Initialization */

  initPTable();

  /* Outer loop traverse the file op-code by op-code until the oEND P-Code
   * has been output.  NOTE:  it is assumed throughout that oEND is the 
   * final P-Code in the program data section.
   */

  while (!(end_out))
    {
      /* The inner loop optimizes the buffered P-Codes until no further
       * changes can be made.  Then the outer loop will advance the buffer
       * by one P-Code
       */

      do
	{
	  nchanges  = unaryOptimize ();
	  nchanges += binaryOptimize();
	  nchanges += BranchOptimize();
	  nchanges += LoadOptimize();
	  nchanges += StoreOptimize();
	} while (nchanges);

      putPCodeFromTable();
    }
}

/***********************************************************************/

void deletePcode(sint16 delIndex)
{
  TRACE(stderr, "[deletePcode]");

  pptr[delIndex]->op   = oNOP;
  pptr[delIndex]->arg1 = 0;
  pptr[delIndex]->arg2 = 0;
  setupPointer();
}

/**********************************************************************/

void deletePcodePair(sint16 delIndex1, sint16 delIndex2)
{
  TRACE(stderr, "[deletePcodePair]");

  pptr[delIndex1]->op   = oNOP;
  pptr[delIndex1]->arg1 = 0;
  pptr[delIndex1]->arg2 = 0;
  pptr[delIndex2]->op   = oNOP;
  pptr[delIndex2]->arg1 = 0;
  pptr[delIndex2]->arg2 = 0;
  setupPointer();
}

/**********************************************************************
 * Private Functions
 **********************************************************************/

/***********************************************************************/

static void putPCodeFromTable(void)
{
  register sint16 i;

  TRACE(stderr, "[putPCodeFromTable]");

  /* Transfer all buffered P-Codes (except NOPs) to the optimized file */
  do
    {
      if ((ptable[0].op != oNOP) && !(end_out))
	{
	  (void)poffAddTmpProgByte(myPoffProgHandle, ptable[0].op);

	  if (ptable[0].op & o8)  
	    (void)poffAddTmpProgByte(myPoffProgHandle, ptable[0].arg1);

	  if (ptable[0].op & o16)
	    { 
	      (void)poffAddTmpProgByte(myPoffProgHandle,
				       (ptable[0].arg2 >> 8));
	      (void)poffAddTmpProgByte(myPoffProgHandle,
				       (ptable[0].arg2 & 0xff));
	    }

	  end_out =(ptable[0].op == oEND);
	}

      /* Move all P-Codes down one slot */

      for (i = 1; i < WINDOW; i++)
	{
	  ptable[i-1].op   = ptable[i].op ;
	  ptable[i-1].arg1 = ptable[i].arg1;
	  ptable[i-1].arg2 = ptable[i].arg2;
	}

      /* Then fill the end slot with a new P-Code from the input file */

      insn_GetOpCode(myPoffHandle, &ptable[WINDOW-1]);

    } while (ptable[0].op == oNOP);
  setupPointer();
}

/**********************************************************************/

static void setupPointer(void)
{
  register sint16 pindex;

  TRACE(stderr, "[setupPointer]");

  for (pindex = 0; pindex < WINDOW; pindex++)
    pptr[pindex] = (OPTYPE *) NULL;

  nops = 0; 
  for (pindex = 0; pindex < WINDOW; pindex++)
    {
      switch (ptable[pindex].op)
	{
	  /* Terminate list when a break from sequential logic is
	   * encountered
	   */

	case oRET   :
	case oEND   :
	case oJMP   :
	case oLABEL :
	case oPCAL  :
	  return;

	  /* Terminate list when a condition break from sequential logic is
	   * encountered but include the conditional branch in the list
	   */

	case oJEQUZ :
	case oJNEQZ :
	case oJLTZ  :
	case oJGTEZ :
	case oJGTZ  :
	case oJLTEZ :
	  pptr[nops] = &ptable[pindex];
	  nops++;
	  return;

	  /* Skip over NOPs and comment class pcodes */

	case oNOP   :
	case oLINE  :
	  break;

	  /* Include all other pcodes in the optimization list and continue */

	default     :
	  pptr[nops] = &ptable[pindex];
	  nops++;
	}
    }
}

/**********************************************************************/

static void initPTable(void)
{
  register sint16 i;

  TRACE(stderr, "[intPTable]");

  /* Skip over leading pcodes.  NOTE:  assumes executable begins after
   * the first oLABEL pcode
   */

  do
    {
      insn_GetOpCode(myPoffHandle, &ptable[0]);

      (void)poffAddTmpProgByte(myPoffProgHandle, ptable[0].op);

      if (ptable[0].op & o8)  
	{
	  (void)poffAddTmpProgByte(myPoffProgHandle, ptable[0].arg1);
	}

      if (ptable[0].op & o16)
	{ 
	  (void)poffAddTmpProgByte(myPoffProgHandle, (ptable[0].arg2 >> 8));
	  (void)poffAddTmpProgByte(myPoffProgHandle, (ptable[0].arg2 & 0xff));
	} /* end if */
    }
  while ((ptable[0].op != oLABEL) && (ptable[0].op != oEND));

  /* Fill the pcode window and setup pointers to working section */

  for (i = 0; i < WINDOW; i++)
    {
      insn_GetOpCode(myPoffHandle, &ptable[i]);
    }
  setupPointer();
}

/***********************************************************************/