//----------------------------------------------------------------------------- // 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". // //----------------------------------------------------------------------------- #include "include.h" static SYMTABLE *pseudoOpcodeSymbols, *opcodeSymbols, *regNameSymbols; // register names // enumerated addressing modes enum { OT_IMPLIED=0, // no operands OT_IMMEDIATE8, // one byte immediate operand OT_IMMEDIATE16, // two byte immediate operand OT_DIRECT, // one byte direct OT_EXTENDED, // two byte absolute OT_RELATIVE8, // one byte relative offset OT_RELATIVE16, // two byte relative offset OT_INDEXED, // indexed (many forms) OT_REGREG, // 2 8 or 16 bit registers OT_STACKS, // stacked register list for S OT_STACKU, // stacked register list for U OT_NUM // number of addressing modes }; // masks for the various addressing modes #define M_IMPLIED (1<numRegs=0; fail=false; done=false; while(!fail&&!done) { if(ParseRegister(theLine,lineIndex,®isterIndex)) { if(registerList->numRegstheRegisters[registerList->numRegs]=(unsigned char)registerIndex; registerList->numRegs++; } if(!ParseComment(theLine,lineIndex)) // if non-end of line, then we must see a separator { if(!ParseCommaSeparator(theLine,lineIndex)) // get the separator { fail=true; } } else { done=true; } } else { fail=true; } } if(!fail) { return(true); } *lineIndex=initialIndex; // put this back if parsing fails return(false); } static bool ParseOffsetRegister(char *theLine,int *lineIndex,int *registerIndex) // Parse a register that can be used for the offset of an indexed addressing mode { int initialIndex; initialIndex=*lineIndex; if(ParseRegister(theLine,lineIndex,registerIndex)) // see if a register can be parsed { if((*registerIndex==R_D)||(*registerIndex==R_A)||(*registerIndex==R_B)) // make sure it is valid as an offset register { return(true); } } *lineIndex=initialIndex; return(false); } static bool ParseIndexRegister(char *theLine,int *lineIndex,int *registerIndex,int *incdecCount) // Parse a register that can be used for the index of an indexed addressing mode, also // handle pre-decrement and post-increment { int initialIndex; *incdecCount=0; initialIndex=*lineIndex; while((*incdecCount>=-1)&&!ParseComment(theLine,lineIndex)&&(theLine[*lineIndex]=='-')) { (*lineIndex)++; (*incdecCount)--; } ParseComment(theLine,lineIndex); if(ParseRegister(theLine,lineIndex,registerIndex)) // see if a register can be parsed { if((*registerIndex==R_X)||(*registerIndex==R_Y)||(*registerIndex==R_U)||(*registerIndex==R_S)||(*registerIndex==R_PC)) { if(*incdecCount==0) // if no predecrement, allow postincrement { while((*incdecCount<=1)&&!ParseComment(theLine,lineIndex)&&(theLine[*lineIndex]=='+')) { (*lineIndex)++; (*incdecCount)++; } return(true); } else // had predecrement, so done { return(true); } } } *lineIndex=initialIndex; return(false); } static bool ParseIndexedNonIndirect(char *theLine,int *lineIndex,INDEXEDADDRESS *indexedAddress) // Attempt to parse an indexed address, but do not pay attention to indirection. // Also, return true as soon as the end of the indexed address is encountered -- even // if not at the end of the line. { int initialIndex; int registerIndex; bool fail; bool done; indexedAddress->haveIndex=false; initialIndex=*lineIndex; fail=done=false; if(ParseCommaSeparator(theLine,lineIndex)) // an initial ',' is allowed, it means that the index is immediate 0 { indexedAddress->offsetIsConstant=true; indexedAddress->constantOffset=0; indexedAddress->constantOffsetUnresolved=false; } else if(ParseOffsetRegister(theLine,lineIndex,®isterIndex)) // if not an initial ',' then try to get an offset register { if(!ParseComment(theLine,lineIndex)) // must not see end of the line at this point { if(ParseCommaSeparator(theLine,lineIndex)) // must have the ',' following the offset register { indexedAddress->offsetIsConstant=false; indexedAddress->offsetRegister=registerIndex; } else { fail=true; } } else { fail=true; } } else if(ParseIndexRegister(theLine,lineIndex,&indexedAddress->indexRegister,&indexedAddress->incdecCount)) // try to get just plain index register { indexedAddress->offsetIsConstant=true; indexedAddress->constantOffsetUnresolved=false; indexedAddress->constantOffset=0; indexedAddress->haveIndex=true; done=true; } else if(ParseExpression(theLine,lineIndex,&indexedAddress->constantOffset,&indexedAddress->constantOffsetUnresolved)) // otherwise, see if expression { indexedAddress->offsetIsConstant=true; if(!ParseComment(theLine,lineIndex)) // if not at the end, then expect a register { if(ParseCommaSeparator(theLine,lineIndex)) // must have the ',' following the offset expression { } else { fail=true; } } else { done=true; // saw an expression, but no index register (this is valid) } } else { fail=true; } if(!fail&&!done) { if(!ParseComment(theLine,lineIndex)) // must not see end of the line at this point { if(ParseIndexRegister(theLine,lineIndex,&indexedAddress->indexRegister,&indexedAddress->incdecCount)) // try to get index register { indexedAddress->haveIndex=true; // got one } else { fail=true; } } } if(!fail) { return(true); // got indexed address! } *lineIndex=initialIndex; // put this back if parsing fails return(false); } static bool ParseIndexed(char *theLine,int *lineIndex,INDEXEDADDRESS *indexedAddress) // Attempt to parse an indexed address. If one can be parsed, update lineIndex, and indexedAddress, // then return true // Otherwise, leave lineIndex unmodified, and return false { int initialIndex; bool fail; initialIndex=*lineIndex; indexedAddress->indirect=false; fail=false; if(theLine[*lineIndex]=='[') // indirect? { (*lineIndex)++; indexedAddress->indirect=true; // remember that } if(!ParseComment(theLine,lineIndex)) // must not see end of the line at this point { if(ParseIndexedNonIndirect(theLine,lineIndex,indexedAddress)) // try to get indexed address { if(indexedAddress->indirect) // if indirect, then we also need the closing ']' { if(!ParseComment(theLine,lineIndex)) { if(theLine[*lineIndex]==']') { (*lineIndex)++; } else { fail=true; } } else { fail=true; } } } else { fail=true; } } else { fail=true; } if(!fail) { if(ParseComment(theLine,lineIndex)) // need to see end of line now { return(true); } } *lineIndex=initialIndex; // put this back if parsing fails return(false); } static bool ParseAbsolute(char *theLine,int *lineIndex,int *value,bool *unresolved) // Attempt to parse an absolute value. If one can be parsed, update lineIndex, value, and unresolved, // then return true // Otherwise, leave lineIndex unmodified, and return false { int initialIndex; initialIndex=*lineIndex; if(ParseExpression(theLine,lineIndex,value,unresolved)) { if(ParseComment(theLine,lineIndex)) { return(true); } } *lineIndex=initialIndex; // put this back if parsing fails return(false); } static bool ParsePossibleOperands(char *theLine,int *lineIndex,int typeMask,int *operandType,int *value,bool *unresolved,INDEXEDADDRESS *indexedAddress,REGLIST *registerList) // passed a line and offset to the operands, attempt to parse // out one of the generic operand types based on the explicit operand types // allowed for the current opcode // If something is successfully parsed, then return true, else return false // NOTE: if the returned type is POT_VALUE or POT_IMMEDIATE, then the result is contained // in value, and unresolved. // If the returned type is POT_INDEXED, the result is contained in indexedAddress. // If the returned type is POT_REGLIST, the result is contained in registerList. { if(typeMask&(M_IMMEDIATE8|M_IMMEDIATE16)) // see if some sort of immediate value is allowed { if(ParseImmediate(theLine,lineIndex,value,unresolved)) { *operandType=POT_IMMEDIATE; return(true); } } if(typeMask&(M_REGREG|M_STACKS|M_STACKU)) // see if some sort of register list is allowed (this takes precedence over indexed addressing) { if(ParseRegisterList(theLine,lineIndex,registerList)) { *operandType=POT_REGLIST; return(true); } } if(typeMask&M_INDEXED) // see if indexed addressing is allowed { if(ParseIndexed(theLine,lineIndex,indexedAddress)) { if(!indexedAddress->haveIndex&&!indexedAddress->indirect&&indexedAddress->offsetIsConstant) // convert non-index register operand into a value { if(typeMask&(M_DIRECT|M_EXTENDED|M_RELATIVE8|M_RELATIVE16)) // see if some sort of absolute value is allowed { *operandType=POT_VALUE; *value=indexedAddress->constantOffset; *unresolved=indexedAddress->constantOffsetUnresolved; return(true); } } else { *operandType=POT_INDEXED; return(true); } } } else if(typeMask&(M_DIRECT|M_EXTENDED|M_RELATIVE8|M_RELATIVE16)) // see if some sort of absolute value is allowed (only check if not indexed, otherwise he tests it) { if(ParseAbsolute(theLine,lineIndex,value,unresolved)) { *operandType=POT_VALUE; return(true); } } return(false); } static bool WriteOpcode(opcode_t opcode,LISTING_RECORD *listingRecord) // Write the passed opcode out -- pay attention to the "prebyte" // and write it only if it is non-zero { bool fail; unsigned char prebyte; fail=false; prebyte=(opcode>>8)&0xff; if(prebyte) // if it has a pre-byte, put out both bytes { fail=!GenerateByte(prebyte,listingRecord); } if(!fail) { fail=!GenerateByte(opcode&0xff,listingRecord); } return(!fail); } static bool HandleDirect(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // deal with direct mode output only // return false only on 'hard' errors { bool fail; fail=false; CheckUnsignedByteRange(value,true,true); // make sure the value is in range if(WriteOpcode(theOpcode->baseOpcode[OT_DIRECT],listingRecord)) { fail=!GenerateByte(value,listingRecord); } else { fail=true; } return(!fail); } static bool HandleExtended(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // deal with extended mode output only // return false only on 'hard' errors { bool fail; fail=false; CheckUnsignedWordRange(value,true,true); // make sure the value is in range if(WriteOpcode(theOpcode->baseOpcode[OT_EXTENDED],listingRecord)) { if(GenerateByte(value>>8,listingRecord)) { fail=!GenerateByte(value&0xFF,listingRecord); } else { fail=true; } } else { fail=true; } return(!fail); } static bool HandleDirectOrExtended(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // a direct or extended address has been parsed // work out which, and generate code // return false only on 'hard' errors { if((value>=0)&&(value<256)) { return(HandleDirect(theOpcode,value,unresolved,listingRecord)); } else { return(HandleExtended(theOpcode,value,unresolved,listingRecord)); } } static bool HandleRelative8(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // a relative 8 bit operand has been parsed // return false only on 'hard' errors { bool fail; int offset; if(WriteOpcode(theOpcode->baseOpcode[OT_RELATIVE8],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 HandleRelative16(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // a relative 16 bit operand has been parsed // return false only on 'hard' errors { bool fail; int offset; if(WriteOpcode(theOpcode->baseOpcode[OT_RELATIVE16],listingRecord)) { offset=0; if(!unresolved&¤tSegment) { offset=value-(currentSegment->currentPC+currentSegment->codeGenOffset+2); Check16RelativeRange(offset,true,true); } if(GenerateByte(offset>>8,listingRecord)) { fail=!GenerateByte(offset&0xFF,listingRecord); } else { fail=true; } } else { fail=true; } return(!fail); } static bool HandleRelative(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // a relative operand (8 or 16 bit) has been parsed // return false only on 'hard' errors { int offset; offset=0; if(!unresolved&¤tSegment) { offset=value-(currentSegment->currentPC+currentSegment->codeGenOffset+2); // see if 8 bit offset will suffice } if(offset>=-128&&offset<128) { return(HandleRelative8(theOpcode,value,unresolved,listingRecord)); } else { return(HandleRelative16(theOpcode,value,unresolved,listingRecord)); } } static bool HandleValue(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an operand which is just a value has been parsed as the operand // Look at the addressing modes allowed for this opcode, and treat the value as // needed // return false only on 'hard' errors { if((theOpcode->typeMask&(M_DIRECT|M_EXTENDED))==(M_DIRECT|M_EXTENDED)) // see if ambiguous direct/extended { return(HandleDirectOrExtended(theOpcode,value,unresolved,listingRecord)); // go resolve the ambiguity } else if(theOpcode->typeMask&M_DIRECT) { return(HandleDirect(theOpcode,value,unresolved,listingRecord)); } else if(theOpcode->typeMask&M_EXTENDED) { return(HandleExtended(theOpcode,value,unresolved,listingRecord)); } else if((theOpcode->typeMask&(M_RELATIVE8|M_RELATIVE16))==(M_RELATIVE8|M_RELATIVE16)) // see if ambiguous relative { return(HandleRelative(theOpcode,value,unresolved,listingRecord)); } else if(theOpcode->typeMask&M_RELATIVE8) { return(HandleRelative8(theOpcode,value,unresolved,listingRecord)); } else if(theOpcode->typeMask&M_RELATIVE16) { return(HandleRelative16(theOpcode,value,unresolved,listingRecord)); } return(true); // this should not occur } static bool HandleImmediate8(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an immediate 8 bit addressing mode was located // return false only on 'hard' errors { bool fail; fail=false; CheckByteRange(value,true,true); if(WriteOpcode(theOpcode->baseOpcode[OT_IMMEDIATE8],listingRecord)) { fail=!GenerateByte(value,listingRecord); } else { fail=true; } return(!fail); } static bool HandleImmediate16(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an immediate 16 bit addressing mode was located // return false only on 'hard' errors { bool fail; fail=false; CheckWordRange(value,true,true); if(WriteOpcode(theOpcode->baseOpcode[OT_IMMEDIATE16],listingRecord)) { if(GenerateByte(value>>8,listingRecord)) { fail=!GenerateByte(value&0xFF,listingRecord); } else { fail=true; } } else { fail=true; } return(!fail); } static bool HandleImmediate(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an ambiguous immediate addressing mode was located // return false only on 'hard' errors { if(value>=-128&&value<256) { return(HandleImmediate8(theOpcode,value,unresolved,listingRecord)); } else { return(HandleImmediate16(theOpcode,value,unresolved,listingRecord)); } } static bool HandleImmediateValue(OPCODE *theOpcode,int value,bool unresolved,LISTING_RECORD *listingRecord) // an immediate value was located, dispatch to the handler based on the // addressing modes allowed by the insn // return false only on 'hard' errors { if((theOpcode->typeMask&(M_IMMEDIATE8|M_IMMEDIATE16))==(M_IMMEDIATE8|M_IMMEDIATE16)) // see if ambiguous { return(HandleImmediate(theOpcode,value,unresolved,listingRecord)); // go resolve the ambiguity } else if(theOpcode->typeMask&M_IMMEDIATE8) { return(HandleImmediate8(theOpcode,value,unresolved,listingRecord)); } else if(theOpcode->typeMask&M_IMMEDIATE16) { return(HandleImmediate16(theOpcode,value,unresolved,listingRecord)); } return(true); // this should not occur } static bool HandleIndexed(OPCODE *theOpcode,INDEXEDADDRESS *indexedAddress,LISTING_RECORD *listingRecord) // an indexed addressing mode was located, deal with it // NOTE: this is difficult to follow because there are lots of cases... // return false only on 'hard' errors { bool fail; unsigned char postByte; // generate the postbyte for the indexed addressing mode in here bool offsetBytes; // tells if offset bytes should be appended postByte=0x80; // initialize (assume it is not a 5-bit constant offset) offsetBytes=false; if(indexedAddress->indirect) // set indirect bit { postByte|=0x10; } if(indexedAddress->haveIndex) // see if there's an index register { if((indexedAddress->indexRegister!=R_PC)&&(indexedAddress->indexRegister!=R_PCR)) { switch(indexedAddress->indexRegister) { case R_X: case R_Y: case R_U: case R_S: postByte|=RegDefs[indexedAddress->indexRegister].indexMask; // set up bits for indexing with this register if(indexedAddress->offsetIsConstant) { if(indexedAddress->constantOffset==0) // 0 constant offset is handled differently { switch(indexedAddress->incdecCount) { case -2: postByte|=0x03; break; case -1: postByte|=0x02; if(indexedAddress->indirect) { AssemblyComplaint(NULL,true,"Predecrement by 1 with indirect is not allowed\n"); } break; case 0: postByte|=0x04; // 0 offset, 0 inc/dec break; case 1: postByte|=0x00; if(indexedAddress->indirect) { AssemblyComplaint(NULL,true,"Postincrement by 1 with indirect is not allowed\n"); } break; case 2: postByte|=0x01; break; default: AssemblyComplaint(NULL,true,"Invalid predecrement/postincrement\n"); break; } } else // non-zero offset { if(indexedAddress->incdecCount==0) { if(!indexedAddress->indirect&&indexedAddress->constantOffset>=-16&&indexedAddress->constantOffset<16) // does the offset fit in 5 bits? (only works if not indirect) { postByte&=0x7F; // knock off the high bit set at the start postByte|=indexedAddress->constantOffset&0x1F; // offset built into postbyte } else { postByte|=0x08; // external offset offsetBytes=true; // need offset bytes } } else { AssemblyComplaint(NULL,true,"Predecrement/postincrement not allowed with non-zero offset\n"); } } } else // register based offset { if((indexedAddress->offsetRegister==R_A)||(indexedAddress->offsetRegister==R_B)||(indexedAddress->offsetRegister==R_D)) { if(indexedAddress->incdecCount==0) { postByte|=RegDefs[indexedAddress->offsetRegister].indexMask; // set up bits for offsetting with this register } else { AssemblyComplaint(NULL,true,"Predecrement/postincrement and register offsets are not allowed together\n"); } } else { AssemblyComplaint(NULL,true,"Invalid offset register\n"); } } break; default: AssemblyComplaint(NULL,true,"Invalid index register\n"); break; } } else // PC based indexed address { if(indexedAddress->incdecCount==0) { if(indexedAddress->offsetIsConstant) { postByte|=RegDefs[indexedAddress->indexRegister].indexMask; // set up bits for indexing with this register offsetBytes=true; // need offset bytes } else { AssemblyComplaint(NULL,true,"PC relative indexing does not allow register offset\n"); } } else { AssemblyComplaint(NULL,true,"PC relative indexing does not allow predecrement/postincrement\n"); } } } else { if((indexedAddress->indirect)&&(indexedAddress->offsetIsConstant)) // if no index register, then must be indirect, and constant { postByte|=0x1F; offsetBytes=true; // this mode requires offset bytes } else { AssemblyComplaint(NULL,true,"Invalid indexed address\n"); } } // if an offset is needed, see if it can be 8 or 16 bits, and adjust the postbyte as needed if(offsetBytes) { if(!((indexedAddress->constantOffset>=-128)&&(indexedAddress->constantOffset<128))) // see if it is not an 8 bit offset { postByte|=0x01; // 16 bit offset } } // write out the instruction fail=false; if(WriteOpcode(theOpcode->baseOpcode[OT_INDEXED],listingRecord)) { if(GenerateByte(postByte,listingRecord)) { if(offsetBytes) { if(postByte&0x01) // see if 16 bit offset { fail=!GenerateByte(indexedAddress->constantOffset>>8,listingRecord); } if(!fail) { fail=!GenerateByte(indexedAddress->constantOffset&0xFF,listingRecord); } } } else { fail=true; } } else { fail=true; } return(!fail); } static bool HandleStackS(OPCODE *theOpcode,REGLIST *regList,LISTING_RECORD *listingRecord) // Look at the list of registers that were parsed, and make an S stack bit-field out // of them. // return false only on 'hard' errors { bool fail; unsigned char bitField; int i; bitField=0; fail=false; for(i=0;inumRegs;i++) { if(regList->theRegisters[i]!=R_S) { bitField|=RegDefs[regList->theRegisters[i]].stackMask; } else { AssemblyComplaint(NULL,true,"'S' is not a valid register here\n"); } } if(WriteOpcode(theOpcode->baseOpcode[OT_STACKS],listingRecord)) { fail=!GenerateByte(bitField,listingRecord); } else { fail=true; } return(!fail); } static bool HandleStackU(OPCODE *theOpcode,REGLIST *regList,LISTING_RECORD *listingRecord) // Look at the list of registers that were parsed, and make a U stack bit-field out // of them. // return false only on 'hard' errors { bool fail; unsigned char bitField; int i; bitField=0; fail=false; for(i=0;inumRegs;i++) { if(regList->theRegisters[i]!=R_U) { bitField|=RegDefs[regList->theRegisters[i]].stackMask; } else { AssemblyComplaint(NULL,true,"'U' is not a valid register here\n"); } } if(WriteOpcode(theOpcode->baseOpcode[OT_STACKU],listingRecord)) { fail=!GenerateByte(bitField,listingRecord); } else { fail=true; } return(!fail); } static bool HandleRegReg(OPCODE *theOpcode,REGLIST *regList,LISTING_RECORD *listingRecord) // Work out register to register operand // return false only on 'hard' errors { bool fail; unsigned char reg0, reg1; fail=false; if(regList->numRegs==2) { reg0=regList->theRegisters[0]; reg1=regList->theRegisters[1]; if((RegDefs[reg0].is16Bit&&RegDefs[reg1].is16Bit)||(!RegDefs[reg0].is16Bit&&!RegDefs[reg1].is16Bit)) { if(WriteOpcode(theOpcode->baseOpcode[OT_REGREG],listingRecord)) { fail=!GenerateByte((RegDefs[reg0].exgIndex<<4)|RegDefs[reg1].exgIndex,listingRecord); } else { fail=true; } } else { AssemblyComplaint(NULL,true,"Registers must be same width\n"); } } else { AssemblyComplaint(NULL,true,"Incorrect number of registers specified\n"); } return(!fail); } static bool HandleRegList(OPCODE *theOpcode,REGLIST *regList,LISTING_RECORD *listingRecord) // an addressing mode which requires a list of registers was located and parsed, deal with it // return false only on 'hard' errors { if(theOpcode->typeMask&M_STACKS) { return(HandleStackS(theOpcode,regList,listingRecord)); } if(theOpcode->typeMask&M_STACKU) { return(HandleStackU(theOpcode,regList,listingRecord)); } else if(theOpcode->typeMask&M_REGREG) { return(HandleRegReg(theOpcode,regList,listingRecord)); } return(true); } 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 operandType; int value; bool unresolved; INDEXEDADDRESS indexedAddress; REGLIST regList; fail=false; actualOpcode=(OPCODE *)theOpcode; if(!ParseComment(theLine,lineIndex)) { if(ParsePossibleOperands(theLine,lineIndex,actualOpcode->typeMask,&operandType,&value,&unresolved,&indexedAddress,®List)) { switch(operandType) { case POT_VALUE: return(HandleValue(actualOpcode,value,unresolved,listingRecord)); break; case POT_IMMEDIATE: return(HandleImmediateValue(actualOpcode,value,unresolved,listingRecord)); break; case POT_INDEXED: return(HandleIndexed(actualOpcode,&indexedAddress,listingRecord)); break; case POT_REGLIST: return(HandleRegList(actualOpcode,®List,listingRecord)); break; } } else { ReportBadOperands(); // could not make sense out of the operands given the allowable addressing modes } } else // hit end of line with no operands { if(actualOpcode->typeMask&M_IMPLIED) { fail=!WriteOpcode(actualOpcode->baseOpcode[OT_IMPLIED],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(regNameSymbols); STDisposeSymbolTable(opcodeSymbols); STDisposeSymbolTable(pseudoOpcodeSymbols); } static bool InitFamily() // initialize symbol tables { unsigned int i; bool fail; fail=false; if((pseudoOpcodeSymbols=STNewSymbolTable())) { for(i=0;!fail&&(i