blob: 79dc04e1700887a4e16896bd775d21dc184429b5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Konstantin M. Anisimov, Igor V. Chebykin
*
*/
#include "IpfPrologEpilogGenerator.h"
#include "IpfIrPrinter.h"
namespace Jitrino {
namespace IPF {
//========================================================================================//
// PrologEpilogGenerator
//========================================================================================//
PrologEpilogGenerator::PrologEpilogGenerator(Cfg &cfg) :
mm(cfg.getMM()),
cfg(cfg),
outRegArgs(mm),
prologInsts(mm),
epilogInsts(mm),
allocInsts(mm),
saveSpInsts(mm),
savePfsInsts(mm),
saveUnatInsts(mm),
saveGrsInsts(mm),
saveFrsInsts(mm),
saveBrsInsts(mm),
savePrsInsts(mm),
saveRpInsts(mm),
restRpInsts(mm),
restPrsInsts(mm),
restBrsInsts(mm),
restFrsInsts(mm),
restGrsInsts(mm),
restUnatInsts(mm),
restPfsInsts(mm),
restSpInsts(mm),
epilogNodes(mm) {
opndManager = cfg.getOpndManager();
p0 = opndManager->getP0();
sp = opndManager->getR12();
stackAddr = opndManager->newRegOpnd(OPND_G_REG, DATA_I64, SPILL_REG1);
}
//----------------------------------------------------------------------------------------//
// Generate prolog and epilog
// save/restore callee saved regs
// build mask of regs not used in method
// generate "alloc"
// calculate number of local grs
// save/restore PFS, Stack pointer and Return pointer
// calculate stack size
// reassign out reg args. Now they are located inverse order in the end of reg
// stack (first in 127, second in 126 ...)
void PrologEpilogGenerator::genPrologEpilog() {
buildSets();
IPF_LOG << endl << " Generate Code" << endl;
genCode();
IPF_LOG << " Reassign OutRegArgs" << endl;
reassignOutRegArgs();
IPF_LOG << endl; opndManager->printStackInfo();
IPF_LOG << endl; printRegMasks(); IPF_LOG << endl;
}
//----------------------------------------------------------------------------------------//
// Build free reg masks and outArgs vector
void PrologEpilogGenerator::buildSets() {
// Build set of RegOpnd used in method. Buld epilog nodes vector
NodeVector &nodes = cfg.search(SEARCH_POST_ORDER); // get nodes
for(uint16 i=0; i<nodes.size(); i++) { // iterate through CFG nodes
if(nodes[i]->getNodeKind() != NODE_BB) continue; // ignore non BB node
InstVector &insts = ((BbNode *)nodes[i])->getInsts(); // get insts
if(insts.size() == 0) continue; // if there are no insts in node - ignore
// check if node is epilog and insert it in epilogNodes list
CompVector &comps = insts.back()->getComps(); // get last inst completers
if(comps.size()>0 && comps[0]==CMPLT_BTYPE_RET) { // if the inst is br.ret - node is epilog
epilogNodes.push_back(nodes[i]); // put it in epilogNodes list
}
// build mask of used registers and vector of outArgs
for(uint16 j=0; j<insts.size(); j++) { // iterate through instructions
OpndVector &opnds = insts[j]->getOpnds(); // get opnds
for(uint16 k=0; k<insts[j]->getNumOpnd(); k++) { // iterate through opnds
if(opnds[k]->isReg() == false) continue; // ignore non register opnd
RegOpnd *opnd = (RegOpnd *)opnds[k];
setRegUsage(opnd, true); // mark reg as used
if (opndManager->isOutReg(opnd)) { // if opnd is out arg
outRegArgs.insert(opnd); // place it in ouRegArgs vector
}
}
}
}
}
//----------------------------------------------------------------------------------------//
// At this point out reg args have temporary locations. First one assigned to gr127, second to 126 ...
// Now we know number of in args and locals. Thus we can assign real locations for out args.
void PrologEpilogGenerator::reassignOutRegArgs() {
// First out arg will have this location
I_32 outArgBase = G_INARG_BASE + opndManager->getLocRegSize();
for(RegOpndSetIterator it=outRegArgs.begin(); it!=outRegArgs.end(); it++) {
setRegUsage(*it, false); // mark old reg as free
}
for(RegOpndSetIterator it=outRegArgs.begin(); it!=outRegArgs.end(); it++) {
RegOpnd *arg = *it;
IPF_LOG << " " << IrPrinter::toString(arg) << " reassigned on ";
I_32 outArgNum = G_OUTARG_BASE - arg->getValue(); // calculate real out arg number
arg->setLocation(outArgBase + outArgNum); // calculate and assign new location
setRegUsage(arg, true); // mark new reg as used
IPF_LOG << IrPrinter::toString(arg) << endl;
}
}
//----------------------------------------------------------------------------------------//
// Generate prolog and epilog code and place it in Enter and Epilog nodes
// Prolog:
// alloc pfsBak = 1, 93, 2, 0 # gen alloc (pfsBak can not be preserved gr)
// adds r12 = -stackSize, r12 # save SP
// adds stackAddr = offset, r12 # if pfsBak is stack opnd - spill pfs
// st8 [stackAddr] = pfsBak #
// mov scratch = unat # if we use preserved grs - spill unat
// adds stackAddr = offset, r12 #
// st8 [stackAddr] = scratch #
// adds stackAddr = offset, r12 # spill preserved grs
// st8.spill [stackAddr] = preservedGr #
// adds stackAddr = offset, r12 # spill preserved frs
// stf.spill [stackAddr] = preservedFr #
// mov brBak = preservedBr # save preserved brs
// mov prBak = pr # save preserved prs
// mov rpBak = b0 # save return poiner
//
// Epilog:
// mov b0 = prBak # restore return poiner
// mov pr = prBak # restore preserved prs
// mov preservedBr = brBak # restore preserved brs
// adds stackAddr = offset, r12 # fill preserved frs
// ldf.fill preservedFr = [stackAddr] #
// adds stackAddr = offset1, r12 # fill preserved grs
// ld8.fill preservedGr = [stackAddr] #
// adds stackAddr = offset, r12 # if we use preserved grs - fill unat
// ld8 scratch = [stackAddr] #
// mov unat = scratch #
// mov.i AR.PFS = pfsBak # restore AR.PFS (if pfsBak is stack opnd - fill pfs)
// adds r12 = stackSize, r12 # restore SP
void PrologEpilogGenerator::genCode() {
containCall = opndManager->getContainCall();
saveRestoreRp(); // affects: mem stack, reg stack use:
saveRestorePr(); // affects: mem stack, reg stack use:
genAlloc(); // affects: mem stack, reg stack use: reg stack
saveRestoreUnat(); // affects: mem stack use:
saveRestorePreservedGr(); // affects: mem stack use:
saveRestorePreservedFr(); // affects: mem stack use:
saveRestorePreservedBr(); // affects: mem stack use:
saveRestoreSp(); // affects: use: mem stack
prologInsts.splice(prologInsts.end(), allocInsts);
prologInsts.splice(prologInsts.end(), saveSpInsts);
prologInsts.splice(prologInsts.end(), savePfsInsts);
prologInsts.splice(prologInsts.end(), saveUnatInsts);
prologInsts.splice(prologInsts.end(), saveGrsInsts);
prologInsts.splice(prologInsts.end(), saveFrsInsts);
prologInsts.splice(prologInsts.end(), saveBrsInsts);
prologInsts.splice(prologInsts.end(), savePrsInsts);
prologInsts.splice(prologInsts.end(), saveRpInsts);
epilogInsts.splice(epilogInsts.end(), restRpInsts);
epilogInsts.splice(epilogInsts.end(), restPrsInsts);
epilogInsts.splice(epilogInsts.end(), restBrsInsts);
epilogInsts.splice(epilogInsts.end(), restFrsInsts);
epilogInsts.splice(epilogInsts.end(), restGrsInsts);
epilogInsts.splice(epilogInsts.end(), restUnatInsts);
epilogInsts.splice(epilogInsts.end(), restPfsInsts);
epilogInsts.splice(epilogInsts.end(), restSpInsts);
// Print Prolog and Epilog insts
IPF_LOG << " Prolog:" << endl << IrPrinter::toString(prologInsts);
IPF_LOG << " Epilog:" << endl << IrPrinter::toString(epilogInsts) << endl;
// Insert prolog instructions in begining of enter node
BbNode *enterNode = (BbNode *)cfg.getEnterNode();
InstVector &enterInsts = enterNode->getInsts();
enterInsts.insert(enterInsts.begin(), prologInsts.begin(), prologInsts.end());
// Insert epilog instructions in each epilog node (all nodes which end with "br.ret")
for(uint16 i=0; i<epilogNodes.size(); i++) {
InstVector &exitInsts = ((BbNode *)epilogNodes[i])->getInsts();
exitInsts.insert(exitInsts.end()-1, epilogInsts.begin(), epilogInsts.end());
}
}
//----------------------------------------------------------------------------------------//
// Generate saving/restoring return pointer
// mov rpBak = b0
void PrologEpilogGenerator::saveRestoreRp() {
if(containCall == false) return; // method does not contain "call" - nothing to do
RegOpnd *b0 = opndManager->getB0(); // return pointer to be saved
RegOpnd *rpBak = newStorage(DATA_B, SITE_REG); // opnd to store return pointer
opndManager->rpBak = rpBak->getLocation(); // set rpBak as storage of return pointer
if (rpBak->isMem()) {
Opnd *offset = opndManager->newImm(rpBak->getValue());
Opnd *scratch = opndManager->newRegOpnd(OPND_G_REG, DATA_B, SPILL_REG2);
saveRpInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, scratch, b0));
saveRpInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
saveRpInsts.push_back(new(mm) Inst(mm, INST_ST, CMPLT_SZ_8, p0, stackAddr, scratch));
restRpInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
restRpInsts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, scratch, stackAddr));
restRpInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, b0, scratch));
} else {
saveRpInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, rpBak, b0));
restRpInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, b0, rpBak));
}
}
//----------------------------------------------------------------------------------------//
// If we use preserved prs - generate saving/restoring predicate registers
void PrologEpilogGenerator::saveRestorePr() {
RegBitSet regMask = usedPrMask & opndManager->preservPrMask;
if(regMask.any() == false) return; // method does not use preserved pr
RegOpnd *prBak = newStorage(DATA_U64, SITE_REG); // opnd to store prs
opndManager->prBak = prBak->getLocation(); // set prBak as storage of prs
if (prBak->isMem()) {
Opnd *offset = opndManager->newImm(prBak->getValue());
Opnd *scratch = opndManager->newRegOpnd(OPND_G_REG, DATA_B, SPILL_REG2);
savePrsInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, scratch, p0));
savePrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
savePrsInsts.push_back(new(mm) Inst(mm, INST_ST, CMPLT_SZ_8, p0, stackAddr, scratch));
restPrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
restPrsInsts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, scratch, stackAddr));
restPrsInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, p0, scratch));
} else {
savePrsInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, prBak, p0));
restPrsInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, p0, prBak));
}
}
//----------------------------------------------------------------------------------------//
// Generate "alloc" and AR.PFS restoring instructions
void PrologEpilogGenerator::genAlloc() {
I_32 locRegSize = calculateLocRegSize(); // actual reg usage in local area
I_32 inRegSize = opndManager->getInRegSize(); // in regs number
I_32 outRegSize = opndManager->getOutRegSize(); // out regs number
if (containCall==false && locRegSize<=inRegSize) return; // method does not need "alloc" inst
Opnd *pfsBak = saveRestorePfs(); // opnd to store AR.PFS
locRegSize = calculateLocRegSize(); // saveRestorePfs can allocate local gr
Opnd *iSize = opndManager->newImm(0); // always 0
Opnd *lSize = opndManager->newImm(locRegSize); // number of in+local gr
Opnd *oSize = opndManager->newImm(outRegSize); // number of output gr
Opnd *rSize = opndManager->newImm(0); // number of rotate gr
allocInsts.push_back(new(mm) Inst(mm, INST_ALLOC, p0, pfsBak, iSize, lSize, oSize, rSize));
}
//----------------------------------------------------------------------------------------//
// Generate instructions for saving/restoring AR.PFS
Opnd* PrologEpilogGenerator::saveRestorePfs() {
if (containCall == false) { // method does not contain "call" - do not save AR.PFS
return opndManager->newRegOpnd(OPND_G_REG, DATA_U64, SPILL_REG2);
}
RegBitSet regMask = usedGrMask;
for(uint16 i=4; i<8; i++) regMask[i] = 1; // do not use preserved gr for saving AR.PFS
Opnd *pfs = opndManager->newRegOpnd(OPND_A_REG, DATA_U64, AR_PFS_NUM);
RegOpnd *pfsBak = newStorage(DATA_U64, SITE_REG);
opndManager->pfsBak = pfsBak->getLocation(); // set the location as storage of AR.PFS
if (pfsBak->isMem()) {
Opnd *offset = opndManager->newImm(pfsBak->getValue());
Opnd *scratch = opndManager->newRegOpnd(OPND_G_REG, DATA_B, SPILL_REG2);
savePfsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
savePfsInsts.push_back(new(mm) Inst(mm, INST_ST, CMPLT_SZ_8, p0, stackAddr, scratch));
restPfsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
restPfsInsts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, scratch, stackAddr));
restPfsInsts.push_back(new(mm) Inst(mm, INST_MOV_I, p0, pfs, scratch));
return scratch;
} else {
restPfsInsts.push_back(new(mm) Inst(mm, INST_MOV_I, p0, pfs, pfsBak));
return pfsBak;
}
}
//----------------------------------------------------------------------------------------//
// Generate instructions for saving/restoring AR.UNAT
void PrologEpilogGenerator::saveRestoreUnat() {
RegBitSet preservGrMask(string("11110000")); // work with r4-r7 only (not with automatic regs r32-r127)
RegBitSet regMask = usedGrMask & preservGrMask;
if(regMask.any() == false) return;
RegOpnd *storage = newStorage(DATA_U64, SITE_STACK);
Opnd *offset = opndManager->newImm(storage->getValue());
Opnd *unat = opndManager->newRegOpnd(OPND_A_REG, DATA_U64, AR_UNAT_NUM);
Opnd *scratch = opndManager->newRegOpnd(OPND_G_REG, DATA_U64, SPILL_REG2);
opndManager->unatBak = storage->getLocation();
saveUnatInsts.push_back(new(mm) Inst(mm, INST_MOV_M, p0, scratch, unat));
saveUnatInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
saveUnatInsts.push_back(new(mm) Inst(mm, INST_ST, CMPLT_SZ_8, p0, stackAddr, scratch));
restUnatInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
restUnatInsts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, scratch, stackAddr));
restUnatInsts.push_back(new(mm) Inst(mm, INST_MOV_M, p0, unat, scratch));
}
//----------------------------------------------------------------------------------------//
// Generate instructions for saving/restoring preserved grs
// adds r14 = offset, r12
// st8.spill [r14] = preserved gr
void PrologEpilogGenerator::saveRestorePreservedGr() {
opndManager->initSavedBase(); // after this point mem local stack must contain preserved regs only
IPF_LOG << " Preserved register saved in memory stack with offset: " << opndManager->savedBase << endl;
RegBitSet preservGrMask(string("11110000")); // work with r4-r7 only (not with automatic regs r32-r127)
RegBitSet regMask = usedGrMask & preservGrMask;
if(regMask.any() == false) return;
IPF_LOG << " Preserved grs:";
for(uint16 i=4; i<8; i++) {
if(regMask[i] == false) continue;
Opnd *storage = newStorage(DATA_U64, SITE_STACK);
Opnd *offset = opndManager->newImm(storage->getValue());
Opnd *preserv = opndManager->newRegOpnd(OPND_G_REG, DATA_U64, i);
saveGrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
saveGrsInsts.push_back(new(mm) Inst(mm, INST_ST8_SPILL, p0, stackAddr, preserv));
restGrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
restGrsInsts.push_back(new(mm) Inst(mm, INST_LD8_FILL, p0, preserv, stackAddr));
IPF_LOG << " " << IrPrinter::toString(preserv);
}
IPF_LOG << endl;
opndManager->savedGrMask = regMask.to_ulong();
}
//----------------------------------------------------------------------------------------//
// Generate instructions for saving/restoring preserved frs
// adds r14 = offset, r12
// stf.spill [r14] = preserved fr
void PrologEpilogGenerator::saveRestorePreservedFr() {
RegBitSet regMask = usedFrMask & opndManager->preservFrMask;
if(regMask.any() == false) return;
IPF_LOG << " Preserved frs:";
for(uint16 i=2; i<32; i++) {
if(regMask[i] == false) continue;
Opnd *storage = newStorage(DATA_F, SITE_STACK);
Opnd *offset = opndManager->newImm(storage->getValue());
Opnd *preserv = opndManager->newRegOpnd(OPND_F_REG, DATA_F, i);
saveFrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
saveFrsInsts.push_back(new(mm) Inst(mm, INST_STF_SPILL, p0, stackAddr, preserv));
restFrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
restFrsInsts.push_back(new(mm) Inst(mm, INST_LDF_FILL, p0, preserv, stackAddr));
IPF_LOG << " " << IrPrinter::toString(preserv);
}
IPF_LOG << endl;
opndManager->savedFrMask = regMask.to_ulong();
}
//----------------------------------------------------------------------------------------//
// Generate instructions for saving/restoring preserved brs
void PrologEpilogGenerator::saveRestorePreservedBr() {
RegBitSet regMask = usedBrMask & opndManager->preservBrMask;
if(regMask.any() == false) return;
IPF_LOG << " Preserved brs:";
for(uint16 i=1; i<6; i++) {
if(regMask[i] == false) continue;
Opnd *storage = newStorage(DATA_B, SITE_STACK);
Opnd *offset = opndManager->newImm(storage->getValue());
Opnd *scratch = opndManager->newRegOpnd(OPND_G_REG, DATA_B, SPILL_REG2);
Opnd *preserv = opndManager->newRegOpnd(OPND_B_REG, DATA_B, i);
saveBrsInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, scratch, preserv));
saveBrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
saveBrsInsts.push_back(new(mm) Inst(mm, INST_ST, CMPLT_SZ_8, p0, stackAddr, scratch));
restBrsInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, stackAddr, offset, sp));
restBrsInsts.push_back(new(mm) Inst(mm, INST_LD, CMPLT_SZ_8, p0, scratch, stackAddr));
restBrsInsts.push_back(new(mm) Inst(mm, INST_MOV, p0, preserv, scratch));
IPF_LOG << " " << IrPrinter::toString(preserv);
}
IPF_LOG << endl;
opndManager->savedBrMask = regMask.to_ulong();
}
//----------------------------------------------------------------------------------------//
// Generate instructions for saving/restoring stack pointer. Instructions are inserted after "alloc"
void PrologEpilogGenerator::saveRestoreSp() {
opndManager->initMemStackSize();
I_32 memStackSize = opndManager->memStackSize;
if (memStackSize <= S_SCRATCH_SIZE) return; // method does not need to save SP
Opnd *memStackSizeOpndNeg = opndManager->newImm(-memStackSize);
Opnd *memStackSizeOpndPos = opndManager->newImm(memStackSize);
saveSpInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, sp, memStackSizeOpndNeg, sp));
restSpInsts.push_back(new(mm) Inst(mm, INST_ADDS, p0, sp, memStackSizeOpndPos, sp));
}
//----------------------------------------------------------------------------------------//
RegOpnd* PrologEpilogGenerator::newStorage(DataKind dataKind, uint16 site) {
I_32 location = LOCATION_INVALID;
if (site==SITE_REG) location = opndManager->newLocation(OPND_G_REG, dataKind, usedGrMask, containCall);
else location = opndManager->newLocSlot(dataKind);
RegOpnd *storage = opndManager->newRegOpnd(OPND_G_REG, dataKind, location); // new storage
if (storage->isMem()) opndManager->calculateOffset(storage); // calc real offset
else setRegUsage(storage, true); // mark reg as used
return storage;
}
//----------------------------------------------------------------------------------------//
void PrologEpilogGenerator::setRegUsage(RegOpnd *opnd, bool flag) {
if(opnd->isMem() == true) return;
uint16 regNum = opnd->getValue();
switch(opnd->getOpndKind()) {
case OPND_G_REG: usedGrMask[regNum] = flag; break;
case OPND_F_REG: usedFrMask[regNum] = flag; break;
case OPND_P_REG: usedPrMask[regNum] = flag; break;
case OPND_B_REG: usedBrMask[regNum] = flag; break;
default: IPF_ERR << " " << opnd->getOpndKind() << endl;
}
}
//----------------------------------------------------------------------------------------//
I_32 PrologEpilogGenerator::calculateLocRegSize() {
uint16 first = G_INARG_BASE; // first possible loc reg opnd location
uint16 last = NUM_G_REG - opndManager->getOutRegSize(); // last possible loc reg opnd location
I_32 locRegSize = 0;
// find last used gr in local area
for(uint16 i=first; i<last; i++) {
if (usedGrMask[i] == true) locRegSize = i;
}
if (locRegSize > 0) locRegSize = locRegSize - first + 1;
opndManager->setLocRegSize(locRegSize); // set new local register area size
return locRegSize;
}
//----------------------------------------------------------------------------------------//
void PrologEpilogGenerator::printRegMasks() {
IPF_LOG << noboolalpha << " Used grs: ";
for(uint16 i=0; i<NUM_G_REG; i++) { if(i%8==0) IPF_LOG << " " << i << " "; IPF_LOG << usedGrMask[i]; }
IPF_LOG << endl << " Used frs: ";
for(uint16 i=0; i<NUM_F_REG; i++) { if(i%8==0) IPF_LOG << " " << i << " "; IPF_LOG << usedFrMask[i]; }
IPF_LOG << endl << " Used prs: ";
for(uint16 i=0; i<NUM_P_REG; i++) { if(i%8==0) IPF_LOG << " " << i << " "; IPF_LOG << usedPrMask[i]; }
IPF_LOG << endl << " Used brs: ";
for(uint16 i=0; i<NUM_B_REG; i++) { if(i%8==0) IPF_LOG << " " << i << " "; IPF_LOG << usedBrMask[i]; }
}
} // IPF
} // Jitrino