// Copyright (C) 2000-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". // Dump segments out in Intel hex format #include "include.h" #define DATARECORD 0 #define ENDRECORD 1 #define EXTADDRESS 2 // gets an extra 4 bits of address (idiotic segment concept) #define EXTLINEARADDRESS 4 // gets an extra 16 bits of address static unsigned int lastAddressHigh; // keeps track of the upper 16 bits of address when dumping intel hex records static void DumpGenericLine(FILE *theFile,unsigned int address,unsigned char recordType,unsigned char *theBytes,int numBytes) // Create a line of intel hex output to theFile { int checkSum; int i; fprintf(theFile,":%02X%04X%02X",numBytes,address&0xFFFF,recordType); checkSum=0; for(i=0;i>8)&0xFF)+numBytes+recordType; fprintf(theFile,"%02X\n",(-checkSum)&0xFF); } static void DumpLine(FILE *theFile,unsigned int address,unsigned char *theBytes,int numBytes) // Create a line of intel hex output to theFile { DumpGenericLine(theFile,address,DATARECORD,theBytes,numBytes); } void DumpLinearAddress(FILE *theFile,unsigned int address) // dump out a linear address extension record for address { unsigned char extendedAddressBuffer[2]; extendedAddressBuffer[0]=address>>24; extendedAddressBuffer[1]=address>>16; DumpGenericLine(theFile,0,EXTLINEARADDRESS,extendedAddressBuffer,2); } void DumpEOR(FILE *theFile) // Dump an end of record marker out to theFile { DumpGenericLine(theFile,0,ENDRECORD,NULL,0); } static void DumpSegment(FILE *theFile,SEGMENT_RECORD *theSegment) // create a hex dump of theSegment to theFile // NOTE: this is careful to dump only the bytes which are marked as used // within theSegment // if theSegment is marked as not generating output, nothing will be dumped { CODE_PAGE *thePage; int i,j,k; if(theSegment->generateOutput) { thePage=theSegment->firstPage; while(thePage) { if((thePage->address&0xFFFF0000)!=lastAddressHigh) { lastAddressHigh=thePage->address&0xFFFF0000; // remember the last high address bits DumpLinearAddress(theFile,lastAddressHigh); // spit out upper address bits } for(i=0;i<256;i+=16) { j=0; while(j<16) { while(j<16&&!(thePage->usageMap[(i+j)>>3]&(1<<(j&7)))) // skip over empty space { j++; } if(j<16) { k=j; while(k<16&&(thePage->usageMap[(i+k)>>3]&(1<<(k&7)))) // count up used space { k++; } DumpLine(theFile,thePage->address+i+j,&thePage->pageData[i+j],k-j); // dump out used bytes j=k; // move forward } } } thePage=thePage->next; } } } static bool OutputSegments(FILE *theFile) // create a hex dump of all segments to theFile // NOTE: this is careful to dump only the bytes which are marked as used // within each segment // Segments marked as not generating output will not be dumped // NOTE: Segments will be dumped in reverse order of creation // this should probably be changed to dump in the order of creation { SEGMENT_RECORD *theSegment; lastAddressHigh=0; // initialize upper address bits theSegment=segmentsHead; while(theSegment) { DumpSegment(theFile,theSegment); theSegment=theSegment->next; } DumpEOR(theFile); return(true); } // output file types handled here (the constuctors for these variables link them to the global // list of output file types that the assembler knows how to handle) static OUTPUTFILE_TYPE outputFileType("intel","Intel format segment dump",false,OutputSegments);