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
00148 insnBuffer[insnCount++] = origInsn;
00149
00150 updateTOCRegister(insnBuffer,&insnCount);
00151
00152
00153 insnBuffer[insnCount++] = Instruction::generateStoreDouble(savedReg,REG_TOC,savedRegSaveOffset);
00154
00155 bool oneWordCounter = (sizeof(uint32_t) == bytesPerBufferEntry());
00156
00157
00158 if(!Instruction::isInLoadOffsetInsnRange(blockCounterOffset)){
00159
00160
00161 insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00162
00163 insnBuffer[insnCount++] = Instruction::generateLoad32BitHigh(scratchReg,blockCounterOffset);
00164 insnBuffer[insnCount++] = Instruction::generateLoad32BitLow(scratchReg,blockCounterOffset);
00165
00166
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
00174 insnBuffer[insnCount++] = Instruction::generateIncrement(savedReg,1);
00175
00176
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
00183 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,scratchRegSaveOffset);
00184
00185
00186 } else {
00187
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
00195 insnBuffer[insnCount++] = Instruction::generateIncrement(savedReg,1);
00196
00197
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
00207
00208 if(isApplicationExit){
00209
00210
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
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
00225 insnBuffer[insnCount++] = Instruction::generateJumpInsn(fromAddr,toAddr);
00226
00227
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
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
00290 for (uint32_t i = 0; i < getNumOfSharedLibFuncs(); i++){
00291 libraryFunctionStubAddrLocs[i] = currentFreeAddress;
00292 currentFreeAddress += incrementSize;
00293 }
00294
00295
00296
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
00320
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
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
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
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
00516
00517
00518 insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromCR(reg);
00519 insnBuffer[(*insnIndex)++] = Instruction::generateStoreWord(reg,REG_TOC,getCRSaveOffset());
00520
00521
00522 insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromSPR(reg,REG_LNK);
00523 insnBuffer[(*insnIndex)++] = Instruction::generateStoreDouble(reg,REG_TOC,getLNKSaveOffset());
00524
00525 updateTOCRegister(insnBuffer,insnIndex);
00526
00527
00528 uint64_t fromAddr = stubAddr + ((*insnIndex) * sizeof(uint32_t));
00529 uint64_t toAddr = funcAddr;
00530
00531
00532 insnBuffer[(*insnIndex)++] = Instruction::generateCallToImmediate(fromAddr,toAddr);
00533
00534
00535 updateTOCRegister(insnBuffer,insnIndex);
00536
00537
00538 insnBuffer[(*insnIndex)++] = Instruction::generateLoadDouble(reg,REG_TOC,getLNKSaveOffset());
00539 insnBuffer[(*insnIndex)++] = Instruction::generateMoveToSPR(reg,REG_LNK);
00540
00541
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
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
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
00587 insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(scratchReg,REG_CTR);
00588 insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,getCTRSaveOffset());
00589
00590
00591 insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(scratchReg,REG_XER);
00592 insnBuffer[insnCount++] = Instruction::generateStoreDouble(scratchReg,REG_TOC,getEXRSaveOffset());
00593
00594
00595 insnBuffer[insnCount++] = Instruction::generateMoveFromFPSCR(scratchReg);
00596 insnBuffer[insnCount++] = Instruction::generateStoreWordFloat(scratchReg,REG_TOC,getFPSCRSaveOffset());
00597
00598
00599 uint32_t bufferOffset = getDataOffsetForInst(0);
00600 insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,firstArgReg);
00601 insnBuffer[insnCount++] = Instruction::generateIncrement(firstArgReg,bufferOffset);
00602
00603
00604 uint32_t bufferCount = getDataBufferEntryCount();
00605 insnBuffer[insnCount++] = Instruction::generateLoad32BitHigh(secondArgReg,bufferCount);
00606 insnBuffer[insnCount++] = Instruction::generateLoad32BitLow(secondArgReg,bufferCount);
00607
00608
00609 uint32_t commentOffset = getCommentAddressOffset();
00610 insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,thirdArgReg);
00611 insnBuffer[insnCount++] = Instruction::generateIncrement(thirdArgReg,commentOffset);
00612
00613
00614 insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(savedReg,REG_LNK);
00615
00616
00617 insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,tocHoldReg);
00618
00619
00620 int32_t callOffset = funcCallAddr - execTOCAddress - tocDistUpdateVal;
00621 if(xcoffFile->is64Bit()){
00622
00623 insnBuffer[insnCount++] = Instruction::generateSPIncrementDouble(-SAFE_FRAME_LOC*sizeof(uint64_t));
00624
00625 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,callOffset);
00626
00627
00628 insnBuffer[insnCount++] = Instruction::generateLoadDouble(REG_TOC,scratchReg,sizeof(uint64_t));
00629
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
00639 insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_CTR);
00640
00641 insnBuffer[insnCount++] = Instruction::generateCallToCTR();
00642
00643
00644 insnBuffer[insnCount++] = Instruction::generateMoveReg(tocHoldReg,REG_TOC);
00645
00646
00647 insnBuffer[insnCount++] = Instruction::generateMoveToSPR(savedReg,REG_LNK);
00648
00649
00650 insnBuffer[insnCount++] = Instruction::generateLoadWordFloat(fpScratchReg,REG_TOC,getFPSCRSaveOffset());
00651 insnBuffer[insnCount++] = Instruction::generateMoveToFPSCR(fpScratchReg);
00652
00653
00654 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,getEXRSaveOffset());
00655 insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_XER);
00656
00657
00658 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,getCTRSaveOffset());
00659 insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_CTR);
00660
00661
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
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
00676 insnBuffer[insnCount++] = Instruction::generateReturnToLnk();
00677
00678 gen->writeInstructions(genBufferOffset,insnCount,insnBuffer);
00679
00680 delete[] insnBuffer;
00681
00682 return (insnCount*sizeof(uint32_t));
00683 }