9
0
Fork 0
nuttx-bb/misc/pascal/insn16/popt/psopt.c

388 lines
11 KiB
C

/**********************************************************************
* psopt.c
* String Stack Optimizaitons
*
* Copyright (C) 2008-2009 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.
*
**********************************************************************/
/* The statement generation logic generates a PUSHS and POPS around
* every statement. These instructions save and restore the string
* stack pointer registers. However, only some statements actually
* modify the string stack. So the first major step in the optimatization
* process is to retain only PUSHS and POPS statements that are
* actually required.
*/
/**********************************************************************
* Included Files
**********************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "keywords.h"
#include "pdefs.h"
#include "pedefs.h"
#include "pinsn16.h"
#include "pxdefs.h"
#include "popt.h"
#include "psopt.h"
/**********************************************************************
* Definitions
**********************************************************************/
#define PBUFFER_SIZE 1024
#define NPBUFFERS 8
/**********************************************************************
* Private Data
**********************************************************************/
static uint8_t *pbuffer[NPBUFFERS];
static int nbytes_in_pbuffer[NPBUFFERS];
static int current_level = -1;
static int inch;
/**********************************************************************
* Private Function Prototypes
**********************************************************************/
static inline void putbuf(int c, poffProgHandle_t poffProgHandle);
static inline void flushc(int c, poffProgHandle_t poffProgHandle);
static inline void flushbuf(poffProgHandle_t poffProgHandle);
static void dopush(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle);
static void dopop(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle);
/**********************************************************************
* Private Inline Functions
**********************************************************************/
static inline void putbuf(int c, poffProgHandle_t poffProgHandle)
{
int dlvl = current_level;
if (dlvl < 0)
{
/* No PUSHS encountered. Write byte directly to output */
poffAddTmpProgByte(poffProgHandle, (uint8_t)c);
}
else
{
/* PUSHS encountered. Write byte into buffer associated with
* nesting level.
*/
int idx = nbytes_in_pbuffer[dlvl];
uint8_t *dest = pbuffer[dlvl] + idx;
*dest = c;
nbytes_in_pbuffer[dlvl] = idx + 1;
}
}
static inline void flushc(int c, poffProgHandle_t poffProgHandle)
{
if (current_level > 0)
{
/* Nested PUSHS encountered. Write byte into buffer associated
* with the previous nesting level.
*/
int dlvl = current_level - 1;
int idx = nbytes_in_pbuffer[dlvl];
uint8_t *dest = pbuffer[dlvl] + idx;
*dest = c;
nbytes_in_pbuffer[dlvl] = idx + 1;
}
else
{
/* Only one PUSHS encountered. Write directly to the output
* buffer
*/
poffAddTmpProgByte(poffProgHandle, (uint8_t)c);
}
}
static inline void flushbuf(poffProgHandle_t poffProgHandle)
{
uint16_t errCode;
int slvl = current_level;
if (nbytes_in_pbuffer[slvl] > 0)
{
if (current_level > 0)
{
/* Nested PUSHS encountered. Flush buffer into buffer associated
* with the previous nesting level.
*/
int dlvl = slvl - 1;
uint8_t *src = pbuffer[slvl];
uint8_t *dest = pbuffer[dlvl] + nbytes_in_pbuffer[dlvl];
memcpy(dest, src, nbytes_in_pbuffer[slvl]);
nbytes_in_pbuffer[dlvl] += nbytes_in_pbuffer[slvl];
}
else
{
/* Only one PUSHS encountered. Flush directly to the output
* buffer
*/
errCode = poffWriteTmpProgBytes(pbuffer[0], nbytes_in_pbuffer[0],
poffProgHandle);
if (errCode != eNOERROR)
{
printf("Error writing to file: %d\n", errCode);
exit(1);
}
}
}
nbytes_in_pbuffer[slvl] = 0;
}
/**********************************************************************
* Private Functions
**********************************************************************/
static void dopush(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle)
{
int opcode;
while (inch != EOF)
{
/* Search for a PUSHS opcode */
if (inch != oPUSHS)
{
/* Its not PUSHS, just echo to the output file/buffer */
putbuf(inch, poffProgHandle);
/* Get the next byte from the input stream */
opcode = inch;
inch = poffGetProgByte(poffHandle);
/* Check for an 8-bit argument */
if ((opcode & o8) != 0)
{
/* Echo the 8-bit argument */
putbuf(inch, poffProgHandle);
inch = poffGetProgByte(poffHandle);
}
/* Check for a 16-bit argument */
if ((opcode & o16) != 0)
{
/* Echo the 16-bit argument */
putbuf(inch, poffProgHandle);
inch = poffGetProgByte(poffHandle);
putbuf(inch, poffProgHandle);
inch = poffGetProgByte(poffHandle);
}
}
else
{
/* We have found PUSHS. No search for the next occurrence
* of either and instruction that increments the string
* stack or for the matching POPS
*/
current_level++;
dopop(poffHandle, poffProgHandle);
current_level--;
}
}
}
static void dopop(poffHandle_t poffHandle, poffProgHandle_t poffProgHandle)
{
int opcode;
int arg16;
int arg16a;
int arg16b;
/* We have found PUSHS. No search for the next occurrence
* of either and instruction that increments the string
* stack or for the matching POPS
*/
/* Skip over the PUSHS for now */
inch = poffGetProgByte(poffHandle);
while (inch != EOF)
{
/* Did we encounter another PUSHS? */
if (inch == oPUSHS)
{
/* Yes... recurse to handle it */
current_level++;
dopop(poffHandle, poffProgHandle);
current_level--;
}
else if (inch == oPOPS)
{
/* Flush the buffered data without the PUSHS */
flushbuf(poffProgHandle);
/* And discard the matching POPS */
inch = poffGetProgByte(poffHandle);
break;
}
else if (inch == oLIB)
{
/* Get the 16-bit argument */
putbuf(inch, poffProgHandle);
arg16a = poffGetProgByte(poffHandle);
putbuf(arg16a, poffProgHandle);
arg16b = poffGetProgByte(poffHandle);
putbuf(arg16b, poffProgHandle);
arg16 = (arg16a << 8) | arg16b;
inch = poffGetProgByte(poffHandle);
/* Is it LIB MKSTK? MKSTKSTR? or MKSTKC? */
if ((arg16 == lbMKSTK) ||
(arg16 == lbMKSTKSTR) ||
(arg16 == lbMKSTKC))
{
/* Flush the buffered data with the PUSHS */
flushc(oPUSHS, poffProgHandle);
flushbuf(poffProgHandle);
/* And break out of the loop to search for
* the next PUSHS
*/
break;
}
}
else
{
/* Something else. Put it in the buffer */
putbuf(inch, poffProgHandle);
/* Get the next byte from the input stream */
opcode = inch;
inch = poffGetProgByte(poffHandle);
/* Check for an 8-bit argument */
if ((opcode & o8) != 0)
{
/* Buffer the 8-bit argument */
putbuf(inch, poffProgHandle);
inch = poffGetProgByte(poffHandle);
}
/* Check for a 16-bit argument */
if ((opcode & o16) != 0)
{
/* Buffer the 16-bit argument */
putbuf(inch, poffProgHandle);
inch = poffGetProgByte(poffHandle);
putbuf(inch, poffProgHandle);
inch = poffGetProgByte(poffHandle);
}
}
}
}
/**********************************************************************
* Global Functions
**********************************************************************/
void stringStackOptimize(poffHandle_t poffHandle,
poffProgHandle_t poffProgHandle)
{
int i;
/* Allocate an array of buffers to hold pcode data */
for (i = 0; i < NPBUFFERS; i++)
{
pbuffer[i] = (uint8_t*)malloc(PBUFFER_SIZE);
if (pbuffer[i] == NULL)
{
printf("Failed to allocate pcode buffer\n");
exit(1);
}
nbytes_in_pbuffer[i] = 0;
}
/* Prime the search logic */
inch = poffGetProgByte(poffHandle);
current_level = -1;
/* And parse the input file to the output file, removing unnecessary string
* stack operations.
*/
dopush(poffHandle, poffProgHandle);
/* Release the buffers */
for (i = 0; i < NPBUFFERS; i++)
{
free(pbuffer[i]);
pbuffer[i] = NULL;
nbytes_in_pbuffer[i] = 0;
}
}
/**********************************************************************/