diff --git a/support/tools/TableGen/CodeEmitterGen.cpp b/support/tools/TableGen/CodeEmitterGen.cpp index 9d0d939c9df..8cb7979333d 100644 --- a/support/tools/TableGen/CodeEmitterGen.cpp +++ b/support/tools/TableGen/CodeEmitterGen.cpp @@ -59,6 +59,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { // unsigned op = 0; std::map OpOrder; + std::map OpContinuous; for (unsigned i = 0, e = Vals.size(); i != e; ++i) { if (Vals[i].getName() != "Inst" && !Vals[i].getValue()->isComplete() && @@ -71,6 +72,90 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { <<" = getMachineOpValue(MI, MI.getOperand("<getNumBits()-1; bit >= 0; --bit) { + if (VarBitInit *VBI = + dynamic_cast(InstInit->getBit(bit))) { + TypedInit *TI = VBI->getVariable(); + if (VarInit *VI = dynamic_cast(TI)) { + // only process the current variable + if (VI->getName() != Vals[i].getName()) + continue; + + if (beginBitInVar == -1) + beginBitInVar = VBI->getBitNum(); + + if (endBitInVar == -1) + endBitInVar = VBI->getBitNum(); + else { + if (endBitInVar == (int)VBI->getBitNum() + 1) + endBitInVar = VBI->getBitNum(); + else { + continuous = false; + break; + } + } + + if (beginBitInInst == -1) + beginBitInInst = bit; + if (endBitInInst == -1) + endBitInInst = bit; + else { + if (endBitInInst == bit + 1) + endBitInInst = bit; + else { + continuous = false; + break; + } + } + + // maintain same distance between bits in field and bits in + // instruction. if the relative distances stay the same + // throughout, + if ((beginBitInVar - (int)VBI->getBitNum()) != + (beginBitInInst - bit)) + { + continuous = false; + break; + } + } + } + } + + if (continuous) { + o << " // continuous: op" << OpOrder[Vals[i].getName()] << "\n"; + + // Mask off the right bits + // Low mask (ie. shift, if necessary) + if (endBitInVar != 0) { + o << " op" << OpOrder[Vals[i].getName()] + << " >>= endBitInVar;\n"; + beginBitInVar -= endBitInVar; + endBitInVar = 0; + } + + // High mask + o << " op" << OpOrder[Vals[i].getName()] + << " &= (1<<" << beginBitInVar+1 << ") - 1;\n"; + + // Shift the value to the correct place (according to place in instr) + if (endBitInInst != 0) + o << " op" << OpOrder[Vals[i].getName()] + << " <<= " << endBitInInst << ";\n"; + + // Just OR in the result + o << " Value |= op" << OpOrder[Vals[i].getName()] << ";\n"; + } + + // otherwise, will be taken care of in the loop below using this value: + OpContinuous[Vals[i].getName()] = continuous; } } @@ -81,18 +166,32 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { // Scan through the field looking for bit initializers of the current // variable... for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) { - if (BitInit *BI=dynamic_cast(FieldInitializer->getBit(i))){ + if (BitInit *BI=dynamic_cast(FieldInitializer->getBit(i))) + { o << " // bit init: f: " << f << ", i: " << i << "\n"; - } else if (UnsetInit *UI = + } else if (UnsetInit *UI = dynamic_cast(FieldInitializer->getBit(i))) { o << " // unset init: f: " << f << ", i: " << i << "\n"; } else if (VarBitInit *VBI = dynamic_cast(FieldInitializer->getBit(i))) { TypedInit *TI = VBI->getVariable(); if (VarInit *VI = dynamic_cast(TI)) { - o << " Value |= getValueBit(op" << OpOrder[VI->getName()] - << ", " << VBI->getBitNum() - << ")" << " << " << i << ";\n"; + // If the bits of the field are laid out consecutively in the + // instruction, then instead of separately ORing in bits, just + // mask and shift the entire field for efficiency. + if (OpContinuous[VI->getName()]) { + // already taken care of in the loop above, thus there is no + // need to individually OR in the bits + + // for debugging, output the regular version anyway, commented + o << " // Value |= getValueBit(op" + << OpOrder[VI->getName()] << ", " << VBI->getBitNum() + << ")" << " << " << i << ";\n"; + } else { + o << " Value |= getValueBit(op" << OpOrder[VI->getName()] + << ", " << VBI->getBitNum() + << ")" << " << " << i << ";\n"; + } } else if (FieldInit *FI = dynamic_cast(TI)) { // FIXME: implement this! o << "FIELD INIT not implemented yet!\n"; @@ -100,7 +199,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { o << "Error: UNIMPLEMENTED\n"; } } - } + } } else { // ignore annul and predict bits since no one sets them yet if (Vals[f].getName() == "annul" || Vals[f].getName() == "predict") { @@ -112,6 +211,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { o << " break;\n" << " }\n"; } + o << " default:\n" << " DEBUG(std::cerr << \"Not supported instr: \" << MI << \"\\n\");\n" << " abort();\n" diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 9d0d939c9df..8cb7979333d 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -59,6 +59,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { // unsigned op = 0; std::map OpOrder; + std::map OpContinuous; for (unsigned i = 0, e = Vals.size(); i != e; ++i) { if (Vals[i].getName() != "Inst" && !Vals[i].getValue()->isComplete() && @@ -71,6 +72,90 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { <<" = getMachineOpValue(MI, MI.getOperand("<getNumBits()-1; bit >= 0; --bit) { + if (VarBitInit *VBI = + dynamic_cast(InstInit->getBit(bit))) { + TypedInit *TI = VBI->getVariable(); + if (VarInit *VI = dynamic_cast(TI)) { + // only process the current variable + if (VI->getName() != Vals[i].getName()) + continue; + + if (beginBitInVar == -1) + beginBitInVar = VBI->getBitNum(); + + if (endBitInVar == -1) + endBitInVar = VBI->getBitNum(); + else { + if (endBitInVar == (int)VBI->getBitNum() + 1) + endBitInVar = VBI->getBitNum(); + else { + continuous = false; + break; + } + } + + if (beginBitInInst == -1) + beginBitInInst = bit; + if (endBitInInst == -1) + endBitInInst = bit; + else { + if (endBitInInst == bit + 1) + endBitInInst = bit; + else { + continuous = false; + break; + } + } + + // maintain same distance between bits in field and bits in + // instruction. if the relative distances stay the same + // throughout, + if ((beginBitInVar - (int)VBI->getBitNum()) != + (beginBitInInst - bit)) + { + continuous = false; + break; + } + } + } + } + + if (continuous) { + o << " // continuous: op" << OpOrder[Vals[i].getName()] << "\n"; + + // Mask off the right bits + // Low mask (ie. shift, if necessary) + if (endBitInVar != 0) { + o << " op" << OpOrder[Vals[i].getName()] + << " >>= endBitInVar;\n"; + beginBitInVar -= endBitInVar; + endBitInVar = 0; + } + + // High mask + o << " op" << OpOrder[Vals[i].getName()] + << " &= (1<<" << beginBitInVar+1 << ") - 1;\n"; + + // Shift the value to the correct place (according to place in instr) + if (endBitInInst != 0) + o << " op" << OpOrder[Vals[i].getName()] + << " <<= " << endBitInInst << ";\n"; + + // Just OR in the result + o << " Value |= op" << OpOrder[Vals[i].getName()] << ";\n"; + } + + // otherwise, will be taken care of in the loop below using this value: + OpContinuous[Vals[i].getName()] = continuous; } } @@ -81,18 +166,32 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { // Scan through the field looking for bit initializers of the current // variable... for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) { - if (BitInit *BI=dynamic_cast(FieldInitializer->getBit(i))){ + if (BitInit *BI=dynamic_cast(FieldInitializer->getBit(i))) + { o << " // bit init: f: " << f << ", i: " << i << "\n"; - } else if (UnsetInit *UI = + } else if (UnsetInit *UI = dynamic_cast(FieldInitializer->getBit(i))) { o << " // unset init: f: " << f << ", i: " << i << "\n"; } else if (VarBitInit *VBI = dynamic_cast(FieldInitializer->getBit(i))) { TypedInit *TI = VBI->getVariable(); if (VarInit *VI = dynamic_cast(TI)) { - o << " Value |= getValueBit(op" << OpOrder[VI->getName()] - << ", " << VBI->getBitNum() - << ")" << " << " << i << ";\n"; + // If the bits of the field are laid out consecutively in the + // instruction, then instead of separately ORing in bits, just + // mask and shift the entire field for efficiency. + if (OpContinuous[VI->getName()]) { + // already taken care of in the loop above, thus there is no + // need to individually OR in the bits + + // for debugging, output the regular version anyway, commented + o << " // Value |= getValueBit(op" + << OpOrder[VI->getName()] << ", " << VBI->getBitNum() + << ")" << " << " << i << ";\n"; + } else { + o << " Value |= getValueBit(op" << OpOrder[VI->getName()] + << ", " << VBI->getBitNum() + << ")" << " << " << i << ";\n"; + } } else if (FieldInit *FI = dynamic_cast(TI)) { // FIXME: implement this! o << "FIELD INIT not implemented yet!\n"; @@ -100,7 +199,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { o << "Error: UNIMPLEMENTED\n"; } } - } + } } else { // ignore annul and predict bits since no one sets them yet if (Vals[f].getName() == "annul" || Vals[f].getName() == "predict") { @@ -112,6 +211,7 @@ void CodeEmitterGen::createEmitter(std::ostream &o) { o << " break;\n" << " }\n"; } + o << " default:\n" << " DEBUG(std::cerr << \"Not supported instr: \" << MI << \"\\n\");\n" << " abort();\n"