// Copyright (C) 1999-2003 Core Technologies. // // This file is part of tpasm. // // tpasm is free software; you can redistribute it and/or modify // it under the terms of the tpasm LICENSE AGREEMENT. // // tpasm is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // tpasm LICENSE AGREEMENT for more details. // // You should have received a copy of the tpasm LICENSE AGREEMENT // along with tpasm; see the file "LICENSE.TXT". // Generate code for Motorola 6805 #include "include.h" static SYMTABLE *pseudoOpcodeSymbols, *opcodeSymbols; // enumerated addressing modes #define OT_INHERENT 0 // no operands #define OT_IMMEDIATE 1 // one byte immediate operand #define OT_DIRECT 2 // one byte direct #define OT_EXTENDED 3 // two byte absolute #define OT_INDIRECT_2 4 // indirect with 2 bytes of offset #define OT_INDIRECT_1 5 // indirect with 1 byte of offset #define OT_INDIRECT_0 6 // indirect with 0 bytes of offset #define OT_RELATIVE 7 // one byte relative offset #define OT_BIT_DIRECT 8 // (convenience) one byte of direct, one relative offset #define OT_DIRECT_RELATIVE 9 // one byte of direct, one relative offset #define OT_BIT_DIRECT_RELATIVE 10 // (convenience) one bit index, one byte of direct, one relative offset #define OT_NUM OT_BIT_DIRECT_RELATIVE+1 // number of addressing modes // masks for the various addressing modes #define M_INHERENT (1<typeMask&M_IMMEDIATE) { CheckByteRange(value,true,true); if(GenerateByte(theOpcode->baseOpcode[OT_IMMEDIATE],listingRecord)) { fail=!GenerateByte(value,listingRecord); } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleDirect(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // deal with direct mode output only { bool fail; fail=false; if(theOpcode->typeMask&M_DIRECT) { CheckUnsignedByteRange(value,true,true); if(GenerateByte(theOpcode->baseOpcode[OT_DIRECT],listingRecord)) { fail=!GenerateByte(value,listingRecord); } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleExtended(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // deal with extended mode output only { bool fail; fail=false; if(theOpcode->typeMask&M_EXTENDED) { CheckUnsignedWordRange(value,true,true); if(GenerateByte(theOpcode->baseOpcode[OT_EXTENDED],listingRecord)) { if(GenerateByte(value>>8,listingRecord)) { fail=!GenerateByte(value&0xFF,listingRecord); } else { fail=true; } } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleDirectOrExtended(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // a direct or extended address has been parsed { bool fail; fail=false; if(theOpcode->typeMask&M_DIRECT) { if(((value>=0)&&(value<256))||!(theOpcode->typeMask&M_EXTENDED)) { fail=!HandleDirect(theOpcode,value,unresolved,listingRecord); } else { fail=!HandleExtended(theOpcode,value,unresolved,listingRecord); } } else { fail=!HandleExtended(theOpcode,value,unresolved,listingRecord); } return(!fail); } static bool HandleIndirect0(OPCODE *theOpcode,LISTING_RECORD *listingRecord) // an indirect 0 addressing mode was located { bool fail; fail=false; if(theOpcode->typeMask&M_INDIRECT_0) { fail=!GenerateByte(theOpcode->baseOpcode[OT_INDIRECT_0],listingRecord); } else { ReportBadOperands(); } return(!fail); } static bool HandleIndirect1(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an indirect 1 addressing mode was located { bool fail; fail=false; if(theOpcode->typeMask&M_INDIRECT_1) { CheckUnsignedByteRange(value,true,true); if(GenerateByte(theOpcode->baseOpcode[OT_INDIRECT_1],listingRecord)) { fail=!GenerateByte(value,listingRecord); } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleIndirect2(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an indirect 2 addressing mode was located { bool fail; fail=false; if(theOpcode->typeMask&M_INDIRECT_2) { CheckUnsignedWordRange(value,true,true); if(GenerateByte(theOpcode->baseOpcode[OT_INDIRECT_2],listingRecord)) { if(GenerateByte(value>>8,listingRecord)) { fail=!GenerateByte(value&0xFF,listingRecord); } else { fail=true; } } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleIndirect1or2(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an indirect 1 or 2 addressing mode was located { bool fail; fail=false; if(theOpcode->typeMask&M_INDIRECT_1) { if(((value>=0)&&(value<256))||!(theOpcode->typeMask&M_INDIRECT_2)) { fail=!HandleIndirect1(theOpcode,value,unresolved,listingRecord); } else { fail=!HandleIndirect2(theOpcode,value,unresolved,listingRecord); } } else { fail=!HandleIndirect2(theOpcode,value,unresolved,listingRecord); } return(!fail); } static bool HandleBitDirect(OPCODE *theOpcode,int value1,bool unresolved1,int value2,bool unresolved2,LISTING_RECORD *listingRecord) // a bit direct operand has been parsed { bool fail; fail=false; if(theOpcode->typeMask&M_BIT_DIRECT) { Check8BitIndexRange(value1,true,true); CheckUnsignedByteRange(value2,true,true); value1&=0x07; if(GenerateByte(theOpcode->baseOpcode[OT_BIT_DIRECT]|(value1<<1),listingRecord)) { fail=!GenerateByte(value2,listingRecord); } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleDirectRelative(OPCODE *theOpcode,int value1,bool unresolved1,int value2,bool unresolved2,LISTING_RECORD *listingRecord) // a direct relative operand has been parsed { int offset; bool fail; fail=false; if(theOpcode->typeMask&M_DIRECT_RELATIVE) { if(GenerateByte(theOpcode->baseOpcode[OT_DIRECT_RELATIVE],listingRecord)) { CheckUnsignedByteRange(value1,true,true); if(GenerateByte(value1,listingRecord)) { offset=0; if(!unresolved2&¤tSegment) { offset=value2-(currentSegment->currentPC+currentSegment->codeGenOffset)-1; Check8RelativeRange(offset,true,true); } fail=!GenerateByte(offset,listingRecord); } else { fail=true; } } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleBitDirectRelative(OPCODE *theOpcode,int value1,bool unresolved1,int value2,bool unresolved2,int value3,bool unresolved3,LISTING_RECORD *listingRecord) // a bit direct relative operand has been parsed { int offset; bool fail; fail=false; if(theOpcode->typeMask&M_BIT_DIRECT_RELATIVE) { Check8BitIndexRange(value1,true,true); value1&=0x07; if(GenerateByte(theOpcode->baseOpcode[OT_BIT_DIRECT_RELATIVE]|(value1<<1),listingRecord)) { CheckUnsignedByteRange(value2,true,true); if(GenerateByte(value2,listingRecord)) { offset=0; if(!unresolved3&¤tSegment) { offset=value3-(currentSegment->currentPC+currentSegment->codeGenOffset)-1; Check8RelativeRange(offset,true,true); } fail=!GenerateByte(offset,listingRecord); } else { fail=true; } } else { fail=true; } } else { ReportBadOperands(); } return(!fail); } static bool HandleRelative(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // a relative operand has been parsed { bool fail; int offset; fail=false; if(GenerateByte(theOpcode->baseOpcode[OT_RELATIVE],listingRecord)) { offset=0; if(!unresolved&¤tSegment) { offset=value-(currentSegment->currentPC+currentSegment->codeGenOffset)-1; Check8RelativeRange(offset,true,true); } fail=!GenerateByte(offset,listingRecord); } else { fail=true; } return(!fail); } static bool HandleSingleAddress(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // a lone address has been parsed // This means it is either a relative address, direct, or extended { bool fail; fail=false; if(theOpcode->typeMask&M_RELATIVE) { fail=!HandleRelative(theOpcode,value,unresolved,listingRecord); } else if(theOpcode->typeMask&(M_DIRECT|M_EXTENDED)) { fail=!HandleDirectOrExtended(theOpcode,value,unresolved,listingRecord); } else { ReportBadOperands(); } return(!fail); } static bool HandleDoubleAddress(OPCODE *theOpcode,int value1,bool unresolved1,int value2,bool unresolved2,LISTING_RECORD *listingRecord) // a dual address has been parsed // This means it is either BIT_DIRECT, or DIRECT_RELATIVE { bool fail; fail=false; if(theOpcode->typeMask&M_BIT_DIRECT) { fail=!HandleBitDirect(theOpcode,value1,unresolved1,value2,unresolved2,listingRecord); } else if(theOpcode->typeMask&M_DIRECT_RELATIVE) { fail=!HandleDirectRelative(theOpcode,value1,unresolved1,value2,unresolved2,listingRecord); } else { ReportBadOperands(); } return(!fail); } static bool HandleTripleAddress(OPCODE *theOpcode,int value1,bool unresolved1,int value2,bool unresolved2,int value3,bool unresolved3,LISTING_RECORD *listingRecord) // a triple address has been parsed // This means it is BIT_DIRECT_RELATIVE { bool fail; fail=false; if(theOpcode->typeMask&M_BIT_DIRECT_RELATIVE) { fail=!HandleBitDirectRelative(theOpcode,value1,unresolved1,value2,unresolved2,value3,unresolved3,listingRecord); } else { ReportBadOperands(); } return(!fail); } static bool HandleSecondValue(OPCODE *theOpcode,char *theLine,int *lineIndex,int value1,bool unresolved1,int value2,bool unresolved2,LISTING_RECORD *listingRecord) // there are two value, and something still remains // the only 3 valued operand type is BIT_DIRECT_RELATIVE // so parse and apply { bool fail; int elementType; int value3; bool unresolved3; fail=false; if(ParseCommaSeparator(theLine,lineIndex)) // make sure the next thing separates operands { if(ParseOperandElement(theLine,lineIndex,&elementType,&value3,&unresolved3)) { if(elementType==POT_VALUE) { if(ParseComment(theLine,lineIndex)) { return(HandleTripleAddress(theOpcode,value1,unresolved1,value2,unresolved2,value3,unresolved3,listingRecord)); } else { ReportBadOperands(); } } else { ReportBadOperands(); } } else { ReportBadOperands(); } } else { ReportBadOperands(); } return(!fail); } static bool HandleFirstValue(OPCODE *theOpcode,char *theLine,int *lineIndex,int value1,bool unresolved1,LISTING_RECORD *listingRecord) // a non-immediate value was parsed, so see what else we can find { bool fail; int elementType; int value2; bool unresolved2; fail=false; if(ParseCommaSeparator(theLine,lineIndex)) // make sure the next thing separates operands { if(ParseOperandElement(theLine,lineIndex,&elementType,&value2,&unresolved2)) { if(elementType==POT_INDEX) { if(ParseComment(theLine,lineIndex)) { return(HandleIndirect1or2(theOpcode,value1,unresolved1,listingRecord)); } else { ReportBadOperands(); } } else if(elementType==POT_VALUE) { if(ParseComment(theLine,lineIndex)) { return(HandleDoubleAddress(theOpcode,value1,unresolved1,value2,unresolved2,listingRecord)); } else { return(HandleSecondValue(theOpcode,theLine,lineIndex,value1,unresolved1,value2,unresolved2,listingRecord)); } } else { ReportBadOperands(); } } else { ReportBadOperands(); } } else { ReportBadOperands(); } return(!fail); } static bool HandleOpcode(void *theOpcode,char *theLine,int *lineIndex,LISTING_RECORD *listingRecord) // look at the type of opcode available, parse operands as allowed // return false only if there was a 'hard' error { OPCODE *actualOpcode; bool fail; int elementType; int value; bool unresolved; fail=false; actualOpcode=(OPCODE *)theOpcode; if(!ParseComment(theLine,lineIndex)) { if(ParseCommaSeparator(theLine,lineIndex)) // see if initial separator (allowed if next thing is an index register) { if(ParseOperandElement(theLine,lineIndex,&elementType,&value,&unresolved)) { if(elementType==POT_INDEX) { if(ParseComment(theLine,lineIndex)) { return(HandleIndirect0(actualOpcode,listingRecord)); } else { ReportBadOperands(); } } else { ReportBadOperands(); } } else { ReportBadOperands(); } } else // first character of operand was not a ',' { if(ParseOperandElement(theLine,lineIndex,&elementType,&value,&unresolved)) { if(elementType==POT_INDEX) { if(ParseComment(theLine,lineIndex)) { return(HandleIndirect0(actualOpcode,listingRecord)); } else { ReportBadOperands(); } } else if(elementType==POT_IMMEDIATE) { if(ParseComment(theLine,lineIndex)) { return(HandleImmediate(actualOpcode,value,unresolved,listingRecord)); } else { ReportBadOperands(); } } else if(elementType==POT_VALUE) { if(ParseComment(theLine,lineIndex)) { return(HandleSingleAddress(actualOpcode,value,unresolved,listingRecord)); } else { return(HandleFirstValue(actualOpcode,theLine,lineIndex,value,unresolved,listingRecord)); } } } else { ReportBadOperands(); } } } else { if(actualOpcode->typeMask&M_INHERENT) { fail=!GenerateByte(actualOpcode->baseOpcode[OT_INHERENT],listingRecord); } else { ReportBadOperands(); } } return(!fail); } static void *MatchOpcode(char *theOpcode) // match opcodes for this processor, return NULL if none matched { return(STFindDataForName(opcodeSymbols,theOpcode)); } static bool HandlePseudoOpcode(PSEUDO_OPCODE *theOpcode,char *theLine,int *lineIndex,bool haveLabel,bool isLocal,char *lineLabel,LISTING_RECORD *listingRecord) // look at the type of opcode available, parse operands as allowed // return false only if there was a 'hard' error { return(theOpcode->theFunction(theOpcode,theLine,lineIndex,haveLabel,isLocal,lineLabel,listingRecord)); } static PSEUDO_OPCODE *MatchPseudoOpcode(char *theOpcode) // match pseudo opcodes for this processor, return NULL if none matched { return((PSEUDO_OPCODE *)STFindDataForName(pseudoOpcodeSymbols,theOpcode)); } static bool SelectProcessor(PROCESSOR *theProcessor) // A processor in this family is being selected to assemble with { return(true); } static void DeselectProcessor(PROCESSOR *theProcessor) // A processor in this family is being deselected { } static void UnInitFamily() // undo what InitFamily did { STDisposeSymbolTable(opcodeSymbols); STDisposeSymbolTable(pseudoOpcodeSymbols); } static bool InitFamily() // initialize symbol table { unsigned int i; bool fail; fail=false; if((pseudoOpcodeSymbols=STNewSymbolTable())) { for(i=0;!fail&&(i