mirror of
https://github.com/Museum-of-Art-and-Digital-Entertainment/macross.git
synced 2024-11-26 22:51:04 +00:00
581 lines
15 KiB
C
581 lines
15 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.
|
|
*/
|
|
/*
|
|
operandStuff_68000.c -- Various target processor routines to handle
|
|
operands in the Macross assembler (68000 version).
|
|
|
|
Chip Morningstar -- Lucasfilm Ltd.
|
|
|
|
26-April-1985
|
|
*/
|
|
|
|
#include "macrossTypes.h"
|
|
#include "macrossGlobals.h"
|
|
|
|
/* corresponds to routines in buildStuff2.c */
|
|
|
|
operandType *
|
|
buildOperand(kindOfOperand, arg1, arg2, arg3, arg4)
|
|
operandKindType kindOfOperand;
|
|
int arg1;
|
|
int arg2;
|
|
int arg3;
|
|
int arg4;
|
|
{
|
|
operandType *result;
|
|
|
|
result = typeAlloc(operandType);
|
|
result->kindOfOperand = kindOfOperand;
|
|
result->nextOperand = NULL;
|
|
switch (kindOfOperand) {
|
|
|
|
case EXPRESSION_OPND:
|
|
result->theOperand.expressionUnion =
|
|
(expressionOperandBodyType *) arg1;
|
|
break;
|
|
|
|
case STRING_OPND:
|
|
result->theOperand.stringUnion =
|
|
(stringOperandBodyType *) arg1;
|
|
break;
|
|
|
|
case BLOCK_OPND:
|
|
result->theOperand.blockUnion = (BlockOperandBodyType *) arg1;
|
|
break;
|
|
|
|
case D_REGISTER_OPND:
|
|
result->theOperand.dRegisterUnion =
|
|
(dRegisterOperandBodyType *) NULL;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
case A_REGISTER_OPND:
|
|
result->theOperand.aRegisterUnion =
|
|
(aRegisterOperandBodyType *) NULL;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
case A_REGISTER_INDIRECT_OPND:
|
|
result->theOperand.aRegisterIndirectUnion =
|
|
(aRegisterIndirectOperandBodyType *) NULL;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
case POSTINCREMENT_OPND:
|
|
result->theOperand.postincrementUnion =
|
|
(postincrementOperandBodyType *) NULL;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
case PREDECREMENT_OPND:
|
|
result->theOperand.predecrementUnion =
|
|
(predecrementOperandBodyType *) NULL;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
case DISPLACEMENT_OPND:
|
|
result->theOperand.displacementUnion =
|
|
(displacementOperandBodyType *) arg2;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
case SELECTED_OPND:
|
|
result->theOperand.selectionUnion =
|
|
(selectedOperandBodyType *) arg2;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
case INDEXED_OPND:
|
|
result->theOperand.indexedUnion =
|
|
(indexedOperandBodyType *) arg1;
|
|
setRegister(result->kindOfOperand, arg2);
|
|
setIndexRegister(result->kindOfOperand, arg3);
|
|
setWL(result->kindOfOperand, (int)arg4);
|
|
break;
|
|
|
|
case INDEX_SELECTED_OPND:
|
|
result->theOperand.indexSelectedUnion =
|
|
(indexSelectedOperandBodyType *) arg1;
|
|
setRegister(result->kindOfOperand, arg2);
|
|
setIndexRegister(result->kindOfOperand, arg3);
|
|
setWL(result->kindOfOperand, (int)arg4);
|
|
break;
|
|
|
|
case PC_DISPLACEMENT_OPND:
|
|
result->theOperand.pcDisplacementUnion =
|
|
(pcDisplacementOperandBodyType *) arg1;
|
|
break;
|
|
|
|
case PC_INDEXED_OPND:
|
|
result->theOperand.pcIndexedUnion =
|
|
(pcIndexedOperandBodyType *) arg1;
|
|
setIndexRegister(result->kindOfOperand, arg2);
|
|
setWL(result->kindOfOperand, (int)arg3);
|
|
break;
|
|
|
|
case IMMEDIATE_OPND:
|
|
result->theOperand.immediateUnion =
|
|
(immediateOperandBodyType *) arg1;
|
|
break;
|
|
|
|
case ABSOLUTE_SHORT_OPND:
|
|
result->theOperand.absoluteShortUnion =
|
|
(absoluteShortOperandBodyType *) arg1;
|
|
break;
|
|
|
|
case ABSOLUTE_LONG_OPND:
|
|
result->theOperand.absoluteLongUnion =
|
|
(absoluteLongOperandBodyType *) arg1;
|
|
break;
|
|
|
|
case CC_REGISTER_OPND:
|
|
result->theOperand.ccRegisterUnion =
|
|
(ccRegisterOperandBodyType *) NULL;
|
|
break;
|
|
|
|
case STATUS_REGISTER_OPND:
|
|
result->theOperand.statusRegisterUnion =
|
|
(statusRegisterOperandBodyType *) NULL;
|
|
break;
|
|
|
|
case USP_REGISTER_OPND:
|
|
result->theOperand.uspRegisterUnion =
|
|
(uspRegisterOperandBodyType *) NULL;
|
|
break;
|
|
|
|
case CONTROL_REGISTER_OPND:
|
|
result->theOperand.controlRegisterUnion =
|
|
(controlRegisterOperandBodyType *) NULL;
|
|
setRegister(result->kindOfOperand, arg1);
|
|
break;
|
|
|
|
default:
|
|
botch("unknown operand kind: %d\n", kindOfOperand);
|
|
break;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
/* corresponds to routines in fixups.c */
|
|
|
|
operandListType *
|
|
duplicateOperandForFixup(operand, isSpecialFunctionOperand)
|
|
operandListType *operand;
|
|
bool isSpecialFunctionOperand;
|
|
{
|
|
operandListType *result;
|
|
|
|
expressionType *duplicateExpressionForFixup();
|
|
|
|
result = typeAlloc(operandListType);
|
|
result->kindOfOperand = operand->kindOfOperand;
|
|
result->nextOperand = NULL;
|
|
if (operand->kindOfOperand != EXPRESSION_OPND)
|
|
newFixupAddressMode = operand->kindOfOperand;
|
|
switch (operandKindField(operand->kindOfOperand)) {
|
|
|
|
case EXPRESSION_OPND:
|
|
case DISPLACEMENT_OPND:
|
|
case SELECTED_OPND:
|
|
case INDEXED_OPND:
|
|
case INDEX_SELECTED_OPND:
|
|
case PC_DISPLACEMENT_OPND:
|
|
case PC_INDEXED_OPND:
|
|
case IMMEDIATE_OPND:
|
|
case ABSOLUTE_SHORT_OPND:
|
|
case ABSOLUTE_LONG_OPND:
|
|
result->theOperand.expressionUnion =
|
|
duplicateExpressionForFixup(operand->theOperand,
|
|
FALSE, isSpecialFunctionOperand);
|
|
break;
|
|
case D_REGISTER_OPND:
|
|
case A_REGISTER_OPND:
|
|
case A_REGISTER_INDIRECT_OPND:
|
|
case POSTINCREMENT_OPND:
|
|
case PREDECREMENT_OPND:
|
|
case CC_REGISTER_OPND:
|
|
case STATUS_REGISTER_OPND:
|
|
case USP_REGISTER_OPND:
|
|
case CONTROL_REGISTER_OPND:
|
|
result->theOperand = operand->theOperand;
|
|
break;
|
|
case STRING_OPND:
|
|
result->theOperand = operand->theOperand;
|
|
break;
|
|
case BLOCK_OPND:
|
|
error(CANT_FORWARD_REFERENCE_BLOCK_ERROR);
|
|
result = NULL;
|
|
break;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
/* corresponds to routines in garbage.c */
|
|
|
|
#define nullFree(thing) if (thing == NULL) return;
|
|
|
|
void
|
|
freeOperand(operand)
|
|
operandType *operand;
|
|
{
|
|
nullFree(operand);
|
|
switch (operandKindField(operand->kindOfOperand)) {
|
|
|
|
case EXPRESSION_OPND:
|
|
case DISPLACEMENT_OPND:
|
|
case INDEXED_OPND:
|
|
case PC_DISPLACEMENT_OPND:
|
|
case PC_INDEXED_OPND:
|
|
case IMMEDIATE_OPND:
|
|
case ABSOLUTE_SHORT_OPND:
|
|
case ABSOLUTE_LONG_OPND:
|
|
freeExpression(operand->theOperand);
|
|
break;
|
|
|
|
case D_REGISTER_OPND:
|
|
case A_REGISTER_OPND:
|
|
case A_REGISTER_INDIRECT_OPND:
|
|
case POSTINCREMENT_OPND:
|
|
case PREDECREMENT_OPND:
|
|
case CC_REGISTER_OPND:
|
|
case STATUS_REGISTER_OPND:
|
|
case USP_REGISTER_OPND:
|
|
case CONTROL_REGISTER_OPND:
|
|
break;
|
|
|
|
case SELECTED_OPND:
|
|
case INDEX_SELECTED_OPND:
|
|
freeSelectionList(operand->theOperand);
|
|
break;
|
|
|
|
case STRING_OPND:
|
|
freeString(operand->theOperand);
|
|
break;
|
|
|
|
case BLOCK_OPND:
|
|
freeBlock(operand->theOperand);
|
|
break;
|
|
|
|
default:
|
|
botch("bad operand kind in freeOperand %d\n",
|
|
operand->kindOfOperand);
|
|
break;
|
|
}
|
|
freeOperand(operand->nextOperand);
|
|
free(operand);
|
|
}
|
|
|
|
/* corresponds to routines in listing.c */
|
|
|
|
void
|
|
expandOperand(addressMode, buffer)
|
|
operandKindType addressMode;
|
|
char *buffer;
|
|
{
|
|
char *bufferPtr;
|
|
|
|
bufferPtr = buffer;
|
|
switch (operandKindField(addressMode)) {
|
|
case D_REGISTER_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "d");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
break;
|
|
case A_REGISTER_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
break;
|
|
case A_REGISTER_INDIRECT_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "[a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
moreTextOptional(buffer, &bufferPtr, "]");
|
|
break;
|
|
case POSTINCREMENT_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "[a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
moreTextOptional(buffer, &bufferPtr, "]+");
|
|
break;
|
|
case PREDECREMENT_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "-[a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
moreTextOptional(buffer, &bufferPtr, "]");
|
|
break;
|
|
case IMMEDIATE_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "#");
|
|
break;
|
|
case CC_REGISTER_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "ccr");
|
|
break;
|
|
case STATUS_REGISTER_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "sr");
|
|
break;
|
|
case USP_REGISTER_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "usp");
|
|
break;
|
|
case CONTROL_REGISTER_OPND:
|
|
if (getRegister(addressMode) == 1)
|
|
moreTextOptional(buffer, &bufferPtr, "sfc");
|
|
else if (getRegister(addressMode) == 2)
|
|
moreTextOptional(buffer, &bufferPtr, "dfc");
|
|
else
|
|
moreTextOptional(buffer, &bufferPtr, "vbr");
|
|
break;
|
|
case SELECTED_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
break;
|
|
case INDEX_SELECTED_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
if (getIndexRegister(addressMode)<8) {
|
|
moreTextOptional(buffer, &bufferPtr, "[a");
|
|
expandNum(buffer, &bufferPtr,
|
|
getIndexRegister(addressMode));
|
|
} else {
|
|
moreTextOptional(buffer, &bufferPtr, "[d");
|
|
expandNum(buffer, &bufferPtr,
|
|
getIndexRegister(addressMode)-8);
|
|
}
|
|
moreTextOptional(buffer, &bufferPtr, "]");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
expandExpression(buffer, &bufferPtr);
|
|
switch(operandKindField(addressMode)) {
|
|
case DISPLACEMENT_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "[a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
moreTextOptional(buffer, &bufferPtr, "]");
|
|
break;
|
|
case INDEXED_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "[a");
|
|
expandNum(buffer, &bufferPtr, getRegister(addressMode));
|
|
moreTextOptional(buffer, &bufferPtr, ",");
|
|
if (getIndexRegister(addressMode)<8) {
|
|
moreTextOptional(buffer, &bufferPtr, "a");
|
|
expandNum(buffer, &bufferPtr,
|
|
getIndexRegister(addressMode));
|
|
} else {
|
|
moreTextOptional(buffer, &bufferPtr, "d");
|
|
expandNum(buffer, &bufferPtr,
|
|
getIndexRegister(addressMode)-8);
|
|
}
|
|
moreTextOptional(buffer, &bufferPtr, ".");
|
|
if (getWL(addressMode))
|
|
moreTextOptional(buffer, &bufferPtr, "l]");
|
|
else
|
|
moreTextOptional(buffer, &bufferPtr, "w]");
|
|
break;
|
|
case PC_DISPLACEMENT_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "[pc]");
|
|
break;
|
|
case PC_INDEXED_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, "[pc,");
|
|
if (getIndexRegister(addressMode)<8) {
|
|
moreTextOptional(buffer, &bufferPtr, "a");
|
|
expandNum(buffer, &bufferPtr,
|
|
getIndexRegister(addressMode));
|
|
} else {
|
|
moreTextOptional(buffer, &bufferPtr, "d");
|
|
expandNum(buffer, &bufferPtr,
|
|
getIndexRegister(addressMode)-8);
|
|
}
|
|
moreTextOptional(buffer, &bufferPtr, ".");
|
|
if (getWL(addressMode))
|
|
moreTextOptional(buffer, &bufferPtr, "l]");
|
|
else
|
|
moreTextOptional(buffer, &bufferPtr, "w]");
|
|
break;
|
|
case ABSOLUTE_SHORT_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, ".w");
|
|
break;
|
|
case ABSOLUTE_LONG_OPND:
|
|
moreTextOptional(buffer, &bufferPtr, ".l");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* corresponds to routines in expressionSemantics.c */
|
|
|
|
#define nullEvaluate(thing) if (thing==NULL) return(NULL);
|
|
#define fail(err) if (!expressionFailed) {\
|
|
error(err);\
|
|
expressionFailed = TRUE;\
|
|
}
|
|
#define fail1(err,arg) if (!expressionFailed) {\
|
|
error(err,arg);\
|
|
expressionFailed = TRUE;\
|
|
}
|
|
#define fail2(err,arg1,arg2) if (!expressionFailed) {\
|
|
error(err,arg1,arg2);\
|
|
expressionFailed = TRUE;\
|
|
}
|
|
|
|
#define qfree2(a,b) if (freeFlag) { free(a); free(b); }
|
|
|
|
#define expansionOff() {saveExpansion=expandMacros; expandMacros=FALSE;}
|
|
#define forceExpansion() {saveExpansion=expandMacros; expandMacros=TRUE;}
|
|
#define expansionOn() expandMacros=saveExpansion;
|
|
|
|
valueType *
|
|
evaluateOperand(operand)
|
|
operandType *operand;
|
|
{
|
|
valueType *result;
|
|
bool saveExpansion;
|
|
expressionType *expression;
|
|
|
|
valueType *evaluateExpression();
|
|
valueType *evaluateSelectionList();
|
|
valueType *newValue();
|
|
|
|
nullEvaluate(operand);
|
|
if (operand->kindOfOperand != EXPRESSION_OPND)
|
|
newFixupAddressMode = operand->kindOfOperand;
|
|
switch (operandKindField(operand->kindOfOperand)) {
|
|
|
|
case EXPRESSION_OPND:
|
|
case DISPLACEMENT_OPND:
|
|
case INDEXED_OPND:
|
|
case PC_DISPLACEMENT_OPND:
|
|
case PC_INDEXED_OPND:
|
|
case IMMEDIATE_OPND:
|
|
case ABSOLUTE_SHORT_OPND:
|
|
case ABSOLUTE_LONG_OPND:
|
|
result = evaluateExpression(operand->theOperand,
|
|
performingFixups ? NO_FIXUP : OPERAND_FIXUP);
|
|
if (operand->kindOfOperand != EXPRESSION_OPND) {
|
|
if (result->addressMode != EXPRESSION_OPND) {
|
|
error(BAD_ADDRESS_MODE_ERROR);
|
|
result->kindOfValue = FAIL;
|
|
} else {
|
|
result->addressMode = operand->kindOfOperand;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SELECTED_OPND:
|
|
case INDEX_SELECTED_OPND:
|
|
result = evaluateSelectionList(operand->theOperand);
|
|
if (result->addressMode != EXPRESSION_OPND) {
|
|
error(BAD_ADDRESS_MODE_ERROR);
|
|
result->kindOfValue = FAIL;
|
|
} else {
|
|
result->addressMode = operand->kindOfOperand;
|
|
}
|
|
break;
|
|
|
|
case D_REGISTER_OPND:
|
|
case A_REGISTER_OPND:
|
|
case A_REGISTER_INDIRECT_OPND:
|
|
case POSTINCREMENT_OPND:
|
|
case PREDECREMENT_OPND:
|
|
case CC_REGISTER_OPND:
|
|
case STATUS_REGISTER_OPND:
|
|
case USP_REGISTER_OPND:
|
|
case CONTROL_REGISTER_OPND:
|
|
result = newValue(ABSOLUTE_VALUE, 0, operand->
|
|
kindOfOperand);
|
|
break;
|
|
|
|
case STRING_OPND:
|
|
result = newValue(STRING_VALUE, operand->theOperand,
|
|
STRING_OPND);
|
|
break;
|
|
|
|
case BLOCK_OPND:
|
|
if (standaloneExpansionFlag)
|
|
forceExpansion();
|
|
assembleBlock(operand->theOperand);
|
|
expansionOn();
|
|
result = newValue(FAIL, 0, BLOCK_OPND);
|
|
break;
|
|
|
|
default:
|
|
botch("bad operand kind in evaluateOperand %d\n",
|
|
operand->kindOfOperand);
|
|
break;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
/* from parserMisc.c */
|
|
|
|
conditionType
|
|
invertConditionCode(conditionCode)
|
|
conditionType conditionCode;
|
|
{
|
|
#define cc (int)conditionCode
|
|
|
|
if ((int)CARRY_COND<=cc && cc<=(int)ALWAYS_COND)
|
|
return((conditionType)
|
|
(cc - (int)CARRY_COND + (int)NOT_CARRY_COND));
|
|
else if ((int)NOT_CARRY_COND<=cc && cc<=(int)NEVER_COND)
|
|
return((conditionType)
|
|
(cc + (int)CARRY_COND - (int)NOT_CARRY_COND));
|
|
else
|
|
botch("invertConditionCode given %d, not a condition code\n");
|
|
}
|
|
|
|
/* from semanticMisc.c */
|
|
|
|
bool
|
|
shouldParenthesize(operand)
|
|
operandType *operand;
|
|
{
|
|
expressionTermKindType kind;
|
|
|
|
switch(operandKindField(operand->kindOfOperand)) {
|
|
case EXPRESSION_OPND:
|
|
case DISPLACEMENT_OPND:
|
|
case INDEXED_OPND:
|
|
case PC_DISPLACEMENT_OPND:
|
|
case PC_INDEXED_OPND:
|
|
case IMMEDIATE_OPND:
|
|
case ABSOLUTE_SHORT_OPND:
|
|
case ABSOLUTE_LONG_OPND:
|
|
kind = operand->theOperand.expressionUnion->kindOfTerm;
|
|
return (kind==UNOP_EXPR || kind==BINOP_EXPR || kind==
|
|
ASSIGN_EXPR);
|
|
break;
|
|
|
|
case STRING_OPND:
|
|
case BLOCK_OPND:
|
|
case D_REGISTER_OPND:
|
|
case A_REGISTER_OPND:
|
|
case A_REGISTER_INDIRECT_OPND:
|
|
case POSTINCREMENT_OPND:
|
|
case PREDECREMENT_OPND:
|
|
case CC_REGISTER_OPND:
|
|
case STATUS_REGISTER_OPND:
|
|
case USP_REGISTER_OPND:
|
|
case CONTROL_REGISTER_OPND:
|
|
case SELECTED_OPND:
|
|
case INDEX_SELECTED_OPND:
|
|
return(FALSE);
|
|
break;
|
|
}
|
|
}
|