mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
12 KiB
338 lines
12 KiB
//////////////////////////////////////////////////////////////
|
|
// //
|
|
// Propeller Spin/PASM Compiler //
|
|
// (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. //
|
|
// Adapted from Chip Gracey's x86 asm code by Roy Eltham //
|
|
// See end of file for terms of use. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// DistillObjects.cpp
|
|
//
|
|
// called Object Distiller in the asm code
|
|
//
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include "Utilities.h"
|
|
#include "PropellerCompilerInternal.h"
|
|
#include "SymbolEngine.h"
|
|
#include "Elementizer.h"
|
|
#include "ErrorStrings.h"
|
|
|
|
bool DistillSetup_Enter(unsigned short value)
|
|
{
|
|
if (g_pCompilerData->dis_ptr == distiller_limit)
|
|
{
|
|
g_pCompilerData->error = true;
|
|
g_pCompilerData->error_msg = g_pErrorStrings[error_odo];
|
|
return false;
|
|
}
|
|
g_pCompilerData->dis[g_pCompilerData->dis_ptr++] = value;
|
|
return true;
|
|
}
|
|
|
|
// create a table of all objects with their offsets and sub objects
|
|
// each entry contains:
|
|
// id, offset, number sub objects, [sub object ids]
|
|
bool DistillSetup_Record(short id, unsigned short offset, unsigned short& subObjectId)
|
|
{
|
|
if (!DistillSetup_Enter(id))
|
|
{
|
|
return false;
|
|
}
|
|
if (!DistillSetup_Enter(offset))
|
|
{
|
|
return false;
|
|
}
|
|
unsigned short numSubObjects = (unsigned short)(g_pCompilerData->obj[offset+3]);
|
|
if (!DistillSetup_Enter(numSubObjects))
|
|
{
|
|
return false;
|
|
}
|
|
if (numSubObjects > 0)
|
|
{
|
|
short startingSubObjectId = subObjectId;
|
|
for (short i = 0; i < numSubObjects; i++)
|
|
{
|
|
if (!DistillSetup_Enter(subObjectId++))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
unsigned short nextSubObjects = (unsigned short)(g_pCompilerData->obj[offset+2]);
|
|
for (short i = 0; i < numSubObjects; i++)
|
|
{
|
|
unsigned short offsetAdjust = *((unsigned short*)&(g_pCompilerData->obj[offset + ((nextSubObjects + i) * 4)]));
|
|
if (!DistillSetup_Record(startingSubObjectId + i, offset + offsetAdjust, subObjectId))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool DistillSetup()
|
|
{
|
|
g_pCompilerData->dis_ptr = 0;
|
|
unsigned short subObjectId = 1;
|
|
if (!DistillSetup_Record(0, 0, subObjectId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Clear all the objects table of offsets to their sub objects
|
|
// this needs to be done so that objects will binary compare with each other properly
|
|
// these offsets get replaced in the reconnect step
|
|
int disPtr = 0;
|
|
while (disPtr < g_pCompilerData->dis_ptr)
|
|
{
|
|
// do we have sub objects?
|
|
unsigned short numSubObjects = g_pCompilerData->dis[disPtr + 2];
|
|
if (numSubObjects > 0)
|
|
{
|
|
unsigned short offset = g_pCompilerData->dis[disPtr + 1];
|
|
|
|
disPtr += numSubObjects;
|
|
|
|
unsigned short offsetAdjust = (unsigned short)(g_pCompilerData->obj[offset + 2]);
|
|
unsigned char* pObj = &(g_pCompilerData->obj[offset + (offsetAdjust * 4)]);
|
|
for (int i = 0; i < numSubObjects; i++)
|
|
{
|
|
*((unsigned short*)&pObj[0]) = 0;
|
|
pObj += 4;
|
|
}
|
|
}
|
|
|
|
disPtr += 3;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// update all objects of the given id to the new id
|
|
// also flags them as "distilled" with the upper bit being on
|
|
void DistillEliminate_Update(unsigned short objectId, int newDisPtr)
|
|
{
|
|
int disPtr = 0;
|
|
|
|
while (disPtr < g_pCompilerData->dis_ptr)
|
|
{
|
|
disPtr += 3;
|
|
unsigned short numSubObjects = g_pCompilerData->dis[disPtr - 1];
|
|
if (numSubObjects > 0)
|
|
{
|
|
for (int i = 0; i < numSubObjects; i++)
|
|
{
|
|
if ((g_pCompilerData->dis[disPtr] & 0x7FFF) == objectId)
|
|
{
|
|
g_pCompilerData->dis[disPtr] = (g_pCompilerData->dis[newDisPtr] | 0x8000);
|
|
}
|
|
disPtr++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DistillEliminate()
|
|
{
|
|
int disPtr = 0;
|
|
|
|
while (disPtr < g_pCompilerData->dis_ptr)
|
|
{
|
|
unsigned short numSubObjects = g_pCompilerData->dis[disPtr + 2];
|
|
if (numSubObjects > 0)
|
|
{
|
|
int i;
|
|
for (i = 0; i < numSubObjects; i++)
|
|
{
|
|
if ((g_pCompilerData->dis[disPtr + 3 + i] & 0x8000) == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (i < numSubObjects)
|
|
{
|
|
// point to next object record
|
|
disPtr += (3 + numSubObjects);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// search for any matching objects
|
|
int newDisPtr = disPtr;
|
|
// point to next object record
|
|
newDisPtr += (3 + numSubObjects);
|
|
|
|
bool bRestart = false;
|
|
while (newDisPtr < g_pCompilerData->dis_ptr)
|
|
{
|
|
unsigned short newNumSubObjects = g_pCompilerData->dis[newDisPtr + 2];
|
|
|
|
if (numSubObjects != newNumSubObjects)
|
|
{
|
|
// point to next object record
|
|
newDisPtr += (3 + newNumSubObjects);
|
|
continue;
|
|
}
|
|
if (newNumSubObjects > 0)
|
|
{
|
|
int i;
|
|
for (i = 0; i < newNumSubObjects; i++)
|
|
{
|
|
if (g_pCompilerData->dis[disPtr + 3 + i] != g_pCompilerData->dis[newDisPtr + 3 + i])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (i < newNumSubObjects)
|
|
{
|
|
// point to next object record
|
|
newDisPtr += (3 + newNumSubObjects);
|
|
continue;
|
|
}
|
|
}
|
|
// compare the object binaries
|
|
unsigned char* pObj = &(g_pCompilerData->obj[g_pCompilerData->dis[disPtr+1]]);
|
|
unsigned short objLength = *((unsigned short*)pObj);
|
|
if (memcmp(pObj, &(g_pCompilerData->obj[g_pCompilerData->dis[newDisPtr+1]]), (size_t)objLength) != 0)
|
|
{
|
|
// point to next object record
|
|
newDisPtr += (3 + newNumSubObjects);
|
|
continue;
|
|
}
|
|
|
|
// the objects match, so update all related sub-object id's
|
|
DistillEliminate_Update(g_pCompilerData->dis[disPtr], newDisPtr);
|
|
DistillEliminate_Update(g_pCompilerData->dis[newDisPtr], newDisPtr);
|
|
|
|
// remove redundant object record from list
|
|
g_pCompilerData->dis_ptr -= (3 + numSubObjects);
|
|
memmove(&g_pCompilerData->dis[disPtr], &g_pCompilerData->dis[disPtr + (3 + numSubObjects)], (g_pCompilerData->dis_ptr - disPtr) * 2);
|
|
|
|
// restart elimination from beginning
|
|
bRestart = true;
|
|
}
|
|
if (bRestart)
|
|
{
|
|
disPtr = 0;
|
|
}
|
|
else
|
|
{
|
|
// point to next object record
|
|
disPtr += (3 + numSubObjects);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
static unsigned char s_rebuildBuffer[min_obj_limit];
|
|
void DistillRebuild()
|
|
{
|
|
int disPtr = 0;
|
|
unsigned short rebuildPtr = 0;
|
|
while (disPtr < g_pCompilerData->dis_ptr)
|
|
{
|
|
// copy the object from obj into the rebuild buffer
|
|
unsigned char* pObj = &(g_pCompilerData->obj[g_pCompilerData->dis[disPtr + 1]]);
|
|
unsigned short objLength = *((unsigned short*)pObj);
|
|
memcpy(&(s_rebuildBuffer[rebuildPtr]), pObj, (size_t)objLength);
|
|
|
|
// fixup the distiller record
|
|
g_pCompilerData->dis[disPtr+1] = rebuildPtr;
|
|
|
|
rebuildPtr += objLength;
|
|
|
|
// point to the next object record
|
|
disPtr += (3 + g_pCompilerData->dis[disPtr + 2]);
|
|
}
|
|
|
|
// copy the rebuilt data back into obj
|
|
g_pCompilerData->obj_ptr = rebuildPtr;
|
|
memcpy(&g_pCompilerData->obj[0], &s_rebuildBuffer[0], (size_t)rebuildPtr);
|
|
}
|
|
|
|
void DistillReconnect(int disPtr = 0)
|
|
{
|
|
unsigned short numSubObjects = g_pCompilerData->dis[disPtr + 2];
|
|
if (numSubObjects > 0)
|
|
{
|
|
// this objects offset in the obj
|
|
unsigned short objectOffset = g_pCompilerData->dis[disPtr + 1];
|
|
// the offset (number of longs) to the sub-object offset list within this obj
|
|
unsigned char subObjectOffsetListPtr = g_pCompilerData->obj[objectOffset + 2];
|
|
// pointer to the sub-object offset list for this obj
|
|
unsigned short* pSubObjectOffsetList = (unsigned short*)&(g_pCompilerData->obj[objectOffset + (subObjectOffsetListPtr * 4)]);
|
|
|
|
for (int i = 0; i < numSubObjects; i++)
|
|
{
|
|
unsigned short subObjectId = g_pCompilerData->dis[disPtr + 3 + i] & 0x7FFF;
|
|
|
|
// find offset of sub-object
|
|
int scanDisPtr = 0;
|
|
for (;;)
|
|
{
|
|
if (g_pCompilerData->dis[scanDisPtr] == subObjectId)
|
|
{
|
|
break;
|
|
}
|
|
scanDisPtr += (3 + g_pCompilerData->dis[scanDisPtr + 2]);
|
|
}
|
|
|
|
// enter relative offset of sub-object
|
|
pSubObjectOffsetList[i*2] = g_pCompilerData->dis[scanDisPtr + 1] - objectOffset;
|
|
|
|
// call recursively to reconnect and sub-objects' sub-objects
|
|
DistillReconnect(scanDisPtr);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool DistillObjects()
|
|
{
|
|
int saved_obj_ptr = g_pCompilerData->obj_ptr;
|
|
|
|
if (!DistillSetup())
|
|
{
|
|
return false;
|
|
}
|
|
DistillEliminate();
|
|
DistillRebuild();
|
|
DistillReconnect();
|
|
|
|
g_pCompilerData->distilled_longs = (saved_obj_ptr - g_pCompilerData->obj_ptr) >> 2;
|
|
|
|
char tempStr[64];
|
|
sprintf(tempStr, "\rDistilled longs: %d", g_pCompilerData->distilled_longs);
|
|
if (!PrintString(tempStr))
|
|
{
|
|
return false;
|
|
}
|
|
return PrintChr(13);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
// TERMS OF USE: MIT License //
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this //
|
|
// software and associated documentation files (the "Software"), to deal in the Software //
|
|
// without restriction, including without limitation the rights to use, copy, modify, //
|
|
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to //
|
|
// permit persons to whom the Software is furnished to do so, subject to the following //
|
|
// conditions: //
|
|
// //
|
|
// The above copyright notice and this permission notice shall be included in all copies //
|
|
// or substantial portions of the Software. //
|
|
// //
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, //
|
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A //
|
|
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT //
|
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION //
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE //
|
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|