forked from Archive/PX4-Autopilot
272 lines
7.7 KiB
C
272 lines
7.7 KiB
C
|
/**********************************************************************
|
||
|
* 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 "pinsn32.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 */
|
||
|
|
||
|
int nops = 0; /* No. Valid Pcode Pointers */
|
||
|
int 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)
|
||
|
{
|
||
|
int 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(int delIndex)
|
||
|
{
|
||
|
TRACE(stderr, "[deletePcode]");
|
||
|
|
||
|
PUTOP(pptr[delIndex], oNOP);
|
||
|
PUTARG(pptr[delIndex], 0);
|
||
|
setupPointer();
|
||
|
}
|
||
|
|
||
|
/**********************************************************************/
|
||
|
|
||
|
void deletePcodePair(int delIndex1, int delIndex2)
|
||
|
{
|
||
|
TRACE(stderr, "[deletePcodePair]");
|
||
|
|
||
|
PUTOP(pptr[delIndex1], oNOP);
|
||
|
PUTARG(pptr[delIndex1], 0);
|
||
|
PUTOP(pptr[delIndex2], oNOP);
|
||
|
PUTARG(pptr[delIndex2], 0);
|
||
|
setupPointer();
|
||
|
}
|
||
|
|
||
|
/**********************************************************************
|
||
|
* Private Functions
|
||
|
**********************************************************************/
|
||
|
|
||
|
/***********************************************************************/
|
||
|
|
||
|
static void putPCodeFromTable(void)
|
||
|
{
|
||
|
register int i;
|
||
|
|
||
|
TRACE(stderr, "[putPCodeFromTable]");
|
||
|
|
||
|
/* Transfer all buffered P-Codes (except NOPs) to the optimized file */
|
||
|
do
|
||
|
{
|
||
|
if ((GETOP(&ptable[0]) != oNOP) && !(end_out))
|
||
|
{
|
||
|
insn_AddTmpOpCode(myPoffProgHandle, &ptable[0]);
|
||
|
end_out = (GETOP(&ptable[0]) == oEND);
|
||
|
}
|
||
|
|
||
|
/* Move all P-Codes down one slot */
|
||
|
|
||
|
for (i = 1; i < WINDOW; i++)
|
||
|
{
|
||
|
ptable[i-1] = ptable[i];
|
||
|
}
|
||
|
|
||
|
/* Then fill the end slot with a new P-Code from the input file */
|
||
|
|
||
|
insn_GetOpCode(myPoffHandle, &ptable[WINDOW-1]);
|
||
|
|
||
|
} while (GETOP(&ptable[0]) == oNOP);
|
||
|
setupPointer();
|
||
|
}
|
||
|
|
||
|
/**********************************************************************/
|
||
|
|
||
|
static void setupPointer(void)
|
||
|
{
|
||
|
register int pindex;
|
||
|
|
||
|
TRACE(stderr, "[setupPointer]");
|
||
|
|
||
|
for (pindex = 0; pindex < WINDOW; pindex++)
|
||
|
pptr[pindex] = (OPTYPE *) NULL;
|
||
|
|
||
|
nops = 0;
|
||
|
for (pindex = 0; pindex < WINDOW; pindex++)
|
||
|
{
|
||
|
switch (GETOP(&ptable[pindex]))
|
||
|
{
|
||
|
/* 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 int i;
|
||
|
|
||
|
TRACE(stderr, "[intPTable]");
|
||
|
|
||
|
/* Skip over leading pcodes. NOTE: assumes executable begins after
|
||
|
* the first oLABEL pcode
|
||
|
*/
|
||
|
|
||
|
do
|
||
|
{
|
||
|
insn_GetOpCode(myPoffHandle, &ptable[0]);
|
||
|
insn_AddTmpOpCode(myPoffProgHandle, &ptable[0]);
|
||
|
}
|
||
|
while ((GETOP(&ptable[0]) != oLABEL) && (GETOP(&ptable[0]) != oEND));
|
||
|
|
||
|
/* Fill the pcode window and setup pointers to working section */
|
||
|
|
||
|
for (i = 0; i < WINDOW; i++)
|
||
|
{
|
||
|
insn_GetOpCode(myPoffHandle, &ptable[i]);
|
||
|
}
|
||
|
setupPointer();
|
||
|
}
|
||
|
|
||
|
/***********************************************************************/
|