00001 #include <SectHeader.h>
00002 #include <Iterator.h>
00003 #include <Function.h>
00004 #include <LineInfoFinder.h>
00005 #include <XCoffFile.h>
00006 #include <CommonMethods.h>
00007 #include <Loop.h>
00008 #include <fstream>
00009 using namespace std;
00010
00011
00012 char* CommonMethods::staticPrintExtension = "static";
00013
00014 CommonMethods::CommonMethods(XCoffFile* xcoff,char* extension,uint32_t phaseNo,uint32_t callCount,char* inpFile)
00015 : XCoffFileGen(xcoff,extension,phaseNo,inpFile),libraryFunctionCount(callCount),
00016 blocksToInstrument(NULL),terminationBlock(NULL),numOfBlocksFiltered(0),
00017 extendedBeginAddr(0),
00018 execTOCAddress(0),tocXorUpdateVal(0),tocDistUpdateVal(0),
00019 sharedLibraryInfoStr(NULL),enableExtendedPrint(false)
00020 {
00021 }
00022
00023 BasicBlock* CommonMethods::findTerminationBlock(){
00024
00025 char* tmpStr = "";
00026 uint32_t allBlocksCount = xcoffFile->getNumberOfBlocks();
00027 if(!allBlocksCount)
00028 return NULL;
00029
00030 BasicBlock** allBlocks = new BasicBlock*[allBlocksCount];
00031 xcoffFile->getAllBlocks(allBlocks);
00032
00033 BasicBlock* mpiexit = NULL;
00034 BasicBlock* regexit = NULL;
00035 BasicBlock* pmacexit = NULL;
00036
00037 for (uint32_t i = 0; i < allBlocksCount; i++){
00038 BasicBlock* bb = allBlocks[i];
00039 if (bb->isTrace() || bb->isJumpTable() || bb->getIndex())
00040 continue;
00041 Function* owner = bb->getFlowGraph()->getFunction();
00042 if (!pmacexit && owner->isAnySymbolA(".__pmac_time_mod_NMOD_end_pmac_clock")){
00043 tmpStr = ".__pmac_time_mod_NMOD_end_pmac_clock";
00044 pmacexit = bb;
00045 }
00046 if (!pmacexit && owner->isAnySymbolA(".end_pmac_fromc")){
00047 tmpStr = ".end_pmac_fromc";
00048 pmacexit = bb;
00049 }
00050 if (!mpiexit &&
00051 (owner->isAnySymbolA(".mpi_finalize") ||
00052 owner->isAnySymbolA(".MPI_Finalize"))){
00053 mpiexit = bb;
00054 }
00055 if (!regexit && owner->isAnySymbolA(".exit")){
00056 regexit = bb;
00057 }
00058 }
00059 delete[] allBlocks;
00060
00061 if (pmacexit) {
00062 PRINT_INFOR("The exit function .end_pmac_fromc(%s) is taken",tmpStr);
00063 return pmacexit;
00064 }
00065 if (mpiexit){
00066 PRINT_INFOR("The exit function .mpi_finalize is taken");
00067 return mpiexit;
00068 }
00069 if (regexit){
00070 PRINT_INFOR("The exit function .exit is taken");
00071 return regexit;
00072 }
00073 return NULL;
00074 }
00075
00076 void CommonMethods::printInstrumentationPoints(){
00077
00078 char instBlockFileName[__MAX_STRING_SIZE];
00079 if (!getPhaseIndex()){
00080 sprintf(instBlockFileName,"%s.%s.%s",xcoffFile->getXCoffFileName(),getFileExtension(),staticPrintExtension);
00081 } else {
00082 sprintf(instBlockFileName,"%s.phase.%d.%s.%s",xcoffFile->getXCoffFileName(),getPhaseIndex(),
00083 getFileExtension(),staticPrintExtension);
00084 }
00085
00086 ofstream instBlockFile;
00087 instBlockFile.open(instBlockFileName);
00088 if (!instBlockFile){
00089 PRINT_ERROR("Instrumented block infor can not be opened [%s]",instBlockFileName);
00090 }
00091
00092 uint32_t memOpCount = 0;
00093 uint32_t fpOpCount = 0;
00094 uint32_t insnCount = 0;
00095
00096 for (uint32_t i=0;i<numberOfInstPoints;i++){
00097 memOpCount += blocksToInstrument[i]->getNumOfMemoryOps();
00098 fpOpCount += blocksToInstrument[i]->getNumOfFloatPOps();
00099 insnCount += blocksToInstrument[i]->getInstructionCount();
00100 }
00101
00102 TextSection* lineInfoSect = (TextSection*)xcoffFile->getRawSection(xcoffFile->getTextSectionIndex());
00103 LineInfoFinder* lineInfoFinder = lineInfoSect->getLineInfoFinder();
00104
00105 instBlockFile << "# appname = " << xcoffFile->getXCoffFileName() << endl;
00106 instBlockFile << "# appsize = " << xcoffFile->getFileSize() << endl;
00107 instBlockFile << "# extension = " << getFileExtension() << endl;
00108 instBlockFile << "# phase = " << getPhaseIndex() << endl;
00109 instBlockFile << "# type = " << getGenClassName() << endl;
00110 instBlockFile << "# candidate = " << xcoffFile->getNumberOfBlocks() << endl;
00111 instBlockFile << "# blocks = " << numberOfInstPoints << endl;
00112 instBlockFile << "# memops = " << memOpCount << endl;
00113 instBlockFile << "# fpops = " << fpOpCount << endl;
00114 instBlockFile << "# insns = " << insnCount << endl;
00115 instBlockFile << "# buffer = " << howManyBufferEntry() << endl;
00116 instBlockFile << "# library = " << getPathToInstLib() << endl;
00117 instBlockFile << "# libTag = " << VersionTag::getLibraryVersionTag() << endl;
00118 instBlockFile << "# " << additionalInfoToPrint() << endl;
00119 if(isExtendedPrint()){
00120 instBlockFile << "# <sequence> <block_uid> <memop> <fpop> <insn> <line> <fname>";
00121 instBlockFile << " <loopcnt> <loopid> <ldepth> <hex_uid> <vaddr>" << endl;
00122 } else {
00123 instBlockFile << "# <sequence> <block_uid> <memop> <fpop> <insn> <line> <fname>";
00124 instBlockFile << " <hex_uid> <vaddr>" << endl;
00125 }
00126
00127 for (uint32_t i = 0; i < numberOfInstPoints; i++){
00128 BasicBlock* bb = blocksToInstrument[i];
00129 uint64_t unq = bb->getHashCode().getValue();
00130 Function* owner = bb->getFlowGraph()->getFunction();
00131 char names[__MAX_STRING_SIZE];
00132 names[0] = '\0';
00133 owner->getAllSymbolNames(names,__MAX_STRING_SIZE,true);
00134 if(!strlen(names)){
00135 strcpy(names,"__name__unknown__");
00136 }
00137 char* absFile = NULL;
00138 uint32_t absLine =0;
00139 if(lineInfoFinder){
00140 uint64_t addr = bb->getBaseAddress();
00141 absFile = lineInfoFinder->getFileName(addr);
00142 absLine = lineInfoFinder->getLineNumberInFile(addr);
00143 }
00144
00145 uint32_t loopId = Invalid_UInteger_ID;
00146 uint32_t loopDepth = 0;
00147 uint32_t loopCount = bb->getFlowGraph()->getNumberOfLoops();
00148
00149 if(isExtendedPrint()){
00150 for(uint32_t j=0;j<loopCount;j++){
00151 Loop* currLoop = bb->getFlowGraph()->getLoop(j);
00152 if(currLoop->isBlockIn(bb->getIndex())){
00153 loopDepth++;
00154 loopId = currLoop->getIndex();
00155 }
00156 }
00157 }
00158
00159 instBlockFile << i << "\t" << unq
00160 << "\t" << bb->getNumOfMemoryOps()
00161 << "\t" << bb->getNumOfFloatPOps()
00162 << "\t" << bb->getInstructionCount()
00163 << "\t" << (absFile ? absFile : "__FILE_UNK__") << ":" << absLine
00164 << "\t" << names << "\t#";
00165 if(isExtendedPrint()){
00166 instBlockFile << "\t" << loopCount << "\t" << (int32_t)loopId << "\t" << loopDepth;
00167 }
00168 instBlockFile << "\t 0x" << hex << unq << "\t0x" << bb->getBaseAddress() << dec
00169 << endl;
00170 }
00171 instBlockFile.close();
00172
00173 char sysCommand[__MAX_STRING_SIZE];
00174 sprintf(sysCommand,"chmod a-w %s",instBlockFileName);
00175
00176 }
00177
00178 void CommonMethods::reserveDataForInstrumentation(){
00179
00180 extendedDataSize = 0;
00181 extendedBeginAddr = 0;
00182 dataBufferEntryCount = 0;
00183
00184 uint64_t dataSectionBeginAddr = xcoffFile->getDataSectionVAddr();
00185 uint32_t dataSectionSize = xcoffFile->getDataSectionSize();
00186
00187 execTOCAddress = xcoffFile->getTOCAddress();
00188
00189 uint64_t currentFreeAddress = dataSectionBeginAddr + dataSectionSize;
00190
00191 uint32_t incrementSize = 0;
00192 if (xcoffFile->is64Bit()){
00193 currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00194 incrementSize = sizeof(uint64_t);
00195 } else {
00196 currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00197 incrementSize = sizeof(uint32_t);
00198 }
00199
00200 extendedBeginAddr = currentFreeAddress;
00201
00202 for (uint32_t i = 0; i < getNumOfSharedLibFuncs(); i++){
00203 libraryFunctionStubAddrLocs[i] = currentFreeAddress;
00204 currentFreeAddress += incrementSize;
00205 }
00206
00207 currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00208
00209 saveAddressCondReg = currentFreeAddress;
00210 currentFreeAddress += sizeof(uint32_t);
00211 saveAddressFPCondReg = currentFreeAddress;
00212 currentFreeAddress += sizeof(uint32_t);
00213
00214 currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00215
00216 saveAddressLinkReg = currentFreeAddress;
00217 currentFreeAddress += sizeof(uint64_t);
00218 saveAddressCtrReg = currentFreeAddress;
00219 currentFreeAddress += sizeof(uint64_t);
00220 saveAddressExpReg = currentFreeAddress;
00221 currentFreeAddress += sizeof(uint64_t);
00222
00223 saveAddressGprRegs = currentFreeAddress;
00224 currentFreeAddress += (sizeof(uint64_t) * NUM_OF_GPR_REGS);
00225 saveAddressFprRegs = currentFreeAddress;
00226 currentFreeAddress += (sizeof(uint64_t) * NUM_OF_FPR_REGS);
00227
00228 char* ptr = xcoffFile->getXCoffFileName();
00229 char* sepPtr = strrchr(ptr,'/');
00230 if(sepPtr){
00231 ptr = (sepPtr + 1);
00232 }
00233 char tmpStr[__MAX_STRING_SIZE];
00234 if(!phaseIndex){
00235 sprintf(tmpStr,"%s 0 %s %d",ptr,getFileExtension(),
00236 getNumberOfInstPoints(NULL));
00237 } else {
00238 sprintf(tmpStr,"%s %d %s %d",ptr,getPhaseIndex(),getFileExtension(),
00239 getNumberOfInstPoints(NULL));
00240 }
00241
00242 commentAddress = currentFreeAddress;
00243 sharedLibraryInfoStr = strdup(tmpStr);
00244 currentFreeAddress += (strlen(sharedLibraryInfoStr) + 1);
00245
00246 dataBufferEntryCount = howManyBufferEntry();
00247 incrementSize = bytesPerBufferEntry();
00248
00249 if(incrementSize == sizeof(uint32_t)){
00250 currentFreeAddress = nextAlignAddressWord(currentFreeAddress);
00251 } else {
00252 currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00253 }
00254
00255 dataBufferAddress = currentFreeAddress;
00256 currentFreeAddress += (dataBufferEntryCount * incrementSize);
00257
00258 extraBlockInfoAddress = currentFreeAddress;
00259 currentFreeAddress += spaceForBlockInfo();
00260
00261 currentFreeAddress = nextAlignAddressDouble(currentFreeAddress);
00262
00263 extendedDataSize = currentFreeAddress - (dataSectionBeginAddr + dataSectionSize);
00264
00265 tocXorUpdateVal = 0;
00266 if(!Instruction::isInLoadOffsetInsnRange((int32_t)(dataBufferAddress-execTOCAddress))){
00267 tocXorUpdateVal = (uint32_t)(extendedBeginAddr ^ execTOCAddress);
00268 tocDistUpdateVal = (uint32_t)(extendedBeginAddr - execTOCAddress);
00269 }
00270
00271 PRINT_INFOR("**** Additional data section inc is %d ***",extendedDataSize);
00272 PRINT_INFOR("**** Number of entries to process is %18d ***",dataBufferEntryCount);
00273 PRINT_INFOR("**** Start address for toc is %#18llx (%lld) ***",
00274 execTOCAddress,execTOCAddress-dataSectionBeginAddr);
00275 PRINT_INFOR("**** Start address for additional is %#18llx (%lld) ***",
00276 extendedBeginAddr,extendedBeginAddr-execTOCAddress);
00277 PRINT_INFOR("**** The tocXorUpdateVal for save is %x %d ***",
00278 tocXorUpdateVal,tocDistUpdateVal);
00279 PRINT_INFOR("**** Start address for the gprs is %#18llx (%lld) ***",
00280 saveAddressGprRegs,saveAddressGprRegs-execTOCAddress);
00281 PRINT_INFOR("**** Start address for the comm is %#18llx (%lld) ***",
00282 commentAddress,commentAddress-execTOCAddress);
00283 PRINT_INFOR("**** Start address for the buffer is %#18llx (%lld) ***",
00284 dataBufferAddress,dataBufferAddress-execTOCAddress);
00285 PRINT_INFOR("**** End address for the buffer is %#18llx (%lld) ***",
00286 currentFreeAddress,currentFreeAddress-execTOCAddress);
00287 }
00288
00289 void CommonMethods::updateTOCRegister(Instruction* insnBuffer,uint32_t* insnIndex){
00290 uint16_t tocUpdateValLow = FIRST_HALFWORD(tocXorUpdateVal);
00291 uint16_t tocUpdateValHigh = SECOND_HALFWORD(tocXorUpdateVal);
00292 if(tocXorUpdateVal){
00293 if(tocUpdateValHigh){
00294 insnBuffer[(*insnIndex)++] = Instruction::generateXorImmShifted(REG_TOC,REG_TOC,tocUpdateValHigh);
00295 }
00296 insnBuffer[(*insnIndex)++] = Instruction::generateXorImm(REG_TOC,REG_TOC,tocUpdateValLow);
00297 }
00298 }
00299 void CommonMethods::saveCTRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00300 int32_t saveOffset = getCTRSaveOffset();
00301 insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromSPR(reg,REG_CTR);
00302 insnBuffer[(*insnIndex)++] = Instruction::generateStoreDouble(reg,REG_TOC,saveOffset);
00303 }
00304 void CommonMethods::restCTRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00305 int32_t saveOffset = getCTRSaveOffset();
00306 insnBuffer[(*insnIndex)++] = Instruction::generateLoadDouble(reg,REG_TOC,saveOffset);
00307 insnBuffer[(*insnIndex)++] = Instruction::generateMoveToSPR(reg,REG_CTR);
00308 }
00309 void CommonMethods::saveEXRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00310 int32_t saveOffset = getEXRSaveOffset();
00311 insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromSPR(reg,REG_XER);
00312 insnBuffer[(*insnIndex)++] = Instruction::generateStoreDouble(reg,REG_TOC,saveOffset);
00313 }
00314 void CommonMethods::restEXRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00315 int32_t saveOffset = getEXRSaveOffset();
00316 insnBuffer[(*insnIndex)++] = Instruction::generateLoadDouble(reg,REG_TOC,saveOffset);
00317 insnBuffer[(*insnIndex)++] = Instruction::generateMoveToSPR(reg,REG_XER);
00318 }
00319 void CommonMethods::saveFPSCRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00320 int32_t saveOffset = getFPSCRSaveOffset();
00321 insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromFPSCR(reg);
00322 insnBuffer[(*insnIndex)++] = Instruction::generateStoreWordFloat(reg,REG_TOC,saveOffset);
00323 }
00324 void CommonMethods::restFPSCRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00325 int32_t saveOffset = getFPSCRSaveOffset();
00326 insnBuffer[(*insnIndex)++] = Instruction::generateLoadWordFloat(reg,REG_TOC,saveOffset);
00327 insnBuffer[(*insnIndex)++] = Instruction::generateMoveToFPSCR(reg);
00328 }
00329 void CommonMethods::saveCRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00330 int32_t saveOffset = getCRSaveOffset();
00331 insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromCR(reg);
00332 insnBuffer[(*insnIndex)++] = Instruction::generateStoreWord(reg,REG_TOC,saveOffset);
00333 }
00334 void CommonMethods::restCRRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00335 int32_t saveOffset = getCRSaveOffset();
00336 insnBuffer[(*insnIndex)++] = Instruction::generateLoadWord(reg,REG_TOC,saveOffset);
00337 insnBuffer[(*insnIndex)++] = Instruction::generateMoveToCR(reg);
00338 }
00339 void CommonMethods::saveLNKRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00340 int32_t saveOffset = getLNKSaveOffset();
00341 insnBuffer[(*insnIndex)++] = Instruction::generateMoveFromSPR(reg,REG_LNK);
00342 insnBuffer[(*insnIndex)++] = Instruction::generateStoreDouble(reg,REG_TOC,saveOffset);
00343 }
00344 void CommonMethods::restLNKRegister(Instruction* insnBuffer,uint32_t* insnIndex,uint32_t reg){
00345 int32_t saveOffset = getLNKSaveOffset();
00346 insnBuffer[(*insnIndex)++] = Instruction::generateLoadDouble(reg,REG_TOC,saveOffset);
00347 insnBuffer[(*insnIndex)++] = Instruction::generateMoveToSPR(reg,REG_LNK);
00348 }
00349
00350
00351 void CommonMethods::generateFuncCallFull(Instruction* insnBuffer,uint32_t* insnIndex,
00352 uint32_t reg,uint64_t stubAddr,uint64_t funcAddr)
00353 {
00354
00355
00356 saveCRRegister(insnBuffer,insnIndex,reg);
00357 saveLNKRegister(insnBuffer,insnIndex,reg);
00358
00359 updateTOCRegister(insnBuffer,insnIndex);
00360
00361 uint64_t fromAddr = stubAddr + ((*insnIndex) * sizeof(uint32_t));
00362 uint64_t toAddr = funcAddr;
00363 insnBuffer[(*insnIndex)++] = Instruction::generateCallToImmediate(fromAddr,toAddr);
00364
00365 updateTOCRegister(insnBuffer,insnIndex);
00366
00367 restLNKRegister(insnBuffer,insnIndex,reg);
00368 restCRRegister(insnBuffer,insnIndex,reg);
00369 }
00370
00371 uint32_t CommonMethods::generateSharedLibFuncWrapper(
00372 uint32_t libFuncIdx,uint64_t funcCallAddr,uint32_t genBufferOffset,BaseGen* gen)
00373 {
00374
00375
00376 uint32_t insnCount = 0;
00377 Instruction* insnBuffer = new Instruction[byteCountForSharedLibFuncWrappers() / sizeof(uint32_t)];
00378
00379 uint32_t scratchReg = 6;
00380 uint32_t fpScratchReg = 3;
00381 uint32_t savedReg = 31;
00382 uint32_t tocHoldReg = 30;
00383 uint32_t firstArgReg = 3;
00384 uint32_t secondArgReg = 4;
00385 uint32_t thirdArgReg = 5;
00386
00387 ASSERT(scratchReg == 6);
00388 ASSERT(fpScratchReg == 3);
00389 ASSERT(savedReg == 31);
00390 ASSERT(tocHoldReg == 30);
00391 ASSERT(firstArgReg == 3);
00392 ASSERT(secondArgReg == 4);
00393 ASSERT(thirdArgReg == 5);
00394
00395 int32_t saveOffset = 0x0;
00396
00397 updateTOCRegister(insnBuffer,&insnCount);
00398
00399 for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00400 saveOffset = getGPRSaveOffset(i);
00401 insnBuffer[insnCount++] = Instruction::generateStoreDouble(i,REG_TOC,saveOffset);
00402 }
00403 for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00404 saveOffset = getFPRSaveOffset(i);
00405 insnBuffer[insnCount++] = Instruction::generateStoreDoubleFloat(i,REG_TOC,saveOffset);
00406 }
00407
00408 saveCTRRegister(insnBuffer,&insnCount,scratchReg);
00409 saveEXRRegister(insnBuffer,&insnCount,scratchReg);
00410 saveFPSCRRegister(insnBuffer,&insnCount,fpScratchReg);
00411
00412 uint32_t bufferOffset = getDataOffsetForInst(0);
00413 insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,firstArgReg);
00414 insnBuffer[insnCount++] = Instruction::generateIncrement(firstArgReg,bufferOffset);
00415
00416 uint32_t bufferCount = getDataBufferEntryCount();
00417 insnBuffer[insnCount++] = Instruction::generateLoad32BitHigh(secondArgReg,bufferCount);
00418 insnBuffer[insnCount++] = Instruction::generateLoad32BitLow(secondArgReg,bufferCount);
00419
00420 uint32_t commentOffset = getCommentAddressOffset();
00421 insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,thirdArgReg);
00422 insnBuffer[insnCount++] = Instruction::generateIncrement(thirdArgReg,commentOffset);
00423
00424 insnBuffer[insnCount++] = Instruction::generateMoveFromSPR(savedReg,REG_LNK);
00425 insnBuffer[insnCount++] = Instruction::generateMoveReg(REG_TOC,tocHoldReg);
00426
00427
00428 int32_t callOffset = funcCallAddr - execTOCAddress - tocDistUpdateVal;
00429 if(xcoffFile->is64Bit()){
00430 insnBuffer[insnCount++] = Instruction::generateSPIncrementDouble(-SAFE_FRAME_LOC*sizeof(uint64_t));
00431 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,REG_TOC,callOffset);
00432 insnBuffer[insnCount++] = Instruction::generateLoadDouble(REG_TOC,scratchReg,sizeof(uint64_t));
00433 insnBuffer[insnCount++] = Instruction::generateLoadDouble(scratchReg,scratchReg,0);
00434 } else {
00435 insnBuffer[insnCount++] = Instruction::generateSPIncrementWord(-SAFE_FRAME_LOC*sizeof(uint64_t));
00436 insnBuffer[insnCount++] = Instruction::generateLoadWord(scratchReg,REG_TOC,callOffset);
00437 insnBuffer[insnCount++] = Instruction::generateLoadWord(REG_TOC,scratchReg,sizeof(uint32_t));
00438 insnBuffer[insnCount++] = Instruction::generateLoadWord(scratchReg,scratchReg,0);
00439 }
00440 insnBuffer[insnCount++] = Instruction::generateMoveToSPR(scratchReg,REG_CTR);
00441 insnBuffer[insnCount++] = Instruction::generateCallToCTR();
00442
00443 insnBuffer[insnCount++] = Instruction::generateMoveReg(tocHoldReg,REG_TOC);
00444 insnBuffer[insnCount++] = Instruction::generateMoveToSPR(savedReg,REG_LNK);
00445
00446 restFPSCRRegister(insnBuffer,&insnCount,fpScratchReg);
00447 restEXRRegister(insnBuffer,&insnCount,scratchReg);
00448 restCTRRegister(insnBuffer,&insnCount,scratchReg);
00449
00450 for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00451 saveOffset = getFPRSaveOffset(i);
00452 insnBuffer[insnCount++] = Instruction::generateLoadDoubleFloat(i,REG_TOC,saveOffset);
00453 }
00454 for(uint32_t i=0;i<=LAST_VOLATILE_REG;i++){
00455 saveOffset = getGPRSaveOffset(i);
00456 insnBuffer[insnCount++] = Instruction::generateLoadDouble(i,REG_TOC,saveOffset);
00457 }
00458 updateTOCRegister(insnBuffer,&insnCount);
00459
00460 insnBuffer[insnCount++] = Instruction::generateReturnToLnk();
00461
00462 gen->writeInstructions(genBufferOffset,insnCount,insnBuffer);
00463
00464 delete[] insnBuffer;
00465
00466 return (insnCount*sizeof(uint32_t));
00467 }