// 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". // Support routines used by numerous processors to help keep the // amount of duplicated code to a minimum #include "include.h" void ReportBadOperands() // complain that the operands are bad { AssemblyComplaint(NULL,true,"Invalid operands\n"); } bool CheckSignedByteRange(int theValue,bool generateMessage,bool isError) // see if theValue looks like a signed byte // if not, return false, and generate a warning or error if told to { if(theValue>=-128&&theValue<128) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Signed byte value (0x%X) out of range\n",theValue); } return(false); } bool CheckUnsignedByteRange(int theValue,bool generateMessage,bool isError) // see if theValue looks like an unsigned byte // if not, return false, and generate a warning or error if told to { if(theValue>=0&&theValue<256) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Unsigned byte value (0x%X) out of range\n",theValue); } return(false); } bool CheckByteRange(int theValue,bool generateMessage,bool isError) // see if theValue looks like a signed byte, or an unsigned byte // if not, return false, and generate a warning or error if told to { if(theValue>=-128&&theValue<256) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Byte value (0x%X) out of range\n",theValue); } return(false); } bool CheckSignedWordRange(int theValue,bool generateMessage,bool isError) // see if theValue looks like a signed word // if not, return false, and generate a warning or error if told to { if(theValue>=-32768&&theValue<32768) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Signed word value (0x%X) out of range\n",theValue); } return(false); } bool CheckUnsignedWordRange(int theValue,bool generateMessage,bool isError) // see if theValue looks like an unsigned word // if not, return false, and generate a warning or error if told to { if(theValue>=0&&theValue<65536) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Unsigned word value (0x%X) out of range\n",theValue); } return(false); } bool CheckWordRange(int theValue,bool generateMessage,bool isError) // see if theValue looks like a signed word, or an unsigned word // if not, return false, and generate a warning or error if told to { if(theValue>=-32768&&theValue<65536) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Word value (0x%X) out of range\n",theValue); } return(false); } bool Check8BitIndexRange(int theValue,bool generateMessage,bool isError) // check value to see if it looks good as 8 bit index // complain if not { if(theValue>=0&&theValue<8) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Bit index (0x%X) out of range\n",theValue); } return(false); } bool Check16BitIndexRange(int theValue,bool generateMessage,bool isError) // check value to see if it looks good as 16 bit index // complain if not { if(theValue>=0&&theValue<16) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Bit index (0x%X) out of range\n",theValue); } return(false); } bool Check32BitIndexRange(int theValue,bool generateMessage,bool isError) // check value to see if it looks good as 32 bit index // complain if not { if(theValue>=0&&theValue<32) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Bit index (0x%X) out of range\n",theValue); } return(false); } bool Check8RelativeRange(int theValue,bool generateMessage,bool isError) // check value to see if it looks good as 8 bit relative offset // complain if not { if(theValue>=-128&&theValue<128) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Relative offset (0x%X) out of range\n",theValue); } return(false); } bool Check16RelativeRange(int theValue,bool generateMessage,bool isError) // check value to see if it looks good as 16 bit relative offset // complain if not { if(theValue>=-32768&&theValue<32768) { return(true); } if(generateMessage) { AssemblyComplaint(NULL,isError,"Relative offset (0x%X) out of range\n",theValue); } return(false); } bool GenerateByte(unsigned char value,LISTING_RECORD *listingRecord) // output the value to the current segment // This will return false only if a "hard" error occurs { bool fail; int length; fail=false; if(currentSegment) { if(!intermediatePass) // only do the real work if necessary { length=strlen(listingRecord->listObjectString); if(length+2listObjectString[length],"%02X ",value); // create list file output } fail=!AddBytesToSegment(currentSegment,currentSegment->currentPC,&value,1); } currentSegment->currentPC++; } else { AssemblyComplaint(NULL,true,"Code cannot occur outside of a segment\n"); } return(!fail); } bool HandleDB(PSEUDO_OPCODE *opcode,char *theLine,int *lineIndex,bool haveLabel,bool isLocal,char *lineLabel,LISTING_RECORD *listingRecord) // declaring bytes of data { int value; bool unresolved; char outputString[MAXSTRING]; int stringLength; bool done, fail; int i; done=false; fail=!ProcessLineLocationLabel(haveLabel,isLocal,lineLabel); // deal with any label on the line while(!done&&!fail) { if(ParseQuotedString(theLine,lineIndex,'"','"',outputString,&stringLength)) { i=0; while(!fail&&i>8,listingRecord)) { fail=!GenerateByte(value&0xFF,listingRecord); } else { fail=true; } } else { if(GenerateByte(value&0xFF,listingRecord)) { fail=!GenerateByte(value>>8,listingRecord); } else { fail=true; } } } else { ReportBadOperands(); done=true; } if(!done&&!fail) // look for separator, or comment { if(ParseComment(theLine,lineIndex)) { done=true; } else if(ParseCommaSeparator(theLine,lineIndex)) { } else { ReportBadOperands(); done=true; } } } return(!fail); } bool HandleLEDW(PSEUDO_OPCODE *opcode,char *theLine,int *lineIndex,bool haveLabel,bool isLocal,char *lineLabel,LISTING_RECORD *listingRecord) // declaring words of data in little endian { return(HandleDW(opcode,theLine,lineIndex,haveLabel,isLocal,lineLabel,listingRecord,false)); } bool HandleBEDW(PSEUDO_OPCODE *opcode,char *theLine,int *lineIndex,bool haveLabel,bool isLocal,char *lineLabel,LISTING_RECORD *listingRecord) // declaring words of data in big endian { return(HandleDW(opcode,theLine,lineIndex,haveLabel,isLocal,lineLabel,listingRecord,true)); } bool HandleDS(PSEUDO_OPCODE *opcode,char *theLine,int *lineIndex,bool haveLabel,bool isLocal,char *lineLabel,LISTING_RECORD *listingRecord) // move the PC forward by the given amount { bool fail; int value; bool unresolved; fail=!ProcessLineLocationLabel(haveLabel,isLocal,lineLabel); // deal with any label on the line if(!fail) { if(ParseExpression(theLine,lineIndex,&value,&unresolved)) { if(ParseComment(theLine,lineIndex)) { if(currentSegment) { if(!unresolved) { if(!intermediatePass) // only do the real work if necessary { fail=!AddSpaceToSegment(currentSegment,currentSegment->currentPC,value); } currentSegment->currentPC+=value; } } else { AssemblyComplaint(NULL,true,"'%s' outside of segment\n",opcode->name); } } else { ReportBadOperands(); } } else { ReportBadOperands(); } } return(!fail); } bool HandleDSW(PSEUDO_OPCODE *opcode,char *theLine,int *lineIndex,bool haveLabel,bool isLocal,char *lineLabel,LISTING_RECORD *listingRecord) // move the PC forward by the given amount times two (do as if skipping this many words) { bool fail; int value; bool unresolved; fail=!ProcessLineLocationLabel(haveLabel,isLocal,lineLabel); // deal with any label on the line if(!fail) { if(ParseExpression(theLine,lineIndex,&value,&unresolved)) { if(ParseComment(theLine,lineIndex)) { value*=2; if(currentSegment) { if(!unresolved) { if(!intermediatePass) // only do the real work if necessary { fail=!AddSpaceToSegment(currentSegment,currentSegment->currentPC,value); } currentSegment->currentPC+=value; } } else { AssemblyComplaint(NULL,true,"'%s' outside of segment\n",opcode->name); } } else { ReportBadOperands(); } } else { ReportBadOperands(); } } return(!fail); } bool HandleIncbin(PSEUDO_OPCODE *opcode,char *theLine,int *lineIndex,bool haveLabel,bool isLocal,char *lineLabel,LISTING_RECORD *listingRecord) // include the data of the given file into the input stream // If there is a problem, report it and return false { bool fail; char fileName[MAXSTRING]; int stringLength; FILE *theFile; unsigned char inputDataBuffer[1024]; int bytesRead; fail=!ProcessLineLocationLabel(haveLabel,isLocal,lineLabel); // deal with any label on the line if(!fail) { if(ParseQuotedString(theLine,lineIndex,'"','"',fileName,&stringLength)) { if(ParseComment(theLine,lineIndex)) // make sure there's nothing else on the line { if(currentSegment) { if((theFile=fopen(fileName,"rb"))) { while(!fail&&((bytesRead=fread(inputDataBuffer,1,1024,theFile))>0)) { if(!intermediatePass) // only do the real work if necessary { fail=!AddBytesToSegment(currentSegment,currentSegment->currentPC,inputDataBuffer,bytesRead); } currentSegment->currentPC+=bytesRead; } fclose(theFile); } else { AssemblyComplaint(NULL,true,"Failed to open file '%s'. %s\n",fileName,strerror(errno)); } } else { AssemblyComplaint(NULL,true,"Code cannot occur outside of a segment\n"); } } else { AssemblyComplaint(NULL,true,"Missing or incorrectly formatted file name\n"); } } else { AssemblyComplaint(NULL,true,"Missing or incorrectly formatted file name\n"); } } return(!fail); }