/********************************************************************** * polocal.c * P-Code Local Optimizer * * Copyright (C) 2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * 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 #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(); } /***********************************************************************/