macross/slinky/poke.c

215 lines
5.3 KiB
C

/*
* Copyright (c) 1987 Fujitsu
*
* 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.
*/
/*
poke.c -- Routines to poke the values of symbolic references into the
generated code for the Slinky linker.
Chip Morningstar -- Lucasfilm Ltd.
18-March-1985
*/
#include "slinkyTypes.h"
#include "slinkyGlobals.h"
bool
isWordSized(value)
int value;
{
return (-32768<=value && value<=65535);
}
bool
isByteSized(value)
int value;
{
return (-128<=value && value<=255);
}
bool
isByteOffset(value)
int value;
{
return (-128<=value && value<=127);
}
int
computeRelativeValue(valueToPoke, codeSegment, offset)
int valueToPoke;
codeSegmentHeaderType *codeSegment;
int offset;
{
int fromLocation;
int result;
fromLocation = codeSegment->segmentStartAddress + offset;
result = valueToPoke - fromLocation;
/* if (result > 0)*/ if (result != 0)
result = result - 1;
else if (result < 0)
result = result + 1;
if (!isByteOffset(result)) {
error(RELATIVE_OFFSET_TOO_LARGE_ERROR, result, offset,
fromLocation);
result = 0;
}
return(result);
}
int
getBaseValue(codeBuffer, offset, referenceKind)
byte codeBuffer[];
int offset;
int referenceKind;
{
int result;
switch (referenceKind) {
case REF_BYTE:
result = codeBuffer[offset];
break;
case REF_DBYTE:
result = (codeBuffer[offset] << 8) | codeBuffer[offset+1];
break;
case REF_WORD:
result = codeBuffer[offset] | (codeBuffer[offset+1] << 8);
break;
}
return(result);
}
void
pokeValue(value, codeBuffer, offset, referenceKind, trueAddress)
int value;
byte codeBuffer[];
int offset;
int referenceKind;
int trueAddress;
{
switch (referenceKind) {
case REF_BYTE:
if (!isByteSized(value)) {
error(BYTE_VALUE_TOO_LARGE_ERROR, value, offset,
trueAddress);
} else {
codeBuffer[offset] = value;
}
if (debug)
printf(" Byte: 0x%02x at (0x%04x) 0x%04x\n\n",
value&0xFF, offset, trueAddress);
break;
case REF_WORD:
if (!isWordSized(value)) {
error(WORD_VALUE_TOO_LARGE_ERROR, value, offset,
trueAddress);
} else {
codeBuffer[offset] = value & 0xFF;
codeBuffer[offset+1] = (value >> 8) & 0xFF;
}
if (debug)
printf(" Word: 0x%04x at (0x%04x) 0x%04x\n\n",
value, offset, trueAddress);
break;
case REF_DBYTE:
if (!isWordSized(value)) {
error(WORD_VALUE_TOO_LARGE_ERROR, value, offset,
trueAddress);
} else {
codeBuffer[offset] = (value >> 8) & 0xFF;
codeBuffer[offset+1] = 0xFF;
}
if (debug)
printf(" Dbyt: 0x%04x at (0x%04x) 0x%04x\n\n",
value, offset, trueAddress);
break;
}
}
void
fixupReference(reference, codeSegment)
expressionReferenceType *reference;
codeSegmentHeaderType *codeSegment;
{
int offset;
addressType baseValue;
int valueToPoke;
/* at this point, we assume we are already pointing at the
correct codeSegment! */
if (debug)
printReferenceFixup(reference);
offset = reference->referenceAddress - codeSegment->
segmentStartAddress + codeSegment->relocationOffset;
relocationOffset = codeSegment->relocationOffset;
baseValue = getBaseValue(codeSegment->segmentCodeBuffer, offset,
reference->referenceKind);
pc = reference->referenceExpression.inCore;
valueToPoke = evaluateExpression();
if (reference->referenceRelative)
valueToPoke = computeRelativeValue(valueToPoke, codeSegment,
offset);
else
valueToPoke = (short)baseValue + (short)valueToPoke;
pokeValue(valueToPoke, codeSegment->segmentCodeBuffer, offset,
reference->referenceKind, codeSegment->segmentStartAddress +
offset);
}
void
pokem()
{
objectFileListType *inputFileList;
codeSegmentHeaderType *codeSegment;
expressionReferenceType *reference;
int referenceCount;
if (debug)
printf("\nFixups:\n");
if (haveExpressionEntryPoint) {
pc = entryPointExpression;
entryPointAddress = evaluateExpression();
}
for (inputFileList = objectFileList; inputFileList != NULL;
inputFileList = inputFileList->nextObjectFile) {
if (inputFileList->name != NULL) {
currentFileName = inputFileList->name;
for (codeSegment = inputFileList->codeSegments; codeSegment!=
NULL; codeSegment = codeSegment->nextSegment) {
for (reference=codeSegment->segmentReferences,
referenceCount=codeSegment->referenceCount;
referenceCount >0; reference++, referenceCount--){
fixupReference(reference, codeSegment);
}
}
}
}
}