Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

/users/u3/mtikir/PMaCInstrumentor_v1601/tools/CountAllBlocks.C

Go to the documentation of this file.
00001 #include <SectHeader.h>
00002 #include <Iterator.h>
00003 #include <Function.h>
00004 #include <LineInfoFinder.h>
00005 #include <XCoffFile.h>
00006 #include <CountAllBlocks.h>
00007 #include <fstream>
00008 using namespace std;
00009 
00010 char* CountAllBlocks::staticPrintExtension = "static";
00011 
00012 CountAllBlocks::CountAllBlocks(XCoffFile* xcoff,char* extension,uint32_t phaseNo)
00013     : XCoffFileGen(xcoff,extension,phaseNo,NULL),libraryFunctionCount(1),
00014       blocksToInstrument(NULL),terminationBlock(NULL),numOfBlocksFiltered(0),
00015       extendedBeginAddr(0),
00016       execTOCAddress(0),tocXorUpdateVal(0),tocDistUpdateVal(0),
00017       sharedLibraryInfoStr(NULL)
00018 {
00019 }
00020 
00021 void CountAllBlocks::selectInstrumentationPoints(char* inpFile){
00022     
00023     terminationBlock = findTerminationBlock();
00024     ASSERT(terminationBlock && "FATAL : There is no exit block");
00025 
00026     uint32_t allBlocksCount = xcoffFile->getNumberOfBlocks();
00027 
00028     bool insertAppExitBlock = true;
00029 
00030     if (allBlocksCount){
00031         blocksToInstrument = new BasicBlock*[allBlocksCount];
00032         xcoffFile->getAllBlocks(blocksToInstrument);
00033 
00034         for (uint32_t i = 0; i < allBlocksCount; i++){
00035             BasicBlock* bb = blocksToInstrument[i];
00036             if (filterBlockForInst(bb)){
00037                 PRINT_DEBUG("Filtering basic block %#12llx",bb->getHashCode().getValue());
00038                 numOfBlocksFiltered++;
00039                 continue;
00040             }
00041             if (insertAppExitBlock && (bb == terminationBlock)){
00042                 PRINT_INFOR("The exit block sequence id will be %#x",numberOfInstPoints);
00043                 insertAppExitBlock = false;
00044             }
00045             blocksToInstrument[numberOfInstPoints++] = bb;
00046         }
00047     } else {
00048         PRINT_ERROR("There is no basic block identified in the executable yet, is executable parsed?");
00049     }
00050 
00051     if (!numberOfInstPoints){
00052         PRINT_ERROR("There is no basic block passed the filter");
00053     }
00054 
00055     if (insertAppExitBlock){
00056         blocksToInstrument[numberOfInstPoints++] = terminationBlock;
00057     }
00058 
00059     PRINT_INFOR("**** Number of basic blocks considered in instrumentation %d ******",numberOfInstPoints);
00060 }
00061 
00062 uint32_t CountAllBlocks::byteCountForInst(uint32_t instPointIdx,uint64_t instStubAddress,TextSection* textSect){
00063     BasicBlock* block = blocksToInstrument[instPointIdx];
00064 
00065     uint64_t instPointAddress = 0;
00066 
00067     if(!block->findFirstInstPoint(&instPointAddress)){
00068         return 0;
00069     }
00070 
00071     ASSERT(textSect->inRange(instPointAddress));
00072 
00073     if(!Instruction::isInJumpInsnRange(instPointAddress,instStubAddress))
00074         return 0;
00075 
00076     int32_t blockCounterOffset = getDataOffsetForInst(instPointIdx);
00077     bool isApplicationExit = (block == terminationBlock);
00078 
00079     uint32_t minInsnCount = 8;
00080     uint32_t tocUpdateInsnCount = 0;
00081     uint32_t indexAccessInsnCount = 0;
00082     uint32_t exitInsnCount = 0;
00083 
00084     if(tocXorUpdateVal){
00085         tocUpdateInsnCount += 2;
00086         if(SECOND_HALFWORD(tocXorUpdateVal)){
00087             tocUpdateInsnCount += 2;
00088         }
00089     }
00090     if(!Instruction::isInLoadOffsetInsnRange(blockCounterOffset)){
00091         indexAccessInsnCount += 4;
00092     }
00093     if(isApplicationExit){
00094         tocUpdateInsnCount *= 2;
00095         exitInsnCount = 11;
00096     }
00097     uint32_t insnCount = minInsnCount + tocUpdateInsnCount + 
00098                          indexAccessInsnCount + exitInsnCount;
00099 
00100     return (insnCount*sizeof(uint32_t));
00101 }
00102 
00103 uint32_t CountAllBlocks::generateCodeForInst(uint32_t instPointIdx,
00104                                                     uint64_t instStubAddress,TextSection* textSect,
00105                                                     BaseGen* gen,uint32_t genBufferOffset)
00106 {
00107     ASSERT(gen->getParsedBase() == (Base*)textSect);
00108     BasicBlock* block = blocksToInstrument[instPointIdx];
00109     ASSERT(block);
00110     ASSERT(extendedDataSize && dataBufferEntryCount);
00111 
00112     uint64_t instPointAddress = 0;
00113 
00114     if(!block->findFirstInstPoint(&instPointAddress)){
00115         PRINT_INFOR("Basic Block %#18llx does not have suitable location for inst",
00116                     block->getHashCode().getValue());
00117         return 0;
00118     }
00119     ASSERT(textSect->inRange(instPointAddress));
00120 
00121     if(!Instruction::isInJumpInsnRange(instPointAddress,instStubAddress)){
00122         PRINT_INFOR("Basic Block %#18llx can not be instrumented due to branch offset limit",
00123                     block->getHashCode().getValue());
00124         return 0;
00125     }
00126 
00127     AddressIterator ait = block->getInstructionIterator();
00128     ait.skipTo(instPointAddress);
00129     Instruction origInsn = textSect->readInstruction(&ait);
00130 
00131     bool isApplicationExit = (block == terminationBlock);
00132 
00133     uint32_t savedReg = 31;
00134     uint32_t scratchReg = 30;
00135     ASSERT(savedReg > LAST_VOLATILE_REG);
00136     ASSERT(scratchReg > LAST_VOLATILE_REG);
00137 
00138     int32_t savedRegSaveOffset   = getGPRSaveOffset(savedReg);
00139     int32_t scratchRegSaveOffset = getGPRSaveOffset(scratchReg);
00140     int32_t blockCounterOffset   = getDataOffsetForInst(instPointIdx);
00141 
00142     uint32_t maxInsnCount = (maxByteCountPerInst() / sizeof(uint32_t));
00143 
00144     uint32_t insnCount = 0;
00145     Instruction* insnBuffer = new Instruction[maxInsnCount];
00146 
00147 /* execute the instruction from the original code that has been replaced */
00148     insnBuffer[insnCount++] = origInsn;
00149 
00150     updateTOCRegister(insnBuffer,&insnCount);
00151 
00152 /* store savedReg to data section (save savedReg) */
00153     insnBuffer[insnCount++] = Instruction::generateStoreDouble(savedReg,REG_TOC,savedRegSaveOffset);
00154 
00155     bool oneWordCounter = (sizeof(uint32_t) == bytesPerBufferEntry());
00156 
00157 /* if blockCounterOffset is too large to be used as an immediate in a load, special steps must be taken */
00158     if(!Instruction::isInLoadOffsetInsnRange(blockCounterOffset)){
00159 
00160     /* store scratchReg to data section (save scratchReg) */
00161         insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00162     /* load counter offset in data section to scratchReg */
00163         insnBuffer[insnCount++] = Instruction::generateLoad32BitHigh(scratchReg,blockCounterOffset);
00164         insnBuffer[insnCount++] = Instruction::generateLoad32BitLow(scratchReg,blockCounterOffset);
00165 
00166     /* load the counter from ext. data section to savedReg */
00167         if(oneWordCounter){
00168             insnBuffer[insnCount++] = Instruction::generateLoadWordIndx(savedReg,REG_TOC,scratchReg);
00169         } else {
00170             insnBuffer[insnCount++] = Instruction::generateLoadDoubleIndx(savedReg,REG_TOC,scratchReg);
00171         }
00172 
00173     /* increment counter */
00174         insnBuffer[insnCount++] = Instruction::generateIncrement(savedReg,1);
00175 
00176     /* store the counter from savedReg to data section */
00177         if(oneWordCounter){
00178             insnBuffer[insnCount++] = Instruction::generateStoreWordIndx(savedReg,REG_TOC,scratchReg);
00179         } else {
00180             insnBuffer[insnCount++] = Instruction::generateStoreDoubleIndx(savedReg,REG_TOC,scratchReg);
00181         }
00182     /* load scrtachReg from data section (restore scratchReg) */
00183         insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00184 
00185 /* if blockCounterOffset is small enough to be used as the immediate in a load */
00186     } else {
00187     /* load the counter from ext. data section to savedReg */
00188         if(oneWordCounter){
00189             insnBuffer[insnCount++] = Instruction::generateLoadWord(savedReg,REG_TOC,blockCounterOffset);
00190         } else {
00191             insnBuffer[insnCount++] = Instruction::generateLoadDouble(savedReg,REG_TOC,blockCounterOffset);
00192         }
00193 
00194     /* increment counter */
00195         insnBuffer[insnCount++] = Instruction::generateIncrement(savedReg,1);
00196 
00197     /* store the counter from savedReg to data section */
00198         if(oneWordCounter){
00199             insnBuffer[insnCount++] = Instruction::generateStoreWord(savedReg,REG_TOC,blockCounterOffset);
00200         } else {
00201             insnBuffer[insnCount++] = Instruction::generateStoreDouble(savedReg,REG_TOC,blockCounterOffset);
00202         }
00203     }
00204 
00205 
00206 /* a function must be called at the exit point of the program to print all of the information collected during
00207    the program run. */
00208     if(isApplicationExit){
00209 
00210 /* save scratch reg, generate a function call, restore scratch reg */
00211         insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00212         generateFuncCallFull(insnBuffer,&insnCount,savedReg,instStubAddress,libraryFuncStubAddrs[0]);
00213         insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00214     }
00215 
00216 /* load savedReg from data section (restore savedReg) */
00217     insnBuffer[insnCount++] = Instruction::generateLoadDouble(savedReg,REG_TOC,savedRegSaveOffset);
00218 
00219     updateTOCRegister(insnBuffer,&insnCount);
00220 
00221     uint64_t fromAddr = instStubAddress + (insnCount * sizeof(uint32_t));
00222     uint64_t toAddr   = instPointAddress + sizeof(uint32_t);
00223 
00224 /* jump from instrumentation code to original code */
00225     insnBuffer[insnCount++] = Instruction::generateJumpInsn(fromAddr,toAddr);
00226 /* put a "tag" instruction (will NOT be execited) after the instrumentation sequence. This makes it easier to
00227    find instrumentation code for debugging and such */
00228     insnBuffer[insnCount++] = Instruction(instPointIdx);
00229 
00230     ASSERT(insnCount <= maxInsnCount);
00231 
00232     gen->writeInstructions(genBufferOffset,insnCount,insnBuffer);
00233 
00234     delete[] insnBuffer;
00235 
00236     fromAddr = instPointAddress;
00237     toAddr   = instStubAddress;
00238     Instruction origJumpToStub = Instruction::generateJumpInsn(fromAddr,toAddr);
00239     gen->writeWord(instPointAddress-textSect->getSectHeader()->GET(s_vaddr),origJumpToStub.bits());
00240 
00241     return (insnCount*sizeof(uint32_t));
00242 }
00243 
00244 /* returns true if the basic block is code as opposed to a "false block" found in a jump table or trace */
00245 bool CountAllBlocks::filterBlockForInst(BasicBlock* bb){
00246     if(!bb)
00247         return true;
00248     if(bb->isTrace() || bb->isJumpTable())
00249         return true;
00250     return false;
00251 }
00252 
00253 void CountAllBlocks::getSharedLibraryPathAndObj(char** path,char** name,char** obj){
00254 
00255     *path = getPathToInstLib();
00256     *obj  = "";
00257     if(xcoffFile->is64Bit()){
00258         *name = "libcntrFunc_64.a";
00259     } else {
00260         *name = "libcntrFunc.a";
00261     }
00262     ASSERT(path && name && obj);
00263 }
00264 
00265 void CountAllBlocks::reserveDataForInstrumentation(){
00266 
00267     extendedDataSize = 0;
00268     extendedBeginAddr = 0;
00269     dataBufferEntryCount = 0;
00270 
00271     uint64_t dataSectionBeginAddr = xcoffFile->getDataSectionVAddr();
00272     uint32_t dataSectionSize = xcoffFile->getDataSectionSize();
00273 
00274     execTOCAddress = xcoffFile->getTOCAddress();
00275 
00276     uint64_t currentFreeAddress = dataSectionBeginAddr + dataSectionSize;
00277 
00278     uint32_t incrementSize = 0;
00279     if (xcoffFile->is64Bit()){
00280         currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00281         incrementSize = sizeof(uint64_t);
00282     } else {
00283         currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00284         incrementSize = sizeof(uint32_t);
00285     }
00286 
00287     extendedBeginAddr = currentFreeAddress;
00288 
00289 /* reserve space for function addrs from the shared library */
00290     for (uint32_t i = 0; i < getNumOfSharedLibFuncs(); i++){
00291         libraryFunctionStubAddrLocs[i] = currentFreeAddress;
00292         currentFreeAddress += incrementSize;
00293     }
00294 
00295 
00296 /* reserve space for registers to be saved */
00297     currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00298 
00299     saveAddressCondReg = currentFreeAddress;
00300     currentFreeAddress += sizeof(uint32_t);
00301     saveAddressFPCondReg = currentFreeAddress;
00302     currentFreeAddress += sizeof(uint32_t);
00303 
00304     currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00305 
00306     saveAddressLinkReg = currentFreeAddress;
00307     currentFreeAddress += sizeof(uint64_t);
00308     saveAddressCtrReg = currentFreeAddress;
00309     currentFreeAddress += sizeof(uint64_t);
00310     saveAddressExpReg = currentFreeAddress;
00311     currentFreeAddress += sizeof(uint64_t);
00312 
00313     saveAddressGprRegs = currentFreeAddress;
00314     currentFreeAddress += (sizeof(uint64_t) * NUM_OF_GPR_REGS);
00315     saveAddressFprRegs = currentFreeAddress;
00316     currentFreeAddress += (sizeof(uint64_t) * NUM_OF_FPR_REGS);
00317         
00318 
00319 /* reserve space for a "comment", which is just some information about the program. first the 
00320    comment string is created, then we figure out its size */
00321     char* ptr = xcoffFile->getXCoffFileName();
00322     char* sepPtr = strrchr(ptr,'/');
00323     if(sepPtr){
00324         ptr = (sepPtr + 1);
00325     }
00326     char tmpStr[__MAX_STRING_SIZE];
00327     if(!phaseIndex){
00328         sprintf(tmpStr,"%s 0 %s %d",ptr,getFileExtension(),
00329                 getNumberOfInstPoints(NULL));
00330     } else {
00331         sprintf(tmpStr,"%s %d %s %d",ptr,getPhaseIndex(),getFileExtension(),
00332                 getNumberOfInstPoints(NULL));
00333     }
00334     commentAddress = currentFreeAddress;
00335     sharedLibraryInfoStr = strdup(tmpStr);
00336     currentFreeAddress += (strlen(sharedLibraryInfoStr) + 1);
00337 
00338 /* reserve space for the block counter */
00339     dataBufferEntryCount = howManyBufferEntry();
00340     incrementSize = bytesPerBufferEntry();
00341     if(incrementSize == sizeof(uint32_t)){
00342         currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00343     } else {
00344         currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00345     }
00346     dataBufferAddress = currentFreeAddress;
00347     currentFreeAddress += (dataBufferEntryCount * incrementSize);
00348 
00349 
00350     currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00351 
00352     extendedDataSize = currentFreeAddress - (dataSectionBeginAddr + dataSectionSize);
00353 
00354 /* If the end of the updated data section has an address that is too large to be used as a load immediate value */
00355     tocXorUpdateVal = 0;
00356     if(!Instruction::isInLoadOffsetInsnRange((int32_t)(dataBufferAddress-execTOCAddress))){
00357         tocXorUpdateVal = (uint32_t)(extendedBeginAddr ^ execTOCAddress);
00358         tocDistUpdateVal = (uint32_t)(extendedBeginAddr - execTOCAddress);
00359     }
00360 
00361     PRINT_INFOR("**** Additional data section inc  is %d ***",extendedDataSize);
00362     PRINT_INFOR("**** Number of entries to process is %18d ***",dataBufferEntryCount);
00363     PRINT_INFOR("**** Start address for toc        is %#18llx (%lld) ***",
00364         execTOCAddress,execTOCAddress-dataSectionBeginAddr);
00365     PRINT_INFOR("**** Start address for additional is %#18llx (%lld) ***",
00366         extendedBeginAddr,extendedBeginAddr-execTOCAddress);
00367     PRINT_INFOR("**** The tocXorUpdateVal for save is %x %d ***",
00368         tocXorUpdateVal,tocDistUpdateVal);
00369     PRINT_INFOR("**** Start address for the gprs   is %#18llx (%lld) ***",
00370         saveAddressGprRegs,saveAddressGprRegs-execTOCAddress);
00371     PRINT_INFOR("**** Start address for the comm   is %#18llx (%lld) ***",
00372         commentAddress,commentAddress-execTOCAddress);
00373     PRINT_INFOR("**** Start address for the buffer is %#18llx (%lld) ***",
00374         dataBufferAddress,dataBufferAddress-execTOCAddress);
00375     PRINT_INFOR("**** End address for the buffer   is %#18llx (%lld) ***",
00376         currentFreeAddress,currentFreeAddress-execTOCAddress);
00377 }
00378 
00379 void CountAllBlocks::initializeReservedData(DataSection* dataSect,BaseGen* gen){
00380 /* write the comment to its reserved space */
00381     gen->writeString(commentAddress-dataSect->getSectHeader()->GET(s_vaddr),
00382                      sharedLibraryInfoStr,strlen(sharedLibraryInfoStr) + 1);
00383 }
00384 
00385 BasicBlock* CountAllBlocks::findTerminationBlock(){
00386 
00387     uint32_t allBlocksCount = xcoffFile->getNumberOfBlocks();
00388     if(!allBlocksCount)
00389         return NULL;
00390 
00391     BasicBlock** allBlocks = new BasicBlock*[allBlocksCount];
00392     xcoffFile->getAllBlocks(allBlocks);
00393 
00394     BasicBlock* mpiexit = NULL;
00395     BasicBlock* regexit = NULL;
00396     BasicBlock* ddiexit = NULL;
00397 
00398     for (uint32_t i = 0; i < allBlocksCount; i++){
00399         BasicBlock* bb = allBlocks[i];
00400         if (bb->isTrace() || bb->isJumpTable() || bb->getIndex())
00401             continue;
00402         Function* owner = bb->getFlowGraph()->getFunction();
00403         if (!ddiexit && owner->isAnySymbolA(".DDI_Finalize")){
00404             ddiexit = bb;
00405         } 
00406         if (!mpiexit && owner->isAnySymbolA(".mpi_finalize")){
00407             mpiexit = bb;
00408         } 
00409         if (!regexit && owner->isAnySymbolA(".exit")){
00410             regexit = bb;
00411         }
00412     }
00413     delete[] allBlocks;
00414 
00415     if (ddiexit) {
00416         PRINT_INFOR("The exit function .DDI_Finalize is taken");
00417         return ddiexit;
00418     }
00419     if (mpiexit){
00420     PRINT_INFOR("The exit function .mpi_finalize is taken");
00421         return mpiexit;
00422     }
00423     if (regexit){
00424         PRINT_INFOR("The exit function .exit is taken");
00425         return regexit;
00426     }
00427     return NULL;
00428 }
00429 
00430 void CountAllBlocks::printInstrumentationPoints(){
00431 
00432     char instBlockFileName[__MAX_STRING_SIZE];
00433     if (!getPhaseIndex()){
00434         sprintf(instBlockFileName,"%s.%s.%s",xcoffFile->getXCoffFileName(),getFileExtension(),staticPrintExtension);
00435     } else {
00436         sprintf(instBlockFileName,"%s.phase.%d.%s.%s",xcoffFile->getXCoffFileName(),getPhaseIndex(),
00437                 getFileExtension(),staticPrintExtension);
00438     }
00439 
00440     ofstream instBlockFile;
00441     instBlockFile.open(instBlockFileName);
00442     if (!instBlockFile){
00443          PRINT_ERROR("Instrumented block infor can not be opened [%s]",instBlockFileName);
00444     }
00445 
00446     uint32_t memOpCount = 0;
00447     uint32_t fpOpCount = 0;
00448     uint32_t insnCount = 0;
00449 
00450     for (uint32_t i=0;i<numberOfInstPoints;i++){
00451         memOpCount += blocksToInstrument[i]->getNumOfMemoryOps();
00452         fpOpCount += blocksToInstrument[i]->getNumOfFloatPOps();
00453         insnCount += blocksToInstrument[i]->getInstructionCount();
00454     }
00455 
00456     TextSection* lineInfoSect = (TextSection*)xcoffFile->getRawSection(xcoffFile->getTextSectionIndex());
00457     LineInfoFinder* lineInfoFinder = lineInfoSect->getLineInfoFinder();
00458 
00459     instBlockFile << "# appname   = " << xcoffFile->getXCoffFileName() << endl;
00460     instBlockFile << "# appsize   = " << xcoffFile->getFileSize() << endl;
00461     instBlockFile << "# extension = " << getFileExtension() << endl;
00462     instBlockFile << "# phase     = " << getPhaseIndex() << endl;
00463     instBlockFile << "# type      = " << getGenClassName() << endl;
00464     instBlockFile << "# candidate = " << xcoffFile->getNumberOfBlocks() << endl;
00465     instBlockFile << "# blocks    = " << numberOfInstPoints << endl;
00466     instBlockFile << "# memops    = " << memOpCount << endl;
00467     instBlockFile << "# fpops     = " << fpOpCount << endl;
00468     instBlockFile << "# insns     = " << insnCount << endl;
00469     instBlockFile << "# buffer    = " << howManyBufferEntry() << endl;
00470     instBlockFile << "# <sequence> <block_uid> <memop> <fpop> <insn> <line> <fname> <hex_uid> <vaddr>" << endl;
00471 
00472     for (uint32_t i = 0; i < numberOfInstPoints; i++){
00473         uint64_t unq = blocksToInstrument[i]->getHashCode().getValue();
00474         Function* owner = blocksToInstrument[i]->getFlowGraph()->getFunction();
00475         char names[__MAX_STRING_SIZE];
00476         names[0] = '\0';
00477         owner->getAllSymbolNames(names,__MAX_STRING_SIZE,true);
00478         if(!strlen(names)){
00479             strcpy(names,"__name__unknown__");
00480         }
00481         char* absFile = NULL;
00482         uint32_t absLine  =0;
00483         if(lineInfoFinder){
00484             uint64_t addr = blocksToInstrument[i]->getBaseAddress();
00485             absFile = lineInfoFinder->getFileName(addr);
00486             absLine = lineInfoFinder->getLineNumberInFile(addr);
00487         }
00488         instBlockFile << i << "\t" << unq 
00489                       << "\t" << blocksToInstrument[i]->getNumOfMemoryOps()
00490                       << "\t" << blocksToInstrument[i]->getNumOfFloatPOps()
00491                       << "\t" << blocksToInstrument[i]->getInstructionCount()
00492                       << "\t" << (absFile ? absFile : "__FILE_UNK__") << ":" << absLine 
00493                       << "\t" << names
00494                       << "\t# 0x" << hex << unq << "\t0x" << blocksToInstrument[i]->getBaseAddress() << dec 
00495                       << endl;    
00496     }
00497     instBlockFile.close();
00498 }
00499 
00500 
00501 void CountAllBlocks::updateTOCRegister(Instruction* insnBuffer,uint32_t* insnIndex){
00502     uint16_t tocUpdateValLow = FIRST_HALFWORD(tocXorUpdateVal);
00503     uint16_t tocUpdateValHigh = SECOND_HALFWORD(tocXorUpdateVal);
00504     if(tocXorUpdateVal){
00505         if(tocUpdateValHigh){
00506             insnBuffer[(*insnIndex)++] = Instruction::generateXorImmShifted(REG_TOC,REG_TOC,tocUpdateValHigh);
00507         }
00508         insnBuffer[(*insnIndex)++] = Instruction::generateXorImm(REG_TOC,REG_TOC,tocUpdateValLow);
00509     }
00510 }
00511 
00512 void CountAllBlocks::generateFuncCallFull(Instruction* insnBuffer,uint32_t* insnIndex,
00513                                                 uint32_t reg,uint64_t stubAddr,uint64_t funcAddr)
00514 {
00515 //    PRINT_INFOR("Generating a function call with args %d %d %#llx %#llx", *insnIndex, reg, stubAddr, funcAddr);
00516 
00517 /* save CR register */
00518     insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromCR(reg);
00519     insnBuffer[(*insnIndex)++] = Instruction::generateStoreWord(reg,REG_TOC,getCRSaveOffset());
00520 
00521 /* save LNK register */
00522     insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromSPR(reg,REG_LNK);
00523     insnBuffer[(*insnIndex)++] = Instruction::generateStoreDouble(reg,REG_TOC,getLNKSaveOffset());
00524 
00525     updateTOCRegister(insnBuffer,insnIndex);
00526 
00527 /* calculate target and source addresses for function call */
00528     uint64_t fromAddr = stubAddr + ((*insnIndex) * sizeof(uint32_t));
00529     uint64_t toAddr   = funcAddr;
00530 
00531 /* generate call to function */
00532     insnBuffer[(*insnIndex)++] = Instruction::generateCallToImmediate(fromAddr,toAddr);
00533 
00534 
00535     updateTOCRegister(insnBuffer,insnIndex);
00536 
00537 /* restore original LNK register value */
00538     insnBuffer[(*insnIndex)++] = Instruction::generateLoadDouble(reg,REG_TOC,getLNKSaveOffset());
00539     insnBuffer[(*insnIndex)++] = Instruction::generateMoveToSPR(reg,REG_LNK);
00540 
00541 /* restore original CR register value */
00542     insnBuffer[(*insnIndex)++] = Instruction::generateLoadWord(reg,REG_TOC,getCRSaveOffset());
00543     insnBuffer[(*insnIndex)++] = Instruction::generateMoveToCR(reg);
00544 }
00545 
00546 uint32_t CountAllBlocks::generateSharedLibFuncWrapper(
00547     uint32_t libFuncIdx,uint64_t funcCallAddr,uint32_t genBufferOffset,BaseGen* gen)
00548 {
00549 
00550 
00551     uint32_t insnCount = 0;
00552     Instruction* insnBuffer = new Instruction[byteCountForSharedLibFuncWrappers() / sizeof(uint32_t)];
00553 
00554     uint32_t scratchReg = 6;
00555     uint32_t fpScratchReg = 3;
00556     uint32_t savedReg = 31;
00557     uint32_t tocHoldReg = 30;
00558     uint32_t firstArgReg = 3;
00559     uint32_t secondArgReg = 4;
00560     uint32_t thirdArgReg = 5;
00561 
00562     ASSERT(scratchReg == 6);
00563     ASSERT(fpScratchReg == 3);
00564     ASSERT(savedReg == 31);
00565     ASSERT(tocHoldReg == 30);
00566     ASSERT(firstArgReg == 3);
00567     ASSERT(secondArgReg == 4);
00568     ASSERT(thirdArgReg == 5);
00569 
00570     int32_t saveOffset = 0x0;
00571 
00572     updateTOCRegister(insnBuffer,&insnCount);
00573 
00574 /* store all GP registers to extended data section */
00575     for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00576         saveOffset = getGPRSaveOffset(i);
00577         insnBuffer[insnCount++] = Instruction::generateStoreDouble(i,REG_TOC,saveOffset);
00578     }
00579 
00580 /* store all FP registers to extended data section */
00581     for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00582         saveOffset = getFPRSaveOffset(i);
00583         insnBuffer[insnCount++] = Instruction::generateStoreDoubleFloat(i,REG_TOC,saveOffset);
00584     }
00585 
00586 /* save CTR Register */
00587     insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(scratchReg,REG_CTR);
00588     insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,getCTRSaveOffset());
00589 
00590 /* save EXR Register */
00591     insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(scratchReg,REG_XER);
00592     insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,getEXRSaveOffset());
00593 
00594 /* save FPSCR Register */
00595     insnBuffer[insnCount++] = Instruction::generateMoveFromFPSCR(scratchReg);
00596     insnBuffer[insnCount++] = Instruction::generateStoreWordFloat(scratchReg,REG_TOC,getFPSCRSaveOffset());
00597 
00598 /* put buffer address (in extended data section) into first argument register to be passed to function */
00599     uint32_t bufferOffset = getDataOffsetForInst(0);
00600     insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,firstArgReg);
00601     insnBuffer[insnCount++] = Instruction::generateIncrement(firstArgReg,bufferOffset);
00602 
00603 /* put the number of buffer entries into second argument register to be passed to function */
00604     uint32_t bufferCount = getDataBufferEntryCount();
00605     insnBuffer[insnCount++] = Instruction::generateLoad32BitHigh(secondArgReg,bufferCount);
00606     insnBuffer[insnCount++] = Instruction::generateLoad32BitLow(secondArgReg,bufferCount);
00607 
00608 /* put comment address (in extended data section) into third argument register to be passed to function */
00609     uint32_t commentOffset = getCommentAddressOffset();
00610     insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,thirdArgReg);
00611     insnBuffer[insnCount++] = Instruction::generateIncrement(thirdArgReg,commentOffset);
00612 
00613 /* save LNK reg to savedReg */
00614     insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(savedReg,REG_LNK);
00615 
00616 /* save TOC reg to tocHoldReg */
00617     insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,tocHoldReg);
00618 
00619 
00620     int32_t callOffset = funcCallAddr - execTOCAddress - tocDistUpdateVal;
00621     if(xcoffFile->is64Bit()){
00622 /* move stack pointer (push a new stack frame) */
00623         insnBuffer[insnCount++] = Instruction::generateSPIncrementDouble(-SAFE_FRAME_LOC*sizeof(uint64_t));
00624 /* load pointer to function address into scratchReg */
00625         insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,callOffset);
00626 /* Each function pointer is composed of the address of function instructions followed by the TOC register value 
00627    for the function. first we load the TOC register for the function into REG_TOC */
00628         insnBuffer[insnCount++] = Instruction::generateLoadDouble(REG_TOC,scratchReg,sizeof(uint64_t));
00629 /* Then we load the function address into scratchReg*/
00630         insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,scratchReg,0);
00631     } else {
00632         insnBuffer[insnCount++] = Instruction::generateSPIncrementWord(-SAFE_FRAME_LOC*sizeof(uint64_t));
00633         insnBuffer[insnCount++] = Instruction::generateLoadWord(scratchReg,REG_TOC,callOffset);
00634         insnBuffer[insnCount++] = Instruction::generateLoadWord(REG_TOC,scratchReg,sizeof(uint32_t));
00635         insnBuffer[insnCount++] = Instruction::generateLoadWord(scratchReg,scratchReg,0);
00636     }
00637 
00638 /* move function address to CTR register */
00639     insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_CTR);
00640 /* call the function by calling the adddress in the CTR reg */
00641     insnBuffer[insnCount++] = Instruction::generateCallToCTR();
00642 
00643 /* restore the original TOC register value */
00644     insnBuffer[insnCount++] = Instruction::generateMoveReg(tocHoldReg,REG_TOC);
00645 
00646 /* restore the original LNK register value */
00647     insnBuffer[insnCount++] = Instruction::generateMoveToSPR(savedReg,REG_LNK);
00648 
00649 /* restore original FPSCR register value */
00650     insnBuffer[insnCount++] = Instruction::generateLoadWordFloat(fpScratchReg,REG_TOC,getFPSCRSaveOffset());
00651     insnBuffer[insnCount++] = Instruction::generateMoveToFPSCR(fpScratchReg);
00652 
00653 /* restore original EXR register value */
00654     insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,getEXRSaveOffset());
00655     insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_XER);
00656 
00657 /* restore original CTR register value */
00658     insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,getCTRSaveOffset());
00659     insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_CTR);
00660 
00661 /* restore original FP register values */
00662     for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00663         saveOffset = getFPRSaveOffset(i);
00664         insnBuffer[insnCount++] = Instruction::generateLoadDoubleFloat(i,REG_TOC,saveOffset);
00665     }
00666 
00667 /* restore original GP register values */
00668     for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00669         saveOffset = getGPRSaveOffset(i);
00670         insnBuffer[insnCount++] = Instruction::generateLoadDouble(i,REG_TOC,saveOffset);
00671     }
00672 
00673     updateTOCRegister(insnBuffer,&insnCount);
00674 
00675 /* return to original code (address held in LNK reg) */
00676     insnBuffer[insnCount++] = Instruction::generateReturnToLnk();
00677 
00678     gen->writeInstructions(genBufferOffset,insnCount,insnBuffer);
00679 
00680     delete[] insnBuffer;
00681 
00682     return (insnCount*sizeof(uint32_t));
00683 }

Generated on Mon Jan 28 11:08:33 2008 for PMaCInstrumentor by doxygen 1.3.5